s3: libsmb: In cli_qpathinfo_send() (SMBtrans2:TRANSACT2_QPATHINFO) check for DFS...
[Samba.git] / auth / ntlmssp / ntlmssp_client.c
blobaf1642d325665590209b082f7b8f9b41272e849d
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 "../libcli/auth/libcli_auth.h"
29 #include "auth/credentials/credentials.h"
30 #include "auth/gensec/gensec.h"
31 #include "auth/gensec/gensec_internal.h"
32 #include "param/param.h"
33 #include "auth/ntlmssp/ntlmssp_private.h"
34 #include "../librpc/gen_ndr/ndr_ntlmssp.h"
35 #include "../auth/ntlmssp/ntlmssp_ndr.h"
36 #include "../nsswitch/libwbclient/wbclient.h"
38 #include "lib/crypto/gnutls_helpers.h"
39 #include <gnutls/gnutls.h>
40 #include <gnutls/crypto.h>
42 #undef DBGC_CLASS
43 #define DBGC_CLASS DBGC_AUTH
45 /*********************************************************************
46 Client side NTLMSSP
47 *********************************************************************/
49 /**
50 * Next state function for the Initial packet
52 * @param ntlmssp_state NTLMSSP State
53 * @param out_mem_ctx The DATA_BLOB *out will be allocated on this context
54 * @param in A NULL data blob (input ignored)
55 * @param out The initial negotiate request to the server, as an talloc()ed DATA_BLOB, on out_mem_ctx
56 * @return Errors or NT_STATUS_OK.
59 NTSTATUS ntlmssp_client_initial(struct gensec_security *gensec_security,
60 TALLOC_CTX *out_mem_ctx,
61 DATA_BLOB in, DATA_BLOB *out)
63 struct gensec_ntlmssp_context *gensec_ntlmssp =
64 talloc_get_type_abort(gensec_security->private_data,
65 struct gensec_ntlmssp_context);
66 struct ntlmssp_state *ntlmssp_state = gensec_ntlmssp->ntlmssp_state;
67 NTSTATUS status;
68 const DATA_BLOB version_blob = ntlmssp_version_blob();
70 /* generate the ntlmssp negotiate packet */
71 status = msrpc_gen(out_mem_ctx,
72 out, "CddAAb",
73 "NTLMSSP",
74 NTLMSSP_NEGOTIATE,
75 ntlmssp_state->neg_flags,
76 "", /* domain */
77 "", /* workstation */
78 version_blob.data, version_blob.length);
79 if (!NT_STATUS_IS_OK(status)) {
80 DEBUG(0, ("ntlmssp_client_initial: failed to generate "
81 "ntlmssp negotiate packet\n"));
82 return status;
85 if (DEBUGLEVEL >= 10) {
86 struct NEGOTIATE_MESSAGE *negotiate = talloc(
87 ntlmssp_state, struct NEGOTIATE_MESSAGE);
88 if (negotiate != NULL) {
89 status = ntlmssp_pull_NEGOTIATE_MESSAGE(
90 out, negotiate, negotiate);
91 if (NT_STATUS_IS_OK(status)) {
92 NDR_PRINT_DEBUG(NEGOTIATE_MESSAGE,
93 negotiate);
95 TALLOC_FREE(negotiate);
99 ntlmssp_state->negotiate_blob = data_blob_dup_talloc(ntlmssp_state,
100 *out);
101 if (ntlmssp_state->negotiate_blob.length != out->length) {
102 return NT_STATUS_NO_MEMORY;
105 ntlmssp_state->expected_state = NTLMSSP_CHALLENGE;
107 return NT_STATUS_MORE_PROCESSING_REQUIRED;
110 NTSTATUS gensec_ntlmssp_resume_ccache(struct gensec_security *gensec_security,
111 TALLOC_CTX *out_mem_ctx,
112 DATA_BLOB in, DATA_BLOB *out)
114 struct gensec_ntlmssp_context *gensec_ntlmssp =
115 talloc_get_type_abort(gensec_security->private_data,
116 struct gensec_ntlmssp_context);
117 struct ntlmssp_state *ntlmssp_state = gensec_ntlmssp->ntlmssp_state;
118 uint32_t neg_flags = 0;
119 uint32_t ntlmssp_command;
120 NTSTATUS status;
121 bool ok;
123 *out = data_blob_null;
125 if (in.length == 0) {
127 * This is compat code for older callers
128 * which were missing the "initial_blob"/"negotiate_blob".
130 * That means we can't calculate the NTLMSSP_MIC
131 * field correctly and need to force the
132 * old_spnego behaviour.
134 DEBUG(10, ("%s: in.length==%u force_old_spnego!\n",
135 __func__, (unsigned int)in.length));
136 ntlmssp_state->force_old_spnego = true;
137 ntlmssp_state->neg_flags |= ntlmssp_state->required_flags;
138 ntlmssp_state->required_flags = 0;
139 ntlmssp_state->expected_state = NTLMSSP_CHALLENGE;
140 return NT_STATUS_MORE_PROCESSING_REQUIRED;
143 /* parse the NTLMSSP packet */
145 if (in.length > UINT16_MAX) {
146 DEBUG(1, ("%s: reject large request of length %u\n",
147 __func__, (unsigned int)in.length));
148 return NT_STATUS_INVALID_PARAMETER;
151 ok = msrpc_parse(ntlmssp_state, &in, "Cdd",
152 "NTLMSSP",
153 &ntlmssp_command,
154 &neg_flags);
155 if (!ok) {
156 DEBUG(1, ("%s: failed to parse NTLMSSP Negotiate of length %u\n",
157 __func__, (unsigned int)in.length));
158 dump_data(2, in.data, in.length);
159 return NT_STATUS_INVALID_PARAMETER;
162 if (ntlmssp_command != NTLMSSP_NEGOTIATE) {
163 DEBUG(1, ("%s: no NTLMSSP Negotiate message (length %u)\n",
164 __func__, (unsigned int)in.length));
165 dump_data(2, in.data, in.length);
166 return NT_STATUS_INVALID_PARAMETER;
169 ntlmssp_state->neg_flags = neg_flags;
170 DEBUG(3, ("Imported Negotiate flags:\n"));
171 debug_ntlmssp_flags(neg_flags);
173 if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_UNICODE) {
174 ntlmssp_state->unicode = true;
175 } else {
176 ntlmssp_state->unicode = false;
179 if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_SIGN) {
180 gensec_security->want_features |= GENSEC_FEATURE_SIGN;
183 if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_SEAL) {
184 gensec_security->want_features |= GENSEC_FEATURE_SEAL;
187 ntlmssp_state->conf_flags = ntlmssp_state->neg_flags;
188 ntlmssp_state->required_flags = 0;
190 if (DEBUGLEVEL >= 10) {
191 struct NEGOTIATE_MESSAGE *negotiate = talloc(
192 ntlmssp_state, struct NEGOTIATE_MESSAGE);
193 if (negotiate != NULL) {
194 status = ntlmssp_pull_NEGOTIATE_MESSAGE(
195 &in, negotiate, negotiate);
196 if (NT_STATUS_IS_OK(status)) {
197 NDR_PRINT_DEBUG(NEGOTIATE_MESSAGE,
198 negotiate);
200 TALLOC_FREE(negotiate);
204 ntlmssp_state->negotiate_blob = data_blob_dup_talloc(ntlmssp_state,
205 in);
206 if (ntlmssp_state->negotiate_blob.length != in.length) {
207 return NT_STATUS_NO_MEMORY;
210 ntlmssp_state->expected_state = NTLMSSP_CHALLENGE;
212 return NT_STATUS_MORE_PROCESSING_REQUIRED;
216 * Next state function for the Challenge Packet. Generate an auth packet.
218 * @param gensec_security GENSEC state
219 * @param out_mem_ctx Memory context for *out
220 * @param in The server challnege, as a DATA_BLOB. reply.data must be NULL
221 * @param out The next request (auth packet) to the server, as an allocated DATA_BLOB, on the out_mem_ctx context
222 * @return Errors or NT_STATUS_OK.
225 NTSTATUS ntlmssp_client_challenge(struct gensec_security *gensec_security,
226 TALLOC_CTX *out_mem_ctx,
227 const DATA_BLOB in, DATA_BLOB *out)
229 struct gensec_ntlmssp_context *gensec_ntlmssp =
230 talloc_get_type_abort(gensec_security->private_data,
231 struct gensec_ntlmssp_context);
232 struct ntlmssp_state *ntlmssp_state = gensec_ntlmssp->ntlmssp_state;
233 uint32_t chal_flags, ntlmssp_command, unkn1 = 0, unkn2 = 0;
234 DATA_BLOB server_domain_blob;
235 DATA_BLOB challenge_blob;
236 DATA_BLOB target_info = data_blob(NULL, 0);
237 char *server_domain;
238 const char *chal_parse_string;
239 const char *chal_parse_string_short = NULL;
240 const char *auth_gen_string;
241 DATA_BLOB lm_response = data_blob(NULL, 0);
242 DATA_BLOB nt_response = data_blob(NULL, 0);
243 DATA_BLOB session_key = data_blob(NULL, 0);
244 DATA_BLOB lm_session_key = data_blob(NULL, 0);
245 DATA_BLOB encrypted_session_key = data_blob(NULL, 0);
246 NTSTATUS nt_status;
247 int flags = 0;
248 const char *user = NULL, *domain = NULL, *workstation = NULL;
249 bool is_anonymous = false;
250 const DATA_BLOB version_blob = ntlmssp_version_blob();
251 const NTTIME *server_timestamp = NULL;
252 uint8_t mic_buffer[NTLMSSP_MIC_SIZE] = { 0, };
253 DATA_BLOB mic_blob = data_blob_const(mic_buffer, sizeof(mic_buffer));
254 gnutls_hmac_hd_t hmac_hnd = NULL;
255 int rc;
257 TALLOC_CTX *mem_ctx = talloc_new(out_mem_ctx);
258 if (!mem_ctx) {
259 return NT_STATUS_NO_MEMORY;
262 if (!msrpc_parse(mem_ctx,
263 &in, "CdBd",
264 "NTLMSSP",
265 &ntlmssp_command,
266 &server_domain_blob,
267 &chal_flags)) {
268 DEBUG(1, ("Failed to parse the NTLMSSP Challenge: (#1)\n"));
269 dump_data(2, in.data, in.length);
270 talloc_free(mem_ctx);
272 return NT_STATUS_INVALID_PARAMETER;
275 data_blob_free(&server_domain_blob);
277 DEBUG(3, ("Got challenge flags:\n"));
278 debug_ntlmssp_flags(chal_flags);
280 nt_status = ntlmssp_handle_neg_flags(ntlmssp_state,
281 chal_flags, "challenge");
282 if (!NT_STATUS_IS_OK(nt_status)) {
283 return nt_status;
286 if (ntlmssp_state->unicode) {
287 if (chal_flags & NTLMSSP_NEGOTIATE_TARGET_INFO) {
288 chal_parse_string = "CdUdbddB";
289 } else {
290 chal_parse_string = "CdUdbdd";
291 chal_parse_string_short = "CdUdb";
293 auth_gen_string = "CdBBUUUBdbb";
294 } else {
295 if (chal_flags & NTLMSSP_NEGOTIATE_TARGET_INFO) {
296 chal_parse_string = "CdAdbddB";
297 } else {
298 chal_parse_string = "CdAdbdd";
299 chal_parse_string_short = "CdAdb";
302 auth_gen_string = "CdBBAAABdbb";
305 if (!msrpc_parse(mem_ctx,
306 &in, chal_parse_string,
307 "NTLMSSP",
308 &ntlmssp_command,
309 &server_domain,
310 &chal_flags,
311 &challenge_blob, 8,
312 &unkn1, &unkn2,
313 &target_info)) {
315 bool ok = false;
317 DEBUG(1, ("Failed to parse the NTLMSSP Challenge: (#2)\n"));
319 if (chal_parse_string_short != NULL) {
321 * In the case where NTLMSSP_NEGOTIATE_TARGET_INFO
322 * is not used, some NTLMSSP servers don't return
323 * the unused unkn1 and unkn2 fields.
324 * See bug:
325 * https://bugzilla.samba.org/show_bug.cgi?id=10016
326 * for packet traces.
327 * Try and parse again without them.
329 ok = msrpc_parse(mem_ctx,
330 &in, chal_parse_string_short,
331 "NTLMSSP",
332 &ntlmssp_command,
333 &server_domain,
334 &chal_flags,
335 &challenge_blob, 8);
336 if (!ok) {
337 DEBUG(1, ("Failed to short parse "
338 "the NTLMSSP Challenge: (#2)\n"));
342 if (!ok) {
343 dump_data(2, in.data, in.length);
344 talloc_free(mem_ctx);
345 return NT_STATUS_INVALID_PARAMETER;
349 if (DEBUGLEVEL >= 10) {
350 struct CHALLENGE_MESSAGE *challenge =
351 talloc(ntlmssp_state, struct CHALLENGE_MESSAGE);
352 if (challenge != NULL) {
353 NTSTATUS status;
354 challenge->NegotiateFlags = chal_flags;
355 status = ntlmssp_pull_CHALLENGE_MESSAGE(
356 &in, challenge, challenge);
357 if (NT_STATUS_IS_OK(status)) {
358 NDR_PRINT_DEBUG(CHALLENGE_MESSAGE,
359 challenge);
361 TALLOC_FREE(challenge);
365 if (chal_flags & NTLMSSP_TARGET_TYPE_SERVER) {
366 ntlmssp_state->server.is_standalone = true;
367 } else {
368 ntlmssp_state->server.is_standalone = false;
370 /* TODO: parse struct_blob and fill in the rest */
371 ntlmssp_state->server.netbios_name = "";
372 ntlmssp_state->server.netbios_domain = talloc_move(ntlmssp_state, &server_domain);
373 ntlmssp_state->server.dns_name = "";
374 ntlmssp_state->server.dns_domain = "";
376 if (challenge_blob.length != 8) {
377 talloc_free(mem_ctx);
378 return NT_STATUS_INVALID_PARAMETER;
381 is_anonymous = cli_credentials_is_anonymous(gensec_security->credentials);
382 cli_credentials_get_ntlm_username_domain(gensec_security->credentials, mem_ctx,
383 &user, &domain);
385 workstation = cli_credentials_get_workstation(gensec_security->credentials);
387 if (user == NULL) {
388 DEBUG(10, ("User is NULL, returning INVALID_PARAMETER\n"));
389 return NT_STATUS_INVALID_PARAMETER;
392 if (domain == NULL) {
393 DEBUG(10, ("Domain is NULL, returning INVALID_PARAMETER\n"));
394 return NT_STATUS_INVALID_PARAMETER;
397 if (workstation == NULL) {
398 DEBUG(10, ("Workstation is NULL, returning INVALID_PARAMETER\n"));
399 return NT_STATUS_INVALID_PARAMETER;
402 if (is_anonymous) {
403 ntlmssp_state->neg_flags |= NTLMSSP_ANONYMOUS;
405 * don't use the ccache for anonymous auth
407 ntlmssp_state->use_ccache = false;
409 if (ntlmssp_state->use_ccache) {
410 struct samr_Password *nt_hash = NULL;
413 * If we have a password given we don't
414 * use the ccache
416 nt_hash = cli_credentials_get_nt_hash(gensec_security->credentials,
417 mem_ctx);
418 if (nt_hash != NULL) {
419 ZERO_STRUCTP(nt_hash);
420 TALLOC_FREE(nt_hash);
421 ntlmssp_state->use_ccache = false;
425 if (ntlmssp_state->use_ccache) {
426 struct wbcCredentialCacheParams params;
427 struct wbcCredentialCacheInfo *info = NULL;
428 struct wbcAuthErrorInfo *error = NULL;
429 struct wbcNamedBlob auth_blobs[2];
430 const struct wbcBlob *wbc_auth_blob = NULL;
431 const struct wbcBlob *wbc_session_key = NULL;
432 wbcErr wbc_status;
433 size_t i;
434 bool new_spnego = false;
436 params.account_name = user;
437 params.domain_name = domain;
438 params.level = WBC_CREDENTIAL_CACHE_LEVEL_NTLMSSP;
440 auth_blobs[0].name = "challenge_blob";
441 auth_blobs[0].flags = 0;
442 auth_blobs[0].blob.data = in.data;
443 auth_blobs[0].blob.length = in.length;
444 auth_blobs[1].name = "negotiate_blob";
445 auth_blobs[1].flags = 0;
446 auth_blobs[1].blob.data = ntlmssp_state->negotiate_blob.data;
447 auth_blobs[1].blob.length = ntlmssp_state->negotiate_blob.length;
448 params.num_blobs = ARRAY_SIZE(auth_blobs);
449 params.blobs = auth_blobs;
451 wbc_status = wbcCredentialCache(&params, &info, &error);
452 wbcFreeMemory(error);
453 if (!WBC_ERROR_IS_OK(wbc_status)) {
454 return NT_STATUS_WRONG_CREDENTIAL_HANDLE;
457 for (i=0; i<info->num_blobs; i++) {
458 if (strequal(info->blobs[i].name, "auth_blob")) {
459 wbc_auth_blob = &info->blobs[i].blob;
461 if (strequal(info->blobs[i].name, "session_key")) {
462 wbc_session_key = &info->blobs[i].blob;
464 if (strequal(info->blobs[i].name, "new_spnego")) {
465 new_spnego = true;
468 if ((wbc_auth_blob == NULL) || (wbc_session_key == NULL)) {
469 wbcFreeMemory(info);
470 return NT_STATUS_WRONG_CREDENTIAL_HANDLE;
473 session_key = data_blob_talloc(mem_ctx,
474 wbc_session_key->data,
475 wbc_session_key->length);
476 if (session_key.length != wbc_session_key->length) {
477 wbcFreeMemory(info);
478 return NT_STATUS_NO_MEMORY;
480 *out = data_blob_talloc(mem_ctx,
481 wbc_auth_blob->data,
482 wbc_auth_blob->length);
483 if (out->length != wbc_auth_blob->length) {
484 wbcFreeMemory(info);
485 return NT_STATUS_NO_MEMORY;
487 ntlmssp_state->new_spnego = new_spnego;
489 wbcFreeMemory(info);
490 goto done;
493 if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_NTLM2) {
494 flags |= CLI_CRED_NTLM2;
496 if (ntlmssp_state->use_ntlmv2) {
497 flags |= CLI_CRED_NTLMv2_AUTH;
499 if (ntlmssp_state->use_nt_response) {
500 flags |= CLI_CRED_NTLM_AUTH;
502 if (ntlmssp_state->allow_lm_response) {
503 flags |= CLI_CRED_LANMAN_AUTH;
506 if (target_info.length != 0 && !is_anonymous) {
507 struct AV_PAIR *pairs = NULL;
508 uint32_t count = 0;
509 enum ndr_err_code err;
510 struct AV_PAIR *timestamp = NULL;
511 struct AV_PAIR *eol = NULL;
512 uint32_t i = 0;
513 const char *service = NULL;
514 const char *hostname = NULL;
516 err = ndr_pull_struct_blob(&target_info,
517 ntlmssp_state,
518 &ntlmssp_state->server.av_pair_list,
519 (ndr_pull_flags_fn_t)ndr_pull_AV_PAIR_LIST);
520 if (!NDR_ERR_CODE_IS_SUCCESS(err)) {
521 return ndr_map_error2ntstatus(err);
524 count = ntlmssp_state->server.av_pair_list.count;
526 * We need room for Flags, SingleHost,
527 * ChannelBindings and Target
529 pairs = talloc_zero_array(ntlmssp_state, struct AV_PAIR,
530 count + 4);
531 if (pairs == NULL) {
532 return NT_STATUS_NO_MEMORY;
535 for (i = 0; i < count; i++) {
536 pairs[i] = ntlmssp_state->server.av_pair_list.pair[i];
539 ntlmssp_state->client.av_pair_list.count = count;
540 ntlmssp_state->client.av_pair_list.pair = pairs;
542 eol = ndr_ntlmssp_find_av(&ntlmssp_state->client.av_pair_list,
543 MsvAvEOL);
544 if (eol == NULL) {
545 return NT_STATUS_INVALID_PARAMETER;
548 timestamp = ndr_ntlmssp_find_av(&ntlmssp_state->client.av_pair_list,
549 MsvAvTimestamp);
550 if (timestamp != NULL) {
551 uint32_t sign_features =
552 GENSEC_FEATURE_SESSION_KEY |
553 GENSEC_FEATURE_SIGN |
554 GENSEC_FEATURE_SEAL;
556 server_timestamp = &timestamp->Value.AvTimestamp;
558 if (ntlmssp_state->force_old_spnego) {
559 sign_features = 0;
562 if (gensec_security->want_features & sign_features) {
563 struct AV_PAIR *av_flags = NULL;
565 av_flags = ndr_ntlmssp_find_av(&ntlmssp_state->client.av_pair_list,
566 MsvAvFlags);
567 if (av_flags == NULL) {
568 av_flags = eol;
569 eol++;
570 count++;
571 *eol = *av_flags;
572 av_flags->AvId = MsvAvFlags;
573 av_flags->Value.AvFlags = 0;
576 av_flags->Value.AvFlags |= NTLMSSP_AVFLAG_MIC_IN_AUTHENTICATE_MESSAGE;
577 ntlmssp_state->new_spnego = true;
582 struct AV_PAIR *SingleHost = NULL;
584 SingleHost = eol;
585 eol++;
586 count++;
587 *eol = *SingleHost;
590 * This is not really used, but we want to
591 * add some more random bytes and match
592 * Windows.
594 SingleHost->AvId = MsvAvSingleHost;
595 SingleHost->Value.AvSingleHost.token_info.Flags = 0;
596 SingleHost->Value.AvSingleHost.token_info.TokenIL = 0;
597 generate_random_buffer(SingleHost->Value.AvSingleHost.token_info.MachineId,
598 sizeof(SingleHost->Value.AvSingleHost.token_info.MachineId));
599 SingleHost->Value.AvSingleHost.remaining = data_blob_null;
603 struct AV_PAIR *ChannelBindings = NULL;
605 ChannelBindings = eol;
606 eol++;
607 count++;
608 *eol = *ChannelBindings;
611 * gensec doesn't support channel bindings yet,
612 * but we want to match Windows on the wire
614 ChannelBindings->AvId = MsvChannelBindings;
615 memset(ChannelBindings->Value.ChannelBindings, 0,
616 sizeof(ChannelBindings->Value.ChannelBindings));
619 service = gensec_get_target_service(gensec_security);
620 hostname = gensec_get_target_hostname(gensec_security);
621 if (service != NULL && hostname != NULL) {
622 struct AV_PAIR *target = NULL;
624 target = eol;
625 eol++;
626 count++;
627 *eol = *target;
629 target->AvId = MsvAvTargetName;
630 target->Value.AvTargetName = talloc_asprintf(pairs, "%s/%s",
631 service,
632 hostname);
633 if (target->Value.AvTargetName == NULL) {
634 return NT_STATUS_NO_MEMORY;
638 ntlmssp_state->client.av_pair_list.count = count;
639 ntlmssp_state->client.av_pair_list.pair = pairs;
641 err = ndr_push_struct_blob(&target_info,
642 ntlmssp_state,
643 &ntlmssp_state->client.av_pair_list,
644 (ndr_push_flags_fn_t)ndr_push_AV_PAIR_LIST);
645 if (!NDR_ERR_CODE_IS_SUCCESS(err)) {
646 return NT_STATUS_NO_MEMORY;
650 nt_status = cli_credentials_get_ntlm_response(gensec_security->credentials, mem_ctx,
651 &flags, challenge_blob,
652 server_timestamp, target_info,
653 &lm_response, &nt_response,
654 &lm_session_key, &session_key);
655 if (!NT_STATUS_IS_OK(nt_status)) {
656 return nt_status;
659 if (!(flags & CLI_CRED_LANMAN_AUTH)) {
660 /* LM Key is still possible, just silly, so we do not
661 * allow it. Fortunetly all LM crypto is off by
662 * default and we require command line options to end
663 * up here */
664 ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_LM_KEY;
667 if (!(flags & CLI_CRED_NTLM2)) {
668 /* NTLM2 is incompatible... */
669 ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_NTLM2;
672 if ((ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_LM_KEY)
673 && ntlmssp_state->allow_lm_key && lm_session_key.length == 16) {
674 DATA_BLOB new_session_key = data_blob_talloc(mem_ctx, NULL, 16);
675 if (lm_response.length == 24) {
676 nt_status = SMBsesskeygen_lm_sess_key(lm_session_key.data,
677 lm_response.data,
678 new_session_key.data);
679 if (!NT_STATUS_IS_OK(nt_status)) {
680 return nt_status;
682 } else {
683 static const uint8_t zeros[24];
684 nt_status = SMBsesskeygen_lm_sess_key(lm_session_key.data,
685 zeros,
686 new_session_key.data);
687 if (!NT_STATUS_IS_OK(nt_status)) {
688 return nt_status;
691 session_key = new_session_key;
692 dump_data_pw("LM session key\n", session_key.data, session_key.length);
696 /* Key exchange encryptes a new client-generated session key with
697 the password-derived key */
698 if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_KEY_EXCH) {
699 /* Make up a new session key */
700 uint8_t client_session_key[16];
701 gnutls_cipher_hd_t cipher_hnd;
702 gnutls_datum_t enc_session_key = {
703 .data = session_key.data,
704 .size = session_key.length,
707 generate_random_buffer(client_session_key, sizeof(client_session_key));
709 /* Encrypt the new session key with the old one */
710 encrypted_session_key = data_blob_talloc(ntlmssp_state,
711 client_session_key, sizeof(client_session_key));
712 dump_data_pw("KEY_EXCH session key:\n", encrypted_session_key.data, encrypted_session_key.length);
714 rc = gnutls_cipher_init(&cipher_hnd,
715 GNUTLS_CIPHER_ARCFOUR_128,
716 &enc_session_key,
717 NULL);
718 if (rc < 0) {
719 nt_status = gnutls_error_to_ntstatus(rc, NT_STATUS_NTLM_BLOCKED);
720 ZERO_ARRAY(client_session_key);
721 goto done;
723 rc = gnutls_cipher_encrypt(cipher_hnd,
724 encrypted_session_key.data,
725 encrypted_session_key.length);
726 gnutls_cipher_deinit(cipher_hnd);
727 if (rc < 0) {
728 nt_status = gnutls_error_to_ntstatus(rc, NT_STATUS_NTLM_BLOCKED);
729 ZERO_ARRAY(client_session_key);
730 goto done;
733 dump_data_pw("KEY_EXCH session key (enc):\n", encrypted_session_key.data, encrypted_session_key.length);
735 /* Mark the new session key as the 'real' session key */
736 session_key = data_blob_talloc(mem_ctx, client_session_key, sizeof(client_session_key));
737 ZERO_ARRAY(client_session_key);
740 /* this generates the actual auth packet */
741 nt_status = msrpc_gen(mem_ctx,
742 out, auth_gen_string,
743 "NTLMSSP",
744 NTLMSSP_AUTH,
745 lm_response.data, lm_response.length,
746 nt_response.data, nt_response.length,
747 domain,
748 user,
749 workstation,
750 encrypted_session_key.data, encrypted_session_key.length,
751 ntlmssp_state->neg_flags,
752 version_blob.data, version_blob.length,
753 mic_blob.data, mic_blob.length);
754 if (!NT_STATUS_IS_OK(nt_status)) {
755 talloc_free(mem_ctx);
756 return nt_status;
759 if (DEBUGLEVEL >= 10) {
760 struct AUTHENTICATE_MESSAGE *authenticate =
761 talloc(ntlmssp_state, struct AUTHENTICATE_MESSAGE);
762 if (authenticate != NULL) {
763 NTSTATUS status;
764 authenticate->NegotiateFlags = ntlmssp_state->neg_flags;
765 status = ntlmssp_pull_AUTHENTICATE_MESSAGE(
766 out, authenticate, authenticate);
767 if (NT_STATUS_IS_OK(status)) {
768 NDR_PRINT_DEBUG(AUTHENTICATE_MESSAGE,
769 authenticate);
771 TALLOC_FREE(authenticate);
776 * We always include the MIC, even without:
777 * av_flags->Value.AvFlags |= NTLMSSP_AVFLAG_MIC_IN_AUTHENTICATE_MESSAGE;
778 * ntlmssp_state->new_spnego = true;
780 * This matches a Windows client.
782 rc = gnutls_hmac_init(&hmac_hnd,
783 GNUTLS_MAC_MD5,
784 session_key.data,
785 MIN(session_key.length, 64));
786 if (rc < 0) {
787 nt_status = gnutls_error_to_ntstatus(rc, NT_STATUS_NTLM_BLOCKED);
788 goto done;
791 rc = gnutls_hmac(hmac_hnd,
792 ntlmssp_state->negotiate_blob.data,
793 ntlmssp_state->negotiate_blob.length);
794 if (rc < 0) {
795 gnutls_hmac_deinit(hmac_hnd, NULL);
796 nt_status = gnutls_error_to_ntstatus(rc, NT_STATUS_NTLM_BLOCKED);
797 goto done;
799 rc = gnutls_hmac(hmac_hnd, in.data, in.length);
800 if (rc < 0) {
801 gnutls_hmac_deinit(hmac_hnd, NULL);
802 nt_status = gnutls_error_to_ntstatus(rc, NT_STATUS_NTLM_BLOCKED);
803 goto done;
805 rc = gnutls_hmac(hmac_hnd, out->data, out->length);
806 if (rc < 0) {
807 gnutls_hmac_deinit(hmac_hnd, NULL);
808 nt_status = gnutls_error_to_ntstatus(rc, NT_STATUS_NTLM_BLOCKED);
809 goto done;
812 gnutls_hmac_deinit(hmac_hnd, mic_buffer);
814 memcpy(out->data + NTLMSSP_MIC_OFFSET, mic_buffer, NTLMSSP_MIC_SIZE);
815 ZERO_ARRAY(mic_buffer);
817 nt_status = NT_STATUS_OK;
818 done:
819 ZERO_ARRAY_LEN(ntlmssp_state->negotiate_blob.data,
820 ntlmssp_state->negotiate_blob.length);
821 data_blob_free(&ntlmssp_state->negotiate_blob);
823 ntlmssp_state->session_key = session_key;
824 talloc_steal(ntlmssp_state, session_key.data);
826 DEBUG(3, ("NTLMSSP: Set final flags:\n"));
827 debug_ntlmssp_flags(ntlmssp_state->neg_flags);
829 talloc_steal(out_mem_ctx, out->data);
831 ntlmssp_state->expected_state = NTLMSSP_DONE;
833 if (gensec_ntlmssp_have_feature(gensec_security, GENSEC_FEATURE_SIGN)) {
834 nt_status = ntlmssp_sign_init(ntlmssp_state);
835 if (!NT_STATUS_IS_OK(nt_status)) {
836 DEBUG(1, ("Could not setup NTLMSSP signing/sealing system (error was: %s)\n",
837 nt_errstr(nt_status)));
838 talloc_free(mem_ctx);
839 return nt_status;
843 talloc_free(mem_ctx);
844 return nt_status;
847 NTSTATUS gensec_ntlmssp_client_start(struct gensec_security *gensec_security)
849 struct gensec_ntlmssp_context *gensec_ntlmssp;
850 struct ntlmssp_state *ntlmssp_state;
851 NTSTATUS nt_status;
853 nt_status = gensec_ntlmssp_start(gensec_security);
854 NT_STATUS_NOT_OK_RETURN(nt_status);
856 gensec_ntlmssp =
857 talloc_get_type_abort(gensec_security->private_data,
858 struct gensec_ntlmssp_context);
860 ntlmssp_state = talloc_zero(gensec_ntlmssp,
861 struct ntlmssp_state);
862 if (!ntlmssp_state) {
863 return NT_STATUS_NO_MEMORY;
866 gensec_ntlmssp->ntlmssp_state = ntlmssp_state;
868 ntlmssp_state = gensec_ntlmssp->ntlmssp_state;
870 ntlmssp_state->role = NTLMSSP_CLIENT;
872 ntlmssp_state->client.netbios_domain = lpcfg_workgroup(gensec_security->settings->lp_ctx);
873 ntlmssp_state->client.netbios_name = cli_credentials_get_workstation(gensec_security->credentials);
875 ntlmssp_state->unicode = gensec_setting_bool(gensec_security->settings, "ntlmssp_client", "unicode", true);
877 ntlmssp_state->use_nt_response = \
878 gensec_setting_bool(gensec_security->settings,
879 "ntlmssp_client",
880 "send_nt_response",
881 true);
883 ntlmssp_state->allow_lm_response = lpcfg_client_lanman_auth(gensec_security->settings->lp_ctx);
885 ntlmssp_state->allow_lm_key = (ntlmssp_state->allow_lm_response
886 && (gensec_setting_bool(gensec_security->settings, "ntlmssp_client", "allow_lm_key", false)
887 || gensec_setting_bool(gensec_security->settings, "ntlmssp_client", "lm_key", false)));
889 ntlmssp_state->use_ntlmv2 = lpcfg_client_ntlmv2_auth(gensec_security->settings->lp_ctx);
891 ntlmssp_state->force_old_spnego = gensec_setting_bool(gensec_security->settings,
892 "ntlmssp_client", "force_old_spnego", false);
894 ntlmssp_state->expected_state = NTLMSSP_INITIAL;
896 ntlmssp_state->neg_flags =
897 NTLMSSP_NEGOTIATE_NTLM |
898 NTLMSSP_NEGOTIATE_VERSION |
899 NTLMSSP_REQUEST_TARGET;
901 if (ntlmssp_state->unicode) {
902 ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_UNICODE;
903 } else {
904 ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_OEM;
907 if (gensec_setting_bool(gensec_security->settings, "ntlmssp_client", "128bit", true)) {
908 ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_128;
911 if (gensec_setting_bool(gensec_security->settings, "ntlmssp_client", "56bit", false)) {
912 ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_56;
915 if (gensec_setting_bool(gensec_security->settings, "ntlmssp_client", "lm_key", false)) {
916 ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_LM_KEY;
919 if (gensec_setting_bool(gensec_security->settings, "ntlmssp_client", "keyexchange", true)) {
920 ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_KEY_EXCH;
923 if (gensec_setting_bool(gensec_security->settings, "ntlmssp_client", "alwayssign", true)) {
924 ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_ALWAYS_SIGN;
927 if (gensec_setting_bool(gensec_security->settings, "ntlmssp_client", "ntlm2", true)) {
928 ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_NTLM2;
929 } else {
930 /* apparently we can't do ntlmv2 if we don't do ntlm2 */
931 ntlmssp_state->use_ntlmv2 = false;
934 if (ntlmssp_state->use_ntlmv2) {
935 ntlmssp_state->required_flags |= NTLMSSP_NEGOTIATE_NTLM2;
936 ntlmssp_state->allow_lm_response = false;
937 ntlmssp_state->allow_lm_key = false;
940 if (ntlmssp_state->allow_lm_key) {
941 ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_LM_KEY;
944 if (gensec_security->want_features & GENSEC_FEATURE_SESSION_KEY) {
946 * We need to set this to allow a later SetPassword
947 * via the SAMR pipe to succeed. Strange.... We could
948 * also add NTLMSSP_NEGOTIATE_SEAL here. JRA.
950 * Without this, Windows will not create the master key
951 * that it thinks is only used for NTLMSSP signing and
952 * sealing. (It is actually pulled out and used directly)
954 * We don't require this here as some servers (e.g. NetAPP)
955 * doesn't support this.
957 ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SIGN;
959 if (gensec_security->want_features & GENSEC_FEATURE_SIGN) {
960 ntlmssp_state->required_flags |= NTLMSSP_NEGOTIATE_SIGN;
962 if (gensec_security->want_features & GENSEC_FEATURE_LDAP_STYLE) {
964 * We need to handle NTLMSSP_NEGOTIATE_SIGN as
965 * NTLMSSP_NEGOTIATE_SEAL if GENSEC_FEATURE_LDAP_STYLE
966 * is requested.
968 ntlmssp_state->force_wrap_seal = true;
971 if (ntlmssp_state->force_wrap_seal) {
972 bool ret;
975 * We want also work against old Samba servers
976 * which didn't had GENSEC_FEATURE_LDAP_STYLE
977 * we negotiate SEAL too. We may remove this
978 * in a few years. As all servers should have
979 * GENSEC_FEATURE_LDAP_STYLE by then.
981 ret = gensec_setting_bool(gensec_security->settings,
982 "ntlmssp_client",
983 "ldap_style_send_seal",
984 true);
985 if (ret) {
986 ntlmssp_state->required_flags |= NTLMSSP_NEGOTIATE_SEAL;
989 if (gensec_security->want_features & GENSEC_FEATURE_SEAL) {
990 ntlmssp_state->required_flags |= NTLMSSP_NEGOTIATE_SIGN;
991 ntlmssp_state->required_flags |= NTLMSSP_NEGOTIATE_SEAL;
993 if (gensec_security->want_features & GENSEC_FEATURE_NTLM_CCACHE) {
994 ntlmssp_state->use_ccache = true;
997 ntlmssp_state->neg_flags |= ntlmssp_state->required_flags;
998 ntlmssp_state->conf_flags = ntlmssp_state->neg_flags;
1000 return NT_STATUS_OK;
1003 NTSTATUS gensec_ntlmssp_resume_ccache_start(struct gensec_security *gensec_security)
1005 struct gensec_ntlmssp_context *gensec_ntlmssp = NULL;
1006 NTSTATUS status;
1008 status = gensec_ntlmssp_client_start(gensec_security);
1009 if (!NT_STATUS_IS_OK(status)) {
1010 return status;
1013 gensec_ntlmssp = talloc_get_type_abort(gensec_security->private_data,
1014 struct gensec_ntlmssp_context);
1015 gensec_ntlmssp->ntlmssp_state->use_ccache = false;
1016 gensec_ntlmssp->ntlmssp_state->resume_ccache = true;
1017 gensec_ntlmssp->ntlmssp_state->expected_state = NTLMSSP_NEGOTIATE;
1019 return NT_STATUS_OK;