1/* 2 * Copyright (c) 2000-2001, Boris Popov 3 * All rights reserved. 4 * 5 * Portions Copyright (C) 2001 - 2012 Apple Inc. All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. All advertising materials mentioning features or use of this software 16 * must display the following acknowledgement: 17 * This product includes software developed by Boris Popov. 18 * 4. Neither the name of the author nor the names of any co-contributors 19 * may be used to endorse or promote products derived from this software 20 * without specific prior written permission. 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32 * SUCH DAMAGE. 33 * 34 */ 35#include <sys/param.h> 36#include <sys/malloc.h> 37#include <sys/kernel.h> 38#include <sys/systm.h> 39#include <sys/conf.h> 40#include <sys/proc.h> 41#include <sys/fcntl.h> 42#include <sys/socket.h> 43#include <sys/sysctl.h> 44#include <libkern/crypto/md5.h> 45 46#include <sys/smb_apple.h> 47 48#include <netsmb/smb.h> 49#include <netsmb/smb_2.h> 50#include <netsmb/smb_conn.h> 51#include <netsmb/smb_subr.h> 52#include <netsmb/smb_rq.h> 53#include <netsmb/smb_dev.h> 54#include <netsmb/md4.h> 55#include <netsmb/smb_packets_2.h> 56 57#include <smbfs/smbfs_subr.h> 58#include <netsmb/smb_converter.h> 59 60#include <crypto/des.h> 61#include <corecrypto/cchmac.h> 62#include <corecrypto/ccsha2.h> 63 64 65#define SMBSIGLEN (8) 66#define SMBSIGOFF (14) 67#define SMBPASTSIG (SMBSIGOFF + SMBSIGLEN) 68#define SMBFUDGESIGN 4 69 70/* SMB2 Signing defines */ 71#define SMB2SIGLEN (16) 72#define SMB2SIGOFF (48) 73 74#ifdef SMB_DEBUG 75/* Need to build with SMB_DEBUG if you what to turn this on */ 76#define SSNDEBUG 0 77#endif // SMB_DEBUG 78 79static u_char N8[] = {0x4b, 0x47, 0x53, 0x21, 0x40, 0x23, 0x24, 0x25}; 80 81 82static void 83smb_E(const u_char *key, u_char *data, u_char *dest) 84{ 85 des_key_schedule *ksp; 86 u_char kk[8]; 87 88 kk[0] = key[0] & 0xfe; 89 kk[1] = key[0] << 7 | (key[1] >> 1 & 0xfe); 90 kk[2] = key[1] << 6 | (key[2] >> 2 & 0xfe); 91 kk[3] = key[2] << 5 | (key[3] >> 3 & 0xfe); 92 kk[4] = key[3] << 4 | (key[4] >> 4 & 0xfe); 93 kk[5] = key[4] << 3 | (key[5] >> 5 & 0xfe); 94 kk[6] = key[5] << 2 | (key[6] >> 6 & 0xfe); 95 kk[7] = key[6] << 1; 96 SMB_MALLOC(ksp, des_key_schedule *, sizeof(des_key_schedule), M_SMBTEMP, M_WAITOK); 97 des_set_key((des_cblock*)kk, *ksp); 98 des_ecb_encrypt((des_cblock*)data, (des_cblock*)dest, *ksp, 1); 99 SMB_FREE(ksp, M_SMBTEMP); 100} 101 102/* 103 * Compute an LM response given the ASCII password and a challenge. 104 */ 105int smb_lmresponse(const u_char *apwd, u_char *C8, u_char *RN) 106{ 107 u_char *p, *P14, *S21; 108 109 SMB_MALLOC(p, u_char *, 14+21, M_SMBTEMP, M_WAITOK); 110 bzero(p, 14 + 21); 111 P14 = p; 112 S21 = p + 14; 113 bcopy(apwd, P14, MIN(14, strnlen((char *)apwd, SMB_MAXPASSWORDLEN + 1))); 114 /* 115 * S21 = concat(Ex(P14, N8), zeros(5)); 116 */ 117 smb_E(P14, N8, S21); 118 smb_E(P14 + 7, N8, S21 + 8); 119 120 smb_E(S21, C8, RN); 121 smb_E(S21 + 7, C8, RN + 8); 122 smb_E(S21 + 14, C8, RN + 16); 123 SMB_FREE(p, M_SMBTEMP); 124 return 24; /* return the len */ 125} 126 127/* 128 * smb_ntlmhash 129 * 130 * Compute the NTLM hash of the given password, which is used in the calculation of 131 * the NTLM Response. Used for both the NTLMv2 and LMv2 hashes. 132 * 133 */ 134static void smb_ntlmhash(const uint8_t *passwd, uint8_t *ntlmHash, size_t ntlmHash_len) 135{ 136 uint16_t *unicode_passwd = NULL; 137 MD4_CTX md4; 138 size_t len; 139 140 bzero(ntlmHash, ntlmHash_len); 141 len = strnlen((char *)passwd, SMB_MAXPASSWORDLEN + 1); 142 143 if (len == 0) { 144 /* Empty password, but we still need to allocate a buffer to */ 145 /* encrypt two NULL bytes so we can compute the NTLM hash correctly. */ 146 len = 1; 147 } 148 149 SMB_MALLOC(unicode_passwd, uint16_t *, len * sizeof(uint16_t), M_SMBTEMP, M_WAITOK); 150 if (unicode_passwd == NULL) /* Should never happen, but better safe than sorry */ 151 return; 152 len = smb_strtouni(unicode_passwd, (char *)passwd, len, UTF_PRECOMPOSED); 153 bzero(&md4, sizeof(md4)); 154 MD4Init(&md4); 155 MD4Update(&md4, (uint8_t *)unicode_passwd, (unsigned int)len); 156 MD4Final(ntlmHash, &md4); 157 SMB_FREE(unicode_passwd, M_SMBTEMP); 158#ifdef SSNDEBUG 159 smb_hexdump(__FUNCTION__, "ntlmHash = ", ntlmHash, 16); 160#endif // SSNDEBUG 161} 162 163/* 164 * Compute an NTLM response given the Unicode password (as an ASCII string, 165 * not a Unicode string!) and a challenge. 166 */ 167void smb_ntlmresponse(const u_char *apwd, u_char *C8, u_char *RN) 168{ 169 u_char S21[SMB_NTLM_LEN]; 170 171 smb_ntlmhash(apwd, S21, sizeof(S21)); 172 173 smb_E(S21, C8, RN); 174 smb_E(S21 + 7, C8, RN + 8); 175 smb_E(S21 + 14, C8, RN + 16); 176} 177 178/* 179 * Initialize the signing data, free the key and 180 * set everything else to zero. 181 */ 182void smb_reset_sig(struct smb_vc *vcp) 183{ 184 if (vcp->vc_mackey != NULL) 185 SMB_FREE(vcp->vc_mackey, M_SMBTEMP); 186 vcp->vc_mackey = NULL; 187 vcp->vc_mackeylen = 0; 188 vcp->vc_seqno = 0; 189} 190 191/* 192 * Sign request with MAC. 193 */ 194int 195smb_rq_sign(struct smb_rq *rqp) 196{ 197 struct smb_vc *vcp = rqp->sr_vc; 198 struct mbchain *mbp; 199 mbuf_t mb; 200 MD5_CTX md5; 201 u_char digest[16]; 202 203 KASSERT(vcp->vc_hflags2 & SMB_FLAGS2_SECURITY_SIGNATURE, 204 ("signatures not enabled")); 205 206 /* 207 * Durring the authentication process we send a magic fake signing string, 208 * because signing really doesn't start until the authentication process is 209 * complete. The sequence number counter starts once we send our authentication 210 * message and must be reset if authentication fails. 211 */ 212 if ((vcp->vc_mackey == NULL) || (rqp->sr_cmd == SMB_COM_SESSION_SETUP_ANDX)) { 213 /* Should never be null, but just to be safe */ 214 if (rqp->sr_rqsig) 215 bcopy("BSRSPLY ", rqp->sr_rqsig, 8); 216 return (0); 217 } 218 /* 219 * This is a bit of a kludge. If the request is non-TRANSACTION, 220 * or it is the first request of a transaction, give it the next 221 * sequence number, and expect the reply to have the sequence number 222 * following that one. Otherwise, it is a secondary request in 223 * a transaction, and it gets the same sequence numbers as the 224 * primary request. 225 */ 226 if (rqp->sr_t2 == NULL || 227 (rqp->sr_t2->t2_flags & SMBT2_SECONDARY) == 0) { 228 rqp->sr_seqno = vcp->vc_seqno++; 229 rqp->sr_rseqno = vcp->vc_seqno++; 230 } else { 231 /* 232 * Sequence numbers are already in the struct because 233 * smb_t2_request_int() uses the same one for all the 234 * requests in the transaction. 235 * (At least we hope so.) 236 */ 237 KASSERT(rqp->sr_t2 == NULL || 238 (rqp->sr_t2->t2_flags & SMBT2_SECONDARY) == 0 || 239 rqp->sr_t2->t2_rq == rqp, 240 ("sec t2 rq not using same smb_rq")); 241 } 242 243 /* Initialize sec. signature field to sequence number + zeros. */ 244 if (rqp->sr_rqsig) { 245 *(uint32_t *)rqp->sr_rqsig = htolel(rqp->sr_seqno); 246 *(uint32_t *)(rqp->sr_rqsig + 4) = 0; 247 } 248 249 /* 250 * Compute HMAC-MD5 of packet data, keyed by MAC key. 251 * Store the first 8 bytes in the sec. signature field. 252 */ 253 smb_rq_getrequest(rqp, &mbp); 254 MD5Init(&md5); 255 MD5Update(&md5, vcp->vc_mackey, vcp->vc_mackeylen); 256 for (mb = mbp->mb_top; mb != NULL; mb = mbuf_next(mb)) 257 MD5Update(&md5, mbuf_data(mb), (unsigned int)mbuf_len(mb)); 258 MD5Final(digest, &md5); 259 if (rqp->sr_rqsig) 260 bcopy(digest, rqp->sr_rqsig, 8); 261 262 return (0); 263} 264 265static int 266smb_verify(struct smb_rq *rqp, uint32_t seqno) 267{ 268 struct smb_vc *vcp = rqp->sr_vc; 269 struct mdchain *mdp; 270 mbuf_t mb; 271 u_char sigbuf[SMBSIGLEN]; 272 MD5_CTX md5; 273 u_char digest[16]; 274 275 /* 276 * Compute HMAC-MD5 of packet data, keyed by MAC key. 277 * We play games to pretend the security signature field 278 * contains their sequence number, to avoid modifying 279 * the packet itself. 280 */ 281 smb_rq_getreply(rqp, &mdp); 282 mb = mdp->md_top; 283 KASSERT(mbuf_len(mb) >= SMB_HDRLEN, ("forgot to mbuf_pullup")); 284 MD5Init(&md5); 285 MD5Update(&md5, vcp->vc_mackey, vcp->vc_mackeylen); 286 MD5Update(&md5, mbuf_data(mb), SMBSIGOFF); 287 *(uint32_t *)sigbuf = htolel(seqno); 288 *(uint32_t *)(sigbuf + 4) = 0; 289 MD5Update(&md5, sigbuf, SMBSIGLEN); 290 MD5Update(&md5, (uint8_t *)mbuf_data(mb) + SMBPASTSIG, 291 (unsigned int)(mbuf_len(mb) - SMBPASTSIG)); 292 for (mb = mbuf_next(mb); mb != NULL; mb = mbuf_next(mb)) 293 if (mbuf_len(mb)) 294 MD5Update(&md5, mbuf_data(mb), (unsigned int)mbuf_len(mb)); 295 MD5Final(digest, &md5); 296 /* 297 * Finally, verify the signature. 298 */ 299 return (bcmp((uint8_t *)mbuf_data(mdp->md_top) + SMBSIGOFF, digest, SMBSIGLEN)); 300} 301 302/* 303 * Verify reply signature. 304 */ 305int 306smb_rq_verify(struct smb_rq *rqp) 307{ 308 struct smb_vc *vcp = rqp->sr_vc; 309 int32_t fudge; 310 311 if (!(vcp->vc_hflags2 & SMB_FLAGS2_SECURITY_SIGNATURE)) { 312 SMBWARNING("signatures not enabled!\n"); 313 return (0); 314 } 315 316 /* 317 * Durring the authentication process we send a dummy signature, because 318 * signing really doesn't start until the authentication process is 319 * complete. The last authentication message return by the server can be 320 * signed, but only if the authentication succeed. If an error is return 321 * then the signing process will fail and if we tested for signing the wrong 322 * error would be return. So durring the authentication process we no longer 323 * verify the signature. From my testing it looks like Windows and Samba 324 * clients do the same thing. 325 */ 326 if ((vcp->vc_mackey == NULL) || (rqp->sr_cmd == SMB_COM_SESSION_SETUP_ANDX)) 327 return (0); 328 329 /* Its an anonymous logins, signing is not supported */ 330 if ((vcp->vc_flags & SMBV_ANONYMOUS_ACCESS) == SMBV_ANONYMOUS_ACCESS) 331 return (0); 332 333 if (smb_verify(rqp, rqp->sr_rseqno) == 0) 334 return (0); 335 336 /* 337 * Now for diag purposes we check whether the client/server idea 338 * of the sequence # has gotten a bit out of sync. This only gets 339 * excute if debugging has been turned on. 340 */ 341 if (smbfs_loglevel) { 342 for (fudge = -SMBFUDGESIGN; fudge <= SMBFUDGESIGN; fudge++) 343 if (fudge == 0) 344 continue; 345 else if (smb_verify(rqp, rqp->sr_rseqno + fudge) == 0) 346 break; 347 348 if (fudge <= SMBFUDGESIGN) 349 SMBERROR("sr_rseqno=%d, but %d would have worked\n", 350 rqp->sr_rseqno, rqp->sr_rseqno + fudge); 351 else 352 SMBERROR("sr_rseqno=%d\n", rqp->sr_rseqno); 353 } 354 355 return (EAUTH); 356} 357 358/* 359 * SMB2 Sign a single request with HMCA-SHA256 360 */ 361static void smb2_sign(struct smb_rq *rqp) 362{ 363 struct smb_vc *vcp = rqp->sr_vc; 364 struct mbchain *mbp; 365 mbuf_t mb; 366 const struct ccdigest_info *di = ccsha256_di(); 367 u_char *mac; 368 369 if (rqp->sr_rqsig == NULL) { 370 SMBDEBUG("sr_rqsig was never allocated.\n"); 371 return; 372 } 373 374 if (di == NULL) { 375 SMBERROR("ccsha256_di returned NULL digest_info\n"); 376 return; 377 } 378 379 /* make sure ccdigest_info size is reasonable (sha256 output len is 32 bytes) */ 380 if (di->output_size > 64) { 381 SMBERROR("Unreasonable output size %lu\n", di->output_size); 382 return; 383 } 384 385 SMB_MALLOC(mac, u_char *, di->output_size, M_SMBTEMP, M_WAITOK); 386 if (mac == NULL) { 387 SMBERROR("Out of memory\n"); 388 return; 389 } 390 391 bzero(mac, di->output_size); 392 393 /* Initialize 16-byte security signature field to all zeros. */ 394 bzero(rqp->sr_rqsig, SMB2SIGLEN); 395 396 /* Set flag to indicate this PDU is signed */ 397 *rqp->sr_flagsp |= htolel(SMB2_FLAGS_SIGNED); 398 399 smb_rq_getrequest(rqp, &mbp); 400 cchmac_di_decl(di, hc); 401 cchmac_init(di, hc, vcp->vc_mackeylen, vcp->vc_mackey); 402 403 for (mb = mbp->mb_top; mb != NULL; mb = mbuf_next(mb)) 404 cchmac_update(di, hc, mbuf_len(mb), mbuf_data(mb)); 405 cchmac_final(di, hc, mac); 406 407 // Copy first 16 bytes of the HMAC hash into the signature field 408 bcopy(mac, rqp->sr_rqsig, SMB2SIGLEN); 409 410 SMB_FREE(mac, M_SMBTEMP); 411} 412 413/* 414 * SMB2 Sign request or compound chain with HMAC-SHA256 415 */ 416int 417smb2_rq_sign(struct smb_rq *rqp) 418{ 419 struct smb_vc *vcp; 420 struct smb_rq *this_rqp; 421 422 if (rqp == NULL) { 423 SMBDEBUG("Called with NULL rqp\n"); 424 return (EINVAL); 425 } 426 427 vcp = rqp->sr_vc; 428 429 if (vcp == NULL) { 430 SMBERROR("vcp is NULL\n"); 431 return (EINVAL); 432 } 433 434 /* Is signing required for the command? */ 435 if ((rqp->sr_command == SMB2_SESSION_SETUP) || (rqp->sr_command == SMB2_OPLOCK_BREAK)) { 436 return (0); 437 } 438 439 /* Do we have a session key? */ 440 if (vcp->vc_mackey == NULL) { 441 SMBDEBUG("No session key for signing.\n"); 442 return (0); 443 } 444 445 this_rqp = rqp; 446 while (this_rqp != NULL) { 447 smb2_sign(this_rqp); 448 this_rqp = this_rqp->sr_next_rqp; 449 } 450 451 return (0); 452} 453 454/* 455 * SMB2 Verify a reply with HMCA-SHA256 456 */ 457static int smb2_verify(struct smb_rq *rqp, struct mdchain *mdp, uint32_t nextCmdOffset, uint8_t *signature) 458{ 459 struct smb_vc *vcp = rqp->sr_vc; 460 mbuf_t mb, mb_temp; 461 size_t mb_off, remaining, mb_len, sign_len, mb_total_len; 462 u_char zero_buf[SMB2SIGLEN]; 463 int result; 464 const struct ccdigest_info *di = ccsha256_di(); 465 u_char *mac; 466 467 if (vcp == NULL) { 468 SMBERROR("vcp is NULL\n"); 469 return (EINVAL); 470 } 471 472 if (di == NULL) { 473 SMBERROR("NULL digest from sha256_di\n"); 474 return (EINVAL); 475 } 476 477 /* make sure ccdigest_info size is reasonable (sha256 output len is 32 bytes) */ 478 if (di->output_size > 64) { 479 SMBERROR("Unreasonable output size %lu\n", di->output_size); 480 return (EINVAL); 481 } 482 483 SMB_MALLOC(mac, u_char *, di->output_size, M_SMBTEMP, M_WAITOK); 484 if (mac == NULL) { 485 SMBERROR("Out of memory\n"); 486 return (ENOMEM); 487 } 488 489 mb = mdp->md_cur; 490 mb_len = (size_t)mbuf_data(mb) + mbuf_len(mb) - (size_t)mdp->md_pos; 491 mb_total_len = mbuf_len(mb); 492 mb_off = mbuf_len(mb) - mb_len; 493 494 /* sanity checks */ 495 if (mb_len < SMB2_HDRLEN) { 496 SMBDEBUG("mbuf not pulled up for SMB2 header, mbuf_len: %lu\n", mbuf_len(mb)); 497 SMB_FREE(mac, M_SMBTEMP); 498 return (EBADRPC); 499 } 500 if (mb_off > mb_total_len) { 501 SMBDEBUG("mb_off: %lu past end of mbuf, mbuf_len: %lu\n", mb_off, mb_total_len); 502 SMB_FREE(mac, M_SMBTEMP); 503 return (EBADRPC); 504 } 505 506 remaining = nextCmdOffset; 507 if (!remaining) { 508 /* 509 * We don't know the length of the reply because it's 510 * not a compound reply, or the end of a compound reply. 511 * So calculate total length of this reply. 512 */ 513 remaining = mb_len; /* length in first mbuf */ 514 mb_temp = mbuf_next(mb); 515 while (mb_temp) { 516 remaining += mbuf_len(mb_temp); 517 mb_temp = mbuf_next(mb_temp); 518 } 519 } 520 521 /* sanity check */ 522 if (remaining < SMB2_HDRLEN) { 523 /* should never happen, but we have to be very careful */ 524 SMBDEBUG("reply length: %lu too short\n", remaining); 525 SMB_FREE(mac, M_SMBTEMP); 526 return (EBADRPC); 527 } 528 529 bzero(zero_buf, SMB2SIGLEN); 530 bzero(mac, di->output_size); 531 cchmac_di_decl(di, hc); 532 cchmac_init(di, hc, vcp->vc_mackeylen, vcp->vc_mackey); 533 534 /* sanity check */ 535 if (mb_len < SMB2SIGOFF) { 536 /* mb_len would go negative when decremented below */ 537 SMBDEBUG("mb_len exhausted: mb_len: %lu SMB2SIGOFF: %u\n", mb_len, (uint32_t)SMB2SIGOFF); 538 SMB_FREE(mac, M_SMBTEMP); 539 return (EBADRPC); 540 } 541 542 /* Sign the first 48 bytes of the reply (up to the signature field) */ 543 cchmac_update(di, hc, SMB2SIGOFF, (uint8_t *)mbuf_data(mb) + mb_off); 544 mb_off += SMB2SIGOFF; 545 mb_len -= SMB2SIGOFF; 546 remaining -= SMB2SIGOFF; 547 548 /* sanity check */ 549 if (mb_off > mb_total_len) { 550 // mb_offset would go past the end of current mbuf, when incremented below */ 551 SMBDEBUG("mb_off past end, mb_off: %lu mbub_len: %lu\n", mb_off, mb_total_len); 552 SMB_FREE(mac, M_SMBTEMP); 553 return (EBADRPC); 554 } 555 /* sanity check */ 556 if (mb_len < SMB2SIGLEN) { 557 /* mb_len would go negative when decremented below */ 558 SMBDEBUG("mb_len exhausted: mb_len: %lu SMB2SIGLEN: %u\n", mb_len, (uint32_t)SMB2SIGLEN); 559 SMB_FREE(mac, M_SMBTEMP); 560 return (EBADRPC); 561 } 562 563 // Sign 16 zeros 564 cchmac_update(di, hc, SMB2SIGLEN, zero_buf); 565 mb_off += SMB2SIGLEN; 566 mb_len -= SMB2SIGLEN; 567 remaining -= SMB2SIGLEN; 568 569 /* Sign remainder of this reply */ 570 while (remaining) { 571 if (!mb_len) { 572 mb = mbuf_next(mb); 573 if (!mb) { 574 SMBDEBUG("mbuf_next didn't return an mbuf\n"); 575 SMB_FREE(mac, M_SMBTEMP); 576 return EBADRPC; 577 } 578 mb_len = mbuf_len(mb); 579 mb_off = 0; 580 } 581 582 /* Calculate length to sign for this pass */ 583 sign_len = remaining; 584 if (sign_len > mb_len) { 585 sign_len = mb_len; 586 } 587 588 /* Sign it */ 589 cchmac_update(di, hc, sign_len, (uint8_t *)mbuf_data(mb) + mb_off); 590 591 mb_off += sign_len; 592 mb_len -= sign_len; 593 remaining -= sign_len; 594 } 595 596 cchmac_final(di, hc, mac); 597 598 /* 599 * Finally, verify the signature. 600 */ 601 result = bcmp(signature, mac, SMB2SIGLEN); 602 SMB_FREE(mac, M_SMBTEMP); 603 return (result); 604} 605 606/* 607 * SMB2 Verify reply signature with HMAC-SHA256 608 */ 609int 610smb2_rq_verify(struct smb_rq *rqp, struct mdchain *mdp, uint8_t *signature) 611{ 612 struct smb_vc *vcp; 613 uint32_t nextCmdOffset; 614 int err; 615 616 if (rqp == NULL) { 617 SMBDEBUG("Called with NULL rqp\n"); 618 return (EINVAL); 619 } 620 621 vcp = rqp->sr_vc; 622 623 if (vcp == NULL) { 624 SMBERROR("NULL vcp\n"); 625 return (0); 626 } 627 nextCmdOffset = rqp->sr_rspnextcmd; 628 629 if (!(vcp->vc_hflags2 & SMB_FLAGS2_SECURITY_SIGNATURE)) { 630 SMBWARNING("signatures not enabled!\n"); 631 return (0); 632 } 633 634 if ((vcp->vc_mackey == NULL) || 635 ( (rqp->sr_command == SMB2_SESSION_SETUP) && !(rqp->sr_rspflags & SMB2_FLAGS_SIGNED))) { 636 /* 637 * Don't verify signature if we don't have a session key from gssd yet. 638 * Don't verify signature if a SessionSetup reply that hasn't 639 * been signed yet (server only signs the final SessionSetup reply). 640 */ 641 return (0); 642 } 643 644 /* Its an anonymous login, signing is not supported */ 645 if ((vcp->vc_flags & SMBV_ANONYMOUS_ACCESS) == SMBV_ANONYMOUS_ACCESS) { 646 return (0); 647 } 648 649 err = smb2_verify(rqp, mdp, nextCmdOffset, signature); 650 651 if (err) { 652 SMBDEBUG("Could not verify signature for sr_command %x, msgid: %llu\n", rqp->sr_command, rqp->sr_messageid); 653 err = EAUTH; 654 } 655 656 return (err); 657} 658