winreg3: Fix a const warning
[Samba/bjacke.git] / libcli / smb / smb_signing.c
blob95c9c27c72cd5e90769a4dcd39249471bee6082d
1 /*
2 Unix SMB/CIFS implementation.
3 SMB Signing Code
4 Copyright (C) Jeremy Allison 2003.
5 Copyright (C) Andrew Bartlett <abartlet@samba.org> 2002-2003
6 Copyright (C) Stefan Metzmacher 2009
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>.
22 #include "includes.h"
23 #include "../lib/crypto/crypto.h"
24 #include "smb_common.h"
25 #include "smb_signing.h"
27 /* Used by the SMB signing functions. */
29 struct smb_signing_state {
30 /* is signing localy allowed */
31 bool allowed;
33 /* is signing localy desired */
34 bool desired;
36 /* is signing localy mandatory */
37 bool mandatory;
39 /* is signing negotiated by the peer */
40 bool negotiated;
42 bool active; /* Have I ever seen a validly signed packet? */
44 /* mac_key.length > 0 means signing is started */
45 DATA_BLOB mac_key;
47 /* the next expected seqnum */
48 uint32_t seqnum;
50 TALLOC_CTX *mem_ctx;
51 void *(*alloc_fn)(TALLOC_CTX *mem_ctx, size_t len);
52 void (*free_fn)(TALLOC_CTX *mem_ctx, void *ptr);
55 static void smb_signing_reset_info(struct smb_signing_state *si)
57 si->active = false;
58 si->seqnum = 0;
60 if (si->free_fn) {
61 si->free_fn(si->mem_ctx, si->mac_key.data);
62 } else {
63 talloc_free(si->mac_key.data);
65 si->mac_key.data = NULL;
66 si->mac_key.length = 0;
69 struct smb_signing_state *smb_signing_init_ex(TALLOC_CTX *mem_ctx,
70 bool allowed,
71 bool desired,
72 bool mandatory,
73 void *(*alloc_fn)(TALLOC_CTX *, size_t),
74 void (*free_fn)(TALLOC_CTX *, void *))
76 struct smb_signing_state *si;
78 if (alloc_fn) {
79 void *p = alloc_fn(mem_ctx, sizeof(struct smb_signing_state));
80 if (p == NULL) {
81 return NULL;
83 memset(p, 0, sizeof(struct smb_signing_state));
84 si = (struct smb_signing_state *)p;
85 si->mem_ctx = mem_ctx;
86 si->alloc_fn = alloc_fn;
87 si->free_fn = free_fn;
88 } else {
89 si = talloc_zero(mem_ctx, struct smb_signing_state);
90 if (si == NULL) {
91 return NULL;
95 if (mandatory) {
96 desired = true;
99 if (desired) {
100 allowed = true;
103 si->allowed = allowed;
104 si->desired = desired;
105 si->mandatory = mandatory;
107 return si;
110 struct smb_signing_state *smb_signing_init(TALLOC_CTX *mem_ctx,
111 bool allowed,
112 bool desired,
113 bool mandatory)
115 return smb_signing_init_ex(mem_ctx, allowed, desired, mandatory,
116 NULL, NULL);
119 static bool smb_signing_good(struct smb_signing_state *si,
120 bool good, uint32_t seq)
122 if (good) {
123 if (!si->active) {
124 si->active = true;
126 return true;
129 if (!si->mandatory && !si->active) {
130 /* Non-mandatory signing - just turn off if this is the first bad packet.. */
131 DEBUG(5, ("smb_signing_good: signing negotiated but not required and peer\n"
132 "isn't sending correct signatures. Turning off.\n"));
133 smb_signing_reset_info(si);
134 return true;
137 /* Mandatory signing or bad packet after signing started - fail and disconnect. */
138 DEBUG(0, ("smb_signing_good: BAD SIG: seq %u\n", (unsigned int)seq));
139 return false;
142 static void smb_signing_md5(const DATA_BLOB *mac_key,
143 const uint8_t *hdr, size_t len,
144 uint32_t seq_number,
145 uint8_t calc_md5_mac[16])
147 const size_t offset_end_of_sig = (HDR_SS_FIELD + 8);
148 uint8_t sequence_buf[8];
149 struct MD5Context md5_ctx;
152 * Firstly put the sequence number into the first 4 bytes.
153 * and zero out the next 4 bytes.
155 * We do this here, to avoid modifying the packet.
158 DEBUG(10,("smb_signing_md5: sequence number %u\n", seq_number ));
160 SIVAL(sequence_buf, 0, seq_number);
161 SIVAL(sequence_buf, 4, 0);
163 /* Calculate the 16 byte MAC - but don't alter the data in the
164 incoming packet.
166 This makes for a bit of fussing about, but it's not too bad.
168 MD5Init(&md5_ctx);
170 /* intialise with the key */
171 MD5Update(&md5_ctx, mac_key->data, mac_key->length);
173 /* copy in the first bit of the SMB header */
174 MD5Update(&md5_ctx, hdr, HDR_SS_FIELD);
176 /* copy in the sequence number, instead of the signature */
177 MD5Update(&md5_ctx, sequence_buf, sizeof(sequence_buf));
179 /* copy in the rest of the packet in, skipping the signature */
180 MD5Update(&md5_ctx, hdr + offset_end_of_sig,
181 len - (offset_end_of_sig));
183 /* calculate the MD5 sig */
184 MD5Final(calc_md5_mac, &md5_ctx);
187 uint32_t smb_signing_next_seqnum(struct smb_signing_state *si, bool oneway)
189 uint32_t seqnum;
191 if (si->mac_key.length == 0) {
192 return 0;
195 seqnum = si->seqnum;
196 if (oneway) {
197 si->seqnum += 1;
198 } else {
199 si->seqnum += 2;
202 return seqnum;
205 void smb_signing_cancel_reply(struct smb_signing_state *si, bool oneway)
207 if (si->mac_key.length == 0) {
208 return;
211 if (oneway) {
212 si->seqnum -= 1;
213 } else {
214 si->seqnum -= 2;
218 void smb_signing_sign_pdu(struct smb_signing_state *si,
219 uint8_t *outhdr, size_t len,
220 uint32_t seqnum)
222 uint8_t calc_md5_mac[16];
223 uint8_t com;
224 uint8_t flags;
226 if (si->mac_key.length == 0) {
227 if (!si->negotiated) {
228 return;
232 /* JRA Paranioa test - we should be able to get rid of this... */
233 if (len < (HDR_SS_FIELD + 8)) {
234 DEBUG(1,("smb_signing_sign_pdu: Logic error. "
235 "Can't check signature on short packet! smb_len = %u\n",
236 (unsigned)len));
237 abort();
240 com = SVAL(outhdr, HDR_COM);
241 flags = SVAL(outhdr, HDR_FLG);
243 if (!(flags & FLAG_REPLY)) {
244 uint16_t flags2 = SVAL(outhdr, HDR_FLG2);
246 * If this is a request, specify what is
247 * supported or required by the client
249 if (si->negotiated && si->desired) {
250 flags2 |= FLAGS2_SMB_SECURITY_SIGNATURES;
252 if (si->negotiated && si->mandatory) {
253 flags2 |= FLAGS2_SMB_SECURITY_SIGNATURES_REQUIRED;
255 SSVAL(outhdr, HDR_FLG2, flags2);
258 if (si->mac_key.length == 0) {
259 /* I wonder what BSRSPYL stands for - but this is what MS
260 actually sends! */
261 if (com == SMBsesssetupX) {
262 memcpy(calc_md5_mac, "BSRSPYL ", 8);
263 } else {
264 memset(calc_md5_mac, 0, 8);
266 } else {
267 smb_signing_md5(&si->mac_key, outhdr, len,
268 seqnum, calc_md5_mac);
271 DEBUG(10, ("smb_signing_sign_pdu: sent SMB signature of\n"));
272 dump_data(10, calc_md5_mac, 8);
274 memcpy(&outhdr[HDR_SS_FIELD], calc_md5_mac, 8);
276 /* outhdr[HDR_SS_FIELD+2]=0;
277 Uncomment this to test if the remote server actually verifies signatures...*/
280 bool smb_signing_check_pdu(struct smb_signing_state *si,
281 const uint8_t *inhdr, size_t len,
282 uint32_t seqnum)
284 bool good;
285 uint8_t calc_md5_mac[16];
286 const uint8_t *reply_sent_mac;
288 if (si->mac_key.length == 0) {
289 return true;
292 if (len < (HDR_SS_FIELD + 8)) {
293 DEBUG(1,("smb_signing_check_pdu: Can't check signature "
294 "on short packet! smb_len = %u\n",
295 (unsigned)len));
296 return false;
299 smb_signing_md5(&si->mac_key, inhdr, len,
300 seqnum, calc_md5_mac);
302 reply_sent_mac = &inhdr[HDR_SS_FIELD];
303 good = (memcmp(reply_sent_mac, calc_md5_mac, 8) == 0);
305 if (!good) {
306 int i;
307 const int sign_range = 5;
309 DEBUG(5, ("smb_signing_check_pdu: BAD SIG: wanted SMB signature of\n"));
310 dump_data(5, calc_md5_mac, 8);
312 DEBUG(5, ("smb_signing_check_pdu: BAD SIG: got SMB signature of\n"));
313 dump_data(5, reply_sent_mac, 8);
315 for (i = -sign_range; i < sign_range; i++) {
316 smb_signing_md5(&si->mac_key, inhdr, len,
317 seqnum+i, calc_md5_mac);
318 if (memcmp(reply_sent_mac, calc_md5_mac, 8) == 0) {
319 DEBUG(0,("smb_signing_check_pdu: "
320 "out of seq. seq num %u matches. "
321 "We were expecting seq %u\n",
322 (unsigned int)seqnum+i,
323 (unsigned int)seqnum));
324 break;
327 } else {
328 DEBUG(10, ("smb_signing_check_pdu: seq %u: "
329 "got good SMB signature of\n",
330 (unsigned int)seqnum));
331 dump_data(10, reply_sent_mac, 8);
334 return smb_signing_good(si, good, seqnum);
337 bool smb_signing_activate(struct smb_signing_state *si,
338 const DATA_BLOB user_session_key,
339 const DATA_BLOB response)
341 size_t len;
342 off_t ofs;
344 if (!user_session_key.length) {
345 return false;
348 if (!si->negotiated) {
349 return false;
352 if (si->active) {
353 return false;
356 if (si->mac_key.length > 0) {
357 return false;
360 smb_signing_reset_info(si);
362 len = response.length + user_session_key.length;
363 if (si->alloc_fn) {
364 si->mac_key.data = (uint8_t *)si->alloc_fn(si->mem_ctx, len);
365 if (si->mac_key.data == NULL) {
366 return false;
368 } else {
369 si->mac_key.data = (uint8_t *)talloc_size(si, len);
370 if (si->mac_key.data == NULL) {
371 return false;
374 si->mac_key.length = len;
376 ofs = 0;
377 memcpy(&si->mac_key.data[ofs], user_session_key.data, user_session_key.length);
379 DEBUG(10, ("smb_signing_activate: user_session_key\n"));
380 dump_data(10, user_session_key.data, user_session_key.length);
382 if (response.length) {
383 ofs = user_session_key.length;
384 memcpy(&si->mac_key.data[ofs], response.data, response.length);
385 DEBUG(10, ("smb_signing_activate: response_data\n"));
386 dump_data(10, response.data, response.length);
387 } else {
388 DEBUG(10, ("smb_signing_activate: NULL response_data\n"));
391 dump_data_pw("smb_signing_activate: mac key is:\n",
392 si->mac_key.data, si->mac_key.length);
394 /* Initialise the sequence number */
395 si->seqnum = 2;
397 return true;
400 bool smb_signing_is_active(struct smb_signing_state *si)
402 return si->active;
405 bool smb_signing_is_allowed(struct smb_signing_state *si)
407 return si->allowed;
410 bool smb_signing_is_mandatory(struct smb_signing_state *si)
412 return si->mandatory;
415 bool smb_signing_set_negotiated(struct smb_signing_state *si,
416 bool allowed, bool mandatory)
418 if (si->active) {
419 return true;
422 if (!si->allowed && mandatory) {
423 return false;
426 if (si->mandatory && !allowed) {
427 return false;
430 if (si->mandatory) {
431 si->negotiated = true;
432 return true;
435 if (mandatory) {
436 si->negotiated = true;
437 return true;
440 if (!si->desired) {
441 si->negotiated = false;
442 return true;
445 if (si->desired && allowed) {
446 si->negotiated = true;
447 return true;
450 si->negotiated = false;
451 return true;
454 bool smb_signing_is_negotiated(struct smb_signing_state *si)
456 return si->negotiated;
459 void smb_key_derivation(const uint8_t *KI, size_t KI_len,
460 uint8_t KO[16])
462 static const uint8_t SSKeyHash[256] = {
463 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79,
464 0x20, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75,
465 0x72, 0x65, 0x20, 0x4b, 0x65, 0x79, 0x20, 0x55,
466 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, 0x79, 0x07,
467 0x6e, 0x28, 0x2e, 0x69, 0x88, 0x10, 0xb3, 0xdb,
468 0x01, 0x55, 0x72, 0xfb, 0x74, 0x14, 0xfb, 0xc4,
469 0xc5, 0xaf, 0x3b, 0x41, 0x65, 0x32, 0x17, 0xba,
470 0xa3, 0x29, 0x08, 0xc1, 0xde, 0x16, 0x61, 0x7e,
471 0x66, 0x98, 0xa4, 0x0b, 0xfe, 0x06, 0x83, 0x53,
472 0x4d, 0x05, 0xdf, 0x6d, 0xa7, 0x51, 0x10, 0x73,
473 0xc5, 0x50, 0xdc, 0x5e, 0xf8, 0x21, 0x46, 0xaa,
474 0x96, 0x14, 0x33, 0xd7, 0x52, 0xeb, 0xaf, 0x1f,
475 0xbf, 0x36, 0x6c, 0xfc, 0xb7, 0x1d, 0x21, 0x19,
476 0x81, 0xd0, 0x6b, 0xfa, 0x77, 0xad, 0xbe, 0x18,
477 0x78, 0xcf, 0x10, 0xbd, 0xd8, 0x78, 0xf7, 0xd3,
478 0xc6, 0xdf, 0x43, 0x32, 0x19, 0xd3, 0x9b, 0xa8,
479 0x4d, 0x9e, 0xaa, 0x41, 0xaf, 0xcb, 0xc6, 0xb9,
480 0x34, 0xe7, 0x48, 0x25, 0xd4, 0x88, 0xc4, 0x51,
481 0x60, 0x38, 0xd9, 0x62, 0xe8, 0x8d, 0x5b, 0x83,
482 0x92, 0x7f, 0xb5, 0x0e, 0x1c, 0x2d, 0x06, 0x91,
483 0xc3, 0x75, 0xb3, 0xcc, 0xf8, 0xf7, 0x92, 0x91,
484 0x0b, 0x3d, 0xa1, 0x10, 0x5b, 0xd5, 0x0f, 0xa8,
485 0x3f, 0x5d, 0x13, 0x83, 0x0a, 0x6b, 0x72, 0x93,
486 0x14, 0x59, 0xd5, 0xab, 0xde, 0x26, 0x15, 0x6d,
487 0x60, 0x67, 0x71, 0x06, 0x6e, 0x3d, 0x0d, 0xa7,
488 0xcb, 0x70, 0xe9, 0x08, 0x5c, 0x99, 0xfa, 0x0a,
489 0x5f, 0x3d, 0x44, 0xa3, 0x8b, 0xc0, 0x8d, 0xda,
490 0xe2, 0x68, 0xd0, 0x0d, 0xcd, 0x7f, 0x3d, 0xf8,
491 0x73, 0x7e, 0x35, 0x7f, 0x07, 0x02, 0x0a, 0xb5,
492 0xe9, 0xb7, 0x87, 0xfb, 0xa1, 0xbf, 0xcb, 0x32,
493 0x31, 0x66, 0x09, 0x48, 0x88, 0xcc, 0x18, 0xa3,
494 0xb2, 0x1f, 0x1f, 0x1b, 0x90, 0x4e, 0xd7, 0xe1
496 HMACMD5Context ctx;
498 hmac_md5_init_limK_to_64(KI, KI_len, &ctx);
499 hmac_md5_update(SSKeyHash, sizeof(SSKeyHash), &ctx);
500 hmac_md5_final(KO, &ctx);
502 ZERO_STRUCT(ctx);