1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #pragma ident "%Z%%M% %I% %E% SMI" 27 28 #include <strings.h> 29 #include <stdlib.h> 30 #include <smbsrv/alloc.h> 31 #include <smbsrv/codepage.h> 32 #include <smbsrv/oem.h> 33 #include <smbsrv/ctype.h> 34 #include <smbsrv/crypt.h> 35 #include <smbsrv/libsmb.h> 36 37 extern void randomize(char *data, unsigned len); 38 static uint64_t unix_micro_to_nt_time(struct timeval *unix_time); 39 40 /* 41 * smb_auth_qnd_unicode 42 * 43 * Quick and dirty unicode conversion! 44 * Returns the length of dst in bytes. 45 */ 46 int 47 smb_auth_qnd_unicode(mts_wchar_t *dst, char *src, int length) 48 { 49 int i; 50 51 unsigned int cpid = oem_get_telnet_cpid(); 52 unsigned int count; 53 mts_wchar_t new_char; 54 55 if ((count = oemstounicodes(dst, src, length, cpid)) == 0) { 56 for (i = 0; i < length; ++i) { 57 new_char = (mts_wchar_t)src[i] & 0xff; 58 dst[i] = LE_IN16(&new_char); 59 } 60 dst[i] = 0; 61 count = length; 62 } 63 64 return (count * sizeof (mts_wchar_t)); 65 } 66 67 /* 68 * smb_auth_lmupr 69 * 70 * Converts the given LM password to all uppercase. 71 * The standard strupr cannot 72 * be used here because lm_pwd doesn't have to be 73 * nul terminated. 74 */ 75 static void 76 smb_auth_lmupr(unsigned char *lm_pwd) 77 { 78 unsigned char *p = lm_pwd; 79 int i; 80 81 for (i = 0; (*p) && (i < SMBAUTH_LM_PWD_SZ); i++) { 82 if (mts_isascii(*p)) { 83 *p = codepage_toupper(*p); 84 p++; 85 } 86 } 87 } 88 89 /* 90 * smb_auth_lm_hash 91 * 92 * Source: Implementing CIFS (Chris Hertel) 93 * 94 * 1. The password, as entered by user, is either padded with nulls 95 * or trimmed to 14 bytes. 96 * . Note that the 14-byte result string is not handled as a 97 * nul-terminated string. 98 * . The given password is OEM not Unicode 99 * 100 * 2. The 14-byte password is converted to all uppercase 101 * 102 * 3. The result is used as key to encrypt the KGS magic string to 103 * make a 16-byte hash. 104 */ 105 int 106 smb_auth_lm_hash(char *password, unsigned char *lm_hash) 107 { 108 unsigned char lm_pwd[SMBAUTH_LM_PWD_SZ]; 109 110 bzero((void *)lm_pwd, SMBAUTH_LM_PWD_SZ); 111 (void) strncpy((char *)lm_pwd, password, SMBAUTH_LM_PWD_SZ); 112 smb_auth_lmupr(lm_pwd); 113 114 return (smb_auth_DES(lm_hash, SMBAUTH_HASH_SZ, lm_pwd, 115 SMBAUTH_LM_PWD_SZ, (unsigned char *)SMBAUTH_LM_MAGIC_STR, 116 sizeof (SMBAUTH_LM_MAGIC_STR))); 117 } 118 119 /* 120 * smb_auth_lm_response 121 * 122 * Create a LM response from the given LM hash and challenge. 123 * 124 * Returns SMBAUTH_FAILURE if any problems occur, SMBAUTH_SUCCESS if 125 * all goes well. 126 */ 127 static int 128 smb_auth_lm_response(unsigned char *hash, 129 unsigned char *challenge, int clen, 130 unsigned char *lm_rsp) 131 { 132 unsigned char S21[21]; 133 134 /* 135 * 14-byte LM Hash should be padded with 5 nul bytes to create 136 * a 21-byte string to be used in producing LM response 137 */ 138 bzero(&S21[SMBAUTH_HASH_SZ], 5); 139 bcopy(hash, S21, SMBAUTH_HASH_SZ); 140 141 /* padded LM Hash -> LM Response */ 142 return (smb_auth_DES(lm_rsp, SMBAUTH_LM_RESP_SZ, S21, 21, 143 challenge, clen)); 144 } 145 146 /* 147 * smb_auth_ntlm_hash 148 * 149 * Make NTLM Hash (using MD4) from the given password. 150 * The result will contain a 16-byte NTLM hash. 151 */ 152 int 153 smb_auth_ntlm_hash(char *password, unsigned char *hash) 154 { 155 mts_wchar_t *unicode_password; 156 int length; 157 int rc; 158 159 if (password == NULL || hash == NULL) 160 return (SMBAUTH_FAILURE); 161 162 length = strlen(password); 163 unicode_password = (mts_wchar_t *) 164 malloc((length + 1) * sizeof (mts_wchar_t)); 165 166 if (unicode_password == NULL) 167 return (SMBAUTH_FAILURE); 168 169 length = smb_auth_qnd_unicode(unicode_password, password, length); 170 rc = smb_auth_md4(hash, (unsigned char *)unicode_password, length); 171 172 free(unicode_password); 173 return (rc); 174 } 175 176 /* 177 * smb_auth_ntlm_response 178 * 179 * Make LM/NTLM response from the given LM/NTLM Hash and given 180 * challenge. 181 */ 182 static int 183 smb_auth_ntlm_response(unsigned char *hash, 184 unsigned char *challenge, int clen, 185 unsigned char *ntlm_rsp) 186 { 187 unsigned char S21[21]; 188 189 bcopy(hash, S21, SMBAUTH_HASH_SZ); 190 bzero(&S21[SMBAUTH_HASH_SZ], 5); 191 if (smb_auth_DES((unsigned char *)ntlm_rsp, SMBAUTH_LM_RESP_SZ, 192 S21, 21, challenge, clen) == SMBAUTH_FAILURE) 193 return (0); 194 return (SMBAUTH_LM_RESP_SZ); 195 } 196 197 /* 198 * smb_auth_gen_data_blob 199 * 200 * Fill the NTLMv2 data blob structure with information as described in 201 * "Implementing CIFS, The Common Internet File System". (pg. 282) 202 */ 203 static void 204 smb_auth_gen_data_blob(smb_auth_data_blob_t *blob, char *ntdomain) 205 { 206 struct timeval now; 207 208 (void) memset(blob->ndb_signature, 1, 2); 209 (void) memset(&blob->ndb_signature[2], 0, 2); 210 (void) memset(blob->ndb_reserved, 0, sizeof (blob->ndb_reserved)); 211 212 (void) gettimeofday(&now, 0); 213 blob->ndb_timestamp = unix_micro_to_nt_time(&now); 214 randomize((char *)blob->ndb_clnt_challenge, 215 SMBAUTH_V2_CLNT_CHALLENGE_SZ); 216 (void) memset(blob->ndb_unknown, 0, sizeof (blob->ndb_unknown)); 217 blob->ndb_names[0].nne_len = smb_auth_qnd_unicode( 218 blob->ndb_names[0].nne_name, ntdomain, strlen(ntdomain)); 219 blob->ndb_names[0].nne_type = SMBAUTH_NAME_TYPE_DOMAIN_NETBIOS; 220 blob->ndb_names[1].nne_len = 0; 221 blob->ndb_names[1].nne_type = SMBAUTH_NAME_TYPE_LIST_END; 222 *blob->ndb_names[1].nne_name = 0; 223 (void) memset(blob->ndb_unknown2, 0, sizeof (blob->ndb_unknown2)); 224 } 225 226 /* 227 * smb_auth_memcpy 228 * 229 * It increments the pointer to the destination buffer for the easy of 230 * concatenation. 231 */ 232 static void 233 smb_auth_memcpy(unsigned char **dstbuf, 234 unsigned char *srcbuf, 235 int srcbuf_len) 236 { 237 (void) memcpy(*dstbuf, srcbuf, srcbuf_len); 238 *dstbuf += srcbuf_len; 239 } 240 241 /* 242 * smb_auth_blob_to_string 243 * 244 * Prepare the data blob string which will be used in NTLMv2 response 245 * generation. 246 * 247 * Assumption: Caller must allocate big enough buffer to prevent buffer 248 * overrun. 249 * 250 * Returns the len of the data blob string. 251 */ 252 static int 253 smb_auth_blob_to_string(smb_auth_data_blob_t *blob, unsigned char *data_blob) 254 { 255 unsigned char *bufp = data_blob; 256 257 smb_auth_memcpy(&bufp, blob->ndb_signature, 258 sizeof (blob->ndb_signature)); 259 smb_auth_memcpy(&bufp, blob->ndb_reserved, 260 sizeof (blob->ndb_reserved)); 261 smb_auth_memcpy(&bufp, (unsigned char *)&blob->ndb_timestamp, 262 sizeof (blob->ndb_timestamp)); 263 smb_auth_memcpy(&bufp, blob->ndb_clnt_challenge, 264 SMBAUTH_V2_CLNT_CHALLENGE_SZ); 265 smb_auth_memcpy(&bufp, blob->ndb_unknown, sizeof (blob->ndb_unknown)); 266 smb_auth_memcpy(&bufp, (unsigned char *)&blob->ndb_names[0].nne_type, 267 sizeof (blob->ndb_names[0].nne_type)); 268 smb_auth_memcpy(&bufp, (unsigned char *)&blob->ndb_names[0].nne_len, 269 sizeof (blob->ndb_names[0].nne_len)); 270 smb_auth_memcpy(&bufp, (unsigned char *)blob->ndb_names[0].nne_name, 271 blob->ndb_names[0].nne_len); 272 smb_auth_memcpy(&bufp, (unsigned char *)&blob->ndb_names[1].nne_type, 273 sizeof (blob->ndb_names[1].nne_type)); 274 smb_auth_memcpy(&bufp, (unsigned char *)&blob->ndb_names[1].nne_len, 275 sizeof (blob->ndb_names[1].nne_len)); 276 smb_auth_memcpy(&bufp, blob->ndb_unknown2, sizeof (blob->ndb_unknown2)); 277 278 /*LINTED E_PTRDIFF_OVERFLOW*/ 279 return (bufp - data_blob); 280 } 281 282 /* 283 * smb_auth_ntlmv2_hash 284 * 285 * The NTLM v2 hash will be created from the given NTLM hash, username, 286 * and the NETBIOS name of the domain. 287 * 288 * The NTLMv2 hash will be returned via the ntlmv2_hash parameter which 289 * will be used in the calculation of the NTLMv2 and LMv2 responses. 290 */ 291 static int 292 smb_auth_ntlmv2_hash(unsigned char *ntlm_hash, 293 char *username, 294 char *ntdomain, 295 unsigned char *ntlmv2_hash) 296 { 297 mts_wchar_t *data; 298 int data_len; 299 unsigned char *buf; 300 int rc; 301 302 if (username == NULL || ntdomain == NULL) 303 return (SMBAUTH_FAILURE); 304 305 (void) utf8_strupr(username); 306 307 data_len = strlen(username) + strlen(ntdomain); 308 buf = (unsigned char *)malloc((data_len + 1) * sizeof (char)); 309 if (buf == NULL) 310 return (SMBAUTH_FAILURE); 311 312 (void) snprintf((char *)buf, data_len + 1, "%s%s", username, ntdomain); 313 data = (mts_wchar_t *)malloc((data_len + 1) * sizeof (mts_wchar_t)); 314 if (data == NULL) { 315 free(buf); 316 return (SMBAUTH_FAILURE); 317 } 318 319 data_len = smb_auth_qnd_unicode(data, (char *)buf, data_len); 320 rc = SMBAUTH_HMACT64((unsigned char *)data, data_len, ntlm_hash, 321 SMBAUTH_HASH_SZ, ntlmv2_hash); 322 323 free(buf); 324 free(data); 325 return (rc); 326 } 327 328 /* 329 * smb_auth_v2_response 330 * 331 * Caculates either the LMv2 or NTLMv2 response. 332 * 333 * Same algorithm is used for calculating both LMv2 or NTLMv2 responses. 334 * This routine will return NTLMv2 response if the data blob information 335 * is passed in as the clnt_data. Otherwise, it will return LMv2 response 336 * with the 8-byte client challenge(a.k.a blip) as the clnt_data. 337 * 338 * (LM/NTLM)v2 response is the hmac-md5 hash of the specified data 339 * (server challenge + NTLMv2 data blob or LMv2 client challenge) 340 * using the NTLMv2 hash as the key. 341 * 342 * Returns the size of the corresponding v2 response upon success. 343 * Otherwise, returns -1 on error. 344 */ 345 static int 346 smb_auth_v2_response( 347 unsigned char *hash, 348 unsigned char *srv_challenge, int slen, 349 unsigned char *clnt_data, int clen, 350 unsigned char *v2_rsp) 351 { 352 unsigned char *hmac_data; 353 354 hmac_data = (unsigned char *)malloc((slen + clen) * sizeof (char)); 355 if (!hmac_data) { 356 return (-1); 357 } 358 359 (void) memcpy(hmac_data, srv_challenge, slen); 360 (void) memcpy(&hmac_data[slen], clnt_data, clen); 361 if (SMBAUTH_HMACT64(hmac_data, slen + clen, (unsigned char *)hash, 362 SMBAUTH_HASH_SZ, (unsigned char *)v2_rsp) != SMBAUTH_SUCCESS) 363 return (-1); 364 (void) memcpy(&v2_rsp[SMBAUTH_HASH_SZ], clnt_data, clen); 365 366 free(hmac_data); 367 return (SMBAUTH_HASH_SZ + clen); 368 } 369 370 /* 371 * smb_auth_set_info 372 * 373 * Fill the smb_auth_info instance with either NTLM or NTLMv2 related 374 * authentication information based on the LMCompatibilityLevel. 375 * 376 * If the LMCompatibilityLevel equals 2, the SMB Redirector will perform 377 * NTLM challenge/response authentication which requires the NTLM hash and 378 * NTLM response. 379 * 380 * If the LMCompatibilityLevel is 3 or above, the SMB Redirector will 381 * perfrom NTLMv2 challenge/response authenticatoin which requires the 382 * NTLM hash, NTLMv2 hash, NTLMv2 response and LMv2 response. 383 * 384 * Returns -1 on error. Otherwise, returns 0 upon success. 385 */ 386 int 387 smb_auth_set_info(char *username, 388 char *password, 389 unsigned char *ntlm_hash, 390 char *domain, 391 unsigned char *srv_challenge_key, 392 int srv_challenge_len, 393 int lmcomp_lvl, 394 smb_auth_info_t *auth) 395 { 396 unsigned short blob_len; 397 unsigned char blob_buf[SMBAUTH_BLOB_MAXLEN]; 398 int rc; 399 char *uppercase_dom; 400 401 auth->lmcompatibility_lvl = lmcomp_lvl; 402 if (lmcomp_lvl == 2) { 403 auth->ci_len = 0; 404 *auth->ci = 0; 405 if (!ntlm_hash) { 406 if (smb_auth_ntlm_hash(password, auth->hash) != 407 SMBAUTH_SUCCESS) 408 return (-1); 409 } else { 410 (void) memcpy(auth->hash, ntlm_hash, SMBAUTH_HASH_SZ); 411 } 412 413 auth->cs_len = smb_auth_ntlm_response(auth->hash, 414 srv_challenge_key, srv_challenge_len, auth->cs); 415 } else { 416 if (!ntlm_hash) { 417 if (smb_auth_ntlm_hash(password, auth->hash) != 418 SMBAUTH_SUCCESS) 419 return (-1); 420 } else { 421 (void) memcpy(auth->hash, ntlm_hash, SMBAUTH_HASH_SZ); 422 } 423 424 if (!domain) 425 return (-1); 426 427 if ((uppercase_dom = strdup(domain)) == NULL) 428 return (-1); 429 430 (void) utf8_strupr(uppercase_dom); 431 432 if (smb_auth_ntlmv2_hash(auth->hash, username, 433 uppercase_dom, auth->hash_v2) != SMBAUTH_SUCCESS) { 434 free(uppercase_dom); 435 return (-1); 436 } 437 438 /* generate data blob */ 439 smb_auth_gen_data_blob(&auth->data_blob, uppercase_dom); 440 free(uppercase_dom); 441 blob_len = smb_auth_blob_to_string(&auth->data_blob, blob_buf); 442 443 /* generate NTLMv2 response */ 444 rc = smb_auth_v2_response(auth->hash_v2, srv_challenge_key, 445 srv_challenge_len, blob_buf, blob_len, auth->cs); 446 447 if (rc < 0) 448 return (-1); 449 450 auth->cs_len = rc; 451 452 /* generate LMv2 response */ 453 rc = smb_auth_v2_response(auth->hash_v2, srv_challenge_key, 454 srv_challenge_len, auth->data_blob.ndb_clnt_challenge, 455 SMBAUTH_V2_CLNT_CHALLENGE_SZ, auth->ci); 456 457 if (rc < 0) 458 return (-1); 459 460 auth->ci_len = rc; 461 } 462 463 return (0); 464 } 465 466 /* 467 * smb_auth_gen_session_key 468 * 469 * Generate the NTLM user session key if LMCompatibilityLevel is 2 or 470 * NTLMv2 user session key if LMCompatibilityLevel is 3 or above. 471 * 472 * NTLM_Session_Key = MD4(NTLM_Hash); 473 * 474 * NTLMv2_Session_Key = HMAC_MD5(NTLMv2Hash, 16, NTLMv2_HMAC, 16) 475 * 476 * Prior to calling this function, the auth instance should be set 477 * via smb_auth_set_info(). 478 * 479 * Returns the appropriate session key. 480 */ 481 int 482 smb_auth_gen_session_key(smb_auth_info_t *auth, unsigned char *session_key) 483 { 484 int rc; 485 486 if (auth->lmcompatibility_lvl == 2) 487 rc = smb_auth_md4(session_key, auth->hash, SMBAUTH_HASH_SZ); 488 else 489 rc = SMBAUTH_HMACT64((unsigned char *)auth->cs, 490 SMBAUTH_HASH_SZ, (unsigned char *)auth->hash_v2, 491 SMBAUTH_SESSION_KEY_SZ, session_key); 492 493 return (rc); 494 } 495 496 /* 100's of ns between 1/1/1970 and 1/1/1601 */ 497 #define NT_TIME_BIAS (134774LL * 24LL * 60LL * 60LL * 10000000LL) 498 499 static uint64_t 500 unix_micro_to_nt_time(struct timeval *unix_time) 501 { 502 uint64_t nt_time; 503 504 nt_time = unix_time->tv_sec; 505 nt_time *= 10000000; /* seconds to 100ns */ 506 nt_time += unix_time->tv_usec * 10; 507 return (nt_time + NT_TIME_BIAS); 508 } 509 510 static boolean_t 511 smb_lm_password_ok( 512 unsigned char *challenge, 513 uint32_t clen, 514 unsigned char *lm_hash, 515 unsigned char *passwd) 516 { 517 unsigned char lm_resp[SMBAUTH_LM_RESP_SZ]; 518 int rc; 519 520 rc = smb_auth_lm_response(lm_hash, challenge, clen, lm_resp); 521 if (rc != SMBAUTH_SUCCESS) 522 return (B_FALSE); 523 524 return (bcmp(lm_resp, passwd, SMBAUTH_LM_RESP_SZ) == 0); 525 } 526 527 static boolean_t 528 smb_ntlm_password_ok( 529 unsigned char *challenge, 530 uint32_t clen, 531 unsigned char *ntlm_hash, 532 unsigned char *passwd) 533 { 534 unsigned char ntlm_resp[SMBAUTH_LM_RESP_SZ]; 535 int rc; 536 537 rc = smb_auth_ntlm_response(ntlm_hash, challenge, clen, ntlm_resp); 538 539 if (rc != SMBAUTH_LM_RESP_SZ) 540 return (B_FALSE); 541 542 return (bcmp(ntlm_resp, passwd, SMBAUTH_LM_RESP_SZ) == 0); 543 } 544 545 static boolean_t 546 smb_ntlmv2_password_ok( 547 unsigned char *challenge, 548 uint32_t clen, 549 unsigned char *ntlm_hash, 550 unsigned char *passwd, 551 int pwdlen, 552 char *domain, 553 char *username) 554 { 555 unsigned char *clnt_blob; 556 int clnt_blob_len; 557 unsigned char ntlmv2_hash[SMBAUTH_HASH_SZ]; 558 unsigned char *ntlmv2_resp; 559 boolean_t ok = B_FALSE; 560 char *dest[3]; 561 int i; 562 563 clnt_blob_len = pwdlen - SMBAUTH_HASH_SZ; 564 clnt_blob = &passwd[SMBAUTH_HASH_SZ]; 565 dest[0] = domain; 566 if ((dest[1] = strdup(domain)) == NULL) 567 return (B_FALSE); 568 (void) utf8_strupr(dest[1]); 569 dest[2] = ""; 570 571 /* 572 * 15.5.2 The NTLMv2 Password Hash, pg. 279, of the "Implementing CIFS" 573 * 574 * The NTLMv2 Hash is created from: 575 * - NTLM hash 576 * - user's username, and 577 * - the name of the logon destination(i.e. the NetBIOS name of either 578 * the SMB server or NT Domain against which the user is trying to 579 * authenticate. 580 * 581 * Experiments show this is not exactly the case. 582 * For Windows Server 2003, the domain name needs to be included and 583 * converted to uppercase. For Vista, the domain name needs to be 584 * included also, but leave the case alone. And in some cases it needs 585 * to be empty. All three variants are tried here. 586 */ 587 588 ntlmv2_resp = (unsigned char *)malloc(SMBAUTH_HASH_SZ + clnt_blob_len); 589 if (ntlmv2_resp == NULL) { 590 free(dest[1]); 591 return (B_FALSE); 592 } 593 594 for (i = 0; i < (sizeof (dest) / sizeof (char *)); i++) { 595 if (smb_auth_ntlmv2_hash(ntlm_hash, username, dest[i], 596 ntlmv2_hash) != SMBAUTH_SUCCESS) 597 break; 598 599 if (smb_auth_v2_response(ntlmv2_hash, challenge, 600 clen, clnt_blob, clnt_blob_len, ntlmv2_resp) < 0) 601 break; 602 603 ok = (bcmp(passwd, ntlmv2_resp, pwdlen) == 0); 604 if (ok == B_TRUE) 605 break; 606 607 } 608 609 free(dest[1]); 610 free(ntlmv2_resp); 611 return (ok); 612 } 613 614 static boolean_t 615 smb_lmv2_password_ok( 616 unsigned char *challenge, 617 uint32_t clen, 618 unsigned char *ntlm_hash, 619 unsigned char *passwd, 620 char *domain, 621 char *username) 622 { 623 unsigned char *clnt_challenge; 624 unsigned char ntlmv2_hash[SMBAUTH_HASH_SZ]; 625 unsigned char lmv2_resp[SMBAUTH_LM_RESP_SZ]; 626 boolean_t ok = B_FALSE; 627 char *dest[3]; 628 int i; 629 630 clnt_challenge = &passwd[SMBAUTH_HASH_SZ]; 631 dest[0] = domain; 632 if ((dest[1] = strdup(domain)) == NULL) 633 return (B_FALSE); 634 (void) utf8_strupr(dest[1]); 635 dest[2] = ""; 636 637 /* 638 * 15.5.2 The NTLMv2 Password Hash, pg. 279, of the "Implementing CIFS" 639 * 640 * The NTLMv2 Hash is created from: 641 * - NTLM hash 642 * - user's username, and 643 * - the name of the logon destination(i.e. the NetBIOS name of either 644 * the SMB server or NT Domain against which the suer is trying to 645 * authenticate. 646 * 647 * Experiments show this is not exactly the case. 648 * For Windows Server 2003, the domain name needs to be included and 649 * converted to uppercase. For Vista, the domain name needs to be 650 * included also, but leave the case alone. And in some cases it needs 651 * to be empty. All three variants are tried here. 652 */ 653 654 for (i = 0; i < (sizeof (dest) / sizeof (char *)); i++) { 655 if (smb_auth_ntlmv2_hash(ntlm_hash, username, dest[i], 656 ntlmv2_hash) != SMBAUTH_SUCCESS) 657 break; 658 659 if (smb_auth_v2_response(ntlmv2_hash, challenge, 660 clen, clnt_challenge, SMBAUTH_V2_CLNT_CHALLENGE_SZ, 661 lmv2_resp) < 0) 662 break; 663 664 ok = (bcmp(passwd, lmv2_resp, SMBAUTH_LM_RESP_SZ) == 0); 665 if (ok == B_TRUE) 666 break; 667 668 } 669 670 free(dest[1]); 671 return (ok); 672 } 673 674 /* 675 * smb_auth_validate_lm 676 * 677 * Validates given LM/LMv2 client response, passed in passwd arg, against 678 * stored user's password, passed in smbpw 679 * 680 * If LM level <=3 server accepts LM responses, otherwise LMv2 681 */ 682 boolean_t 683 smb_auth_validate_lm( 684 unsigned char *challenge, 685 uint32_t clen, 686 smb_passwd_t *smbpw, 687 unsigned char *passwd, 688 int pwdlen, 689 char *domain, 690 char *username) 691 { 692 boolean_t ok = B_FALSE; 693 int64_t lmlevel; 694 695 if (pwdlen != SMBAUTH_LM_RESP_SZ) 696 return (B_FALSE); 697 698 if (smb_config_getnum(SMB_CI_LM_LEVEL, &lmlevel) != SMBD_SMF_OK) 699 return (B_FALSE); 700 701 if (lmlevel <= 3) { 702 ok = smb_lm_password_ok(challenge, clen, smbpw->pw_lmhash, 703 passwd); 704 } 705 706 if (!ok) 707 ok = smb_lmv2_password_ok(challenge, clen, smbpw->pw_nthash, 708 passwd, domain, username); 709 710 return (ok); 711 } 712 713 /* 714 * smb_auth_validate_nt 715 * 716 * Validates given NTLM/NTLMv2 client response, passed in passwd arg, against 717 * stored user's password, passed in smbpw 718 * 719 * If LM level <=4 server accepts NTLM/NTLMv2 responses, otherwise only NTLMv2 720 */ 721 boolean_t 722 smb_auth_validate_nt( 723 unsigned char *challenge, 724 uint32_t clen, 725 smb_passwd_t *smbpw, 726 unsigned char *passwd, 727 int pwdlen, 728 char *domain, 729 char *username) 730 { 731 int64_t lmlevel; 732 boolean_t ok; 733 734 if (smb_config_getnum(SMB_CI_LM_LEVEL, &lmlevel) != SMBD_SMF_OK) 735 return (B_FALSE); 736 737 if ((lmlevel == 5) && (pwdlen <= SMBAUTH_LM_RESP_SZ)) 738 return (B_FALSE); 739 740 if (pwdlen > SMBAUTH_LM_RESP_SZ) 741 ok = smb_ntlmv2_password_ok(challenge, clen, 742 smbpw->pw_nthash, passwd, pwdlen, domain, username); 743 else 744 ok = smb_ntlm_password_ok(challenge, clen, 745 smbpw->pw_nthash, passwd); 746 747 return (ok); 748 } 749