2 Unix SMB/Netbios implementation.
4 handle NTLMSSP, server side
6 Copyright (C) Andrew Tridgell 2001
7 Copyright (C) Andrew Bartlett 2001-2010
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program. If not, see <http://www.gnu.org/licenses/>.
24 #include "lib/util/time_basic.h"
25 #include "auth/ntlmssp/ntlmssp.h"
26 #include "auth/ntlmssp/ntlmssp_private.h"
27 #include "../librpc/gen_ndr/ndr_ntlmssp.h"
28 #include "auth/ntlmssp/ntlmssp_ndr.h"
29 #include "../libcli/auth/libcli_auth.h"
30 #include "../lib/crypto/crypto.h"
31 #include "auth/gensec/gensec.h"
32 #include "auth/gensec/gensec_internal.h"
33 #include "auth/common_auth.h"
34 #include "param/param.h"
35 #include "param/loadparm.h"
36 #include "libcli/security/session.h"
39 * Determine correct target name flags for reply, given server role
40 * and negotiated flags
42 * @param ntlmssp_state NTLMSSP State
43 * @param neg_flags The flags from the packet
44 * @param chal_flags The flags to be set in the reply packet
45 * @return The 'target name' string.
48 const char *ntlmssp_target_name(struct ntlmssp_state
*ntlmssp_state
,
49 uint32_t neg_flags
, uint32_t *chal_flags
)
51 if (neg_flags
& NTLMSSP_REQUEST_TARGET
) {
52 *chal_flags
|= NTLMSSP_NEGOTIATE_TARGET_INFO
;
53 *chal_flags
|= NTLMSSP_REQUEST_TARGET
;
54 if (ntlmssp_state
->server
.is_standalone
) {
55 *chal_flags
|= NTLMSSP_TARGET_TYPE_SERVER
;
56 return ntlmssp_state
->server
.netbios_name
;
58 *chal_flags
|= NTLMSSP_TARGET_TYPE_DOMAIN
;
59 return ntlmssp_state
->server
.netbios_domain
;
67 * Next state function for the NTLMSSP Negotiate packet
69 * @param gensec_security GENSEC state
70 * @param out_mem_ctx Memory context for *out
71 * @param in The request, as a DATA_BLOB. reply.data must be NULL
72 * @param out The reply, as an allocated DATA_BLOB, caller to free.
73 * @return Errors or MORE_PROCESSING_REQUIRED if (normal) a reply is required.
76 NTSTATUS
gensec_ntlmssp_server_negotiate(struct gensec_security
*gensec_security
,
77 TALLOC_CTX
*out_mem_ctx
,
78 const DATA_BLOB request
, DATA_BLOB
*reply
)
80 struct gensec_ntlmssp_context
*gensec_ntlmssp
=
81 talloc_get_type_abort(gensec_security
->private_data
,
82 struct gensec_ntlmssp_context
);
83 struct ntlmssp_state
*ntlmssp_state
= gensec_ntlmssp
->ntlmssp_state
;
84 struct auth4_context
*auth_context
= gensec_security
->auth_context
;
85 DATA_BLOB struct_blob
;
86 uint32_t neg_flags
= 0;
87 uint32_t ntlmssp_command
, chal_flags
;
89 const char *target_name
;
91 struct timeval tv_now
= timeval_current();
95 * Windows NT 4.0, windows_2000: use 30 minutes,
96 * Windows XP, Windows Server 2003, Windows Vista,
97 * Windows Server 2008, Windows 7, and Windows Server 2008 R2
100 * Newer systems doesn't check this, likely because the
101 * connectionless NTLMSSP is no longer supported.
103 * As we expect the AUTHENTICATION_MESSAGE to arrive
104 * directly after the NEGOTIATE_MESSAGE (typically less than
105 * as 1 second later). We use a hard timeout of 30 Minutes.
107 * We don't look at AUTHENTICATE_MESSAGE.NtChallengeResponse.TimeStamp
108 * instead we just remember our own time.
110 uint32_t max_lifetime
= 30 * 60;
111 struct timeval tv_end
= timeval_add(&tv_now
, max_lifetime
, 0);
113 /* parse the NTLMSSP packet */
115 file_save("ntlmssp_negotiate.dat", request
.data
, request
.length
);
118 if (request
.length
) {
119 if (request
.length
> UINT16_MAX
) {
120 DEBUG(1, ("ntlmssp_server_negotiate: reject large request of length %u\n",
121 (unsigned int)request
.length
));
122 return NT_STATUS_INVALID_PARAMETER
;
125 if ((request
.length
< 16) || !msrpc_parse(ntlmssp_state
, &request
, "Cdd",
129 DEBUG(1, ("ntlmssp_server_negotiate: failed to parse NTLMSSP Negotiate of length %u\n",
130 (unsigned int)request
.length
));
131 dump_data(2, request
.data
, request
.length
);
132 return NT_STATUS_INVALID_PARAMETER
;
134 debug_ntlmssp_flags(neg_flags
);
136 if (DEBUGLEVEL
>= 10) {
137 struct NEGOTIATE_MESSAGE
*negotiate
= talloc(
138 ntlmssp_state
, struct NEGOTIATE_MESSAGE
);
139 if (negotiate
!= NULL
) {
140 status
= ntlmssp_pull_NEGOTIATE_MESSAGE(
141 &request
, negotiate
, negotiate
);
142 if (NT_STATUS_IS_OK(status
)) {
143 NDR_PRINT_DEBUG(NEGOTIATE_MESSAGE
,
146 TALLOC_FREE(negotiate
);
151 status
= ntlmssp_handle_neg_flags(ntlmssp_state
, neg_flags
, "negotiate");
152 if (!NT_STATUS_IS_OK(status
)){
156 /* Ask our caller what challenge they would like in the packet */
157 if (auth_context
->get_ntlm_challenge
) {
158 status
= auth_context
->get_ntlm_challenge(auth_context
, cryptkey
);
159 if (!NT_STATUS_IS_OK(status
)) {
160 DEBUG(1, ("gensec_ntlmssp_server_negotiate: failed to get challenge: %s\n",
165 DEBUG(1, ("gensec_ntlmssp_server_negotiate: backend doesn't give a challenge\n"));
166 return NT_STATUS_NOT_IMPLEMENTED
;
169 /* The flags we send back are not just the negotiated flags,
170 * they are also 'what is in this packet'. Therfore, we
171 * operate on 'chal_flags' from here on
174 chal_flags
= ntlmssp_state
->neg_flags
;
175 ntlmssp_state
->server
.challenge_endtime
= timeval_to_nttime(&tv_end
);
177 /* get the right name to fill in as 'target' */
178 target_name
= ntlmssp_target_name(ntlmssp_state
,
179 neg_flags
, &chal_flags
);
180 if (target_name
== NULL
)
181 return NT_STATUS_INVALID_PARAMETER
;
183 ntlmssp_state
->chal
= data_blob_talloc(ntlmssp_state
, cryptkey
, 8);
184 ntlmssp_state
->internal_chal
= data_blob_talloc(ntlmssp_state
,
187 /* This creates the 'blob' of names that appears at the end of the packet */
188 if (chal_flags
& NTLMSSP_NEGOTIATE_TARGET_INFO
) {
189 enum ndr_err_code err
;
190 struct AV_PAIR
*pairs
= NULL
;
193 pairs
= talloc_zero_array(ntlmssp_state
, struct AV_PAIR
, count
+ 1);
195 return NT_STATUS_NO_MEMORY
;
198 pairs
[0].AvId
= MsvAvNbDomainName
;
199 pairs
[0].Value
.AvNbDomainName
= target_name
;
201 pairs
[1].AvId
= MsvAvNbComputerName
;
202 pairs
[1].Value
.AvNbComputerName
= ntlmssp_state
->server
.netbios_name
;
204 pairs
[2].AvId
= MsvAvDnsDomainName
;
205 pairs
[2].Value
.AvDnsDomainName
= ntlmssp_state
->server
.dns_domain
;
207 pairs
[3].AvId
= MsvAvDnsComputerName
;
208 pairs
[3].Value
.AvDnsComputerName
= ntlmssp_state
->server
.dns_name
;
210 if (!ntlmssp_state
->force_old_spnego
) {
211 pairs
[4].AvId
= MsvAvTimestamp
;
212 pairs
[4].Value
.AvTimestamp
=
213 timeval_to_nttime(&tv_now
);
216 pairs
[5].AvId
= MsvAvEOL
;
218 pairs
[4].AvId
= MsvAvEOL
;
221 ntlmssp_state
->server
.av_pair_list
.count
= count
;
222 ntlmssp_state
->server
.av_pair_list
.pair
= pairs
;
224 err
= ndr_push_struct_blob(&struct_blob
,
226 &ntlmssp_state
->server
.av_pair_list
,
227 (ndr_push_flags_fn_t
)ndr_push_AV_PAIR_LIST
);
228 if (!NDR_ERR_CODE_IS_SUCCESS(err
)) {
229 return NT_STATUS_NO_MEMORY
;
232 struct_blob
= data_blob_null
;
236 /* Marshal the packet in the right format, be it unicode or ASCII */
237 const char *gen_string
;
238 const DATA_BLOB version_blob
= ntlmssp_version_blob();
240 if (ntlmssp_state
->unicode
) {
241 gen_string
= "CdUdbddBb";
243 gen_string
= "CdAdbddBb";
246 status
= msrpc_gen(out_mem_ctx
, reply
, gen_string
,
253 struct_blob
.data
, struct_blob
.length
,
254 version_blob
.data
, version_blob
.length
);
256 if (!NT_STATUS_IS_OK(status
)) {
257 data_blob_free(&struct_blob
);
261 if (DEBUGLEVEL
>= 10) {
262 struct CHALLENGE_MESSAGE
*challenge
= talloc(
263 ntlmssp_state
, struct CHALLENGE_MESSAGE
);
264 if (challenge
!= NULL
) {
265 challenge
->NegotiateFlags
= chal_flags
;
266 status
= ntlmssp_pull_CHALLENGE_MESSAGE(
267 reply
, challenge
, challenge
);
268 if (NT_STATUS_IS_OK(status
)) {
269 NDR_PRINT_DEBUG(CHALLENGE_MESSAGE
,
272 TALLOC_FREE(challenge
);
277 data_blob_free(&struct_blob
);
279 ntlmssp_state
->negotiate_blob
= data_blob_dup_talloc(ntlmssp_state
,
281 if (ntlmssp_state
->negotiate_blob
.length
!= request
.length
) {
282 return NT_STATUS_NO_MEMORY
;
285 ntlmssp_state
->challenge_blob
= data_blob_dup_talloc(ntlmssp_state
,
287 if (ntlmssp_state
->challenge_blob
.length
!= reply
->length
) {
288 return NT_STATUS_NO_MEMORY
;
291 ntlmssp_state
->expected_state
= NTLMSSP_AUTH
;
293 return NT_STATUS_MORE_PROCESSING_REQUIRED
;
296 struct ntlmssp_server_auth_state
{
297 DATA_BLOB user_session_key
;
298 DATA_BLOB lm_session_key
;
299 /* internal variables used by KEY_EXCH (client-supplied user session key */
300 DATA_BLOB encrypted_session_key
;
302 /* internal variables used by NTLM2 */
303 uint8_t session_nonce
[16];
307 * Next state function for the Authenticate packet
309 * @param ntlmssp_state NTLMSSP State
310 * @param request The request, as a DATA_BLOB
311 * @return Errors or NT_STATUS_OK.
314 static NTSTATUS
ntlmssp_server_preauth(struct gensec_security
*gensec_security
,
315 struct gensec_ntlmssp_context
*gensec_ntlmssp
,
316 struct ntlmssp_server_auth_state
*state
,
317 const DATA_BLOB request
)
319 struct ntlmssp_state
*ntlmssp_state
= gensec_ntlmssp
->ntlmssp_state
;
320 struct auth4_context
*auth_context
= gensec_security
->auth_context
;
321 uint32_t ntlmssp_command
, auth_flags
;
323 const unsigned int version_len
= 8;
324 DATA_BLOB version_blob
= data_blob_null
;
325 const unsigned int mic_len
= NTLMSSP_MIC_SIZE
;
326 DATA_BLOB mic_blob
= data_blob_null
;
327 uint8_t session_nonce_hash
[16];
328 const char *parse_string
;
330 struct timeval endtime
;
331 bool expired
= false;
334 file_save("ntlmssp_auth.dat", request
.data
, request
.length
);
337 if (ntlmssp_state
->unicode
) {
338 parse_string
= "CdBBUUUBdbb";
340 parse_string
= "CdBBAAABdbb";
344 data_blob_free(&ntlmssp_state
->session_key
);
345 data_blob_free(&ntlmssp_state
->lm_resp
);
346 data_blob_free(&ntlmssp_state
->nt_resp
);
348 ntlmssp_state
->user
= NULL
;
349 ntlmssp_state
->domain
= NULL
;
350 ntlmssp_state
->client
.netbios_name
= NULL
;
352 /* now the NTLMSSP encoded auth hashes */
353 ok
= msrpc_parse(ntlmssp_state
, &request
, parse_string
,
356 &ntlmssp_state
->lm_resp
,
357 &ntlmssp_state
->nt_resp
,
358 &ntlmssp_state
->domain
,
359 &ntlmssp_state
->user
,
360 &ntlmssp_state
->client
.netbios_name
,
361 &state
->encrypted_session_key
,
363 &version_blob
, version_len
,
366 DEBUG(10, ("ntlmssp_server_auth: failed to parse NTLMSSP (nonfatal):\n"));
367 dump_data(10, request
.data
, request
.length
);
369 data_blob_free(&version_blob
);
370 data_blob_free(&mic_blob
);
372 if (ntlmssp_state
->unicode
) {
373 parse_string
= "CdBBUUUBd";
375 parse_string
= "CdBBAAABd";
378 ok
= msrpc_parse(ntlmssp_state
, &request
, parse_string
,
381 &ntlmssp_state
->lm_resp
,
382 &ntlmssp_state
->nt_resp
,
383 &ntlmssp_state
->domain
,
384 &ntlmssp_state
->user
,
385 &ntlmssp_state
->client
.netbios_name
,
386 &state
->encrypted_session_key
,
391 DEBUG(10, ("ntlmssp_server_auth: failed to parse NTLMSSP (nonfatal):\n"));
392 dump_data(10, request
.data
, request
.length
);
395 data_blob_free(&state
->encrypted_session_key
);
398 /* Try again with a shorter string (Win9X truncates this packet) */
399 if (ntlmssp_state
->unicode
) {
400 parse_string
= "CdBBUUU";
402 parse_string
= "CdBBAAA";
405 /* now the NTLMSSP encoded auth hashes */
406 if (!msrpc_parse(ntlmssp_state
, &request
, parse_string
,
409 &ntlmssp_state
->lm_resp
,
410 &ntlmssp_state
->nt_resp
,
411 &ntlmssp_state
->domain
,
412 &ntlmssp_state
->user
,
413 &ntlmssp_state
->client
.netbios_name
)) {
414 DEBUG(1, ("ntlmssp_server_auth: failed to parse NTLMSSP (tried both formats):\n"));
415 dump_data(2, request
.data
, request
.length
);
417 return NT_STATUS_INVALID_PARAMETER
;
421 talloc_steal(state
, state
->encrypted_session_key
.data
);
423 if (auth_flags
!= 0) {
424 nt_status
= ntlmssp_handle_neg_flags(ntlmssp_state
,
427 if (!NT_STATUS_IS_OK(nt_status
)){
432 if (DEBUGLEVEL
>= 10) {
433 struct AUTHENTICATE_MESSAGE
*authenticate
= talloc(
434 ntlmssp_state
, struct AUTHENTICATE_MESSAGE
);
435 if (authenticate
!= NULL
) {
437 authenticate
->NegotiateFlags
= auth_flags
;
438 status
= ntlmssp_pull_AUTHENTICATE_MESSAGE(
439 &request
, authenticate
, authenticate
);
440 if (NT_STATUS_IS_OK(status
)) {
441 NDR_PRINT_DEBUG(AUTHENTICATE_MESSAGE
,
444 TALLOC_FREE(authenticate
);
448 DEBUG(3,("Got user=[%s] domain=[%s] workstation=[%s] len1=%lu len2=%lu\n",
449 ntlmssp_state
->user
, ntlmssp_state
->domain
,
450 ntlmssp_state
->client
.netbios_name
,
451 (unsigned long)ntlmssp_state
->lm_resp
.length
,
452 (unsigned long)ntlmssp_state
->nt_resp
.length
));
455 file_save("nthash1.dat", &ntlmssp_state
->nt_resp
.data
, &ntlmssp_state
->nt_resp
.length
);
456 file_save("lmhash1.dat", &ntlmssp_state
->lm_resp
.data
, &ntlmssp_state
->lm_resp
.length
);
459 if (ntlmssp_state
->nt_resp
.length
> 24) {
460 struct NTLMv2_RESPONSE v2_resp
;
461 enum ndr_err_code err
;
464 const struct AV_PAIR
*flags
= NULL
;
465 const struct AV_PAIR
*eol
= NULL
;
466 uint32_t av_flags
= 0;
468 err
= ndr_pull_struct_blob(&ntlmssp_state
->nt_resp
,
471 (ndr_pull_flags_fn_t
)ndr_pull_NTLMv2_RESPONSE
);
472 if (!NDR_ERR_CODE_IS_SUCCESS(err
)) {
473 nt_status
= ndr_map_error2ntstatus(err
);
474 DEBUG(1,("%s: failed to parse NTLMv2_RESPONSE of length %zu for "
475 "user=[%s] domain=[%s] workstation=[%s] - %s %s\n",
476 __func__
, ntlmssp_state
->nt_resp
.length
,
477 ntlmssp_state
->user
, ntlmssp_state
->domain
,
478 ntlmssp_state
->client
.netbios_name
,
479 ndr_errstr(err
), nt_errstr(nt_status
)));
484 NDR_PRINT_DEBUG(NTLMv2_RESPONSE
, &v2_resp
);
487 eol
= ndr_ntlmssp_find_av(&v2_resp
.Challenge
.AvPairs
,
490 DEBUG(1,("%s: missing MsvAvEOL for "
491 "user=[%s] domain=[%s] workstation=[%s]\n",
492 __func__
, ntlmssp_state
->user
, ntlmssp_state
->domain
,
493 ntlmssp_state
->client
.netbios_name
));
494 return NT_STATUS_INVALID_PARAMETER
;
497 flags
= ndr_ntlmssp_find_av(&v2_resp
.Challenge
.AvPairs
,
500 av_flags
= flags
->Value
.AvFlags
;
503 if (av_flags
& NTLMSSP_AVFLAG_MIC_IN_AUTHENTICATE_MESSAGE
) {
504 if (mic_blob
.length
!= NTLMSSP_MIC_SIZE
) {
505 DEBUG(1,("%s: mic_blob.length[%u] for "
506 "user=[%s] domain=[%s] workstation=[%s]\n",
508 (unsigned)mic_blob
.length
,
510 ntlmssp_state
->domain
,
511 ntlmssp_state
->client
.netbios_name
));
512 return NT_STATUS_INVALID_PARAMETER
;
516 (NTLMSSP_MIC_OFFSET
+ NTLMSSP_MIC_SIZE
))
518 DEBUG(1,("%s: missing MIC "
519 "request.length[%u] for "
520 "user=[%s] domain=[%s] workstation=[%s]\n",
522 (unsigned)request
.length
,
524 ntlmssp_state
->domain
,
525 ntlmssp_state
->client
.netbios_name
));
526 return NT_STATUS_INVALID_PARAMETER
;
529 ntlmssp_state
->new_spnego
= true;
532 count
= ntlmssp_state
->server
.av_pair_list
.count
;
533 if (v2_resp
.Challenge
.AvPairs
.count
< count
) {
534 return NT_STATUS_INVALID_PARAMETER
;
537 for (i
= 0; i
< count
; i
++) {
538 const struct AV_PAIR
*sp
=
539 &ntlmssp_state
->server
.av_pair_list
.pair
[i
];
540 const struct AV_PAIR
*cp
= NULL
;
542 if (sp
->AvId
== MsvAvEOL
) {
546 cp
= ndr_ntlmssp_find_av(&v2_resp
.Challenge
.AvPairs
,
549 DEBUG(1,("%s: AvId 0x%x missing for"
550 "user=[%s] domain=[%s] "
551 "workstation=[%s]\n",
555 ntlmssp_state
->domain
,
556 ntlmssp_state
->client
.netbios_name
));
557 return NT_STATUS_INVALID_PARAMETER
;
561 #define CASE_STRING(v) case Msv ## v: do { \
563 if (sp->Value.v == NULL) { \
564 return NT_STATUS_INTERNAL_ERROR; \
566 if (cp->Value.v == NULL) { \
567 DEBUG(1,("%s: invalid %s " \
568 "got[%s] expect[%s] for " \
569 "user=[%s] domain=[%s] workstation=[%s]\n", \
573 ntlmssp_state->user, \
574 ntlmssp_state->domain, \
575 ntlmssp_state->client.netbios_name)); \
576 return NT_STATUS_INVALID_PARAMETER; \
578 cmp = strcmp(cp->Value.v, sp->Value.v); \
580 DEBUG(1,("%s: invalid %s " \
581 "got[%s] expect[%s] for " \
582 "user=[%s] domain=[%s] workstation=[%s]\n", \
586 ntlmssp_state->user, \
587 ntlmssp_state->domain, \
588 ntlmssp_state->client.netbios_name)); \
589 return NT_STATUS_INVALID_PARAMETER; \
592 CASE_STRING(AvNbComputerName
);
593 CASE_STRING(AvNbDomainName
);
594 CASE_STRING(AvDnsComputerName
);
595 CASE_STRING(AvDnsDomainName
);
596 CASE_STRING(AvDnsTreeName
);
598 if (cp
->Value
.AvTimestamp
!= sp
->Value
.AvTimestamp
) {
601 struct timeval_buf tmp1
;
602 struct timeval_buf tmp2
;
604 nttime_to_timeval(&ct
,
605 cp
->Value
.AvTimestamp
);
606 nttime_to_timeval(&st
,
607 sp
->Value
.AvTimestamp
);
609 DEBUG(1,("%s: invalid AvTimestamp "
610 "got[%s] expect[%s] for "
611 "user=[%s] domain=[%s] "
612 "workstation=[%s]\n",
614 timeval_str_buf(&ct
, false,
616 timeval_str_buf(&st
, false,
619 ntlmssp_state
->domain
,
620 ntlmssp_state
->client
.netbios_name
));
621 return NT_STATUS_INVALID_PARAMETER
;
626 * This can't happen as we control
627 * ntlmssp_state->server.av_pair_list
629 return NT_STATUS_INTERNAL_ERROR
;
634 nttime_to_timeval(&endtime
, ntlmssp_state
->server
.challenge_endtime
);
635 expired
= timeval_expired(&endtime
);
637 struct timeval_buf tmp
;
638 DEBUG(1,("%s: challenge invalid (expired %s) for "
639 "user=[%s] domain=[%s] workstation=[%s]\n",
641 timeval_str_buf(&endtime
, false, true, &tmp
),
642 ntlmssp_state
->user
, ntlmssp_state
->domain
,
643 ntlmssp_state
->client
.netbios_name
));
644 return NT_STATUS_INVALID_PARAMETER
;
647 /* NTLM2 uses a 'challenge' that is made of up both the server challenge, and a
650 However, the NTLM2 flag may still be set for the real NTLMv2 logins, be careful.
652 if (ntlmssp_state
->neg_flags
& NTLMSSP_NEGOTIATE_NTLM2
) {
653 if (ntlmssp_state
->nt_resp
.length
== 24 && ntlmssp_state
->lm_resp
.length
== 24) {
654 MD5_CTX md5_session_nonce_ctx
;
655 state
->doing_ntlm2
= true;
657 memcpy(state
->session_nonce
, ntlmssp_state
->internal_chal
.data
, 8);
658 memcpy(&state
->session_nonce
[8], ntlmssp_state
->lm_resp
.data
, 8);
660 SMB_ASSERT(ntlmssp_state
->internal_chal
.data
&& ntlmssp_state
->internal_chal
.length
== 8);
662 MD5Init(&md5_session_nonce_ctx
);
663 MD5Update(&md5_session_nonce_ctx
, state
->session_nonce
, 16);
664 MD5Final(session_nonce_hash
, &md5_session_nonce_ctx
);
666 /* LM response is no longer useful */
667 data_blob_free(&ntlmssp_state
->lm_resp
);
669 /* We changed the effective challenge - set it */
670 if (auth_context
->set_ntlm_challenge
) {
671 nt_status
= auth_context
->set_ntlm_challenge(auth_context
,
673 "NTLMSSP callback (NTLM2)");
674 if (!NT_STATUS_IS_OK(nt_status
)) {
675 DEBUG(1, ("gensec_ntlmssp_server_negotiate: failed to get challenge: %s\n",
676 nt_errstr(nt_status
)));
680 DEBUG(1, ("gensec_ntlmssp_server_negotiate: backend doesn't have facility for challenge to be set\n"));
682 return NT_STATUS_NOT_IMPLEMENTED
;
685 /* LM Key is incompatible. */
686 ntlmssp_state
->neg_flags
&= ~NTLMSSP_NEGOTIATE_LM_KEY
;
693 * Check the password on an NTLMSSP login.
695 * Return the session keys used on the connection.
698 static NTSTATUS
ntlmssp_server_check_password(struct gensec_security
*gensec_security
,
699 struct gensec_ntlmssp_context
*gensec_ntlmssp
,
701 DATA_BLOB
*user_session_key
, DATA_BLOB
*lm_session_key
)
703 struct ntlmssp_state
*ntlmssp_state
= gensec_ntlmssp
->ntlmssp_state
;
704 struct auth4_context
*auth_context
= gensec_security
->auth_context
;
705 NTSTATUS nt_status
= NT_STATUS_NOT_IMPLEMENTED
;
706 struct auth_session_info
*session_info
= NULL
;
707 struct auth_usersupplied_info
*user_info
;
709 user_info
= talloc_zero(ntlmssp_state
, struct auth_usersupplied_info
);
711 return NT_STATUS_NO_MEMORY
;
714 user_info
->logon_parameters
= MSV1_0_ALLOW_SERVER_TRUST_ACCOUNT
| MSV1_0_ALLOW_WORKSTATION_TRUST_ACCOUNT
;
715 user_info
->flags
= 0;
716 user_info
->mapped_state
= false;
717 user_info
->client
.account_name
= ntlmssp_state
->user
;
718 user_info
->client
.domain_name
= ntlmssp_state
->domain
;
719 user_info
->workstation_name
= ntlmssp_state
->client
.netbios_name
;
720 user_info
->remote_host
= gensec_get_remote_address(gensec_security
);
721 user_info
->service_description
722 = gensec_get_target_service_description(gensec_security
);
724 user_info
->password_state
= AUTH_PASSWORD_RESPONSE
;
725 user_info
->password
.response
.lanman
= ntlmssp_state
->lm_resp
;
726 user_info
->password
.response
.lanman
.data
= talloc_steal(user_info
, ntlmssp_state
->lm_resp
.data
);
727 user_info
->password
.response
.nt
= ntlmssp_state
->nt_resp
;
728 user_info
->password
.response
.nt
.data
= talloc_steal(user_info
, ntlmssp_state
->nt_resp
.data
);
730 if (auth_context
->check_ntlm_password
) {
731 uint8_t authoritative
= 0;
733 nt_status
= auth_context
->check_ntlm_password(auth_context
,
737 &gensec_ntlmssp
->server_returned_info
,
738 user_session_key
, lm_session_key
);
741 if (!NT_STATUS_IS_OK(nt_status
)) {
742 DEBUG(5, (__location__
": Checking NTLMSSP password for %s\\%s failed: %s\n", user_info
->client
.domain_name
, user_info
->client
.account_name
, nt_errstr(nt_status
)));
744 TALLOC_FREE(user_info
);
746 NT_STATUS_NOT_OK_RETURN(nt_status
);
748 if (lpcfg_map_to_guest(gensec_security
->settings
->lp_ctx
) != NEVER_MAP_TO_GUEST
749 && auth_context
->generate_session_info
!= NULL
)
754 * We need to check if the auth is anonymous or mapped to guest
756 tmp_status
= auth_context
->generate_session_info(auth_context
, mem_ctx
,
757 gensec_ntlmssp
->server_returned_info
,
758 gensec_ntlmssp
->ntlmssp_state
->user
,
759 AUTH_SESSION_INFO_SIMPLE_PRIVILEGES
,
761 if (!NT_STATUS_IS_OK(tmp_status
)) {
763 * We don't care about failures,
764 * the worst result is that we try MIC checking
765 * for a map to guest authentication.
767 TALLOC_FREE(session_info
);
771 if (session_info
!= NULL
) {
772 if (security_session_user_level(session_info
, NULL
) < SECURITY_USER
) {
774 * Anonymous and GUEST are not secure anyway.
775 * avoid new_spnego and MIC checking.
777 ntlmssp_state
->new_spnego
= false;
778 ntlmssp_state
->neg_flags
&= ~NTLMSSP_NEGOTIATE_SIGN
;
779 ntlmssp_state
->neg_flags
&= ~NTLMSSP_NEGOTIATE_SEAL
;
781 TALLOC_FREE(session_info
);
784 talloc_steal(mem_ctx
, user_session_key
->data
);
785 talloc_steal(mem_ctx
, lm_session_key
->data
);
791 * Next state function for the Authenticate packet
792 * (after authentication - figures out the session keys etc)
794 * @param ntlmssp_state NTLMSSP State
795 * @return Errors or NT_STATUS_OK.
798 static NTSTATUS
ntlmssp_server_postauth(struct gensec_security
*gensec_security
,
799 struct gensec_ntlmssp_context
*gensec_ntlmssp
,
800 struct ntlmssp_server_auth_state
*state
,
803 struct ntlmssp_state
*ntlmssp_state
= gensec_ntlmssp
->ntlmssp_state
;
804 DATA_BLOB user_session_key
= state
->user_session_key
;
805 DATA_BLOB lm_session_key
= state
->lm_session_key
;
806 NTSTATUS nt_status
= NT_STATUS_OK
;
807 DATA_BLOB session_key
= data_blob(NULL
, 0);
809 dump_data_pw("NT session key:\n", user_session_key
.data
, user_session_key
.length
);
810 dump_data_pw("LM first-8:\n", lm_session_key
.data
, lm_session_key
.length
);
812 /* Handle the different session key derivation for NTLM2 */
813 if (state
->doing_ntlm2
) {
814 if (user_session_key
.data
&& user_session_key
.length
== 16) {
815 session_key
= data_blob_talloc(ntlmssp_state
,
817 hmac_md5(user_session_key
.data
, state
->session_nonce
,
818 sizeof(state
->session_nonce
), session_key
.data
);
819 DEBUG(10,("ntlmssp_server_auth: Created NTLM2 session key.\n"));
820 dump_data_pw("NTLM2 session key:\n", session_key
.data
, session_key
.length
);
823 DEBUG(10,("ntlmssp_server_auth: Failed to create NTLM2 session key.\n"));
824 session_key
= data_blob_null
;
826 } else if ((ntlmssp_state
->neg_flags
& NTLMSSP_NEGOTIATE_LM_KEY
)
827 /* Ensure we can never get here on NTLMv2 */
828 && (ntlmssp_state
->nt_resp
.length
== 0 || ntlmssp_state
->nt_resp
.length
== 24)) {
830 if (lm_session_key
.data
&& lm_session_key
.length
>= 8) {
831 if (ntlmssp_state
->lm_resp
.data
&& ntlmssp_state
->lm_resp
.length
== 24) {
832 session_key
= data_blob_talloc(ntlmssp_state
,
834 if (session_key
.data
== NULL
) {
835 return NT_STATUS_NO_MEMORY
;
837 SMBsesskeygen_lm_sess_key(lm_session_key
.data
, ntlmssp_state
->lm_resp
.data
,
839 DEBUG(10,("ntlmssp_server_auth: Created NTLM session key.\n"));
841 static const uint8_t zeros
[24] = {0, };
842 session_key
= data_blob_talloc(
843 ntlmssp_state
, NULL
, 16);
844 if (session_key
.data
== NULL
) {
845 return NT_STATUS_NO_MEMORY
;
847 SMBsesskeygen_lm_sess_key(zeros
, zeros
,
849 DEBUG(10,("ntlmssp_server_auth: Created NTLM session key.\n"));
851 dump_data_pw("LM session key:\n", session_key
.data
,
854 /* LM Key not selected */
855 ntlmssp_state
->neg_flags
&= ~NTLMSSP_NEGOTIATE_LM_KEY
;
857 DEBUG(10,("ntlmssp_server_auth: Failed to create NTLM session key.\n"));
858 session_key
= data_blob_null
;
861 } else if (user_session_key
.data
) {
862 session_key
= user_session_key
;
863 DEBUG(10,("ntlmssp_server_auth: Using unmodified nt session key.\n"));
864 dump_data_pw("unmodified session key:\n", session_key
.data
, session_key
.length
);
866 /* LM Key not selected */
867 ntlmssp_state
->neg_flags
&= ~NTLMSSP_NEGOTIATE_LM_KEY
;
869 } else if (lm_session_key
.data
) {
870 /* Very weird to have LM key, but no user session key, but anyway.. */
871 session_key
= lm_session_key
;
872 DEBUG(10,("ntlmssp_server_auth: Using unmodified lm session key.\n"));
873 dump_data_pw("unmodified session key:\n", session_key
.data
, session_key
.length
);
875 /* LM Key not selected */
876 ntlmssp_state
->neg_flags
&= ~NTLMSSP_NEGOTIATE_LM_KEY
;
879 DEBUG(10,("ntlmssp_server_auth: Failed to create unmodified session key.\n"));
880 session_key
= data_blob_null
;
882 /* LM Key not selected */
883 ntlmssp_state
->neg_flags
&= ~NTLMSSP_NEGOTIATE_LM_KEY
;
886 /* With KEY_EXCH, the client supplies the proposed session key,
887 but encrypts it with the long-term key */
888 if (ntlmssp_state
->neg_flags
& NTLMSSP_NEGOTIATE_KEY_EXCH
) {
889 if (!state
->encrypted_session_key
.data
890 || state
->encrypted_session_key
.length
!= 16) {
891 DEBUG(1, ("Client-supplied KEY_EXCH session key was of invalid length (%u)!\n",
892 (unsigned)state
->encrypted_session_key
.length
));
893 return NT_STATUS_INVALID_PARAMETER
;
894 } else if (!session_key
.data
|| session_key
.length
!= 16) {
895 DEBUG(5, ("server session key is invalid (len == %u), cannot do KEY_EXCH!\n",
896 (unsigned int)session_key
.length
));
897 ntlmssp_state
->session_key
= session_key
;
898 talloc_steal(ntlmssp_state
, session_key
.data
);
900 dump_data_pw("KEY_EXCH session key (enc):\n",
901 state
->encrypted_session_key
.data
,
902 state
->encrypted_session_key
.length
);
903 arcfour_crypt(state
->encrypted_session_key
.data
,
905 state
->encrypted_session_key
.length
);
906 ntlmssp_state
->session_key
= data_blob_talloc(ntlmssp_state
,
907 state
->encrypted_session_key
.data
,
908 state
->encrypted_session_key
.length
);
909 dump_data_pw("KEY_EXCH session key:\n",
910 state
->encrypted_session_key
.data
,
911 state
->encrypted_session_key
.length
);
914 ntlmssp_state
->session_key
= session_key
;
915 talloc_steal(ntlmssp_state
, session_key
.data
);
918 if (ntlmssp_state
->new_spnego
) {
920 uint8_t mic_buffer
[NTLMSSP_MIC_SIZE
] = { 0, };
923 hmac_md5_init_limK_to_64(ntlmssp_state
->session_key
.data
,
924 ntlmssp_state
->session_key
.length
,
927 hmac_md5_update(ntlmssp_state
->negotiate_blob
.data
,
928 ntlmssp_state
->negotiate_blob
.length
,
930 hmac_md5_update(ntlmssp_state
->challenge_blob
.data
,
931 ntlmssp_state
->challenge_blob
.length
,
934 /* checked were we set ntlmssp_state->new_spnego */
935 SMB_ASSERT(request
.length
>
936 (NTLMSSP_MIC_OFFSET
+ NTLMSSP_MIC_SIZE
));
938 hmac_md5_update(request
.data
, NTLMSSP_MIC_OFFSET
, &ctx
);
939 hmac_md5_update(mic_buffer
, NTLMSSP_MIC_SIZE
, &ctx
);
940 hmac_md5_update(request
.data
+
941 (NTLMSSP_MIC_OFFSET
+ NTLMSSP_MIC_SIZE
),
943 (NTLMSSP_MIC_OFFSET
+ NTLMSSP_MIC_SIZE
),
945 hmac_md5_final(mic_buffer
, &ctx
);
947 cmp
= memcmp(request
.data
+ NTLMSSP_MIC_OFFSET
,
948 mic_buffer
, NTLMSSP_MIC_SIZE
);
950 DEBUG(1,("%s: invalid NTLMSSP_MIC for "
951 "user=[%s] domain=[%s] workstation=[%s]\n",
954 ntlmssp_state
->domain
,
955 ntlmssp_state
->client
.netbios_name
));
956 dump_data(1, request
.data
+ NTLMSSP_MIC_OFFSET
,
958 dump_data(1, mic_buffer
,
960 return NT_STATUS_INVALID_PARAMETER
;
964 data_blob_free(&ntlmssp_state
->negotiate_blob
);
965 data_blob_free(&ntlmssp_state
->challenge_blob
);
967 if (gensec_ntlmssp_have_feature(gensec_security
, GENSEC_FEATURE_SIGN
)) {
968 nt_status
= ntlmssp_sign_init(ntlmssp_state
);
971 ntlmssp_state
->expected_state
= NTLMSSP_DONE
;
978 * Next state function for the NTLMSSP Authenticate packet
980 * @param gensec_security GENSEC state
981 * @param out_mem_ctx Memory context for *out
982 * @param in The request, as a DATA_BLOB. reply.data must be NULL
983 * @param out The reply, as an allocated DATA_BLOB, caller to free.
984 * @return Errors or NT_STATUS_OK if authentication sucessful
987 NTSTATUS
gensec_ntlmssp_server_auth(struct gensec_security
*gensec_security
,
988 TALLOC_CTX
*out_mem_ctx
,
989 const DATA_BLOB in
, DATA_BLOB
*out
)
991 struct gensec_ntlmssp_context
*gensec_ntlmssp
=
992 talloc_get_type_abort(gensec_security
->private_data
,
993 struct gensec_ntlmssp_context
);
994 struct ntlmssp_server_auth_state
*state
;
997 /* zero the outbound NTLMSSP packet */
998 *out
= data_blob_null
;
1000 state
= talloc_zero(gensec_ntlmssp
, struct ntlmssp_server_auth_state
);
1001 if (state
== NULL
) {
1002 return NT_STATUS_NO_MEMORY
;
1005 nt_status
= ntlmssp_server_preauth(gensec_security
, gensec_ntlmssp
, state
, in
);
1006 if (!NT_STATUS_IS_OK(nt_status
)) {
1012 * Note we don't check here for NTLMv2 auth settings. If NTLMv2 auth
1013 * is required (by "ntlm auth = no" and "lm auth = no" being set in the
1014 * smb.conf file) and no NTLMv2 response was sent then the password check
1015 * will fail here. JRA.
1018 /* Finally, actually ask if the password is OK */
1019 nt_status
= ntlmssp_server_check_password(gensec_security
, gensec_ntlmssp
,
1021 &state
->user_session_key
,
1022 &state
->lm_session_key
);
1023 if (!NT_STATUS_IS_OK(nt_status
)) {
1028 /* When we get more async in the auth code behind
1029 ntlmssp_state->check_password, the ntlmssp_server_postpath
1030 can be done in a callback */
1032 nt_status
= ntlmssp_server_postauth(gensec_security
, gensec_ntlmssp
, state
, in
);