r23792: convert Samba4 to GPLv3
[ira/wip.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
24
25 /*
26   sign an outgoing packet
27 */
28 void smbsrv_sign_packet(struct smbsrv_request *req)
29 {
30 #if 0
31         /* enable this when packet signing is preventing you working out why valgrind 
32            says that data is uninitialised */
33         file_save("pkt.dat", req->out.buffer, req->out.size);
34 #endif
35
36         switch (req->smb_conn->signing.signing_state) {
37         case SMB_SIGNING_ENGINE_OFF:
38                 break;
39
40         case SMB_SIGNING_ENGINE_BSRSPYL:
41                 /* mark the packet as signed - BEFORE we sign it...*/
42                 mark_packet_signed(&req->out);
43                 
44                 /* I wonder what BSRSPYL stands for - but this is what MS 
45                    actually sends! */
46                 memcpy((req->out.hdr + HDR_SS_FIELD), "BSRSPYL ", 8);
47                 break;
48
49         case SMB_SIGNING_ENGINE_ON:
50                         
51                 sign_outgoing_message(&req->out, 
52                                       &req->smb_conn->signing.mac_key, 
53                                       req->seq_num+1);
54                 break;
55         }
56         return;
57 }
58
59
60
61 /*
62   setup the signing key for a connection. Called after authentication succeeds
63   in a session setup
64 */
65 BOOL smbsrv_setup_signing(struct smbsrv_connection *smb_conn,
66                           DATA_BLOB *session_key,
67                           DATA_BLOB *response)
68 {
69         if (!set_smb_signing_common(&smb_conn->signing)) {
70                 return False;
71         }
72         return smbcli_simple_set_signing(smb_conn,
73                                          &smb_conn->signing, session_key, response);
74 }
75
76 void smbsrv_signing_restart(struct smbsrv_connection *smb_conn,
77                             DATA_BLOB *session_key,
78                             DATA_BLOB *response) 
79 {
80         if (!smb_conn->signing.seen_valid) {
81                 DEBUG(5, ("Client did not send a valid signature on "
82                           "SPNEGO session setup - ignored, expect good next time\n"));
83                 /* force things back on (most clients do not sign this packet)... */
84                 smbsrv_setup_signing(smb_conn, session_key, response);
85                 smb_conn->signing.next_seq_num = 2;
86                 if (smb_conn->signing.mandatory_signing) {
87                         DEBUG(5, ("Configured for mandatory signing, 'good packet seen' forced on\n"));
88                         /* if this is mandatory, then
89                          * pretend we have seen a
90                          * valid packet, so we don't
91                          * turn it off */
92                         smb_conn->signing.seen_valid = True;
93                 }
94         }
95 }
96
97 BOOL smbsrv_init_signing(struct smbsrv_connection *smb_conn)
98 {
99         smb_conn->signing.mac_key = data_blob(NULL, 0);
100         if (!smbcli_set_signing_off(&smb_conn->signing)) {
101                 return False;
102         }
103         
104         switch (lp_server_signing()) {
105         case SMB_SIGNING_OFF:
106                 smb_conn->signing.allow_smb_signing = False;
107                 break;
108         case SMB_SIGNING_SUPPORTED:
109                 smb_conn->signing.allow_smb_signing = True;
110                 break;
111         case SMB_SIGNING_REQUIRED:
112                 smb_conn->signing.allow_smb_signing = True;
113                 smb_conn->signing.mandatory_signing = True;
114                 break;
115         case SMB_SIGNING_AUTO:
116                 if (lp_domain_logons()) {
117                         smb_conn->signing.allow_smb_signing = True;
118                 } else {
119                         smb_conn->signing.allow_smb_signing = False;
120                 }
121                 break;
122         }
123         return True;
124 }
125
126 /*
127   allocate a sequence number to a request
128 */
129 static void req_signing_alloc_seq_num(struct smbsrv_request *req)
130 {
131         req->seq_num = req->smb_conn->signing.next_seq_num;
132
133         if (req->smb_conn->signing.signing_state != SMB_SIGNING_ENGINE_OFF) {
134                 req->smb_conn->signing.next_seq_num += 2;
135         }
136 }
137
138 /*
139   called for requests that do not produce a reply of their own
140 */
141 void smbsrv_signing_no_reply(struct smbsrv_request *req)
142 {
143         if (req->smb_conn->signing.signing_state != SMB_SIGNING_ENGINE_OFF) {
144                 req->smb_conn->signing.next_seq_num--;
145         }
146 }
147
148 /***********************************************************
149  SMB signing - Simple implementation - check a MAC sent by client
150 ************************************************************/
151 /**
152  * Check a packet supplied by the server.
153  * @return False if we had an established signing connection
154  *         which had a back checksum, True otherwise
155  */
156 BOOL smbsrv_signing_check_incoming(struct smbsrv_request *req)
157 {
158         BOOL good;
159
160         req_signing_alloc_seq_num(req);
161
162         switch (req->smb_conn->signing.signing_state) 
163         {
164         case SMB_SIGNING_ENGINE_OFF:
165                 return True;
166         case SMB_SIGNING_ENGINE_BSRSPYL:
167         case SMB_SIGNING_ENGINE_ON:
168         {                       
169                 if (req->in.size < (HDR_SS_FIELD + 8)) {
170                         return False;
171                 } else {
172                         good = check_signed_incoming_message(&req->in, 
173                                                              &req->smb_conn->signing.mac_key, 
174                                                              req->seq_num);
175                         
176                         return signing_good(&req->smb_conn->signing, 
177                                             req->seq_num+1, good);
178                 }
179         }
180         }
181         return False;
182 }