120bc01c3e5e6bfdfd848add1bf02cc25396b444
[kai/samba-autobuild/.git] / source4 / smb_server / smb / signing.c
1 /* 
2    Unix SMB/CIFS implementation.
3    
4    Copyright (C) Andrew Tridgell              2004
5    
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 3 of the License, or
9    (at your option) any later version.
10    
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15    
16    You should have received a copy of the GNU General Public License
17    along with this program.  If not, see <http://www.gnu.org/licenses/>.
18 */
19
20 #include "includes.h"
21 #include "smb_server/smb_server.h"
22 #include "libcli/raw/libcliraw.h"
23 #include "param/param.h"
24
25
26 /*
27   sign an outgoing packet
28 */
29 void smbsrv_sign_packet(struct smbsrv_request *req)
30 {
31 #if 0
32         /* enable this when packet signing is preventing you working out why valgrind 
33            says that data is uninitialised */
34         file_save("pkt.dat", req->out.buffer, req->out.size);
35 #endif
36
37         switch (req->smb_conn->signing.signing_state) {
38         case SMB_SIGNING_ENGINE_OFF:
39                 break;
40
41         case SMB_SIGNING_ENGINE_BSRSPYL:
42                 /* mark the packet as signed - BEFORE we sign it...*/
43                 mark_packet_signed(&req->out);
44                 
45                 /* I wonder what BSRSPYL stands for - but this is what MS 
46                    actually sends! */
47                 memcpy((req->out.hdr + HDR_SS_FIELD), "BSRSPYL ", 8);
48                 break;
49
50         case SMB_SIGNING_ENGINE_ON:
51                         
52                 sign_outgoing_message(&req->out, 
53                                       &req->smb_conn->signing.mac_key, 
54                                       req->seq_num+1);
55                 break;
56         }
57         return;
58 }
59
60
61
62 /*
63   setup the signing key for a connection. Called after authentication succeeds
64   in a session setup
65 */
66 BOOL smbsrv_setup_signing(struct smbsrv_connection *smb_conn,
67                           DATA_BLOB *session_key,
68                           DATA_BLOB *response)
69 {
70         if (!set_smb_signing_common(&smb_conn->signing)) {
71                 return False;
72         }
73         return smbcli_simple_set_signing(smb_conn,
74                                          &smb_conn->signing, session_key, response);
75 }
76
77 void smbsrv_signing_restart(struct smbsrv_connection *smb_conn,
78                             DATA_BLOB *session_key,
79                             DATA_BLOB *response) 
80 {
81         if (!smb_conn->signing.seen_valid) {
82                 DEBUG(5, ("Client did not send a valid signature on "
83                           "SPNEGO session setup - ignored, expect good next time\n"));
84                 /* force things back on (most clients do not sign this packet)... */
85                 smbsrv_setup_signing(smb_conn, session_key, response);
86                 smb_conn->signing.next_seq_num = 2;
87                 if (smb_conn->signing.mandatory_signing) {
88                         DEBUG(5, ("Configured for mandatory signing, 'good packet seen' forced on\n"));
89                         /* if this is mandatory, then
90                          * pretend we have seen a
91                          * valid packet, so we don't
92                          * turn it off */
93                         smb_conn->signing.seen_valid = True;
94                 }
95         }
96 }
97
98 BOOL smbsrv_init_signing(struct smbsrv_connection *smb_conn)
99 {
100         smb_conn->signing.mac_key = data_blob(NULL, 0);
101         if (!smbcli_set_signing_off(&smb_conn->signing)) {
102                 return False;
103         }
104         
105         switch (lp_server_signing()) {
106         case SMB_SIGNING_OFF:
107                 smb_conn->signing.allow_smb_signing = False;
108                 break;
109         case SMB_SIGNING_SUPPORTED:
110                 smb_conn->signing.allow_smb_signing = True;
111                 break;
112         case SMB_SIGNING_REQUIRED:
113                 smb_conn->signing.allow_smb_signing = True;
114                 smb_conn->signing.mandatory_signing = True;
115                 break;
116         case SMB_SIGNING_AUTO:
117                 if (lp_domain_logons()) {
118                         smb_conn->signing.allow_smb_signing = True;
119                 } else {
120                         smb_conn->signing.allow_smb_signing = False;
121                 }
122                 break;
123         }
124         return True;
125 }
126
127 /*
128   allocate a sequence number to a request
129 */
130 static void req_signing_alloc_seq_num(struct smbsrv_request *req)
131 {
132         req->seq_num = req->smb_conn->signing.next_seq_num;
133
134         if (req->smb_conn->signing.signing_state != SMB_SIGNING_ENGINE_OFF) {
135                 req->smb_conn->signing.next_seq_num += 2;
136         }
137 }
138
139 /*
140   called for requests that do not produce a reply of their own
141 */
142 void smbsrv_signing_no_reply(struct smbsrv_request *req)
143 {
144         if (req->smb_conn->signing.signing_state != SMB_SIGNING_ENGINE_OFF) {
145                 req->smb_conn->signing.next_seq_num--;
146         }
147 }
148
149 /***********************************************************
150  SMB signing - Simple implementation - check a MAC sent by client
151 ************************************************************/
152 /**
153  * Check a packet supplied by the server.
154  * @return False if we had an established signing connection
155  *         which had a back checksum, True otherwise
156  */
157 BOOL smbsrv_signing_check_incoming(struct smbsrv_request *req)
158 {
159         BOOL good;
160
161         req_signing_alloc_seq_num(req);
162
163         switch (req->smb_conn->signing.signing_state) 
164         {
165         case SMB_SIGNING_ENGINE_OFF:
166                 return True;
167         case SMB_SIGNING_ENGINE_BSRSPYL:
168         case SMB_SIGNING_ENGINE_ON:
169         {                       
170                 if (req->in.size < (HDR_SS_FIELD + 8)) {
171                         return False;
172                 } else {
173                         good = check_signed_incoming_message(&req->in, 
174                                                              &req->smb_conn->signing.mac_key, 
175                                                              req->seq_num);
176                         
177                         return signing_good(&req->smb_conn->signing, 
178                                             req->seq_num+1, good);
179                 }
180         }
181         }
182         return False;
183 }