ldap_server: Log authorization for simple binds
[Samba.git] / auth / ntlmssp / ntlmssp_client.c
blob5edd5f4fce64cd6f40d1d2c1a295640c1304b020
1 /*
2 Unix SMB/Netbios implementation.
3 Version 3.0
4 handle NLTMSSP, client server side parsing
6 Copyright (C) Andrew Tridgell 2001
7 Copyright (C) Andrew Bartlett <abartlet@samba.org> 2001-2005
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 struct auth_session_info;
26 #include "includes.h"
27 #include "auth/ntlmssp/ntlmssp.h"
28 #include "../lib/crypto/crypto.h"
29 #include "../libcli/auth/libcli_auth.h"
30 #include "auth/credentials/credentials.h"
31 #include "auth/gensec/gensec.h"
32 #include "auth/gensec/gensec_internal.h"
33 #include "param/param.h"
34 #include "auth/ntlmssp/ntlmssp_private.h"
35 #include "../librpc/gen_ndr/ndr_ntlmssp.h"
36 #include "../auth/ntlmssp/ntlmssp_ndr.h"
37 #include "../nsswitch/libwbclient/wbclient.h"
39 /*********************************************************************
40 Client side NTLMSSP
41 *********************************************************************/
43 /**
44 * Next state function for the Initial packet
46 * @param ntlmssp_state NTLMSSP State
47 * @param out_mem_ctx The DATA_BLOB *out will be allocated on this context
48 * @param in A NULL data blob (input ignored)
49 * @param out The initial negotiate request to the server, as an talloc()ed DATA_BLOB, on out_mem_ctx
50 * @return Errors or NT_STATUS_OK.
53 NTSTATUS ntlmssp_client_initial(struct gensec_security *gensec_security,
54 TALLOC_CTX *out_mem_ctx,
55 DATA_BLOB in, DATA_BLOB *out)
57 struct gensec_ntlmssp_context *gensec_ntlmssp =
58 talloc_get_type_abort(gensec_security->private_data,
59 struct gensec_ntlmssp_context);
60 struct ntlmssp_state *ntlmssp_state = gensec_ntlmssp->ntlmssp_state;
61 NTSTATUS status;
62 const DATA_BLOB version_blob = ntlmssp_version_blob();
64 /* generate the ntlmssp negotiate packet */
65 status = msrpc_gen(out_mem_ctx,
66 out, "CddAAb",
67 "NTLMSSP",
68 NTLMSSP_NEGOTIATE,
69 ntlmssp_state->neg_flags,
70 "", /* domain */
71 "", /* workstation */
72 version_blob.data, version_blob.length);
73 if (!NT_STATUS_IS_OK(status)) {
74 DEBUG(0, ("ntlmssp_client_initial: failed to generate "
75 "ntlmssp negotiate packet\n"));
76 return status;
79 if (DEBUGLEVEL >= 10) {
80 struct NEGOTIATE_MESSAGE *negotiate = talloc(
81 ntlmssp_state, struct NEGOTIATE_MESSAGE);
82 if (negotiate != NULL) {
83 status = ntlmssp_pull_NEGOTIATE_MESSAGE(
84 out, negotiate, negotiate);
85 if (NT_STATUS_IS_OK(status)) {
86 NDR_PRINT_DEBUG(NEGOTIATE_MESSAGE,
87 negotiate);
89 TALLOC_FREE(negotiate);
93 ntlmssp_state->negotiate_blob = data_blob_dup_talloc(ntlmssp_state,
94 *out);
95 if (ntlmssp_state->negotiate_blob.length != out->length) {
96 return NT_STATUS_NO_MEMORY;
99 ntlmssp_state->expected_state = NTLMSSP_CHALLENGE;
101 return NT_STATUS_MORE_PROCESSING_REQUIRED;
104 NTSTATUS gensec_ntlmssp_resume_ccache(struct gensec_security *gensec_security,
105 TALLOC_CTX *out_mem_ctx,
106 DATA_BLOB in, DATA_BLOB *out)
108 struct gensec_ntlmssp_context *gensec_ntlmssp =
109 talloc_get_type_abort(gensec_security->private_data,
110 struct gensec_ntlmssp_context);
111 struct ntlmssp_state *ntlmssp_state = gensec_ntlmssp->ntlmssp_state;
112 uint32_t neg_flags = 0;
113 uint32_t ntlmssp_command;
114 NTSTATUS status;
115 bool ok;
117 *out = data_blob_null;
119 if (in.length == 0) {
121 * This is compat code for older callers
122 * which were missing the "initial_blob"/"negotiate_blob".
124 * That means we can't calculate the NTLMSSP_MIC
125 * field correctly and need to force the
126 * old_spnego behaviour.
128 DEBUG(10, ("%s: in.length==%u force_old_spnego!\n",
129 __func__, (unsigned int)in.length));
130 ntlmssp_state->force_old_spnego = true;
131 ntlmssp_state->neg_flags |= ntlmssp_state->required_flags;
132 ntlmssp_state->required_flags = 0;
133 ntlmssp_state->expected_state = NTLMSSP_CHALLENGE;
134 return NT_STATUS_MORE_PROCESSING_REQUIRED;
137 /* parse the NTLMSSP packet */
139 if (in.length > UINT16_MAX) {
140 DEBUG(1, ("%s: reject large request of length %u\n",
141 __func__, (unsigned int)in.length));
142 return NT_STATUS_INVALID_PARAMETER;
145 ok = msrpc_parse(ntlmssp_state, &in, "Cdd",
146 "NTLMSSP",
147 &ntlmssp_command,
148 &neg_flags);
149 if (!ok) {
150 DEBUG(1, ("%s: failed to parse NTLMSSP Negotiate of length %u\n",
151 __func__, (unsigned int)in.length));
152 dump_data(2, in.data, in.length);
153 return NT_STATUS_INVALID_PARAMETER;
156 if (ntlmssp_command != NTLMSSP_NEGOTIATE) {
157 DEBUG(1, ("%s: no NTLMSSP Negotiate message (length %u)\n",
158 __func__, (unsigned int)in.length));
159 dump_data(2, in.data, in.length);
160 return NT_STATUS_INVALID_PARAMETER;
163 ntlmssp_state->neg_flags = neg_flags;
164 DEBUG(3, ("Imported Negotiate flags:\n"));
165 debug_ntlmssp_flags(neg_flags);
167 if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_UNICODE) {
168 ntlmssp_state->unicode = true;
169 } else {
170 ntlmssp_state->unicode = false;
173 if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_SIGN) {
174 gensec_security->want_features |= GENSEC_FEATURE_SIGN;
177 if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_SEAL) {
178 gensec_security->want_features |= GENSEC_FEATURE_SEAL;
181 ntlmssp_state->conf_flags = ntlmssp_state->neg_flags;
182 ntlmssp_state->required_flags = 0;
184 if (DEBUGLEVEL >= 10) {
185 struct NEGOTIATE_MESSAGE *negotiate = talloc(
186 ntlmssp_state, struct NEGOTIATE_MESSAGE);
187 if (negotiate != NULL) {
188 status = ntlmssp_pull_NEGOTIATE_MESSAGE(
189 &in, negotiate, negotiate);
190 if (NT_STATUS_IS_OK(status)) {
191 NDR_PRINT_DEBUG(NEGOTIATE_MESSAGE,
192 negotiate);
194 TALLOC_FREE(negotiate);
198 ntlmssp_state->negotiate_blob = data_blob_dup_talloc(ntlmssp_state,
199 in);
200 if (ntlmssp_state->negotiate_blob.length != in.length) {
201 return NT_STATUS_NO_MEMORY;
204 ntlmssp_state->expected_state = NTLMSSP_CHALLENGE;
206 return NT_STATUS_MORE_PROCESSING_REQUIRED;
210 * Next state function for the Challenge Packet. Generate an auth packet.
212 * @param gensec_security GENSEC state
213 * @param out_mem_ctx Memory context for *out
214 * @param in The server challnege, as a DATA_BLOB. reply.data must be NULL
215 * @param out The next request (auth packet) to the server, as an allocated DATA_BLOB, on the out_mem_ctx context
216 * @return Errors or NT_STATUS_OK.
219 NTSTATUS ntlmssp_client_challenge(struct gensec_security *gensec_security,
220 TALLOC_CTX *out_mem_ctx,
221 const DATA_BLOB in, DATA_BLOB *out)
223 struct gensec_ntlmssp_context *gensec_ntlmssp =
224 talloc_get_type_abort(gensec_security->private_data,
225 struct gensec_ntlmssp_context);
226 struct ntlmssp_state *ntlmssp_state = gensec_ntlmssp->ntlmssp_state;
227 uint32_t chal_flags, ntlmssp_command, unkn1 = 0, unkn2 = 0;
228 DATA_BLOB server_domain_blob;
229 DATA_BLOB challenge_blob;
230 DATA_BLOB target_info = data_blob(NULL, 0);
231 char *server_domain;
232 const char *chal_parse_string;
233 const char *chal_parse_string_short = NULL;
234 const char *auth_gen_string;
235 DATA_BLOB lm_response = data_blob(NULL, 0);
236 DATA_BLOB nt_response = data_blob(NULL, 0);
237 DATA_BLOB session_key = data_blob(NULL, 0);
238 DATA_BLOB lm_session_key = data_blob(NULL, 0);
239 DATA_BLOB encrypted_session_key = data_blob(NULL, 0);
240 NTSTATUS nt_status;
241 int flags = 0;
242 const char *user = NULL, *domain = NULL, *workstation = NULL;
243 bool is_anonymous = false;
244 const DATA_BLOB version_blob = ntlmssp_version_blob();
245 const NTTIME *server_timestamp = NULL;
246 uint8_t mic_buffer[NTLMSSP_MIC_SIZE] = { 0, };
247 DATA_BLOB mic_blob = data_blob_const(mic_buffer, sizeof(mic_buffer));
248 HMACMD5Context ctx;
250 TALLOC_CTX *mem_ctx = talloc_new(out_mem_ctx);
251 if (!mem_ctx) {
252 return NT_STATUS_NO_MEMORY;
255 if (!msrpc_parse(mem_ctx,
256 &in, "CdBd",
257 "NTLMSSP",
258 &ntlmssp_command,
259 &server_domain_blob,
260 &chal_flags)) {
261 DEBUG(1, ("Failed to parse the NTLMSSP Challenge: (#1)\n"));
262 dump_data(2, in.data, in.length);
263 talloc_free(mem_ctx);
265 return NT_STATUS_INVALID_PARAMETER;
268 data_blob_free(&server_domain_blob);
270 DEBUG(3, ("Got challenge flags:\n"));
271 debug_ntlmssp_flags(chal_flags);
273 nt_status = ntlmssp_handle_neg_flags(ntlmssp_state,
274 chal_flags, "challenge");
275 if (!NT_STATUS_IS_OK(nt_status)) {
276 return nt_status;
279 if (ntlmssp_state->unicode) {
280 if (chal_flags & NTLMSSP_NEGOTIATE_TARGET_INFO) {
281 chal_parse_string = "CdUdbddB";
282 } else {
283 chal_parse_string = "CdUdbdd";
284 chal_parse_string_short = "CdUdb";
286 auth_gen_string = "CdBBUUUBdbb";
287 } else {
288 if (chal_flags & NTLMSSP_NEGOTIATE_TARGET_INFO) {
289 chal_parse_string = "CdAdbddB";
290 } else {
291 chal_parse_string = "CdAdbdd";
292 chal_parse_string_short = "CdAdb";
295 auth_gen_string = "CdBBAAABdbb";
298 if (!msrpc_parse(mem_ctx,
299 &in, chal_parse_string,
300 "NTLMSSP",
301 &ntlmssp_command,
302 &server_domain,
303 &chal_flags,
304 &challenge_blob, 8,
305 &unkn1, &unkn2,
306 &target_info)) {
308 bool ok = false;
310 DEBUG(1, ("Failed to parse the NTLMSSP Challenge: (#2)\n"));
312 if (chal_parse_string_short != NULL) {
314 * In the case where NTLMSSP_NEGOTIATE_TARGET_INFO
315 * is not used, some NTLMSSP servers don't return
316 * the unused unkn1 and unkn2 fields.
317 * See bug:
318 * https://bugzilla.samba.org/show_bug.cgi?id=10016
319 * for packet traces.
320 * Try and parse again without them.
322 ok = msrpc_parse(mem_ctx,
323 &in, chal_parse_string_short,
324 "NTLMSSP",
325 &ntlmssp_command,
326 &server_domain,
327 &chal_flags,
328 &challenge_blob, 8);
329 if (!ok) {
330 DEBUG(1, ("Failed to short parse "
331 "the NTLMSSP Challenge: (#2)\n"));
335 if (!ok) {
336 dump_data(2, in.data, in.length);
337 talloc_free(mem_ctx);
338 return NT_STATUS_INVALID_PARAMETER;
342 if (chal_flags & NTLMSSP_TARGET_TYPE_SERVER) {
343 ntlmssp_state->server.is_standalone = true;
344 } else {
345 ntlmssp_state->server.is_standalone = false;
347 /* TODO: parse struct_blob and fill in the rest */
348 ntlmssp_state->server.netbios_name = "";
349 ntlmssp_state->server.netbios_domain = talloc_move(ntlmssp_state, &server_domain);
350 ntlmssp_state->server.dns_name = "";
351 ntlmssp_state->server.dns_domain = "";
353 if (challenge_blob.length != 8) {
354 talloc_free(mem_ctx);
355 return NT_STATUS_INVALID_PARAMETER;
358 is_anonymous = cli_credentials_is_anonymous(gensec_security->credentials);
359 cli_credentials_get_ntlm_username_domain(gensec_security->credentials, mem_ctx,
360 &user, &domain);
362 workstation = cli_credentials_get_workstation(gensec_security->credentials);
364 if (user == NULL) {
365 DEBUG(10, ("User is NULL, returning INVALID_PARAMETER\n"));
366 return NT_STATUS_INVALID_PARAMETER;
369 if (domain == NULL) {
370 DEBUG(10, ("Domain is NULL, returning INVALID_PARAMETER\n"));
371 return NT_STATUS_INVALID_PARAMETER;
374 if (workstation == NULL) {
375 DEBUG(10, ("Workstation is NULL, returning INVALID_PARAMETER\n"));
376 return NT_STATUS_INVALID_PARAMETER;
379 if (is_anonymous) {
380 ntlmssp_state->neg_flags |= NTLMSSP_ANONYMOUS;
382 * don't use the ccache for anonymous auth
384 ntlmssp_state->use_ccache = false;
386 if (ntlmssp_state->use_ccache) {
387 struct samr_Password *nt_hash = NULL;
390 * If we have a password given we don't
391 * use the ccache
393 nt_hash = cli_credentials_get_nt_hash(gensec_security->credentials,
394 mem_ctx);
395 if (nt_hash != NULL) {
396 ZERO_STRUCTP(nt_hash);
397 TALLOC_FREE(nt_hash);
398 ntlmssp_state->use_ccache = false;
402 if (ntlmssp_state->use_ccache) {
403 struct wbcCredentialCacheParams params;
404 struct wbcCredentialCacheInfo *info = NULL;
405 struct wbcAuthErrorInfo *error = NULL;
406 struct wbcNamedBlob auth_blobs[2];
407 const struct wbcBlob *wbc_auth_blob = NULL;
408 const struct wbcBlob *wbc_session_key = NULL;
409 wbcErr wbc_status;
410 int i;
411 bool new_spnego = false;
413 params.account_name = user;
414 params.domain_name = domain;
415 params.level = WBC_CREDENTIAL_CACHE_LEVEL_NTLMSSP;
417 auth_blobs[0].name = "challenge_blob";
418 auth_blobs[0].flags = 0;
419 auth_blobs[0].blob.data = in.data;
420 auth_blobs[0].blob.length = in.length;
421 auth_blobs[1].name = "negotiate_blob";
422 auth_blobs[1].flags = 0;
423 auth_blobs[1].blob.data = ntlmssp_state->negotiate_blob.data;
424 auth_blobs[1].blob.length = ntlmssp_state->negotiate_blob.length;
425 params.num_blobs = ARRAY_SIZE(auth_blobs);
426 params.blobs = auth_blobs;
428 wbc_status = wbcCredentialCache(&params, &info, &error);
429 wbcFreeMemory(error);
430 if (!WBC_ERROR_IS_OK(wbc_status)) {
431 return NT_STATUS_WRONG_CREDENTIAL_HANDLE;
434 for (i=0; i<info->num_blobs; i++) {
435 if (strequal(info->blobs[i].name, "auth_blob")) {
436 wbc_auth_blob = &info->blobs[i].blob;
438 if (strequal(info->blobs[i].name, "session_key")) {
439 wbc_session_key = &info->blobs[i].blob;
441 if (strequal(info->blobs[i].name, "new_spnego")) {
442 new_spnego = true;
445 if ((wbc_auth_blob == NULL) || (wbc_session_key == NULL)) {
446 wbcFreeMemory(info);
447 return NT_STATUS_WRONG_CREDENTIAL_HANDLE;
450 session_key = data_blob_talloc(mem_ctx,
451 wbc_session_key->data,
452 wbc_session_key->length);
453 if (session_key.length != wbc_session_key->length) {
454 wbcFreeMemory(info);
455 return NT_STATUS_NO_MEMORY;
457 *out = data_blob_talloc(mem_ctx,
458 wbc_auth_blob->data,
459 wbc_auth_blob->length);
460 if (out->length != wbc_auth_blob->length) {
461 wbcFreeMemory(info);
462 return NT_STATUS_NO_MEMORY;
464 ntlmssp_state->new_spnego = new_spnego;
466 wbcFreeMemory(info);
467 goto done;
470 if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_NTLM2) {
471 flags |= CLI_CRED_NTLM2;
473 if (ntlmssp_state->use_ntlmv2) {
474 flags |= CLI_CRED_NTLMv2_AUTH;
476 if (ntlmssp_state->use_nt_response) {
477 flags |= CLI_CRED_NTLM_AUTH;
479 if (ntlmssp_state->allow_lm_response) {
480 flags |= CLI_CRED_LANMAN_AUTH;
483 if (target_info.length != 0 && !is_anonymous) {
484 struct AV_PAIR *pairs = NULL;
485 uint32_t count = 0;
486 enum ndr_err_code err;
487 struct AV_PAIR *timestamp = NULL;
488 struct AV_PAIR *eol = NULL;
489 uint32_t i = 0;
490 const char *service = NULL;
491 const char *hostname = NULL;
493 err = ndr_pull_struct_blob(&target_info,
494 ntlmssp_state,
495 &ntlmssp_state->server.av_pair_list,
496 (ndr_pull_flags_fn_t)ndr_pull_AV_PAIR_LIST);
497 if (!NDR_ERR_CODE_IS_SUCCESS(err)) {
498 return ndr_map_error2ntstatus(err);
501 count = ntlmssp_state->server.av_pair_list.count;
503 * We need room for Flags, SingleHost,
504 * ChannelBindings and Target
506 pairs = talloc_zero_array(ntlmssp_state, struct AV_PAIR,
507 count + 4);
508 if (pairs == NULL) {
509 return NT_STATUS_NO_MEMORY;
512 for (i = 0; i < count; i++) {
513 pairs[i] = ntlmssp_state->server.av_pair_list.pair[i];
516 ntlmssp_state->client.av_pair_list.count = count;
517 ntlmssp_state->client.av_pair_list.pair = pairs;
519 eol = ndr_ntlmssp_find_av(&ntlmssp_state->client.av_pair_list,
520 MsvAvEOL);
521 if (eol == NULL) {
522 return NT_STATUS_INVALID_PARAMETER;
525 timestamp = ndr_ntlmssp_find_av(&ntlmssp_state->client.av_pair_list,
526 MsvAvTimestamp);
527 if (timestamp != NULL) {
528 uint32_t sign_features =
529 GENSEC_FEATURE_SESSION_KEY |
530 GENSEC_FEATURE_SIGN |
531 GENSEC_FEATURE_SEAL;
533 server_timestamp = &timestamp->Value.AvTimestamp;
535 if (ntlmssp_state->force_old_spnego) {
536 sign_features = 0;
539 if (gensec_security->want_features & sign_features) {
540 struct AV_PAIR *av_flags = NULL;
542 av_flags = ndr_ntlmssp_find_av(&ntlmssp_state->client.av_pair_list,
543 MsvAvFlags);
544 if (av_flags == NULL) {
545 av_flags = eol;
546 eol++;
547 count++;
548 *eol = *av_flags;
549 av_flags->AvId = MsvAvFlags;
550 av_flags->Value.AvFlags = 0;
553 av_flags->Value.AvFlags |= NTLMSSP_AVFLAG_MIC_IN_AUTHENTICATE_MESSAGE;
554 ntlmssp_state->new_spnego = true;
559 struct AV_PAIR *SingleHost = NULL;
561 SingleHost = eol;
562 eol++;
563 count++;
564 *eol = *SingleHost;
567 * This is not really used, but we want to
568 * add some more random bytes and match
569 * Windows.
571 SingleHost->AvId = MsvAvSingleHost;
572 SingleHost->Value.AvSingleHost.token_info.Flags = 0;
573 SingleHost->Value.AvSingleHost.token_info.TokenIL = 0;
574 generate_random_buffer(SingleHost->Value.AvSingleHost.token_info.MachineId,
575 sizeof(SingleHost->Value.AvSingleHost.token_info.MachineId));
576 SingleHost->Value.AvSingleHost.remaining = data_blob_null;
580 struct AV_PAIR *ChannelBindings = NULL;
582 ChannelBindings = eol;
583 eol++;
584 count++;
585 *eol = *ChannelBindings;
588 * gensec doesn't support channel bindings yet,
589 * but we want to match Windows on the wire
591 ChannelBindings->AvId = MsvChannelBindings;
592 memset(ChannelBindings->Value.ChannelBindings, 0,
593 sizeof(ChannelBindings->Value.ChannelBindings));
596 service = gensec_get_target_service(gensec_security);
597 hostname = gensec_get_target_hostname(gensec_security);
598 if (service != NULL && hostname != NULL) {
599 struct AV_PAIR *target = NULL;
601 target = eol;
602 eol++;
603 count++;
604 *eol = *target;
606 target->AvId = MsvAvTargetName;
607 target->Value.AvTargetName = talloc_asprintf(pairs, "%s/%s",
608 service,
609 hostname);
610 if (target->Value.AvTargetName == NULL) {
611 return NT_STATUS_NO_MEMORY;
615 ntlmssp_state->client.av_pair_list.count = count;
616 ntlmssp_state->client.av_pair_list.pair = pairs;
618 err = ndr_push_struct_blob(&target_info,
619 ntlmssp_state,
620 &ntlmssp_state->client.av_pair_list,
621 (ndr_push_flags_fn_t)ndr_push_AV_PAIR_LIST);
622 if (!NDR_ERR_CODE_IS_SUCCESS(err)) {
623 return NT_STATUS_NO_MEMORY;
627 nt_status = cli_credentials_get_ntlm_response(gensec_security->credentials, mem_ctx,
628 &flags, challenge_blob,
629 server_timestamp, target_info,
630 &lm_response, &nt_response,
631 &lm_session_key, &session_key);
632 if (!NT_STATUS_IS_OK(nt_status)) {
633 return nt_status;
636 if (!(flags & CLI_CRED_LANMAN_AUTH)) {
637 /* LM Key is still possible, just silly, so we do not
638 * allow it. Fortunetly all LM crypto is off by
639 * default and we require command line options to end
640 * up here */
641 ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_LM_KEY;
644 if (!(flags & CLI_CRED_NTLM2)) {
645 /* NTLM2 is incompatible... */
646 ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_NTLM2;
649 if ((ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_LM_KEY)
650 && ntlmssp_state->allow_lm_key && lm_session_key.length == 16) {
651 DATA_BLOB new_session_key = data_blob_talloc(mem_ctx, NULL, 16);
652 if (lm_response.length == 24) {
653 SMBsesskeygen_lm_sess_key(lm_session_key.data, lm_response.data,
654 new_session_key.data);
655 } else {
656 static const uint8_t zeros[24];
657 SMBsesskeygen_lm_sess_key(lm_session_key.data, zeros,
658 new_session_key.data);
660 session_key = new_session_key;
661 dump_data_pw("LM session key\n", session_key.data, session_key.length);
665 /* Key exchange encryptes a new client-generated session key with
666 the password-derived key */
667 if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_KEY_EXCH) {
668 /* Make up a new session key */
669 uint8_t client_session_key[16];
670 generate_secret_buffer(client_session_key, sizeof(client_session_key));
672 /* Encrypt the new session key with the old one */
673 encrypted_session_key = data_blob_talloc(ntlmssp_state,
674 client_session_key, sizeof(client_session_key));
675 dump_data_pw("KEY_EXCH session key:\n", encrypted_session_key.data, encrypted_session_key.length);
676 arcfour_crypt(encrypted_session_key.data, session_key.data, encrypted_session_key.length);
677 dump_data_pw("KEY_EXCH session key (enc):\n", encrypted_session_key.data, encrypted_session_key.length);
679 /* Mark the new session key as the 'real' session key */
680 session_key = data_blob_talloc(mem_ctx, client_session_key, sizeof(client_session_key));
683 /* this generates the actual auth packet */
684 nt_status = msrpc_gen(mem_ctx,
685 out, auth_gen_string,
686 "NTLMSSP",
687 NTLMSSP_AUTH,
688 lm_response.data, lm_response.length,
689 nt_response.data, nt_response.length,
690 domain,
691 user,
692 workstation,
693 encrypted_session_key.data, encrypted_session_key.length,
694 ntlmssp_state->neg_flags,
695 version_blob.data, version_blob.length,
696 mic_blob.data, mic_blob.length);
697 if (!NT_STATUS_IS_OK(nt_status)) {
698 talloc_free(mem_ctx);
699 return nt_status;
703 * We always include the MIC, even without:
704 * av_flags->Value.AvFlags |= NTLMSSP_AVFLAG_MIC_IN_AUTHENTICATE_MESSAGE;
705 * ntlmssp_state->new_spnego = true;
707 * This matches a Windows client.
709 hmac_md5_init_limK_to_64(session_key.data,
710 session_key.length,
711 &ctx);
712 hmac_md5_update(ntlmssp_state->negotiate_blob.data,
713 ntlmssp_state->negotiate_blob.length,
714 &ctx);
715 hmac_md5_update(in.data, in.length, &ctx);
716 hmac_md5_update(out->data, out->length, &ctx);
717 hmac_md5_final(mic_buffer, &ctx);
718 memcpy(out->data + NTLMSSP_MIC_OFFSET, mic_buffer, NTLMSSP_MIC_SIZE);
720 done:
721 data_blob_free(&ntlmssp_state->negotiate_blob);
723 ntlmssp_state->session_key = session_key;
724 talloc_steal(ntlmssp_state, session_key.data);
726 DEBUG(3, ("NTLMSSP: Set final flags:\n"));
727 debug_ntlmssp_flags(ntlmssp_state->neg_flags);
729 talloc_steal(out_mem_ctx, out->data);
731 ntlmssp_state->expected_state = NTLMSSP_DONE;
733 if (gensec_ntlmssp_have_feature(gensec_security, GENSEC_FEATURE_SIGN)) {
734 nt_status = ntlmssp_sign_init(ntlmssp_state);
735 if (!NT_STATUS_IS_OK(nt_status)) {
736 DEBUG(1, ("Could not setup NTLMSSP signing/sealing system (error was: %s)\n",
737 nt_errstr(nt_status)));
738 talloc_free(mem_ctx);
739 return nt_status;
743 talloc_free(mem_ctx);
744 return NT_STATUS_OK;
747 NTSTATUS gensec_ntlmssp_client_start(struct gensec_security *gensec_security)
749 struct gensec_ntlmssp_context *gensec_ntlmssp;
750 struct ntlmssp_state *ntlmssp_state;
751 NTSTATUS nt_status;
753 nt_status = gensec_ntlmssp_start(gensec_security);
754 NT_STATUS_NOT_OK_RETURN(nt_status);
756 gensec_ntlmssp =
757 talloc_get_type_abort(gensec_security->private_data,
758 struct gensec_ntlmssp_context);
760 ntlmssp_state = talloc_zero(gensec_ntlmssp,
761 struct ntlmssp_state);
762 if (!ntlmssp_state) {
763 return NT_STATUS_NO_MEMORY;
766 gensec_ntlmssp->ntlmssp_state = ntlmssp_state;
768 ntlmssp_state = gensec_ntlmssp->ntlmssp_state;
770 ntlmssp_state->role = NTLMSSP_CLIENT;
772 ntlmssp_state->client.netbios_domain = lpcfg_workgroup(gensec_security->settings->lp_ctx);
773 ntlmssp_state->client.netbios_name = cli_credentials_get_workstation(gensec_security->credentials);
775 ntlmssp_state->unicode = gensec_setting_bool(gensec_security->settings, "ntlmssp_client", "unicode", true);
777 ntlmssp_state->use_nt_response = gensec_setting_bool(gensec_security->settings, "ntlmssp_client", "send_nt_reponse", true);
779 ntlmssp_state->allow_lm_response = lpcfg_client_lanman_auth(gensec_security->settings->lp_ctx);
781 ntlmssp_state->allow_lm_key = (ntlmssp_state->allow_lm_response
782 && (gensec_setting_bool(gensec_security->settings, "ntlmssp_client", "allow_lm_key", false)
783 || gensec_setting_bool(gensec_security->settings, "ntlmssp_client", "lm_key", false)));
785 ntlmssp_state->use_ntlmv2 = lpcfg_client_ntlmv2_auth(gensec_security->settings->lp_ctx);
787 ntlmssp_state->force_old_spnego = gensec_setting_bool(gensec_security->settings,
788 "ntlmssp_client", "force_old_spnego", false);
790 ntlmssp_state->expected_state = NTLMSSP_INITIAL;
792 ntlmssp_state->neg_flags =
793 NTLMSSP_NEGOTIATE_NTLM |
794 NTLMSSP_NEGOTIATE_VERSION |
795 NTLMSSP_REQUEST_TARGET;
797 if (ntlmssp_state->unicode) {
798 ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_UNICODE;
799 } else {
800 ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_OEM;
803 if (gensec_setting_bool(gensec_security->settings, "ntlmssp_client", "128bit", true)) {
804 ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_128;
807 if (gensec_setting_bool(gensec_security->settings, "ntlmssp_client", "56bit", false)) {
808 ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_56;
811 if (gensec_setting_bool(gensec_security->settings, "ntlmssp_client", "lm_key", false)) {
812 ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_LM_KEY;
815 if (gensec_setting_bool(gensec_security->settings, "ntlmssp_client", "keyexchange", true)) {
816 ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_KEY_EXCH;
819 if (gensec_setting_bool(gensec_security->settings, "ntlmssp_client", "alwayssign", true)) {
820 ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_ALWAYS_SIGN;
823 if (gensec_setting_bool(gensec_security->settings, "ntlmssp_client", "ntlm2", true)) {
824 ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_NTLM2;
825 } else {
826 /* apparently we can't do ntlmv2 if we don't do ntlm2 */
827 ntlmssp_state->use_ntlmv2 = false;
830 if (ntlmssp_state->use_ntlmv2) {
831 ntlmssp_state->required_flags |= NTLMSSP_NEGOTIATE_NTLM2;
832 ntlmssp_state->allow_lm_response = false;
833 ntlmssp_state->allow_lm_key = false;
836 if (ntlmssp_state->allow_lm_key) {
837 ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_LM_KEY;
840 if (gensec_security->want_features & GENSEC_FEATURE_SESSION_KEY) {
842 * We need to set this to allow a later SetPassword
843 * via the SAMR pipe to succeed. Strange.... We could
844 * also add NTLMSSP_NEGOTIATE_SEAL here. JRA.
846 * Without this, Windows will not create the master key
847 * that it thinks is only used for NTLMSSP signing and
848 * sealing. (It is actually pulled out and used directly)
850 * We don't require this here as some servers (e.g. NetAPP)
851 * doesn't support this.
853 ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SIGN;
855 if (gensec_security->want_features & GENSEC_FEATURE_SIGN) {
856 ntlmssp_state->required_flags |= NTLMSSP_NEGOTIATE_SIGN;
858 if (gensec_security->want_features & GENSEC_FEATURE_LDAP_STYLE) {
860 * We need to handle NTLMSSP_NEGOTIATE_SIGN as
861 * NTLMSSP_NEGOTIATE_SEAL if GENSEC_FEATURE_LDAP_STYLE
862 * is requested.
864 ntlmssp_state->force_wrap_seal = true;
866 * We want also work against old Samba servers
867 * which didn't had GENSEC_FEATURE_LDAP_STYLE
868 * we negotiate SEAL too. We may remove this
869 * in a few years. As all servers should have
870 * GENSEC_FEATURE_LDAP_STYLE by then.
872 ntlmssp_state->required_flags |= NTLMSSP_NEGOTIATE_SEAL;
875 if (gensec_security->want_features & GENSEC_FEATURE_SEAL) {
876 ntlmssp_state->required_flags |= NTLMSSP_NEGOTIATE_SIGN;
877 ntlmssp_state->required_flags |= NTLMSSP_NEGOTIATE_SEAL;
879 if (gensec_security->want_features & GENSEC_FEATURE_NTLM_CCACHE) {
880 ntlmssp_state->use_ccache = true;
883 ntlmssp_state->neg_flags |= ntlmssp_state->required_flags;
884 ntlmssp_state->conf_flags = ntlmssp_state->neg_flags;
886 return NT_STATUS_OK;
889 NTSTATUS gensec_ntlmssp_resume_ccache_start(struct gensec_security *gensec_security)
891 struct gensec_ntlmssp_context *gensec_ntlmssp = NULL;
892 NTSTATUS status;
894 status = gensec_ntlmssp_client_start(gensec_security);
895 if (!NT_STATUS_IS_OK(status)) {
896 return status;
899 gensec_ntlmssp = talloc_get_type_abort(gensec_security->private_data,
900 struct gensec_ntlmssp_context);
901 gensec_ntlmssp->ntlmssp_state->use_ccache = false;
902 gensec_ntlmssp->ntlmssp_state->resume_ccache = true;
903 gensec_ntlmssp->ntlmssp_state->expected_state = NTLMSSP_NEGOTIATE;
905 return NT_STATUS_OK;