auth/ntlmssp: add ntlmssp_client:ldap_style_send_seal option
[Samba.git] / auth / ntlmssp / ntlmssp_client.c
blob54fda41b534d50a8515cd29e349c852cef78ed50
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 #undef DBGC_CLASS
40 #define DBGC_CLASS DBGC_AUTH
42 /*********************************************************************
43 Client side NTLMSSP
44 *********************************************************************/
46 /**
47 * Next state function for the Initial packet
49 * @param ntlmssp_state NTLMSSP State
50 * @param out_mem_ctx The DATA_BLOB *out will be allocated on this context
51 * @param in A NULL data blob (input ignored)
52 * @param out The initial negotiate request to the server, as an talloc()ed DATA_BLOB, on out_mem_ctx
53 * @return Errors or NT_STATUS_OK.
56 NTSTATUS ntlmssp_client_initial(struct gensec_security *gensec_security,
57 TALLOC_CTX *out_mem_ctx,
58 DATA_BLOB in, DATA_BLOB *out)
60 struct gensec_ntlmssp_context *gensec_ntlmssp =
61 talloc_get_type_abort(gensec_security->private_data,
62 struct gensec_ntlmssp_context);
63 struct ntlmssp_state *ntlmssp_state = gensec_ntlmssp->ntlmssp_state;
64 NTSTATUS status;
65 const DATA_BLOB version_blob = ntlmssp_version_blob();
67 /* generate the ntlmssp negotiate packet */
68 status = msrpc_gen(out_mem_ctx,
69 out, "CddAAb",
70 "NTLMSSP",
71 NTLMSSP_NEGOTIATE,
72 ntlmssp_state->neg_flags,
73 "", /* domain */
74 "", /* workstation */
75 version_blob.data, version_blob.length);
76 if (!NT_STATUS_IS_OK(status)) {
77 DEBUG(0, ("ntlmssp_client_initial: failed to generate "
78 "ntlmssp negotiate packet\n"));
79 return status;
82 if (DEBUGLEVEL >= 10) {
83 struct NEGOTIATE_MESSAGE *negotiate = talloc(
84 ntlmssp_state, struct NEGOTIATE_MESSAGE);
85 if (negotiate != NULL) {
86 status = ntlmssp_pull_NEGOTIATE_MESSAGE(
87 out, negotiate, negotiate);
88 if (NT_STATUS_IS_OK(status)) {
89 NDR_PRINT_DEBUG(NEGOTIATE_MESSAGE,
90 negotiate);
92 TALLOC_FREE(negotiate);
96 ntlmssp_state->negotiate_blob = data_blob_dup_talloc(ntlmssp_state,
97 *out);
98 if (ntlmssp_state->negotiate_blob.length != out->length) {
99 return NT_STATUS_NO_MEMORY;
102 ntlmssp_state->expected_state = NTLMSSP_CHALLENGE;
104 return NT_STATUS_MORE_PROCESSING_REQUIRED;
107 NTSTATUS gensec_ntlmssp_resume_ccache(struct gensec_security *gensec_security,
108 TALLOC_CTX *out_mem_ctx,
109 DATA_BLOB in, DATA_BLOB *out)
111 struct gensec_ntlmssp_context *gensec_ntlmssp =
112 talloc_get_type_abort(gensec_security->private_data,
113 struct gensec_ntlmssp_context);
114 struct ntlmssp_state *ntlmssp_state = gensec_ntlmssp->ntlmssp_state;
115 uint32_t neg_flags = 0;
116 uint32_t ntlmssp_command;
117 NTSTATUS status;
118 bool ok;
120 *out = data_blob_null;
122 if (in.length == 0) {
124 * This is compat code for older callers
125 * which were missing the "initial_blob"/"negotiate_blob".
127 * That means we can't calculate the NTLMSSP_MIC
128 * field correctly and need to force the
129 * old_spnego behaviour.
131 DEBUG(10, ("%s: in.length==%u force_old_spnego!\n",
132 __func__, (unsigned int)in.length));
133 ntlmssp_state->force_old_spnego = true;
134 ntlmssp_state->neg_flags |= ntlmssp_state->required_flags;
135 ntlmssp_state->required_flags = 0;
136 ntlmssp_state->expected_state = NTLMSSP_CHALLENGE;
137 return NT_STATUS_MORE_PROCESSING_REQUIRED;
140 /* parse the NTLMSSP packet */
142 if (in.length > UINT16_MAX) {
143 DEBUG(1, ("%s: reject large request of length %u\n",
144 __func__, (unsigned int)in.length));
145 return NT_STATUS_INVALID_PARAMETER;
148 ok = msrpc_parse(ntlmssp_state, &in, "Cdd",
149 "NTLMSSP",
150 &ntlmssp_command,
151 &neg_flags);
152 if (!ok) {
153 DEBUG(1, ("%s: failed to parse NTLMSSP Negotiate of length %u\n",
154 __func__, (unsigned int)in.length));
155 dump_data(2, in.data, in.length);
156 return NT_STATUS_INVALID_PARAMETER;
159 if (ntlmssp_command != NTLMSSP_NEGOTIATE) {
160 DEBUG(1, ("%s: no NTLMSSP Negotiate message (length %u)\n",
161 __func__, (unsigned int)in.length));
162 dump_data(2, in.data, in.length);
163 return NT_STATUS_INVALID_PARAMETER;
166 ntlmssp_state->neg_flags = neg_flags;
167 DEBUG(3, ("Imported Negotiate flags:\n"));
168 debug_ntlmssp_flags(neg_flags);
170 if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_UNICODE) {
171 ntlmssp_state->unicode = true;
172 } else {
173 ntlmssp_state->unicode = false;
176 if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_SIGN) {
177 gensec_security->want_features |= GENSEC_FEATURE_SIGN;
180 if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_SEAL) {
181 gensec_security->want_features |= GENSEC_FEATURE_SEAL;
184 ntlmssp_state->conf_flags = ntlmssp_state->neg_flags;
185 ntlmssp_state->required_flags = 0;
187 if (DEBUGLEVEL >= 10) {
188 struct NEGOTIATE_MESSAGE *negotiate = talloc(
189 ntlmssp_state, struct NEGOTIATE_MESSAGE);
190 if (negotiate != NULL) {
191 status = ntlmssp_pull_NEGOTIATE_MESSAGE(
192 &in, negotiate, negotiate);
193 if (NT_STATUS_IS_OK(status)) {
194 NDR_PRINT_DEBUG(NEGOTIATE_MESSAGE,
195 negotiate);
197 TALLOC_FREE(negotiate);
201 ntlmssp_state->negotiate_blob = data_blob_dup_talloc(ntlmssp_state,
202 in);
203 if (ntlmssp_state->negotiate_blob.length != in.length) {
204 return NT_STATUS_NO_MEMORY;
207 ntlmssp_state->expected_state = NTLMSSP_CHALLENGE;
209 return NT_STATUS_MORE_PROCESSING_REQUIRED;
213 * Next state function for the Challenge Packet. Generate an auth packet.
215 * @param gensec_security GENSEC state
216 * @param out_mem_ctx Memory context for *out
217 * @param in The server challnege, as a DATA_BLOB. reply.data must be NULL
218 * @param out The next request (auth packet) to the server, as an allocated DATA_BLOB, on the out_mem_ctx context
219 * @return Errors or NT_STATUS_OK.
222 NTSTATUS ntlmssp_client_challenge(struct gensec_security *gensec_security,
223 TALLOC_CTX *out_mem_ctx,
224 const DATA_BLOB in, DATA_BLOB *out)
226 struct gensec_ntlmssp_context *gensec_ntlmssp =
227 talloc_get_type_abort(gensec_security->private_data,
228 struct gensec_ntlmssp_context);
229 struct ntlmssp_state *ntlmssp_state = gensec_ntlmssp->ntlmssp_state;
230 uint32_t chal_flags, ntlmssp_command, unkn1 = 0, unkn2 = 0;
231 DATA_BLOB server_domain_blob;
232 DATA_BLOB challenge_blob;
233 DATA_BLOB target_info = data_blob(NULL, 0);
234 char *server_domain;
235 const char *chal_parse_string;
236 const char *chal_parse_string_short = NULL;
237 const char *auth_gen_string;
238 DATA_BLOB lm_response = data_blob(NULL, 0);
239 DATA_BLOB nt_response = data_blob(NULL, 0);
240 DATA_BLOB session_key = data_blob(NULL, 0);
241 DATA_BLOB lm_session_key = data_blob(NULL, 0);
242 DATA_BLOB encrypted_session_key = data_blob(NULL, 0);
243 NTSTATUS nt_status;
244 int flags = 0;
245 const char *user = NULL, *domain = NULL, *workstation = NULL;
246 bool is_anonymous = false;
247 const DATA_BLOB version_blob = ntlmssp_version_blob();
248 const NTTIME *server_timestamp = NULL;
249 uint8_t mic_buffer[NTLMSSP_MIC_SIZE] = { 0, };
250 DATA_BLOB mic_blob = data_blob_const(mic_buffer, sizeof(mic_buffer));
251 HMACMD5Context ctx;
253 TALLOC_CTX *mem_ctx = talloc_new(out_mem_ctx);
254 if (!mem_ctx) {
255 return NT_STATUS_NO_MEMORY;
258 if (!msrpc_parse(mem_ctx,
259 &in, "CdBd",
260 "NTLMSSP",
261 &ntlmssp_command,
262 &server_domain_blob,
263 &chal_flags)) {
264 DEBUG(1, ("Failed to parse the NTLMSSP Challenge: (#1)\n"));
265 dump_data(2, in.data, in.length);
266 talloc_free(mem_ctx);
268 return NT_STATUS_INVALID_PARAMETER;
271 data_blob_free(&server_domain_blob);
273 DEBUG(3, ("Got challenge flags:\n"));
274 debug_ntlmssp_flags(chal_flags);
276 nt_status = ntlmssp_handle_neg_flags(ntlmssp_state,
277 chal_flags, "challenge");
278 if (!NT_STATUS_IS_OK(nt_status)) {
279 return nt_status;
282 if (ntlmssp_state->unicode) {
283 if (chal_flags & NTLMSSP_NEGOTIATE_TARGET_INFO) {
284 chal_parse_string = "CdUdbddB";
285 } else {
286 chal_parse_string = "CdUdbdd";
287 chal_parse_string_short = "CdUdb";
289 auth_gen_string = "CdBBUUUBdbb";
290 } else {
291 if (chal_flags & NTLMSSP_NEGOTIATE_TARGET_INFO) {
292 chal_parse_string = "CdAdbddB";
293 } else {
294 chal_parse_string = "CdAdbdd";
295 chal_parse_string_short = "CdAdb";
298 auth_gen_string = "CdBBAAABdbb";
301 if (!msrpc_parse(mem_ctx,
302 &in, chal_parse_string,
303 "NTLMSSP",
304 &ntlmssp_command,
305 &server_domain,
306 &chal_flags,
307 &challenge_blob, 8,
308 &unkn1, &unkn2,
309 &target_info)) {
311 bool ok = false;
313 DEBUG(1, ("Failed to parse the NTLMSSP Challenge: (#2)\n"));
315 if (chal_parse_string_short != NULL) {
317 * In the case where NTLMSSP_NEGOTIATE_TARGET_INFO
318 * is not used, some NTLMSSP servers don't return
319 * the unused unkn1 and unkn2 fields.
320 * See bug:
321 * https://bugzilla.samba.org/show_bug.cgi?id=10016
322 * for packet traces.
323 * Try and parse again without them.
325 ok = msrpc_parse(mem_ctx,
326 &in, chal_parse_string_short,
327 "NTLMSSP",
328 &ntlmssp_command,
329 &server_domain,
330 &chal_flags,
331 &challenge_blob, 8);
332 if (!ok) {
333 DEBUG(1, ("Failed to short parse "
334 "the NTLMSSP Challenge: (#2)\n"));
338 if (!ok) {
339 dump_data(2, in.data, in.length);
340 talloc_free(mem_ctx);
341 return NT_STATUS_INVALID_PARAMETER;
345 if (chal_flags & NTLMSSP_TARGET_TYPE_SERVER) {
346 ntlmssp_state->server.is_standalone = true;
347 } else {
348 ntlmssp_state->server.is_standalone = false;
350 /* TODO: parse struct_blob and fill in the rest */
351 ntlmssp_state->server.netbios_name = "";
352 ntlmssp_state->server.netbios_domain = talloc_move(ntlmssp_state, &server_domain);
353 ntlmssp_state->server.dns_name = "";
354 ntlmssp_state->server.dns_domain = "";
356 if (challenge_blob.length != 8) {
357 talloc_free(mem_ctx);
358 return NT_STATUS_INVALID_PARAMETER;
361 is_anonymous = cli_credentials_is_anonymous(gensec_security->credentials);
362 cli_credentials_get_ntlm_username_domain(gensec_security->credentials, mem_ctx,
363 &user, &domain);
365 workstation = cli_credentials_get_workstation(gensec_security->credentials);
367 if (user == NULL) {
368 DEBUG(10, ("User is NULL, returning INVALID_PARAMETER\n"));
369 return NT_STATUS_INVALID_PARAMETER;
372 if (domain == NULL) {
373 DEBUG(10, ("Domain is NULL, returning INVALID_PARAMETER\n"));
374 return NT_STATUS_INVALID_PARAMETER;
377 if (workstation == NULL) {
378 DEBUG(10, ("Workstation is NULL, returning INVALID_PARAMETER\n"));
379 return NT_STATUS_INVALID_PARAMETER;
382 if (is_anonymous) {
383 ntlmssp_state->neg_flags |= NTLMSSP_ANONYMOUS;
385 * don't use the ccache for anonymous auth
387 ntlmssp_state->use_ccache = false;
389 if (ntlmssp_state->use_ccache) {
390 struct samr_Password *nt_hash = NULL;
393 * If we have a password given we don't
394 * use the ccache
396 nt_hash = cli_credentials_get_nt_hash(gensec_security->credentials,
397 mem_ctx);
398 if (nt_hash != NULL) {
399 ZERO_STRUCTP(nt_hash);
400 TALLOC_FREE(nt_hash);
401 ntlmssp_state->use_ccache = false;
405 if (ntlmssp_state->use_ccache) {
406 struct wbcCredentialCacheParams params;
407 struct wbcCredentialCacheInfo *info = NULL;
408 struct wbcAuthErrorInfo *error = NULL;
409 struct wbcNamedBlob auth_blobs[2];
410 const struct wbcBlob *wbc_auth_blob = NULL;
411 const struct wbcBlob *wbc_session_key = NULL;
412 wbcErr wbc_status;
413 int i;
414 bool new_spnego = false;
416 params.account_name = user;
417 params.domain_name = domain;
418 params.level = WBC_CREDENTIAL_CACHE_LEVEL_NTLMSSP;
420 auth_blobs[0].name = "challenge_blob";
421 auth_blobs[0].flags = 0;
422 auth_blobs[0].blob.data = in.data;
423 auth_blobs[0].blob.length = in.length;
424 auth_blobs[1].name = "negotiate_blob";
425 auth_blobs[1].flags = 0;
426 auth_blobs[1].blob.data = ntlmssp_state->negotiate_blob.data;
427 auth_blobs[1].blob.length = ntlmssp_state->negotiate_blob.length;
428 params.num_blobs = ARRAY_SIZE(auth_blobs);
429 params.blobs = auth_blobs;
431 wbc_status = wbcCredentialCache(&params, &info, &error);
432 wbcFreeMemory(error);
433 if (!WBC_ERROR_IS_OK(wbc_status)) {
434 return NT_STATUS_WRONG_CREDENTIAL_HANDLE;
437 for (i=0; i<info->num_blobs; i++) {
438 if (strequal(info->blobs[i].name, "auth_blob")) {
439 wbc_auth_blob = &info->blobs[i].blob;
441 if (strequal(info->blobs[i].name, "session_key")) {
442 wbc_session_key = &info->blobs[i].blob;
444 if (strequal(info->blobs[i].name, "new_spnego")) {
445 new_spnego = true;
448 if ((wbc_auth_blob == NULL) || (wbc_session_key == NULL)) {
449 wbcFreeMemory(info);
450 return NT_STATUS_WRONG_CREDENTIAL_HANDLE;
453 session_key = data_blob_talloc(mem_ctx,
454 wbc_session_key->data,
455 wbc_session_key->length);
456 if (session_key.length != wbc_session_key->length) {
457 wbcFreeMemory(info);
458 return NT_STATUS_NO_MEMORY;
460 *out = data_blob_talloc(mem_ctx,
461 wbc_auth_blob->data,
462 wbc_auth_blob->length);
463 if (out->length != wbc_auth_blob->length) {
464 wbcFreeMemory(info);
465 return NT_STATUS_NO_MEMORY;
467 ntlmssp_state->new_spnego = new_spnego;
469 wbcFreeMemory(info);
470 goto done;
473 if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_NTLM2) {
474 flags |= CLI_CRED_NTLM2;
476 if (ntlmssp_state->use_ntlmv2) {
477 flags |= CLI_CRED_NTLMv2_AUTH;
479 if (ntlmssp_state->use_nt_response) {
480 flags |= CLI_CRED_NTLM_AUTH;
482 if (ntlmssp_state->allow_lm_response) {
483 flags |= CLI_CRED_LANMAN_AUTH;
486 if (target_info.length != 0 && !is_anonymous) {
487 struct AV_PAIR *pairs = NULL;
488 uint32_t count = 0;
489 enum ndr_err_code err;
490 struct AV_PAIR *timestamp = NULL;
491 struct AV_PAIR *eol = NULL;
492 uint32_t i = 0;
493 const char *service = NULL;
494 const char *hostname = NULL;
496 err = ndr_pull_struct_blob(&target_info,
497 ntlmssp_state,
498 &ntlmssp_state->server.av_pair_list,
499 (ndr_pull_flags_fn_t)ndr_pull_AV_PAIR_LIST);
500 if (!NDR_ERR_CODE_IS_SUCCESS(err)) {
501 return ndr_map_error2ntstatus(err);
504 count = ntlmssp_state->server.av_pair_list.count;
506 * We need room for Flags, SingleHost,
507 * ChannelBindings and Target
509 pairs = talloc_zero_array(ntlmssp_state, struct AV_PAIR,
510 count + 4);
511 if (pairs == NULL) {
512 return NT_STATUS_NO_MEMORY;
515 for (i = 0; i < count; i++) {
516 pairs[i] = ntlmssp_state->server.av_pair_list.pair[i];
519 ntlmssp_state->client.av_pair_list.count = count;
520 ntlmssp_state->client.av_pair_list.pair = pairs;
522 eol = ndr_ntlmssp_find_av(&ntlmssp_state->client.av_pair_list,
523 MsvAvEOL);
524 if (eol == NULL) {
525 return NT_STATUS_INVALID_PARAMETER;
528 timestamp = ndr_ntlmssp_find_av(&ntlmssp_state->client.av_pair_list,
529 MsvAvTimestamp);
530 if (timestamp != NULL) {
531 uint32_t sign_features =
532 GENSEC_FEATURE_SESSION_KEY |
533 GENSEC_FEATURE_SIGN |
534 GENSEC_FEATURE_SEAL;
536 server_timestamp = &timestamp->Value.AvTimestamp;
538 if (ntlmssp_state->force_old_spnego) {
539 sign_features = 0;
542 if (gensec_security->want_features & sign_features) {
543 struct AV_PAIR *av_flags = NULL;
545 av_flags = ndr_ntlmssp_find_av(&ntlmssp_state->client.av_pair_list,
546 MsvAvFlags);
547 if (av_flags == NULL) {
548 av_flags = eol;
549 eol++;
550 count++;
551 *eol = *av_flags;
552 av_flags->AvId = MsvAvFlags;
553 av_flags->Value.AvFlags = 0;
556 av_flags->Value.AvFlags |= NTLMSSP_AVFLAG_MIC_IN_AUTHENTICATE_MESSAGE;
557 ntlmssp_state->new_spnego = true;
562 struct AV_PAIR *SingleHost = NULL;
564 SingleHost = eol;
565 eol++;
566 count++;
567 *eol = *SingleHost;
570 * This is not really used, but we want to
571 * add some more random bytes and match
572 * Windows.
574 SingleHost->AvId = MsvAvSingleHost;
575 SingleHost->Value.AvSingleHost.token_info.Flags = 0;
576 SingleHost->Value.AvSingleHost.token_info.TokenIL = 0;
577 generate_random_buffer(SingleHost->Value.AvSingleHost.token_info.MachineId,
578 sizeof(SingleHost->Value.AvSingleHost.token_info.MachineId));
579 SingleHost->Value.AvSingleHost.remaining = data_blob_null;
583 struct AV_PAIR *ChannelBindings = NULL;
585 ChannelBindings = eol;
586 eol++;
587 count++;
588 *eol = *ChannelBindings;
591 * gensec doesn't support channel bindings yet,
592 * but we want to match Windows on the wire
594 ChannelBindings->AvId = MsvChannelBindings;
595 memset(ChannelBindings->Value.ChannelBindings, 0,
596 sizeof(ChannelBindings->Value.ChannelBindings));
599 service = gensec_get_target_service(gensec_security);
600 hostname = gensec_get_target_hostname(gensec_security);
601 if (service != NULL && hostname != NULL) {
602 struct AV_PAIR *target = NULL;
604 target = eol;
605 eol++;
606 count++;
607 *eol = *target;
609 target->AvId = MsvAvTargetName;
610 target->Value.AvTargetName = talloc_asprintf(pairs, "%s/%s",
611 service,
612 hostname);
613 if (target->Value.AvTargetName == NULL) {
614 return NT_STATUS_NO_MEMORY;
618 ntlmssp_state->client.av_pair_list.count = count;
619 ntlmssp_state->client.av_pair_list.pair = pairs;
621 err = ndr_push_struct_blob(&target_info,
622 ntlmssp_state,
623 &ntlmssp_state->client.av_pair_list,
624 (ndr_push_flags_fn_t)ndr_push_AV_PAIR_LIST);
625 if (!NDR_ERR_CODE_IS_SUCCESS(err)) {
626 return NT_STATUS_NO_MEMORY;
630 nt_status = cli_credentials_get_ntlm_response(gensec_security->credentials, mem_ctx,
631 &flags, challenge_blob,
632 server_timestamp, target_info,
633 &lm_response, &nt_response,
634 &lm_session_key, &session_key);
635 if (!NT_STATUS_IS_OK(nt_status)) {
636 return nt_status;
639 if (!(flags & CLI_CRED_LANMAN_AUTH)) {
640 /* LM Key is still possible, just silly, so we do not
641 * allow it. Fortunetly all LM crypto is off by
642 * default and we require command line options to end
643 * up here */
644 ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_LM_KEY;
647 if (!(flags & CLI_CRED_NTLM2)) {
648 /* NTLM2 is incompatible... */
649 ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_NTLM2;
652 if ((ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_LM_KEY)
653 && ntlmssp_state->allow_lm_key && lm_session_key.length == 16) {
654 DATA_BLOB new_session_key = data_blob_talloc(mem_ctx, NULL, 16);
655 if (lm_response.length == 24) {
656 SMBsesskeygen_lm_sess_key(lm_session_key.data, lm_response.data,
657 new_session_key.data);
658 } else {
659 static const uint8_t zeros[24];
660 SMBsesskeygen_lm_sess_key(lm_session_key.data, zeros,
661 new_session_key.data);
663 session_key = new_session_key;
664 dump_data_pw("LM session key\n", session_key.data, session_key.length);
668 /* Key exchange encryptes a new client-generated session key with
669 the password-derived key */
670 if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_KEY_EXCH) {
671 /* Make up a new session key */
672 uint8_t client_session_key[16];
673 generate_secret_buffer(client_session_key, sizeof(client_session_key));
675 /* Encrypt the new session key with the old one */
676 encrypted_session_key = data_blob_talloc(ntlmssp_state,
677 client_session_key, sizeof(client_session_key));
678 dump_data_pw("KEY_EXCH session key:\n", encrypted_session_key.data, encrypted_session_key.length);
679 arcfour_crypt(encrypted_session_key.data, session_key.data, encrypted_session_key.length);
680 dump_data_pw("KEY_EXCH session key (enc):\n", encrypted_session_key.data, encrypted_session_key.length);
682 /* Mark the new session key as the 'real' session key */
683 session_key = data_blob_talloc(mem_ctx, client_session_key, sizeof(client_session_key));
686 /* this generates the actual auth packet */
687 nt_status = msrpc_gen(mem_ctx,
688 out, auth_gen_string,
689 "NTLMSSP",
690 NTLMSSP_AUTH,
691 lm_response.data, lm_response.length,
692 nt_response.data, nt_response.length,
693 domain,
694 user,
695 workstation,
696 encrypted_session_key.data, encrypted_session_key.length,
697 ntlmssp_state->neg_flags,
698 version_blob.data, version_blob.length,
699 mic_blob.data, mic_blob.length);
700 if (!NT_STATUS_IS_OK(nt_status)) {
701 talloc_free(mem_ctx);
702 return nt_status;
706 * We always include the MIC, even without:
707 * av_flags->Value.AvFlags |= NTLMSSP_AVFLAG_MIC_IN_AUTHENTICATE_MESSAGE;
708 * ntlmssp_state->new_spnego = true;
710 * This matches a Windows client.
712 hmac_md5_init_limK_to_64(session_key.data,
713 session_key.length,
714 &ctx);
715 hmac_md5_update(ntlmssp_state->negotiate_blob.data,
716 ntlmssp_state->negotiate_blob.length,
717 &ctx);
718 hmac_md5_update(in.data, in.length, &ctx);
719 hmac_md5_update(out->data, out->length, &ctx);
720 hmac_md5_final(mic_buffer, &ctx);
721 memcpy(out->data + NTLMSSP_MIC_OFFSET, mic_buffer, NTLMSSP_MIC_SIZE);
723 done:
724 data_blob_free(&ntlmssp_state->negotiate_blob);
726 ntlmssp_state->session_key = session_key;
727 talloc_steal(ntlmssp_state, session_key.data);
729 DEBUG(3, ("NTLMSSP: Set final flags:\n"));
730 debug_ntlmssp_flags(ntlmssp_state->neg_flags);
732 talloc_steal(out_mem_ctx, out->data);
734 ntlmssp_state->expected_state = NTLMSSP_DONE;
736 if (gensec_ntlmssp_have_feature(gensec_security, GENSEC_FEATURE_SIGN)) {
737 nt_status = ntlmssp_sign_init(ntlmssp_state);
738 if (!NT_STATUS_IS_OK(nt_status)) {
739 DEBUG(1, ("Could not setup NTLMSSP signing/sealing system (error was: %s)\n",
740 nt_errstr(nt_status)));
741 talloc_free(mem_ctx);
742 return nt_status;
746 talloc_free(mem_ctx);
747 return NT_STATUS_OK;
750 NTSTATUS gensec_ntlmssp_client_start(struct gensec_security *gensec_security)
752 struct gensec_ntlmssp_context *gensec_ntlmssp;
753 struct ntlmssp_state *ntlmssp_state;
754 NTSTATUS nt_status;
756 nt_status = gensec_ntlmssp_start(gensec_security);
757 NT_STATUS_NOT_OK_RETURN(nt_status);
759 gensec_ntlmssp =
760 talloc_get_type_abort(gensec_security->private_data,
761 struct gensec_ntlmssp_context);
763 ntlmssp_state = talloc_zero(gensec_ntlmssp,
764 struct ntlmssp_state);
765 if (!ntlmssp_state) {
766 return NT_STATUS_NO_MEMORY;
769 gensec_ntlmssp->ntlmssp_state = ntlmssp_state;
771 ntlmssp_state = gensec_ntlmssp->ntlmssp_state;
773 ntlmssp_state->role = NTLMSSP_CLIENT;
775 ntlmssp_state->client.netbios_domain = lpcfg_workgroup(gensec_security->settings->lp_ctx);
776 ntlmssp_state->client.netbios_name = cli_credentials_get_workstation(gensec_security->credentials);
778 ntlmssp_state->unicode = gensec_setting_bool(gensec_security->settings, "ntlmssp_client", "unicode", true);
780 ntlmssp_state->use_nt_response = gensec_setting_bool(gensec_security->settings, "ntlmssp_client", "send_nt_reponse", true);
782 ntlmssp_state->allow_lm_response = lpcfg_client_lanman_auth(gensec_security->settings->lp_ctx);
784 ntlmssp_state->allow_lm_key = (ntlmssp_state->allow_lm_response
785 && (gensec_setting_bool(gensec_security->settings, "ntlmssp_client", "allow_lm_key", false)
786 || gensec_setting_bool(gensec_security->settings, "ntlmssp_client", "lm_key", false)));
788 ntlmssp_state->use_ntlmv2 = lpcfg_client_ntlmv2_auth(gensec_security->settings->lp_ctx);
790 ntlmssp_state->force_old_spnego = gensec_setting_bool(gensec_security->settings,
791 "ntlmssp_client", "force_old_spnego", false);
793 ntlmssp_state->expected_state = NTLMSSP_INITIAL;
795 ntlmssp_state->neg_flags =
796 NTLMSSP_NEGOTIATE_NTLM |
797 NTLMSSP_NEGOTIATE_VERSION |
798 NTLMSSP_REQUEST_TARGET;
800 if (ntlmssp_state->unicode) {
801 ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_UNICODE;
802 } else {
803 ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_OEM;
806 if (gensec_setting_bool(gensec_security->settings, "ntlmssp_client", "128bit", true)) {
807 ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_128;
810 if (gensec_setting_bool(gensec_security->settings, "ntlmssp_client", "56bit", false)) {
811 ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_56;
814 if (gensec_setting_bool(gensec_security->settings, "ntlmssp_client", "lm_key", false)) {
815 ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_LM_KEY;
818 if (gensec_setting_bool(gensec_security->settings, "ntlmssp_client", "keyexchange", true)) {
819 ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_KEY_EXCH;
822 if (gensec_setting_bool(gensec_security->settings, "ntlmssp_client", "alwayssign", true)) {
823 ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_ALWAYS_SIGN;
826 if (gensec_setting_bool(gensec_security->settings, "ntlmssp_client", "ntlm2", true)) {
827 ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_NTLM2;
828 } else {
829 /* apparently we can't do ntlmv2 if we don't do ntlm2 */
830 ntlmssp_state->use_ntlmv2 = false;
833 if (ntlmssp_state->use_ntlmv2) {
834 ntlmssp_state->required_flags |= NTLMSSP_NEGOTIATE_NTLM2;
835 ntlmssp_state->allow_lm_response = false;
836 ntlmssp_state->allow_lm_key = false;
839 if (ntlmssp_state->allow_lm_key) {
840 ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_LM_KEY;
843 if (gensec_security->want_features & GENSEC_FEATURE_SESSION_KEY) {
845 * We need to set this to allow a later SetPassword
846 * via the SAMR pipe to succeed. Strange.... We could
847 * also add NTLMSSP_NEGOTIATE_SEAL here. JRA.
849 * Without this, Windows will not create the master key
850 * that it thinks is only used for NTLMSSP signing and
851 * sealing. (It is actually pulled out and used directly)
853 * We don't require this here as some servers (e.g. NetAPP)
854 * doesn't support this.
856 ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SIGN;
858 if (gensec_security->want_features & GENSEC_FEATURE_SIGN) {
859 ntlmssp_state->required_flags |= NTLMSSP_NEGOTIATE_SIGN;
861 if (gensec_security->want_features & GENSEC_FEATURE_LDAP_STYLE) {
863 * We need to handle NTLMSSP_NEGOTIATE_SIGN as
864 * NTLMSSP_NEGOTIATE_SEAL if GENSEC_FEATURE_LDAP_STYLE
865 * is requested.
867 ntlmssp_state->force_wrap_seal = true;
870 if (ntlmssp_state->force_wrap_seal) {
871 bool ret;
874 * We want also work against old Samba servers
875 * which didn't had GENSEC_FEATURE_LDAP_STYLE
876 * we negotiate SEAL too. We may remove this
877 * in a few years. As all servers should have
878 * GENSEC_FEATURE_LDAP_STYLE by then.
880 ret = gensec_setting_bool(gensec_security->settings,
881 "ntlmssp_client",
882 "ldap_style_send_seal",
883 true);
884 if (ret) {
885 ntlmssp_state->required_flags |= NTLMSSP_NEGOTIATE_SEAL;
888 if (gensec_security->want_features & GENSEC_FEATURE_SEAL) {
889 ntlmssp_state->required_flags |= NTLMSSP_NEGOTIATE_SIGN;
890 ntlmssp_state->required_flags |= NTLMSSP_NEGOTIATE_SEAL;
892 if (gensec_security->want_features & GENSEC_FEATURE_NTLM_CCACHE) {
893 ntlmssp_state->use_ccache = true;
896 ntlmssp_state->neg_flags |= ntlmssp_state->required_flags;
897 ntlmssp_state->conf_flags = ntlmssp_state->neg_flags;
899 return NT_STATUS_OK;
902 NTSTATUS gensec_ntlmssp_resume_ccache_start(struct gensec_security *gensec_security)
904 struct gensec_ntlmssp_context *gensec_ntlmssp = NULL;
905 NTSTATUS status;
907 status = gensec_ntlmssp_client_start(gensec_security);
908 if (!NT_STATUS_IS_OK(status)) {
909 return status;
912 gensec_ntlmssp = talloc_get_type_abort(gensec_security->private_data,
913 struct gensec_ntlmssp_context);
914 gensec_ntlmssp->ntlmssp_state->use_ccache = false;
915 gensec_ntlmssp->ntlmssp_state->resume_ccache = true;
916 gensec_ntlmssp->ntlmssp_state->expected_state = NTLMSSP_NEGOTIATE;
918 return NT_STATUS_OK;