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