s4-scripting: samba-tool: Fix domain info usage message
[Samba/vl.git] / source3 / libsmb / ntlmssp.c
blob989f26b458d5c1fa633c8484d864a0e4123086f5
1 /*
2 Unix SMB/Netbios implementation.
3 Version 3.0
4 handle NLTMSSP, server side
6 Copyright (C) Andrew Tridgell 2001
7 Copyright (C) Andrew Bartlett 2001-2010
8 Copyright (C) Stefan Metzmacher 2005
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 3 of the License, or
13 (at your option) any later version.
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program. If not, see <http://www.gnu.org/licenses/>.
24 #include "includes.h"
25 #include "../auth/ntlmssp/ntlmssp.h"
26 #include "../auth/ntlmssp/ntlmssp_private.h"
27 #include "../libcli/auth/libcli_auth.h"
28 #include "../librpc/gen_ndr/ndr_ntlmssp.h"
29 #include "../auth/ntlmssp/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"
35 static NTSTATUS ntlmssp_client_initial(struct ntlmssp_state *ntlmssp_state,
36 TALLOC_CTX *out_mem_ctx,
37 DATA_BLOB reply, DATA_BLOB *next_request);
38 static NTSTATUS ntlmssp_client_challenge(struct ntlmssp_state *ntlmssp_state,
39 TALLOC_CTX *out_mem_ctx, /* Unused at this time */
40 const DATA_BLOB reply, DATA_BLOB *next_request);
41 /**
42 * Callbacks for NTLMSSP - for both client and server operating modes
46 static const struct ntlmssp_callbacks {
47 enum ntlmssp_role role;
48 enum ntlmssp_message_type ntlmssp_command;
49 NTSTATUS (*fn)(struct ntlmssp_state *ntlmssp_state,
50 TALLOC_CTX *out_mem_ctx,
51 DATA_BLOB in, DATA_BLOB *out);
52 } ntlmssp_callbacks[] = {
53 {NTLMSSP_CLIENT, NTLMSSP_INITIAL, ntlmssp_client_initial},
54 {NTLMSSP_SERVER, NTLMSSP_NEGOTIATE, ntlmssp_server_negotiate},
55 {NTLMSSP_CLIENT, NTLMSSP_CHALLENGE, ntlmssp_client_challenge},
56 {NTLMSSP_SERVER, NTLMSSP_AUTH, ntlmssp_server_auth},
57 {NTLMSSP_CLIENT, NTLMSSP_UNKNOWN, NULL},
58 {NTLMSSP_SERVER, NTLMSSP_UNKNOWN, NULL}
62 /**
63 * Default challenge generation code.
67 static NTSTATUS get_challenge(const struct ntlmssp_state *ntlmssp_state,
68 uint8_t chal[8])
70 generate_random_buffer(chal, 8);
71 return NT_STATUS_OK;
74 /**
75 * Default 'we can set the challenge to anything we like' implementation
79 static bool may_set_challenge(const struct ntlmssp_state *ntlmssp_state)
81 return True;
84 /**
85 * Default 'we can set the challenge to anything we like' implementation
87 * Does not actually do anything, as the value is always in the structure anyway.
91 static NTSTATUS set_challenge(struct ntlmssp_state *ntlmssp_state, DATA_BLOB *challenge)
93 SMB_ASSERT(challenge->length == 8);
94 return NT_STATUS_OK;
97 /**
98 * Set a username on an NTLMSSP context - ensures it is talloc()ed
102 NTSTATUS ntlmssp_set_username(struct ntlmssp_state *ntlmssp_state, const char *user)
104 ntlmssp_state->user = talloc_strdup(ntlmssp_state, user ? user : "" );
105 if (!ntlmssp_state->user) {
106 return NT_STATUS_NO_MEMORY;
108 return NT_STATUS_OK;
112 * Converts a password to the hashes on an NTLMSSP context.
115 NTSTATUS ntlmssp_set_password(struct ntlmssp_state *ntlmssp_state, const char *password)
117 TALLOC_FREE(ntlmssp_state->lm_hash);
118 TALLOC_FREE(ntlmssp_state->nt_hash);
119 if (!password) {
120 return NT_STATUS_OK;
121 } else {
122 uint8_t lm_hash[16];
123 uint8_t nt_hash[16];
125 if (E_deshash(password, lm_hash)) {
126 ntlmssp_state->lm_hash = (uint8_t *)
127 talloc_memdup(ntlmssp_state, lm_hash, 16);
128 if (!ntlmssp_state->lm_hash) {
129 return NT_STATUS_NO_MEMORY;
133 E_md4hash(password, nt_hash);
135 ntlmssp_state->nt_hash = (uint8_t *)
136 talloc_memdup(ntlmssp_state, nt_hash, 16);
137 if (!ntlmssp_state->nt_hash) {
138 TALLOC_FREE(ntlmssp_state->lm_hash);
139 return NT_STATUS_NO_MEMORY;
142 return NT_STATUS_OK;
146 * Set a domain on an NTLMSSP context - ensures it is talloc()ed
149 NTSTATUS ntlmssp_set_domain(struct ntlmssp_state *ntlmssp_state, const char *domain)
151 ntlmssp_state->domain = talloc_strdup(ntlmssp_state,
152 domain ? domain : "" );
153 if (!ntlmssp_state->domain) {
154 return NT_STATUS_NO_MEMORY;
156 return NT_STATUS_OK;
160 * Request features for the NTLMSSP negotiation
162 * @param ntlmssp_state NTLMSSP state
163 * @param feature_list List of space seperated features requested from NTLMSSP.
165 void ntlmssp_want_feature_list(struct ntlmssp_state *ntlmssp_state, char *feature_list)
168 * We need to set this to allow a later SetPassword
169 * via the SAMR pipe to succeed. Strange.... We could
170 * also add NTLMSSP_NEGOTIATE_SEAL here. JRA.
172 if (in_list("NTLMSSP_FEATURE_SESSION_KEY", feature_list, True)) {
173 ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SIGN;
175 if (in_list("NTLMSSP_FEATURE_SIGN", feature_list, True)) {
176 ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SIGN;
178 if(in_list("NTLMSSP_FEATURE_SEAL", feature_list, True)) {
179 ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SEAL;
181 if (in_list("NTLMSSP_FEATURE_CCACHE", feature_list, true)) {
182 ntlmssp_state->use_ccache = true;
187 * Request a feature for the NTLMSSP negotiation
189 * @param ntlmssp_state NTLMSSP state
190 * @param feature Bit flag specifying the requested feature
192 void ntlmssp_want_feature(struct ntlmssp_state *ntlmssp_state, uint32_t feature)
194 /* As per JRA's comment above */
195 if (feature & NTLMSSP_FEATURE_SESSION_KEY) {
196 ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SIGN;
198 if (feature & NTLMSSP_FEATURE_SIGN) {
199 ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SIGN;
201 if (feature & NTLMSSP_FEATURE_SEAL) {
202 ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SIGN;
203 ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SEAL;
205 if (feature & NTLMSSP_FEATURE_CCACHE) {
206 ntlmssp_state->use_ccache = true;
211 * Next state function for the NTLMSSP state machine
213 * @param ntlmssp_state NTLMSSP State
214 * @param in The packet in from the NTLMSSP partner, as a DATA_BLOB
215 * @param out The reply, as an allocated DATA_BLOB, caller to free.
216 * @return Errors, NT_STATUS_MORE_PROCESSING_REQUIRED or NT_STATUS_OK.
219 NTSTATUS ntlmssp_update(struct ntlmssp_state *ntlmssp_state,
220 const DATA_BLOB input, DATA_BLOB *out)
222 uint32_t ntlmssp_command;
223 int i;
225 if (ntlmssp_state->expected_state == NTLMSSP_DONE) {
226 /* Called update after negotiations finished. */
227 DEBUG(1, ("Called NTLMSSP after state machine was 'done'\n"));
228 return NT_STATUS_INVALID_PARAMETER;
231 *out = data_blob_null;
233 if (!input.length) {
234 switch (ntlmssp_state->role) {
235 case NTLMSSP_CLIENT:
236 ntlmssp_command = NTLMSSP_INITIAL;
237 break;
238 case NTLMSSP_SERVER:
239 /* 'datagram' mode - no neg packet */
240 ntlmssp_command = NTLMSSP_NEGOTIATE;
241 break;
242 default:
243 DEBUG(1, ("Invalid role: %d\n", ntlmssp_state->role));
244 return NT_STATUS_INVALID_PARAMETER;
246 } else {
247 if (!msrpc_parse(ntlmssp_state, &input, "Cd",
248 "NTLMSSP",
249 &ntlmssp_command)) {
250 DEBUG(1, ("Failed to parse NTLMSSP packet, could not extract NTLMSSP command\n"));
251 dump_data(2, input.data, input.length);
252 return NT_STATUS_INVALID_PARAMETER;
256 if (ntlmssp_command != ntlmssp_state->expected_state) {
257 DEBUG(1, ("got NTLMSSP command %u, expected %u\n", ntlmssp_command, ntlmssp_state->expected_state));
258 return NT_STATUS_INVALID_PARAMETER;
261 for (i=0; ntlmssp_callbacks[i].fn; i++) {
262 if (ntlmssp_callbacks[i].role == ntlmssp_state->role
263 && ntlmssp_callbacks[i].ntlmssp_command == ntlmssp_command) {
264 return ntlmssp_callbacks[i].fn(ntlmssp_state, ntlmssp_state, input, out);
268 DEBUG(1, ("failed to find NTLMSSP callback for NTLMSSP mode %u, command %u\n",
269 ntlmssp_state->role, ntlmssp_command));
271 return NT_STATUS_INVALID_PARAMETER;
275 * Create an NTLMSSP state machine
277 * @param ntlmssp_state NTLMSSP State, allocated by this function
280 NTSTATUS ntlmssp_server_start(TALLOC_CTX *mem_ctx,
281 bool is_standalone,
282 const char *netbios_name,
283 const char *netbios_domain,
284 const char *dns_name,
285 const char *dns_domain,
286 struct ntlmssp_state **_ntlmssp_state)
288 struct ntlmssp_state *ntlmssp_state;
290 if (!netbios_name) {
291 netbios_name = "";
294 if (!netbios_domain) {
295 netbios_domain = "";
298 if (!dns_domain) {
299 dns_domain = "";
302 if (!dns_name) {
303 dns_name = "";
306 ntlmssp_state = talloc_zero(mem_ctx, struct ntlmssp_state);
307 if (!ntlmssp_state) {
308 return NT_STATUS_NO_MEMORY;
311 ntlmssp_state->role = NTLMSSP_SERVER;
313 ntlmssp_state->get_challenge = get_challenge;
314 ntlmssp_state->set_challenge = set_challenge;
315 ntlmssp_state->may_set_challenge = may_set_challenge;
317 ntlmssp_state->server.is_standalone = is_standalone;
319 ntlmssp_state->expected_state = NTLMSSP_NEGOTIATE;
321 ntlmssp_state->allow_lm_key = lp_lanman_auth();
323 ntlmssp_state->neg_flags =
324 NTLMSSP_NEGOTIATE_128 |
325 NTLMSSP_NEGOTIATE_56 |
326 NTLMSSP_NEGOTIATE_VERSION |
327 NTLMSSP_NEGOTIATE_ALWAYS_SIGN |
328 NTLMSSP_NEGOTIATE_NTLM |
329 NTLMSSP_NEGOTIATE_NTLM2 |
330 NTLMSSP_NEGOTIATE_KEY_EXCH;
332 ntlmssp_state->server.netbios_name = talloc_strdup(ntlmssp_state, netbios_name);
333 if (!ntlmssp_state->server.netbios_name) {
334 talloc_free(ntlmssp_state);
335 return NT_STATUS_NO_MEMORY;
337 ntlmssp_state->server.netbios_domain = talloc_strdup(ntlmssp_state, netbios_domain);
338 if (!ntlmssp_state->server.netbios_domain) {
339 talloc_free(ntlmssp_state);
340 return NT_STATUS_NO_MEMORY;
342 ntlmssp_state->server.dns_name = talloc_strdup(ntlmssp_state, dns_name);
343 if (!ntlmssp_state->server.dns_name) {
344 talloc_free(ntlmssp_state);
345 return NT_STATUS_NO_MEMORY;
347 ntlmssp_state->server.dns_domain = talloc_strdup(ntlmssp_state, dns_domain);
348 if (!ntlmssp_state->server.dns_domain) {
349 talloc_free(ntlmssp_state);
350 return NT_STATUS_NO_MEMORY;
353 *_ntlmssp_state = ntlmssp_state;
354 return NT_STATUS_OK;
357 /*********************************************************************
358 Client side NTLMSSP
359 *********************************************************************/
362 * Next state function for the Initial packet
364 * @param ntlmssp_state NTLMSSP State
365 * @param request The request, as a DATA_BLOB. reply.data must be NULL
366 * @param request The reply, as an allocated DATA_BLOB, caller to free.
367 * @return Errors or NT_STATUS_OK.
370 static NTSTATUS ntlmssp_client_initial(struct ntlmssp_state *ntlmssp_state,
371 TALLOC_CTX *out_mem_ctx,
372 DATA_BLOB in, DATA_BLOB *out)
374 const char *domain = ntlmssp_state->client.netbios_domain;
375 const char *workstation = ntlmssp_state->client.netbios_name;
376 NTSTATUS status;
378 /* These don't really matter in the initial packet, so don't panic if they are not set */
379 if (!domain) {
380 domain = "";
383 if (!workstation) {
384 workstation = "";
387 if (ntlmssp_state->unicode) {
388 ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_UNICODE;
389 } else {
390 ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_OEM;
393 if (ntlmssp_state->use_ntlmv2) {
394 ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_NTLM2;
397 /* generate the ntlmssp negotiate packet */
398 status = msrpc_gen(out_mem_ctx,
399 out, "CddAA",
400 "NTLMSSP",
401 NTLMSSP_NEGOTIATE,
402 ntlmssp_state->neg_flags,
403 domain,
404 workstation);
406 if (!NT_STATUS_IS_OK(status)) {
407 DEBUG(0, ("ntlmssp_client_initial: failed to generate "
408 "ntlmssp negotiate packet\n"));
409 return status;
412 if (DEBUGLEVEL >= 10) {
413 struct NEGOTIATE_MESSAGE *negotiate = talloc(
414 talloc_tos(), struct NEGOTIATE_MESSAGE);
415 if (negotiate != NULL) {
416 status = ntlmssp_pull_NEGOTIATE_MESSAGE(
417 out, negotiate, negotiate);
418 if (NT_STATUS_IS_OK(status)) {
419 NDR_PRINT_DEBUG(NEGOTIATE_MESSAGE,
420 negotiate);
422 TALLOC_FREE(negotiate);
426 ntlmssp_state->expected_state = NTLMSSP_CHALLENGE;
428 return NT_STATUS_MORE_PROCESSING_REQUIRED;
432 * Next state function for the Challenge Packet. Generate an auth packet.
434 * @param ntlmssp_state NTLMSSP State
435 * @param request The request, as a DATA_BLOB. reply.data must be NULL
436 * @param request The reply, as an allocated DATA_BLOB, caller to free.
437 * @return Errors or NT_STATUS_OK.
440 static NTSTATUS ntlmssp_client_challenge(struct ntlmssp_state *ntlmssp_state,
441 TALLOC_CTX *out_mem_ctx, /* Unused at this time */
442 const DATA_BLOB reply, DATA_BLOB *next_request)
444 uint32_t chal_flags, ntlmssp_command, unkn1, unkn2;
445 DATA_BLOB server_domain_blob;
446 DATA_BLOB challenge_blob;
447 DATA_BLOB struct_blob = data_blob_null;
448 char *server_domain;
449 const char *chal_parse_string;
450 const char *auth_gen_string;
451 DATA_BLOB lm_response = data_blob_null;
452 DATA_BLOB nt_response = data_blob_null;
453 DATA_BLOB session_key = data_blob_null;
454 DATA_BLOB encrypted_session_key = data_blob_null;
455 NTSTATUS nt_status = NT_STATUS_OK;
457 if (ntlmssp_state->use_ccache) {
458 struct wbcCredentialCacheParams params;
459 struct wbcCredentialCacheInfo *info = NULL;
460 struct wbcAuthErrorInfo *error = NULL;
461 struct wbcNamedBlob auth_blob;
462 struct wbcBlob *wbc_next = NULL;
463 struct wbcBlob *wbc_session_key = NULL;
464 wbcErr wbc_status;
465 int i;
467 params.account_name = ntlmssp_state->user;
468 params.domain_name = ntlmssp_state->domain;
469 params.level = WBC_CREDENTIAL_CACHE_LEVEL_NTLMSSP;
471 auth_blob.name = "challenge_blob";
472 auth_blob.flags = 0;
473 auth_blob.blob.data = reply.data;
474 auth_blob.blob.length = reply.length;
475 params.num_blobs = 1;
476 params.blobs = &auth_blob;
478 wbc_status = wbcCredentialCache(&params, &info, &error);
479 wbcFreeMemory(error);
480 if (!WBC_ERROR_IS_OK(wbc_status)) {
481 goto noccache;
484 for (i=0; i<info->num_blobs; i++) {
485 if (strequal(info->blobs[i].name, "auth_blob")) {
486 wbc_next = &info->blobs[i].blob;
488 if (strequal(info->blobs[i].name, "session_key")) {
489 wbc_session_key = &info->blobs[i].blob;
492 if ((wbc_next == NULL) || (wbc_session_key == NULL)) {
493 wbcFreeMemory(info);
494 goto noccache;
497 *next_request = data_blob(wbc_next->data, wbc_next->length);
498 ntlmssp_state->session_key = data_blob(
499 wbc_session_key->data, wbc_session_key->length);
501 wbcFreeMemory(info);
502 goto done;
505 noccache:
507 if (!msrpc_parse(ntlmssp_state, &reply, "CdBd",
508 "NTLMSSP",
509 &ntlmssp_command,
510 &server_domain_blob,
511 &chal_flags)) {
512 DEBUG(1, ("Failed to parse the NTLMSSP Challenge: (#1)\n"));
513 dump_data(2, reply.data, reply.length);
515 return NT_STATUS_INVALID_PARAMETER;
518 if (DEBUGLEVEL >= 10) {
519 struct CHALLENGE_MESSAGE *challenge = talloc(
520 talloc_tos(), struct CHALLENGE_MESSAGE);
521 if (challenge != NULL) {
522 NTSTATUS status;
523 challenge->NegotiateFlags = chal_flags;
524 status = ntlmssp_pull_CHALLENGE_MESSAGE(
525 &reply, challenge, challenge);
526 if (NT_STATUS_IS_OK(status)) {
527 NDR_PRINT_DEBUG(CHALLENGE_MESSAGE,
528 challenge);
530 TALLOC_FREE(challenge);
534 data_blob_free(&server_domain_blob);
536 DEBUG(3, ("Got challenge flags:\n"));
537 debug_ntlmssp_flags(chal_flags);
539 ntlmssp_handle_neg_flags(ntlmssp_state, chal_flags, lp_client_lanman_auth());
541 if (ntlmssp_state->unicode) {
542 if (chal_flags & NTLMSSP_NEGOTIATE_TARGET_INFO) {
543 chal_parse_string = "CdUdbddB";
544 } else {
545 chal_parse_string = "CdUdbdd";
547 auth_gen_string = "CdBBUUUBd";
548 } else {
549 if (chal_flags & NTLMSSP_NEGOTIATE_TARGET_INFO) {
550 chal_parse_string = "CdAdbddB";
551 } else {
552 chal_parse_string = "CdAdbdd";
555 auth_gen_string = "CdBBAAABd";
558 DEBUG(3, ("NTLMSSP: Set final flags:\n"));
559 debug_ntlmssp_flags(ntlmssp_state->neg_flags);
561 if (!msrpc_parse(ntlmssp_state, &reply, chal_parse_string,
562 "NTLMSSP",
563 &ntlmssp_command,
564 &server_domain,
565 &chal_flags,
566 &challenge_blob, 8,
567 &unkn1, &unkn2,
568 &struct_blob)) {
569 DEBUG(1, ("Failed to parse the NTLMSSP Challenge: (#2)\n"));
570 dump_data(2, reply.data, reply.length);
571 return NT_STATUS_INVALID_PARAMETER;
574 if (chal_flags & NTLMSSP_TARGET_TYPE_SERVER) {
575 ntlmssp_state->server.is_standalone = true;
576 } else {
577 ntlmssp_state->server.is_standalone = false;
579 /* TODO: parse struct_blob and fill in the rest */
580 ntlmssp_state->server.netbios_name = "";
581 ntlmssp_state->server.netbios_domain = server_domain;
582 ntlmssp_state->server.dns_name = "";
583 ntlmssp_state->server.dns_domain = "";
585 if (challenge_blob.length != 8) {
586 data_blob_free(&struct_blob);
587 return NT_STATUS_INVALID_PARAMETER;
590 if (!ntlmssp_state->nt_hash) {
591 static const uint8_t zeros[16] = {0, };
592 /* do nothing - blobs are zero length */
594 /* session key is all zeros */
595 session_key = data_blob_talloc(ntlmssp_state, zeros, 16);
597 /* not doing NLTM2 without a password */
598 ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_NTLM2;
599 } else if (ntlmssp_state->use_ntlmv2) {
600 if (!struct_blob.length) {
601 /* be lazy, match win2k - we can't do NTLMv2 without it */
602 DEBUG(1, ("Server did not provide 'target information', required for NTLMv2\n"));
603 return NT_STATUS_INVALID_PARAMETER;
606 /* TODO: if the remote server is standalone, then we should replace 'domain'
607 with the server name as supplied above */
609 if (!SMBNTLMv2encrypt_hash(ntlmssp_state,
610 ntlmssp_state->user,
611 ntlmssp_state->domain,
612 ntlmssp_state->nt_hash, &challenge_blob,
613 &struct_blob,
614 &lm_response, &nt_response, NULL,
615 &session_key)) {
616 data_blob_free(&challenge_blob);
617 data_blob_free(&struct_blob);
618 return NT_STATUS_NO_MEMORY;
620 } else if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_NTLM2) {
621 struct MD5Context md5_session_nonce_ctx;
622 uint8_t session_nonce[16];
623 uint8_t session_nonce_hash[16];
624 uint8_t user_session_key[16];
626 lm_response = data_blob_talloc(ntlmssp_state, NULL, 24);
627 generate_random_buffer(lm_response.data, 8);
628 memset(lm_response.data+8, 0, 16);
630 memcpy(session_nonce, challenge_blob.data, 8);
631 memcpy(&session_nonce[8], lm_response.data, 8);
633 MD5Init(&md5_session_nonce_ctx);
634 MD5Update(&md5_session_nonce_ctx, challenge_blob.data, 8);
635 MD5Update(&md5_session_nonce_ctx, lm_response.data, 8);
636 MD5Final(session_nonce_hash, &md5_session_nonce_ctx);
638 DEBUG(5, ("NTLMSSP challenge set by NTLM2\n"));
639 DEBUG(5, ("challenge is: \n"));
640 dump_data(5, session_nonce_hash, 8);
642 nt_response = data_blob_talloc(ntlmssp_state, NULL, 24);
643 SMBNTencrypt_hash(ntlmssp_state->nt_hash,
644 session_nonce_hash,
645 nt_response.data);
647 session_key = data_blob_talloc(ntlmssp_state, NULL, 16);
649 SMBsesskeygen_ntv1(ntlmssp_state->nt_hash, user_session_key);
650 hmac_md5(user_session_key, session_nonce, sizeof(session_nonce), session_key.data);
651 dump_data_pw("NTLM2 session key:\n", session_key.data, session_key.length);
652 } else {
653 /* lanman auth is insecure, it may be disabled */
654 if (lp_client_lanman_auth() && ntlmssp_state->lm_hash) {
655 lm_response = data_blob_talloc(ntlmssp_state,
656 NULL, 24);
657 SMBencrypt_hash(ntlmssp_state->lm_hash,challenge_blob.data,
658 lm_response.data);
661 nt_response = data_blob_talloc(ntlmssp_state, NULL, 24);
662 SMBNTencrypt_hash(ntlmssp_state->nt_hash,challenge_blob.data,
663 nt_response.data);
665 session_key = data_blob_talloc(ntlmssp_state, NULL, 16);
666 if ((ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_LM_KEY)
667 && lp_client_lanman_auth() && ntlmssp_state->lm_hash) {
668 SMBsesskeygen_lm_sess_key(ntlmssp_state->lm_hash, lm_response.data,
669 session_key.data);
670 dump_data_pw("LM session key\n", session_key.data, session_key.length);
671 } else {
672 SMBsesskeygen_ntv1(ntlmssp_state->nt_hash, session_key.data);
673 dump_data_pw("NT session key:\n", session_key.data, session_key.length);
676 data_blob_free(&struct_blob);
678 /* Key exchange encryptes a new client-generated session key with
679 the password-derived key */
680 if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_KEY_EXCH) {
681 /* Make up a new session key */
682 uint8_t client_session_key[16];
683 generate_random_buffer(client_session_key, sizeof(client_session_key));
685 /* Encrypt the new session key with the old one */
686 encrypted_session_key = data_blob(client_session_key, sizeof(client_session_key));
687 dump_data_pw("KEY_EXCH session key:\n", encrypted_session_key.data, encrypted_session_key.length);
688 arcfour_crypt_blob(encrypted_session_key.data, encrypted_session_key.length, &session_key);
689 dump_data_pw("KEY_EXCH session key (enc):\n", encrypted_session_key.data, encrypted_session_key.length);
691 /* Mark the new session key as the 'real' session key */
692 data_blob_free(&session_key);
693 session_key = data_blob_talloc(ntlmssp_state,
694 client_session_key,
695 sizeof(client_session_key));
698 /* this generates the actual auth packet */
699 nt_status = msrpc_gen(ntlmssp_state, next_request, auth_gen_string,
700 "NTLMSSP",
701 NTLMSSP_AUTH,
702 lm_response.data, lm_response.length,
703 nt_response.data, nt_response.length,
704 ntlmssp_state->domain,
705 ntlmssp_state->user,
706 ntlmssp_state->client.netbios_name,
707 encrypted_session_key.data, encrypted_session_key.length,
708 ntlmssp_state->neg_flags);
710 if (!NT_STATUS_IS_OK(nt_status)) {
711 return NT_STATUS_NO_MEMORY;
714 if (DEBUGLEVEL >= 10) {
715 struct AUTHENTICATE_MESSAGE *authenticate = talloc(
716 talloc_tos(), struct AUTHENTICATE_MESSAGE);
717 if (authenticate != NULL) {
718 NTSTATUS status;
719 authenticate->NegotiateFlags =
720 ntlmssp_state->neg_flags;
721 status = ntlmssp_pull_AUTHENTICATE_MESSAGE(
722 next_request, authenticate, authenticate);
723 if (NT_STATUS_IS_OK(status)) {
724 NDR_PRINT_DEBUG(AUTHENTICATE_MESSAGE,
725 authenticate);
727 TALLOC_FREE(authenticate);
731 data_blob_free(&encrypted_session_key);
733 data_blob_free(&ntlmssp_state->chal);
735 ntlmssp_state->session_key = session_key;
737 ntlmssp_state->chal = challenge_blob;
738 ntlmssp_state->lm_resp = lm_response;
739 ntlmssp_state->nt_resp = nt_response;
741 done:
743 ntlmssp_state->expected_state = NTLMSSP_DONE;
745 if (!NT_STATUS_IS_OK(nt_status = ntlmssp_sign_init(ntlmssp_state))) {
746 DEBUG(1, ("Could not setup NTLMSSP signing/sealing system (error was: %s)\n", nt_errstr(nt_status)));
749 return nt_status;
752 NTSTATUS ntlmssp_client_start(TALLOC_CTX *mem_ctx,
753 const char *netbios_name,
754 const char *netbios_domain,
755 bool use_ntlmv2,
756 struct ntlmssp_state **_ntlmssp_state)
758 struct ntlmssp_state *ntlmssp_state;
760 if (!netbios_name) {
761 netbios_name = "";
764 if (!netbios_domain) {
765 netbios_domain = "";
768 ntlmssp_state = talloc_zero(mem_ctx, struct ntlmssp_state);
769 if (!ntlmssp_state) {
770 return NT_STATUS_NO_MEMORY;
773 ntlmssp_state->role = NTLMSSP_CLIENT;
775 ntlmssp_state->unicode = True;
777 ntlmssp_state->use_ntlmv2 = use_ntlmv2;
779 ntlmssp_state->expected_state = NTLMSSP_INITIAL;
781 ntlmssp_state->neg_flags =
782 NTLMSSP_NEGOTIATE_128 |
783 NTLMSSP_NEGOTIATE_ALWAYS_SIGN |
784 NTLMSSP_NEGOTIATE_NTLM |
785 NTLMSSP_NEGOTIATE_NTLM2 |
786 NTLMSSP_NEGOTIATE_KEY_EXCH |
787 NTLMSSP_REQUEST_TARGET;
789 ntlmssp_state->client.netbios_name = talloc_strdup(ntlmssp_state, netbios_name);
790 if (!ntlmssp_state->client.netbios_name) {
791 talloc_free(ntlmssp_state);
792 return NT_STATUS_NO_MEMORY;
794 ntlmssp_state->client.netbios_domain = talloc_strdup(ntlmssp_state, netbios_domain);
795 if (!ntlmssp_state->client.netbios_domain) {
796 talloc_free(ntlmssp_state);
797 return NT_STATUS_NO_MEMORY;
800 *_ntlmssp_state = ntlmssp_state;
801 return NT_STATUS_OK;