Changeset 740 for vendor/current/source3/libsmb/ntlmssp.c
- Timestamp:
- Nov 14, 2012, 12:59:34 PM (13 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
vendor/current/source3/libsmb/ntlmssp.c
r414 r740 5 5 6 6 Copyright (C) Andrew Tridgell 2001 7 Copyright (C) Andrew Bartlett 2001-20 038 Copyright (C) Andrew Bartlett 2005 (Updated from gensec).7 Copyright (C) Andrew Bartlett 2001-2010 8 Copyright (C) Stefan Metzmacher 2005 9 9 10 10 This program is free software; you can redistribute it and/or modify … … 23 23 24 24 #include "includes.h" 25 #include "../libcli/auth/ntlmssp.h" 26 #include "../libcli/auth/ntlmssp_private.h" 25 27 #include "../libcli/auth/libcli_auth.h" 26 28 #include "../librpc/gen_ndr/ndr_ntlmssp.h" 27 #include "libsmb/ntlmssp_ndr.h" 29 #include "../libcli/auth/ntlmssp_ndr.h" 30 #include "../lib/crypto/md5.h" 31 #include "../lib/crypto/arcfour.h" 32 #include "../lib/crypto/hmacmd5.h" 33 #include "../nsswitch/libwbclient/wbclient.h" 28 34 29 35 static NTSTATUS ntlmssp_client_initial(struct ntlmssp_state *ntlmssp_state, 36 TALLOC_CTX *out_mem_ctx, /* Unused at this time */ 30 37 DATA_BLOB reply, DATA_BLOB *next_request); 31 static NTSTATUS ntlmssp_server_negotiate(struct ntlmssp_state *ntlmssp_state,32 const DATA_BLOB in, DATA_BLOB *out);33 38 static NTSTATUS ntlmssp_client_challenge(struct ntlmssp_state *ntlmssp_state, 39 TALLOC_CTX *out_mem_ctx, /* Unused at this time */ 34 40 const DATA_BLOB reply, DATA_BLOB *next_request); 35 static NTSTATUS ntlmssp_server_auth(struct ntlmssp_state *ntlmssp_state,36 const DATA_BLOB request, DATA_BLOB *reply);37 38 41 /** 39 42 * Callbacks for NTLMSSP - for both client and server operating modes … … 42 45 43 46 static const struct ntlmssp_callbacks { 44 enum NTLMSSP_ROLErole;45 enum NTLM_MESSAGE_TYPEntlmssp_command;47 enum ntlmssp_role role; 48 enum ntlmssp_message_type ntlmssp_command; 46 49 NTSTATUS (*fn)(struct ntlmssp_state *ntlmssp_state, 50 TALLOC_CTX *out_mem_ctx, 47 51 DATA_BLOB in, DATA_BLOB *out); 48 52 } ntlmssp_callbacks[] = { … … 57 61 58 62 /** 59 * Print out the NTLMSSP flags for debugging60 * @param neg_flags The flags from the packet61 */62 63 void debug_ntlmssp_flags(uint32 neg_flags)64 {65 DEBUG(3,("Got NTLMSSP neg_flags=0x%08x\n", neg_flags));66 67 if (neg_flags & NTLMSSP_NEGOTIATE_UNICODE)68 DEBUGADD(4, (" NTLMSSP_NEGOTIATE_UNICODE\n"));69 if (neg_flags & NTLMSSP_NEGOTIATE_OEM)70 DEBUGADD(4, (" NTLMSSP_NEGOTIATE_OEM\n"));71 if (neg_flags & NTLMSSP_REQUEST_TARGET)72 DEBUGADD(4, (" NTLMSSP_REQUEST_TARGET\n"));73 if (neg_flags & NTLMSSP_NEGOTIATE_SIGN)74 DEBUGADD(4, (" NTLMSSP_NEGOTIATE_SIGN\n"));75 if (neg_flags & NTLMSSP_NEGOTIATE_SEAL)76 DEBUGADD(4, (" NTLMSSP_NEGOTIATE_SEAL\n"));77 if (neg_flags & NTLMSSP_NEGOTIATE_DATAGRAM)78 DEBUGADD(4, (" NTLMSSP_NEGOTIATE_DATAGRAM\n"));79 if (neg_flags & NTLMSSP_NEGOTIATE_LM_KEY)80 DEBUGADD(4, (" NTLMSSP_NEGOTIATE_LM_KEY\n"));81 if (neg_flags & NTLMSSP_NEGOTIATE_NETWARE)82 DEBUGADD(4, (" NTLMSSP_NEGOTIATE_NETWARE\n"));83 if (neg_flags & NTLMSSP_NEGOTIATE_NTLM)84 DEBUGADD(4, (" NTLMSSP_NEGOTIATE_NTLM\n"));85 if (neg_flags & NTLMSSP_NEGOTIATE_OEM_DOMAIN_SUPPLIED)86 DEBUGADD(4, (" NTLMSSP_NEGOTIATE_OEM_DOMAIN_SUPPLIED\n"));87 if (neg_flags & NTLMSSP_NEGOTIATE_OEM_WORKSTATION_SUPPLIED)88 DEBUGADD(4, (" NTLMSSP_NEGOTIATE_OEM_WORKSTATION_SUPPLIED\n"));89 if (neg_flags & NTLMSSP_NEGOTIATE_THIS_IS_LOCAL_CALL)90 DEBUGADD(4, (" NTLMSSP_NEGOTIATE_THIS_IS_LOCAL_CALL\n"));91 if (neg_flags & NTLMSSP_NEGOTIATE_ALWAYS_SIGN)92 DEBUGADD(4, (" NTLMSSP_NEGOTIATE_ALWAYS_SIGN\n"));93 if (neg_flags & NTLMSSP_REQUEST_NON_NT_SESSION_KEY)94 DEBUGADD(4, (" NTLMSSP_REQUEST_NON_NT_SESSION_KEY\n"));95 if (neg_flags & NTLMSSP_NEGOTIATE_NTLM2)96 DEBUGADD(4, (" NTLMSSP_NEGOTIATE_NTLM2\n"));97 if (neg_flags & NTLMSSP_NEGOTIATE_TARGET_INFO)98 DEBUGADD(4, (" NTLMSSP_NEGOTIATE_TARGET_INFO\n"));99 if (neg_flags & NTLMSSP_NEGOTIATE_VERSION)100 DEBUGADD(4, (" NTLMSSP_NEGOTIATE_VERSION\n"));101 if (neg_flags & NTLMSSP_NEGOTIATE_128)102 DEBUGADD(4, (" NTLMSSP_NEGOTIATE_128\n"));103 if (neg_flags & NTLMSSP_NEGOTIATE_KEY_EXCH)104 DEBUGADD(4, (" NTLMSSP_NEGOTIATE_KEY_EXCH\n"));105 if (neg_flags & NTLMSSP_NEGOTIATE_56)106 DEBUGADD(4, (" NTLMSSP_NEGOTIATE_56\n"));107 }108 109 /**110 63 * Default challenge generation code. 111 64 * 112 65 */ 113 66 114 static voidget_challenge(const struct ntlmssp_state *ntlmssp_state,115 uint8_t chal[8])67 static NTSTATUS get_challenge(const struct ntlmssp_state *ntlmssp_state, 68 uint8_t chal[8]) 116 69 { 117 70 generate_random_buffer(chal, 8); 71 return NT_STATUS_OK; 118 72 } 119 73 … … 146 100 */ 147 101 148 NTSTATUS ntlmssp_set_username( NTLMSSP_STATE*ntlmssp_state, const char *user)102 NTSTATUS ntlmssp_set_username(struct ntlmssp_state *ntlmssp_state, const char *user) 149 103 { 150 104 ntlmssp_state->user = talloc_strdup(ntlmssp_state, user ? user : "" ); … … 159 113 * 160 114 */ 161 NTSTATUS ntlmssp_set_hashes( NTLMSSP_STATE*ntlmssp_state,162 const unsigned charlm_hash[16],163 const unsigned charnt_hash[16])164 { 165 ntlmssp_state->lm_hash = (u nsigned char*)115 NTSTATUS ntlmssp_set_hashes(struct ntlmssp_state *ntlmssp_state, 116 const uint8_t lm_hash[16], 117 const uint8_t nt_hash[16]) 118 { 119 ntlmssp_state->lm_hash = (uint8_t *) 166 120 TALLOC_MEMDUP(ntlmssp_state, lm_hash, 16); 167 ntlmssp_state->nt_hash = (u nsigned char*)121 ntlmssp_state->nt_hash = (uint8_t *) 168 122 TALLOC_MEMDUP(ntlmssp_state, nt_hash, 16); 169 123 if (!ntlmssp_state->lm_hash || !ntlmssp_state->nt_hash) { … … 179 133 * 180 134 */ 181 NTSTATUS ntlmssp_set_password( NTLMSSP_STATE*ntlmssp_state, const char *password)135 NTSTATUS ntlmssp_set_password(struct ntlmssp_state *ntlmssp_state, const char *password) 182 136 { 183 137 if (!password) { … … 185 139 ntlmssp_state->nt_hash = NULL; 186 140 } else { 187 u nsigned charlm_hash[16];188 u nsigned charnt_hash[16];141 uint8_t lm_hash[16]; 142 uint8_t nt_hash[16]; 189 143 190 144 E_deshash(password, lm_hash); … … 199 153 * 200 154 */ 201 NTSTATUS ntlmssp_set_domain( NTLMSSP_STATE*ntlmssp_state, const char *domain)155 NTSTATUS ntlmssp_set_domain(struct ntlmssp_state *ntlmssp_state, const char *domain) 202 156 { 203 157 ntlmssp_state->domain = talloc_strdup(ntlmssp_state, … … 210 164 211 165 /** 212 * Set a workstation on an NTLMSSP context - ensures it is talloc()ed213 *214 */215 NTSTATUS ntlmssp_set_workstation(NTLMSSP_STATE *ntlmssp_state, const char *workstation)216 {217 ntlmssp_state->workstation = talloc_strdup(ntlmssp_state, workstation);218 if (!ntlmssp_state->workstation) {219 return NT_STATUS_NO_MEMORY;220 }221 return NT_STATUS_OK;222 }223 224 /**225 * Store a DATA_BLOB containing an NTLMSSP response, for use later.226 * This copies the data blob227 */228 229 NTSTATUS ntlmssp_store_response(NTLMSSP_STATE *ntlmssp_state,230 DATA_BLOB response)231 {232 ntlmssp_state->stored_response = data_blob_talloc(ntlmssp_state,233 response.data,234 response.length);235 return NT_STATUS_OK;236 }237 238 /**239 166 * Request features for the NTLMSSP negotiation 240 167 * … … 242 169 * @param feature_list List of space seperated features requested from NTLMSSP. 243 170 */ 244 void ntlmssp_want_feature_list( NTLMSSP_STATE*ntlmssp_state, char *feature_list)171 void ntlmssp_want_feature_list(struct ntlmssp_state *ntlmssp_state, char *feature_list) 245 172 { 246 173 /* … … 269 196 * @param feature Bit flag specifying the requested feature 270 197 */ 271 void ntlmssp_want_feature( NTLMSSP_STATE *ntlmssp_state, uint32feature)198 void ntlmssp_want_feature(struct ntlmssp_state *ntlmssp_state, uint32_t feature) 272 199 { 273 200 /* As per JRA's comment above */ … … 295 222 */ 296 223 297 NTSTATUS ntlmssp_update(NTLMSSP_STATE *ntlmssp_state, 298 const DATA_BLOB in, DATA_BLOB *out) 299 { 300 DATA_BLOB input; 301 uint32 ntlmssp_command; 224 NTSTATUS ntlmssp_update(struct ntlmssp_state *ntlmssp_state, 225 const DATA_BLOB input, DATA_BLOB *out) 226 { 227 uint32_t ntlmssp_command; 302 228 int i; 303 229 … … 309 235 310 236 *out = data_blob_null; 311 312 if (!in.length && ntlmssp_state->stored_response.length) {313 input = ntlmssp_state->stored_response;314 315 /* we only want to read the stored response once - overwrite it */316 ntlmssp_state->stored_response = data_blob_null;317 } else {318 input = in;319 }320 237 321 238 if (!input.length) { … … 328 245 ntlmssp_command = NTLMSSP_NEGOTIATE; 329 246 break; 247 default: 248 DEBUG(1, ("Invalid role: %d\n", ntlmssp_state->role)); 249 return NT_STATUS_INVALID_PARAMETER; 330 250 } 331 251 } else { … … 347 267 if (ntlmssp_callbacks[i].role == ntlmssp_state->role 348 268 && ntlmssp_callbacks[i].ntlmssp_command == ntlmssp_command) { 349 return ntlmssp_callbacks[i].fn(ntlmssp_state, input, out);269 return ntlmssp_callbacks[i].fn(ntlmssp_state, ntlmssp_state, input, out); 350 270 } 351 271 } … … 358 278 359 279 /** 360 * End an NTLMSSP state machine361 *362 * @param ntlmssp_state NTLMSSP State, free()ed by this function363 */364 365 void ntlmssp_end(NTLMSSP_STATE **ntlmssp_state)366 {367 (*ntlmssp_state)->ref_count--;368 369 if ((*ntlmssp_state)->ref_count == 0) {370 data_blob_free(&(*ntlmssp_state)->chal);371 data_blob_free(&(*ntlmssp_state)->lm_resp);372 data_blob_free(&(*ntlmssp_state)->nt_resp);373 TALLOC_FREE(*ntlmssp_state);374 }375 376 *ntlmssp_state = NULL;377 return;378 }379 380 /**381 * Determine correct target name flags for reply, given server role382 * and negotiated flags383 *384 * @param ntlmssp_state NTLMSSP State385 * @param neg_flags The flags from the packet386 * @param chal_flags The flags to be set in the reply packet387 * @return The 'target name' string.388 */389 390 static const char *ntlmssp_target_name(struct ntlmssp_state *ntlmssp_state,391 uint32 neg_flags, uint32 *chal_flags)392 {393 if (neg_flags & NTLMSSP_REQUEST_TARGET) {394 *chal_flags |= NTLMSSP_NEGOTIATE_TARGET_INFO;395 *chal_flags |= NTLMSSP_REQUEST_TARGET;396 if (ntlmssp_state->server_role == ROLE_STANDALONE) {397 *chal_flags |= NTLMSSP_TARGET_TYPE_SERVER;398 return ntlmssp_state->get_global_myname();399 } else {400 *chal_flags |= NTLMSSP_TARGET_TYPE_DOMAIN;401 return ntlmssp_state->get_domain();402 };403 } else {404 return "";405 }406 }407 408 static void ntlmssp_handle_neg_flags(struct ntlmssp_state *ntlmssp_state,409 uint32 neg_flags, bool allow_lm) {410 if (neg_flags & NTLMSSP_NEGOTIATE_UNICODE) {411 ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_UNICODE;412 ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_OEM;413 ntlmssp_state->unicode = True;414 } else {415 ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_UNICODE;416 ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_OEM;417 ntlmssp_state->unicode = False;418 }419 420 if ((neg_flags & NTLMSSP_NEGOTIATE_LM_KEY) && allow_lm) {421 /* other end forcing us to use LM */422 ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_LM_KEY;423 ntlmssp_state->use_ntlmv2 = False;424 } else {425 ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_LM_KEY;426 }427 428 if (!(neg_flags & NTLMSSP_NEGOTIATE_ALWAYS_SIGN)) {429 ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_ALWAYS_SIGN;430 }431 432 if (!(neg_flags & NTLMSSP_NEGOTIATE_NTLM2)) {433 ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_NTLM2;434 }435 436 if (!(neg_flags & NTLMSSP_NEGOTIATE_128)) {437 ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_128;438 }439 440 if (!(neg_flags & NTLMSSP_NEGOTIATE_56)) {441 ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_56;442 }443 444 if (!(neg_flags & NTLMSSP_NEGOTIATE_KEY_EXCH)) {445 ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_KEY_EXCH;446 }447 448 if (!(neg_flags & NTLMSSP_NEGOTIATE_SIGN)) {449 ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_SIGN;450 }451 452 if (!(neg_flags & NTLMSSP_NEGOTIATE_SEAL)) {453 ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_SEAL;454 }455 456 /* Woop Woop - unknown flag for Windows compatibility...457 What does this really do ? JRA. */458 if (!(neg_flags & NTLMSSP_NEGOTIATE_VERSION)) {459 ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_VERSION;460 }461 462 if ((neg_flags & NTLMSSP_REQUEST_TARGET)) {463 ntlmssp_state->neg_flags |= NTLMSSP_REQUEST_TARGET;464 }465 }466 467 /**468 Weaken NTLMSSP keys to cope with down-level clients and servers.469 470 We probably should have some parameters to control this, but as471 it only occours for LM_KEY connections, and this is controlled472 by the client lanman auth/lanman auth parameters, it isn't too bad.473 */474 475 DATA_BLOB ntlmssp_weaken_keys(NTLMSSP_STATE *ntlmssp_state, TALLOC_CTX *mem_ctx)476 {477 DATA_BLOB weakened_key = data_blob_talloc(mem_ctx,478 ntlmssp_state->session_key.data,479 ntlmssp_state->session_key.length);480 481 /* Nothing to weaken. We certainly don't want to 'extend' the length... */482 if (weakened_key.length < 16) {483 /* perhaps there was no key? */484 return weakened_key;485 }486 487 /* Key weakening not performed on the master key for NTLM2488 and does not occour for NTLM1. Therefore we only need489 to do this for the LM_KEY.490 */491 492 if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_LM_KEY) {493 /* LM key doesn't support 128 bit crypto, so this is494 * the best we can do. If you negotiate 128 bit, but495 * not 56, you end up with 40 bit... */496 if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_56) {497 weakened_key.data[7] = 0xa0;498 } else { /* forty bits */499 weakened_key.data[5] = 0xe5;500 weakened_key.data[6] = 0x38;501 weakened_key.data[7] = 0xb0;502 }503 weakened_key.length = 8;504 }505 return weakened_key;506 }507 508 /**509 * Next state function for the Negotiate packet510 *511 * @param ntlmssp_state NTLMSSP State512 * @param request The request, as a DATA_BLOB513 * @param request The reply, as an allocated DATA_BLOB, caller to free.514 * @return Errors or MORE_PROCESSING_REQUIRED if a reply is sent.515 */516 517 static NTSTATUS ntlmssp_server_negotiate(struct ntlmssp_state *ntlmssp_state,518 const DATA_BLOB request, DATA_BLOB *reply)519 {520 DATA_BLOB struct_blob;521 const char *dnsname;522 char *dnsdomname = NULL;523 uint32 neg_flags = 0;524 uint32 ntlmssp_command, chal_flags;525 uint8_t cryptkey[8];526 const char *target_name;527 struct NEGOTIATE_MESSAGE negotiate;528 struct CHALLENGE_MESSAGE challenge;529 530 /* parse the NTLMSSP packet */531 #if 0532 file_save("ntlmssp_negotiate.dat", request.data, request.length);533 #endif534 535 if (request.length) {536 if ((request.length < 16) || !msrpc_parse(ntlmssp_state, &request, "Cdd",537 "NTLMSSP",538 &ntlmssp_command,539 &neg_flags)) {540 DEBUG(1, ("ntlmssp_server_negotiate: failed to parse NTLMSSP Negotiate of length %u\n",541 (unsigned int)request.length));542 dump_data(2, request.data, request.length);543 return NT_STATUS_INVALID_PARAMETER;544 }545 debug_ntlmssp_flags(neg_flags);546 547 if (DEBUGLEVEL >= 10) {548 if (NT_STATUS_IS_OK(ntlmssp_pull_NEGOTIATE_MESSAGE(&request,549 ntlmssp_state,550 NULL,551 &negotiate)))552 {553 NDR_PRINT_DEBUG(NEGOTIATE_MESSAGE, &negotiate);554 }555 }556 }557 558 ntlmssp_handle_neg_flags(ntlmssp_state, neg_flags, lp_lanman_auth());559 560 /* Ask our caller what challenge they would like in the packet */561 ntlmssp_state->get_challenge(ntlmssp_state, cryptkey);562 563 /* Check if we may set the challenge */564 if (!ntlmssp_state->may_set_challenge(ntlmssp_state)) {565 ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_NTLM2;566 }567 568 /* The flags we send back are not just the negotiated flags,569 * they are also 'what is in this packet'. Therfore, we570 * operate on 'chal_flags' from here on571 */572 573 chal_flags = ntlmssp_state->neg_flags;574 575 /* get the right name to fill in as 'target' */576 target_name = ntlmssp_target_name(ntlmssp_state,577 neg_flags, &chal_flags);578 if (target_name == NULL)579 return NT_STATUS_INVALID_PARAMETER;580 581 ntlmssp_state->chal = data_blob_talloc(ntlmssp_state, cryptkey, 8);582 ntlmssp_state->internal_chal = data_blob_talloc(ntlmssp_state,583 cryptkey, 8);584 585 /* This should be a 'netbios domain -> DNS domain' mapping */586 dnsdomname = get_mydnsdomname(ntlmssp_state);587 if (!dnsdomname) {588 dnsdomname = talloc_strdup(ntlmssp_state, "");589 }590 if (!dnsdomname) {591 return NT_STATUS_NO_MEMORY;592 }593 strlower_m(dnsdomname);594 595 dnsname = get_mydnsfullname();596 if (!dnsname) {597 dnsname = "";598 }599 600 /* This creates the 'blob' of names that appears at the end of the packet */601 if (chal_flags & NTLMSSP_NEGOTIATE_TARGET_INFO)602 {603 msrpc_gen(ntlmssp_state, &struct_blob, "aaaaa",604 MsvAvNbDomainName, target_name,605 MsvAvNbComputerName, ntlmssp_state->get_global_myname(),606 MsvAvDnsDomainName, dnsdomname,607 MsvAvDnsComputerName, dnsname,608 MsvAvEOL, "");609 } else {610 struct_blob = data_blob_null;611 }612 613 {614 /* Marshel the packet in the right format, be it unicode or ASCII */615 const char *gen_string;616 if (ntlmssp_state->unicode) {617 gen_string = "CdUdbddB";618 } else {619 gen_string = "CdAdbddB";620 }621 622 msrpc_gen(ntlmssp_state, reply, gen_string,623 "NTLMSSP",624 NTLMSSP_CHALLENGE,625 target_name,626 chal_flags,627 cryptkey, 8,628 0, 0,629 struct_blob.data, struct_blob.length);630 631 if (DEBUGLEVEL >= 10) {632 if (NT_STATUS_IS_OK(ntlmssp_pull_CHALLENGE_MESSAGE(reply,633 ntlmssp_state,634 NULL,635 &challenge)))636 {637 NDR_PRINT_DEBUG(CHALLENGE_MESSAGE, &challenge);638 }639 }640 }641 642 data_blob_free(&struct_blob);643 644 ntlmssp_state->expected_state = NTLMSSP_AUTH;645 646 return NT_STATUS_MORE_PROCESSING_REQUIRED;647 }648 649 /**650 * Next state function for the Authenticate packet651 *652 * @param ntlmssp_state NTLMSSP State653 * @param request The request, as a DATA_BLOB654 * @param request The reply, as an allocated DATA_BLOB, caller to free.655 * @return Errors or NT_STATUS_OK.656 */657 658 static NTSTATUS ntlmssp_server_auth(struct ntlmssp_state *ntlmssp_state,659 const DATA_BLOB request, DATA_BLOB *reply)660 {661 DATA_BLOB encrypted_session_key = data_blob_null;662 DATA_BLOB user_session_key = data_blob_null;663 DATA_BLOB lm_session_key = data_blob_null;664 DATA_BLOB session_key = data_blob_null;665 uint32 ntlmssp_command, auth_flags;666 NTSTATUS nt_status = NT_STATUS_OK;667 struct AUTHENTICATE_MESSAGE authenticate;668 669 /* used by NTLM2 */670 bool doing_ntlm2 = False;671 672 uchar session_nonce[16];673 uchar session_nonce_hash[16];674 675 const char *parse_string;676 677 /* parse the NTLMSSP packet */678 *reply = data_blob_null;679 680 #if 0681 file_save("ntlmssp_auth.dat", request.data, request.length);682 #endif683 684 if (ntlmssp_state->unicode) {685 parse_string = "CdBBUUUBd";686 } else {687 parse_string = "CdBBAAABd";688 }689 690 data_blob_free(&ntlmssp_state->lm_resp);691 data_blob_free(&ntlmssp_state->nt_resp);692 693 ntlmssp_state->user = NULL;694 ntlmssp_state->domain = NULL;695 ntlmssp_state->workstation = NULL;696 697 /* now the NTLMSSP encoded auth hashes */698 if (!msrpc_parse(ntlmssp_state, &request, parse_string,699 "NTLMSSP",700 &ntlmssp_command,701 &ntlmssp_state->lm_resp,702 &ntlmssp_state->nt_resp,703 &ntlmssp_state->domain,704 &ntlmssp_state->user,705 &ntlmssp_state->workstation,706 &encrypted_session_key,707 &auth_flags)) {708 auth_flags = 0;709 710 /* Try again with a shorter string (Win9X truncates this packet) */711 if (ntlmssp_state->unicode) {712 parse_string = "CdBBUUU";713 } else {714 parse_string = "CdBBAAA";715 }716 717 /* now the NTLMSSP encoded auth hashes */718 if (!msrpc_parse(ntlmssp_state, &request, parse_string,719 "NTLMSSP",720 &ntlmssp_command,721 &ntlmssp_state->lm_resp,722 &ntlmssp_state->nt_resp,723 &ntlmssp_state->domain,724 &ntlmssp_state->user,725 &ntlmssp_state->workstation)) {726 DEBUG(1, ("ntlmssp_server_auth: failed to parse NTLMSSP (tried both formats):\n"));727 dump_data(2, request.data, request.length);728 729 return NT_STATUS_INVALID_PARAMETER;730 }731 }732 733 if (auth_flags)734 ntlmssp_handle_neg_flags(ntlmssp_state, auth_flags, lp_lanman_auth());735 736 if (DEBUGLEVEL >= 10) {737 if (NT_STATUS_IS_OK(ntlmssp_pull_AUTHENTICATE_MESSAGE(&request,738 ntlmssp_state,739 NULL,740 &authenticate)))741 {742 NDR_PRINT_DEBUG(AUTHENTICATE_MESSAGE, &authenticate);743 }744 }745 746 DEBUG(3,("Got user=[%s] domain=[%s] workstation=[%s] len1=%lu len2=%lu\n",747 ntlmssp_state->user, ntlmssp_state->domain, ntlmssp_state->workstation, (unsigned long)ntlmssp_state->lm_resp.length, (unsigned long)ntlmssp_state->nt_resp.length));748 749 #if 0750 file_save("nthash1.dat", &ntlmssp_state->nt_resp.data, &ntlmssp_state->nt_resp.length);751 file_save("lmhash1.dat", &ntlmssp_state->lm_resp.data, &ntlmssp_state->lm_resp.length);752 #endif753 754 /* NTLM2 uses a 'challenge' that is made of up both the server challenge, and a755 client challenge756 757 However, the NTLM2 flag may still be set for the real NTLMv2 logins, be careful.758 */759 if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_NTLM2) {760 if (ntlmssp_state->nt_resp.length == 24 && ntlmssp_state->lm_resp.length == 24) {761 struct MD5Context md5_session_nonce_ctx;762 SMB_ASSERT(ntlmssp_state->internal_chal.data && ntlmssp_state->internal_chal.length == 8);763 764 doing_ntlm2 = True;765 766 memcpy(session_nonce, ntlmssp_state->internal_chal.data, 8);767 memcpy(&session_nonce[8], ntlmssp_state->lm_resp.data, 8);768 769 MD5Init(&md5_session_nonce_ctx);770 MD5Update(&md5_session_nonce_ctx, session_nonce, 16);771 MD5Final(session_nonce_hash, &md5_session_nonce_ctx);772 773 ntlmssp_state->chal = data_blob_talloc(774 ntlmssp_state, session_nonce_hash, 8);775 776 /* LM response is no longer useful */777 data_blob_free(&ntlmssp_state->lm_resp);778 779 /* We changed the effective challenge - set it */780 if (!NT_STATUS_IS_OK(nt_status = ntlmssp_state->set_challenge(ntlmssp_state, &ntlmssp_state->chal))) {781 data_blob_free(&encrypted_session_key);782 return nt_status;783 }784 785 /* LM Key is incompatible. */786 ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_LM_KEY;787 }788 }789 790 /*791 * Note we don't check here for NTLMv2 auth settings. If NTLMv2 auth792 * is required (by "ntlm auth = no" and "lm auth = no" being set in the793 * smb.conf file) and no NTLMv2 response was sent then the password check794 * will fail here. JRA.795 */796 797 /* Finally, actually ask if the password is OK */798 799 if (!NT_STATUS_IS_OK(nt_status = ntlmssp_state->check_password(ntlmssp_state,800 &user_session_key, &lm_session_key))) {801 data_blob_free(&encrypted_session_key);802 return nt_status;803 }804 805 dump_data_pw("NT session key:\n", user_session_key.data, user_session_key.length);806 dump_data_pw("LM first-8:\n", lm_session_key.data, lm_session_key.length);807 808 /* Handle the different session key derivation for NTLM2 */809 if (doing_ntlm2) {810 if (user_session_key.data && user_session_key.length == 16) {811 session_key = data_blob_talloc(ntlmssp_state,812 NULL, 16);813 hmac_md5(user_session_key.data, session_nonce,814 sizeof(session_nonce), session_key.data);815 DEBUG(10,("ntlmssp_server_auth: Created NTLM2 session key.\n"));816 dump_data_pw("NTLM2 session key:\n", session_key.data, session_key.length);817 818 } else {819 DEBUG(10,("ntlmssp_server_auth: Failed to create NTLM2 session key.\n"));820 session_key = data_blob_null;821 }822 } else if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_LM_KEY) {823 if (lm_session_key.data && lm_session_key.length >= 8) {824 if (ntlmssp_state->lm_resp.data && ntlmssp_state->lm_resp.length == 24) {825 session_key = data_blob_talloc(ntlmssp_state,826 NULL, 16);827 if (session_key.data == NULL) {828 return NT_STATUS_NO_MEMORY;829 }830 SMBsesskeygen_lm_sess_key(lm_session_key.data, ntlmssp_state->lm_resp.data,831 session_key.data);832 DEBUG(10,("ntlmssp_server_auth: Created NTLM session key.\n"));833 } else {834 uint8 zeros[24];835 ZERO_STRUCT(zeros);836 session_key = data_blob_talloc(837 ntlmssp_state, NULL, 16);838 if (session_key.data == NULL) {839 return NT_STATUS_NO_MEMORY;840 }841 SMBsesskeygen_lm_sess_key(842 lm_session_key.data, zeros,843 session_key.data);844 }845 dump_data_pw("LM session key:\n", session_key.data,846 session_key.length);847 } else {848 DEBUG(10,("ntlmssp_server_auth: Failed to create NTLM session key.\n"));849 session_key = data_blob_null;850 }851 } else if (user_session_key.data) {852 session_key = user_session_key;853 DEBUG(10,("ntlmssp_server_auth: Using unmodified nt session key.\n"));854 dump_data_pw("unmodified session key:\n", session_key.data, session_key.length);855 } else if (lm_session_key.data) {856 session_key = lm_session_key;857 DEBUG(10,("ntlmssp_server_auth: Using unmodified lm session key.\n"));858 dump_data_pw("unmodified session key:\n", session_key.data, session_key.length);859 } else {860 DEBUG(10,("ntlmssp_server_auth: Failed to create unmodified session key.\n"));861 session_key = data_blob_null;862 }863 864 /* With KEY_EXCH, the client supplies the proposed session key,865 but encrypts it with the long-term key */866 if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_KEY_EXCH) {867 if (!encrypted_session_key.data || encrypted_session_key.length != 16) {868 data_blob_free(&encrypted_session_key);869 DEBUG(1, ("Client-supplied KEY_EXCH session key was of invalid length (%u)!\n",870 (unsigned int)encrypted_session_key.length));871 return NT_STATUS_INVALID_PARAMETER;872 } else if (!session_key.data || session_key.length != 16) {873 DEBUG(5, ("server session key is invalid (len == %u), cannot do KEY_EXCH!\n",874 (unsigned int)session_key.length));875 ntlmssp_state->session_key = session_key;876 } else {877 dump_data_pw("KEY_EXCH session key (enc):\n", encrypted_session_key.data, encrypted_session_key.length);878 arcfour_crypt_blob(encrypted_session_key.data,879 encrypted_session_key.length,880 &session_key);881 ntlmssp_state->session_key = data_blob_talloc(882 ntlmssp_state, encrypted_session_key.data,883 encrypted_session_key.length);884 dump_data_pw("KEY_EXCH session key:\n", encrypted_session_key.data,885 encrypted_session_key.length);886 }887 } else {888 ntlmssp_state->session_key = session_key;889 }890 891 if (!NT_STATUS_IS_OK(nt_status)) {892 ntlmssp_state->session_key = data_blob_null;893 } else if (ntlmssp_state->session_key.length) {894 nt_status = ntlmssp_sign_init(ntlmssp_state);895 }896 897 data_blob_free(&encrypted_session_key);898 899 /* Only one authentication allowed per server state. */900 ntlmssp_state->expected_state = NTLMSSP_DONE;901 902 return nt_status;903 }904 905 /**906 280 * Create an NTLMSSP state machine 907 281 * … … 909 283 */ 910 284 911 NTSTATUS ntlmssp_server_start(NTLMSSP_STATE **ntlmssp_state) 912 { 913 *ntlmssp_state = TALLOC_ZERO_P(NULL, NTLMSSP_STATE); 914 if (!*ntlmssp_state) { 915 DEBUG(0,("ntlmssp_server_start: talloc failed!\n")); 916 talloc_destroy(*ntlmssp_state); 917 return NT_STATUS_NO_MEMORY; 918 } 919 920 (*ntlmssp_state)->role = NTLMSSP_SERVER; 921 922 (*ntlmssp_state)->get_challenge = get_challenge; 923 (*ntlmssp_state)->set_challenge = set_challenge; 924 (*ntlmssp_state)->may_set_challenge = may_set_challenge; 925 926 (*ntlmssp_state)->get_global_myname = global_myname; 927 (*ntlmssp_state)->get_domain = lp_workgroup; 928 (*ntlmssp_state)->server_role = ROLE_DOMAIN_MEMBER; /* a good default */ 929 930 (*ntlmssp_state)->expected_state = NTLMSSP_NEGOTIATE; 931 932 (*ntlmssp_state)->ref_count = 1; 933 934 (*ntlmssp_state)->neg_flags = 285 NTSTATUS ntlmssp_server_start(TALLOC_CTX *mem_ctx, 286 bool is_standalone, 287 const char *netbios_name, 288 const char *netbios_domain, 289 const char *dns_name, 290 const char *dns_domain, 291 struct ntlmssp_state **_ntlmssp_state) 292 { 293 struct ntlmssp_state *ntlmssp_state; 294 295 if (!netbios_name) { 296 netbios_name = ""; 297 } 298 299 if (!netbios_domain) { 300 netbios_domain = ""; 301 } 302 303 if (!dns_domain) { 304 dns_domain = ""; 305 } 306 307 if (!dns_name) { 308 dns_name = ""; 309 } 310 311 ntlmssp_state = talloc_zero(mem_ctx, struct ntlmssp_state); 312 if (!ntlmssp_state) { 313 return NT_STATUS_NO_MEMORY; 314 } 315 316 ntlmssp_state->role = NTLMSSP_SERVER; 317 318 ntlmssp_state->get_challenge = get_challenge; 319 ntlmssp_state->set_challenge = set_challenge; 320 ntlmssp_state->may_set_challenge = may_set_challenge; 321 322 ntlmssp_state->server.is_standalone = is_standalone; 323 324 ntlmssp_state->expected_state = NTLMSSP_NEGOTIATE; 325 326 ntlmssp_state->allow_lm_key = lp_lanman_auth(); 327 328 ntlmssp_state->neg_flags = 935 329 NTLMSSP_NEGOTIATE_128 | 936 330 NTLMSSP_NEGOTIATE_56 | … … 943 337 NTLMSSP_NEGOTIATE_SEAL; 944 338 339 ntlmssp_state->server.netbios_name = talloc_strdup(ntlmssp_state, netbios_name); 340 if (!ntlmssp_state->server.netbios_name) { 341 talloc_free(ntlmssp_state); 342 return NT_STATUS_NO_MEMORY; 343 } 344 ntlmssp_state->server.netbios_domain = talloc_strdup(ntlmssp_state, netbios_domain); 345 if (!ntlmssp_state->server.netbios_domain) { 346 talloc_free(ntlmssp_state); 347 return NT_STATUS_NO_MEMORY; 348 } 349 ntlmssp_state->server.dns_name = talloc_strdup(ntlmssp_state, dns_name); 350 if (!ntlmssp_state->server.dns_name) { 351 talloc_free(ntlmssp_state); 352 return NT_STATUS_NO_MEMORY; 353 } 354 ntlmssp_state->server.dns_domain = talloc_strdup(ntlmssp_state, dns_domain); 355 if (!ntlmssp_state->server.dns_domain) { 356 talloc_free(ntlmssp_state); 357 return NT_STATUS_NO_MEMORY; 358 } 359 360 *_ntlmssp_state = ntlmssp_state; 945 361 return NT_STATUS_OK; 946 362 } … … 960 376 961 377 static NTSTATUS ntlmssp_client_initial(struct ntlmssp_state *ntlmssp_state, 378 TALLOC_CTX *out_mem_ctx, /* Unused at this time */ 962 379 DATA_BLOB reply, DATA_BLOB *next_request) 963 380 { 964 struct NEGOTIATE_MESSAGE negotiate;381 NTSTATUS status; 965 382 966 383 if (ntlmssp_state->unicode) { … … 975 392 976 393 /* generate the ntlmssp negotiate packet */ 977 msrpc_gen(ntlmssp_state, next_request, "CddAA",394 status = msrpc_gen(ntlmssp_state, next_request, "CddAA", 978 395 "NTLMSSP", 979 396 NTLMSSP_NEGOTIATE, 980 397 ntlmssp_state->neg_flags, 981 ntlmssp_state->get_domain(), 982 ntlmssp_state->get_global_myname()); 398 ntlmssp_state->client.netbios_domain, 399 ntlmssp_state->client.netbios_name); 400 if (!NT_STATUS_IS_OK(status)) { 401 DEBUG(0, ("ntlmssp_client_initial: failed to generate " 402 "ntlmssp negotiate packet\n")); 403 return status; 404 } 983 405 984 406 if (DEBUGLEVEL >= 10) { 985 if (NT_STATUS_IS_OK(ntlmssp_pull_NEGOTIATE_MESSAGE(next_request, 986 ntlmssp_state, 987 NULL, 988 &negotiate))) 989 { 990 NDR_PRINT_DEBUG(NEGOTIATE_MESSAGE, &negotiate); 407 struct NEGOTIATE_MESSAGE *negotiate = talloc( 408 talloc_tos(), struct NEGOTIATE_MESSAGE); 409 if (negotiate != NULL) { 410 status = ntlmssp_pull_NEGOTIATE_MESSAGE( 411 next_request, negotiate, negotiate); 412 if (NT_STATUS_IS_OK(status)) { 413 NDR_PRINT_DEBUG(NEGOTIATE_MESSAGE, 414 negotiate); 415 } 416 TALLOC_FREE(negotiate); 991 417 } 992 418 } … … 1007 433 1008 434 static NTSTATUS ntlmssp_client_challenge(struct ntlmssp_state *ntlmssp_state, 435 TALLOC_CTX *out_mem_ctx, /* Unused at this time */ 1009 436 const DATA_BLOB reply, DATA_BLOB *next_request) 1010 437 { 1011 uint32 chal_flags, ntlmssp_command, unkn1, unkn2;438 uint32_t chal_flags, ntlmssp_command, unkn1, unkn2; 1012 439 DATA_BLOB server_domain_blob; 1013 440 DATA_BLOB challenge_blob; … … 1021 448 DATA_BLOB encrypted_session_key = data_blob_null; 1022 449 NTSTATUS nt_status = NT_STATUS_OK; 1023 struct CHALLENGE_MESSAGE challenge;1024 struct AUTHENTICATE_MESSAGE authenticate;1025 450 1026 451 if (ntlmssp_state->use_ccache) { … … 1046 471 1047 472 wbc_status = wbcCredentialCache(¶ms, &info, &error); 1048 if (error != NULL) { 1049 wbcFreeMemory(error); 1050 } 473 wbcFreeMemory(error); 1051 474 if (!WBC_ERROR_IS_OK(wbc_status)) { 1052 475 goto noccache; … … 1088 511 1089 512 if (DEBUGLEVEL >= 10) { 1090 if (NT_STATUS_IS_OK(ntlmssp_pull_CHALLENGE_MESSAGE(&reply, 1091 ntlmssp_state, 1092 NULL, 1093 &challenge))) 1094 { 1095 NDR_PRINT_DEBUG(CHALLENGE_MESSAGE, &challenge); 513 struct CHALLENGE_MESSAGE *challenge = talloc( 514 talloc_tos(), struct CHALLENGE_MESSAGE); 515 if (challenge != NULL) { 516 NTSTATUS status; 517 challenge->NegotiateFlags = chal_flags; 518 status = ntlmssp_pull_CHALLENGE_MESSAGE( 519 &reply, challenge, challenge); 520 if (NT_STATUS_IS_OK(status)) { 521 NDR_PRINT_DEBUG(CHALLENGE_MESSAGE, 522 challenge); 523 } 524 TALLOC_FREE(challenge); 1096 525 } 1097 526 } … … 1137 566 } 1138 567 1139 ntlmssp_state->server_domain = server_domain; 568 if (chal_flags & NTLMSSP_TARGET_TYPE_SERVER) { 569 ntlmssp_state->server.is_standalone = true; 570 } else { 571 ntlmssp_state->server.is_standalone = false; 572 } 573 /* TODO: parse struct_blob and fill in the rest */ 574 ntlmssp_state->server.netbios_name = ""; 575 ntlmssp_state->server.netbios_domain = server_domain; 576 ntlmssp_state->server.dns_name = ""; 577 ntlmssp_state->server.dns_domain = ""; 1140 578 1141 579 if (challenge_blob.length != 8) { … … 1145 583 1146 584 if (!ntlmssp_state->nt_hash || !ntlmssp_state->lm_hash) { 1147 uchar zeros[16];585 static const uint8_t zeros[16] = {0, }; 1148 586 /* do nothing - blobs are zero length */ 1149 1150 ZERO_STRUCT(zeros);1151 587 1152 588 /* session key is all zeros */ … … 1178 614 } else if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_NTLM2) { 1179 615 struct MD5Context md5_session_nonce_ctx; 1180 u charsession_nonce[16];1181 u charsession_nonce_hash[16];1182 u charuser_session_key[16];616 uint8_t session_nonce[16]; 617 uint8_t session_nonce_hash[16]; 618 uint8_t user_session_key[16]; 1183 619 1184 620 lm_response = data_blob_talloc(ntlmssp_state, NULL, 24); … … 1238 674 if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_KEY_EXCH) { 1239 675 /* Make up a new session key */ 1240 uint8 client_session_key[16];676 uint8_t client_session_key[16]; 1241 677 generate_random_buffer(client_session_key, sizeof(client_session_key)); 1242 678 … … 1255 691 1256 692 /* this generates the actual auth packet */ 1257 if (!msrpc_gen(ntlmssp_state, next_request, auth_gen_string,693 nt_status = msrpc_gen(ntlmssp_state, next_request, auth_gen_string, 1258 694 "NTLMSSP", 1259 695 NTLMSSP_AUTH, … … 1262 698 ntlmssp_state->domain, 1263 699 ntlmssp_state->user, 1264 ntlmssp_state-> get_global_myname(),700 ntlmssp_state->client.netbios_name, 1265 701 encrypted_session_key.data, encrypted_session_key.length, 1266 ntlmssp_state->neg_flags)) { 1267 702 ntlmssp_state->neg_flags); 703 704 if (!NT_STATUS_IS_OK(nt_status)) { 1268 705 return NT_STATUS_NO_MEMORY; 1269 706 } 1270 707 1271 708 if (DEBUGLEVEL >= 10) { 1272 if (NT_STATUS_IS_OK(ntlmssp_pull_AUTHENTICATE_MESSAGE(next_request, 1273 ntlmssp_state, 1274 NULL, 1275 &authenticate))) 1276 { 1277 NDR_PRINT_DEBUG(AUTHENTICATE_MESSAGE, &authenticate); 709 struct AUTHENTICATE_MESSAGE *authenticate = talloc( 710 talloc_tos(), struct AUTHENTICATE_MESSAGE); 711 if (authenticate != NULL) { 712 NTSTATUS status; 713 authenticate->NegotiateFlags = 714 ntlmssp_state->neg_flags; 715 status = ntlmssp_pull_AUTHENTICATE_MESSAGE( 716 next_request, authenticate, authenticate); 717 if (NT_STATUS_IS_OK(status)) { 718 NDR_PRINT_DEBUG(AUTHENTICATE_MESSAGE, 719 authenticate); 720 } 721 TALLOC_FREE(authenticate); 1278 722 } 1279 723 } … … 1300 744 } 1301 745 1302 NTSTATUS ntlmssp_client_start(NTLMSSP_STATE **ntlmssp_state) 1303 { 1304 *ntlmssp_state = TALLOC_ZERO_P(NULL, NTLMSSP_STATE); 1305 if (!*ntlmssp_state) { 1306 DEBUG(0,("ntlmssp_client_start: talloc failed!\n")); 1307 talloc_destroy(*ntlmssp_state); 1308 return NT_STATUS_NO_MEMORY; 1309 } 1310 1311 (*ntlmssp_state)->role = NTLMSSP_CLIENT; 1312 1313 (*ntlmssp_state)->get_global_myname = global_myname; 1314 (*ntlmssp_state)->get_domain = lp_workgroup; 1315 1316 (*ntlmssp_state)->unicode = True; 1317 1318 (*ntlmssp_state)->use_ntlmv2 = lp_client_ntlmv2_auth(); 1319 1320 (*ntlmssp_state)->expected_state = NTLMSSP_INITIAL; 1321 1322 (*ntlmssp_state)->ref_count = 1; 1323 1324 (*ntlmssp_state)->neg_flags = 746 NTSTATUS ntlmssp_client_start(TALLOC_CTX *mem_ctx, 747 const char *netbios_name, 748 const char *netbios_domain, 749 bool use_ntlmv2, 750 struct ntlmssp_state **_ntlmssp_state) 751 { 752 struct ntlmssp_state *ntlmssp_state; 753 754 if (!netbios_name) { 755 netbios_name = ""; 756 } 757 758 if (!netbios_domain) { 759 netbios_domain = ""; 760 } 761 762 ntlmssp_state = talloc_zero(mem_ctx, struct ntlmssp_state); 763 if (!ntlmssp_state) { 764 return NT_STATUS_NO_MEMORY; 765 } 766 767 ntlmssp_state->role = NTLMSSP_CLIENT; 768 769 ntlmssp_state->unicode = True; 770 771 ntlmssp_state->use_ntlmv2 = use_ntlmv2; 772 773 ntlmssp_state->expected_state = NTLMSSP_INITIAL; 774 775 ntlmssp_state->neg_flags = 1325 776 NTLMSSP_NEGOTIATE_128 | 1326 777 NTLMSSP_NEGOTIATE_ALWAYS_SIGN | … … 1330 781 NTLMSSP_REQUEST_TARGET; 1331 782 783 ntlmssp_state->client.netbios_name = talloc_strdup(ntlmssp_state, netbios_name); 784 if (!ntlmssp_state->client.netbios_name) { 785 talloc_free(ntlmssp_state); 786 return NT_STATUS_NO_MEMORY; 787 } 788 ntlmssp_state->client.netbios_domain = talloc_strdup(ntlmssp_state, netbios_domain); 789 if (!ntlmssp_state->client.netbios_domain) { 790 talloc_free(ntlmssp_state); 791 return NT_STATUS_NO_MEMORY; 792 } 793 794 *_ntlmssp_state = ntlmssp_state; 1332 795 return NT_STATUS_OK; 1333 796 }
Note:
See TracChangeset
for help on using the changeset viewer.