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