util_sd: Make server conncection optional
[Samba.git] / auth / ntlmssp / ntlmssp_server.c
blob2f3f0bb723f8107c133e4ed02f2895dce3666cff
1 /*
2 Unix SMB/Netbios implementation.
3 Version 3.0
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/>.
23 #include "includes.h"
24 #include "auth/ntlmssp/ntlmssp.h"
25 #include "auth/ntlmssp/ntlmssp_private.h"
26 #include "../librpc/gen_ndr/ndr_ntlmssp.h"
27 #include "auth/ntlmssp/ntlmssp_ndr.h"
28 #include "../libcli/auth/libcli_auth.h"
29 #include "../lib/crypto/crypto.h"
30 #include "auth/gensec/gensec.h"
31 #include "auth/gensec/gensec_internal.h"
32 #include "auth/common_auth.h"
34 /**
35 * Determine correct target name flags for reply, given server role
36 * and negotiated flags
38 * @param ntlmssp_state NTLMSSP State
39 * @param neg_flags The flags from the packet
40 * @param chal_flags The flags to be set in the reply packet
41 * @return The 'target name' string.
44 const char *ntlmssp_target_name(struct ntlmssp_state *ntlmssp_state,
45 uint32_t neg_flags, uint32_t *chal_flags)
47 if (neg_flags & NTLMSSP_REQUEST_TARGET) {
48 *chal_flags |= NTLMSSP_NEGOTIATE_TARGET_INFO;
49 *chal_flags |= NTLMSSP_REQUEST_TARGET;
50 if (ntlmssp_state->server.is_standalone) {
51 *chal_flags |= NTLMSSP_TARGET_TYPE_SERVER;
52 return ntlmssp_state->server.netbios_name;
53 } else {
54 *chal_flags |= NTLMSSP_TARGET_TYPE_DOMAIN;
55 return ntlmssp_state->server.netbios_domain;
57 } else {
58 return "";
62 /**
63 * Next state function for the NTLMSSP Negotiate packet
65 * @param gensec_security GENSEC state
66 * @param out_mem_ctx Memory context for *out
67 * @param in The request, as a DATA_BLOB. reply.data must be NULL
68 * @param out The reply, as an allocated DATA_BLOB, caller to free.
69 * @return Errors or MORE_PROCESSING_REQUIRED if (normal) a reply is required.
72 NTSTATUS gensec_ntlmssp_server_negotiate(struct gensec_security *gensec_security,
73 TALLOC_CTX *out_mem_ctx,
74 const DATA_BLOB request, DATA_BLOB *reply)
76 struct gensec_ntlmssp_context *gensec_ntlmssp =
77 talloc_get_type_abort(gensec_security->private_data,
78 struct gensec_ntlmssp_context);
79 struct ntlmssp_state *ntlmssp_state = gensec_ntlmssp->ntlmssp_state;
80 struct auth4_context *auth_context = gensec_security->auth_context;
81 DATA_BLOB struct_blob;
82 uint32_t neg_flags = 0;
83 uint32_t ntlmssp_command, chal_flags;
84 uint8_t cryptkey[8];
85 const char *target_name;
86 NTSTATUS status;
88 /* parse the NTLMSSP packet */
89 #if 0
90 file_save("ntlmssp_negotiate.dat", request.data, request.length);
91 #endif
93 if (request.length) {
94 if ((request.length < 16) || !msrpc_parse(ntlmssp_state, &request, "Cdd",
95 "NTLMSSP",
96 &ntlmssp_command,
97 &neg_flags)) {
98 DEBUG(1, ("ntlmssp_server_negotiate: failed to parse NTLMSSP Negotiate of length %u\n",
99 (unsigned int)request.length));
100 dump_data(2, request.data, request.length);
101 return NT_STATUS_INVALID_PARAMETER;
103 debug_ntlmssp_flags(neg_flags);
105 if (DEBUGLEVEL >= 10) {
106 struct NEGOTIATE_MESSAGE *negotiate = talloc(
107 ntlmssp_state, struct NEGOTIATE_MESSAGE);
108 if (negotiate != NULL) {
109 status = ntlmssp_pull_NEGOTIATE_MESSAGE(
110 &request, negotiate, negotiate);
111 if (NT_STATUS_IS_OK(status)) {
112 NDR_PRINT_DEBUG(NEGOTIATE_MESSAGE,
113 negotiate);
115 TALLOC_FREE(negotiate);
120 ntlmssp_handle_neg_flags(ntlmssp_state, neg_flags, ntlmssp_state->allow_lm_key);
122 /* Ask our caller what challenge they would like in the packet */
123 if (auth_context->get_ntlm_challenge) {
124 status = auth_context->get_ntlm_challenge(auth_context, cryptkey);
125 if (!NT_STATUS_IS_OK(status)) {
126 DEBUG(1, ("gensec_ntlmssp_server_negotiate: failed to get challenge: %s\n",
127 nt_errstr(status)));
128 return status;
130 } else {
131 DEBUG(1, ("gensec_ntlmssp_server_negotiate: backend doesn't give a challenge\n"));
132 return NT_STATUS_NOT_IMPLEMENTED;
135 /* The flags we send back are not just the negotiated flags,
136 * they are also 'what is in this packet'. Therfore, we
137 * operate on 'chal_flags' from here on
140 chal_flags = ntlmssp_state->neg_flags;
142 /* get the right name to fill in as 'target' */
143 target_name = ntlmssp_target_name(ntlmssp_state,
144 neg_flags, &chal_flags);
145 if (target_name == NULL)
146 return NT_STATUS_INVALID_PARAMETER;
148 ntlmssp_state->chal = data_blob_talloc(ntlmssp_state, cryptkey, 8);
149 ntlmssp_state->internal_chal = data_blob_talloc(ntlmssp_state,
150 cryptkey, 8);
152 /* This creates the 'blob' of names that appears at the end of the packet */
153 if (chal_flags & NTLMSSP_NEGOTIATE_TARGET_INFO)
155 status = msrpc_gen(ntlmssp_state, &struct_blob, "aaaaa",
156 MsvAvNbDomainName, target_name,
157 MsvAvNbComputerName, ntlmssp_state->server.netbios_name,
158 MsvAvDnsDomainName, ntlmssp_state->server.dns_domain,
159 MsvAvDnsComputerName, ntlmssp_state->server.dns_name,
160 MsvAvEOL, "");
161 if (!NT_STATUS_IS_OK(status)) {
162 return status;
164 } else {
165 struct_blob = data_blob_null;
169 /* Marshal the packet in the right format, be it unicode or ASCII */
170 const char *gen_string;
171 DATA_BLOB version_blob = data_blob_null;
173 if (chal_flags & NTLMSSP_NEGOTIATE_VERSION) {
174 enum ndr_err_code err;
175 struct ntlmssp_VERSION vers;
177 /* "What Windows returns" as a version number. */
178 ZERO_STRUCT(vers);
179 vers.ProductMajorVersion = NTLMSSP_WINDOWS_MAJOR_VERSION_6;
180 vers.ProductMinorVersion = NTLMSSP_WINDOWS_MINOR_VERSION_1;
181 vers.ProductBuild = 0;
182 vers.NTLMRevisionCurrent = NTLMSSP_REVISION_W2K3;
184 err = ndr_push_struct_blob(&version_blob,
185 ntlmssp_state,
186 &vers,
187 (ndr_push_flags_fn_t)ndr_push_ntlmssp_VERSION);
189 if (!NDR_ERR_CODE_IS_SUCCESS(err)) {
190 data_blob_free(&struct_blob);
191 return NT_STATUS_NO_MEMORY;
195 if (ntlmssp_state->unicode) {
196 gen_string = "CdUdbddBb";
197 } else {
198 gen_string = "CdAdbddBb";
201 status = msrpc_gen(out_mem_ctx, reply, gen_string,
202 "NTLMSSP",
203 NTLMSSP_CHALLENGE,
204 target_name,
205 chal_flags,
206 cryptkey, 8,
207 0, 0,
208 struct_blob.data, struct_blob.length,
209 version_blob.data, version_blob.length);
211 if (!NT_STATUS_IS_OK(status)) {
212 data_blob_free(&version_blob);
213 data_blob_free(&struct_blob);
214 return status;
217 data_blob_free(&version_blob);
219 if (DEBUGLEVEL >= 10) {
220 struct CHALLENGE_MESSAGE *challenge = talloc(
221 ntlmssp_state, struct CHALLENGE_MESSAGE);
222 if (challenge != NULL) {
223 challenge->NegotiateFlags = chal_flags;
224 status = ntlmssp_pull_CHALLENGE_MESSAGE(
225 reply, challenge, challenge);
226 if (NT_STATUS_IS_OK(status)) {
227 NDR_PRINT_DEBUG(CHALLENGE_MESSAGE,
228 challenge);
230 TALLOC_FREE(challenge);
235 data_blob_free(&struct_blob);
237 ntlmssp_state->expected_state = NTLMSSP_AUTH;
239 return NT_STATUS_MORE_PROCESSING_REQUIRED;
242 struct ntlmssp_server_auth_state {
243 DATA_BLOB user_session_key;
244 DATA_BLOB lm_session_key;
245 /* internal variables used by KEY_EXCH (client-supplied user session key */
246 DATA_BLOB encrypted_session_key;
247 bool doing_ntlm2;
248 /* internal variables used by NTLM2 */
249 uint8_t session_nonce[16];
253 * Next state function for the Authenticate packet
255 * @param ntlmssp_state NTLMSSP State
256 * @param request The request, as a DATA_BLOB
257 * @return Errors or NT_STATUS_OK.
260 static NTSTATUS ntlmssp_server_preauth(struct gensec_security *gensec_security,
261 struct gensec_ntlmssp_context *gensec_ntlmssp,
262 struct ntlmssp_server_auth_state *state,
263 const DATA_BLOB request)
265 struct ntlmssp_state *ntlmssp_state = gensec_ntlmssp->ntlmssp_state;
266 struct auth4_context *auth_context = gensec_security->auth_context;
267 uint32_t ntlmssp_command, auth_flags;
268 NTSTATUS nt_status;
270 uint8_t session_nonce_hash[16];
272 const char *parse_string;
274 #if 0
275 file_save("ntlmssp_auth.dat", request.data, request.length);
276 #endif
278 if (ntlmssp_state->unicode) {
279 parse_string = "CdBBUUUBd";
280 } else {
281 parse_string = "CdBBAAABd";
284 /* zero these out */
285 data_blob_free(&ntlmssp_state->session_key);
286 data_blob_free(&ntlmssp_state->lm_resp);
287 data_blob_free(&ntlmssp_state->nt_resp);
289 ntlmssp_state->user = NULL;
290 ntlmssp_state->domain = NULL;
291 ntlmssp_state->client.netbios_name = NULL;
293 /* now the NTLMSSP encoded auth hashes */
294 if (!msrpc_parse(ntlmssp_state, &request, parse_string,
295 "NTLMSSP",
296 &ntlmssp_command,
297 &ntlmssp_state->lm_resp,
298 &ntlmssp_state->nt_resp,
299 &ntlmssp_state->domain,
300 &ntlmssp_state->user,
301 &ntlmssp_state->client.netbios_name,
302 &state->encrypted_session_key,
303 &auth_flags)) {
304 DEBUG(10, ("ntlmssp_server_auth: failed to parse NTLMSSP (nonfatal):\n"));
305 dump_data(10, request.data, request.length);
307 /* zero this out */
308 data_blob_free(&state->encrypted_session_key);
309 auth_flags = 0;
311 /* Try again with a shorter string (Win9X truncates this packet) */
312 if (ntlmssp_state->unicode) {
313 parse_string = "CdBBUUU";
314 } else {
315 parse_string = "CdBBAAA";
318 /* now the NTLMSSP encoded auth hashes */
319 if (!msrpc_parse(ntlmssp_state, &request, parse_string,
320 "NTLMSSP",
321 &ntlmssp_command,
322 &ntlmssp_state->lm_resp,
323 &ntlmssp_state->nt_resp,
324 &ntlmssp_state->domain,
325 &ntlmssp_state->user,
326 &ntlmssp_state->client.netbios_name)) {
327 DEBUG(1, ("ntlmssp_server_auth: failed to parse NTLMSSP (tried both formats):\n"));
328 dump_data(2, request.data, request.length);
330 return NT_STATUS_INVALID_PARAMETER;
334 talloc_steal(state, state->encrypted_session_key.data);
336 if (auth_flags)
337 ntlmssp_handle_neg_flags(ntlmssp_state, auth_flags, ntlmssp_state->allow_lm_key);
339 if (DEBUGLEVEL >= 10) {
340 struct AUTHENTICATE_MESSAGE *authenticate = talloc(
341 ntlmssp_state, struct AUTHENTICATE_MESSAGE);
342 if (authenticate != NULL) {
343 NTSTATUS status;
344 authenticate->NegotiateFlags = auth_flags;
345 status = ntlmssp_pull_AUTHENTICATE_MESSAGE(
346 &request, authenticate, authenticate);
347 if (NT_STATUS_IS_OK(status)) {
348 NDR_PRINT_DEBUG(AUTHENTICATE_MESSAGE,
349 authenticate);
351 TALLOC_FREE(authenticate);
355 DEBUG(3,("Got user=[%s] domain=[%s] workstation=[%s] len1=%lu len2=%lu\n",
356 ntlmssp_state->user, ntlmssp_state->domain,
357 ntlmssp_state->client.netbios_name,
358 (unsigned long)ntlmssp_state->lm_resp.length,
359 (unsigned long)ntlmssp_state->nt_resp.length));
361 #if 0
362 file_save("nthash1.dat", &ntlmssp_state->nt_resp.data, &ntlmssp_state->nt_resp.length);
363 file_save("lmhash1.dat", &ntlmssp_state->lm_resp.data, &ntlmssp_state->lm_resp.length);
364 #endif
366 /* NTLM2 uses a 'challenge' that is made of up both the server challenge, and a
367 client challenge
369 However, the NTLM2 flag may still be set for the real NTLMv2 logins, be careful.
371 if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_NTLM2) {
372 if (ntlmssp_state->nt_resp.length == 24 && ntlmssp_state->lm_resp.length == 24) {
373 MD5_CTX md5_session_nonce_ctx;
374 state->doing_ntlm2 = true;
376 memcpy(state->session_nonce, ntlmssp_state->internal_chal.data, 8);
377 memcpy(&state->session_nonce[8], ntlmssp_state->lm_resp.data, 8);
379 SMB_ASSERT(ntlmssp_state->internal_chal.data && ntlmssp_state->internal_chal.length == 8);
381 MD5Init(&md5_session_nonce_ctx);
382 MD5Update(&md5_session_nonce_ctx, state->session_nonce, 16);
383 MD5Final(session_nonce_hash, &md5_session_nonce_ctx);
385 /* LM response is no longer useful */
386 data_blob_free(&ntlmssp_state->lm_resp);
388 /* We changed the effective challenge - set it */
389 if (auth_context->set_ntlm_challenge) {
390 nt_status = auth_context->set_ntlm_challenge(auth_context,
391 session_nonce_hash,
392 "NTLMSSP callback (NTLM2)");
393 if (!NT_STATUS_IS_OK(nt_status)) {
394 DEBUG(1, ("gensec_ntlmssp_server_negotiate: failed to get challenge: %s\n",
395 nt_errstr(nt_status)));
396 return nt_status;
398 } else {
399 DEBUG(1, ("gensec_ntlmssp_server_negotiate: backend doesn't have facility for challenge to be set\n"));
401 return NT_STATUS_NOT_IMPLEMENTED;
404 /* LM Key is incompatible. */
405 ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_LM_KEY;
408 return NT_STATUS_OK;
412 * Check the password on an NTLMSSP login.
414 * Return the session keys used on the connection.
417 static NTSTATUS ntlmssp_server_check_password(struct gensec_security *gensec_security,
418 struct gensec_ntlmssp_context *gensec_ntlmssp,
419 TALLOC_CTX *mem_ctx,
420 DATA_BLOB *user_session_key, DATA_BLOB *lm_session_key)
422 struct ntlmssp_state *ntlmssp_state = gensec_ntlmssp->ntlmssp_state;
423 struct auth4_context *auth_context = gensec_security->auth_context;
424 NTSTATUS nt_status = NT_STATUS_NOT_IMPLEMENTED;
425 struct auth_usersupplied_info *user_info;
427 user_info = talloc_zero(ntlmssp_state, struct auth_usersupplied_info);
428 if (!user_info) {
429 return NT_STATUS_NO_MEMORY;
432 user_info->logon_parameters = MSV1_0_ALLOW_SERVER_TRUST_ACCOUNT | MSV1_0_ALLOW_WORKSTATION_TRUST_ACCOUNT;
433 user_info->flags = 0;
434 user_info->mapped_state = false;
435 user_info->client.account_name = ntlmssp_state->user;
436 user_info->client.domain_name = ntlmssp_state->domain;
437 user_info->workstation_name = ntlmssp_state->client.netbios_name;
438 user_info->remote_host = gensec_get_remote_address(gensec_security);
440 user_info->password_state = AUTH_PASSWORD_RESPONSE;
441 user_info->password.response.lanman = ntlmssp_state->lm_resp;
442 user_info->password.response.lanman.data = talloc_steal(user_info, ntlmssp_state->lm_resp.data);
443 user_info->password.response.nt = ntlmssp_state->nt_resp;
444 user_info->password.response.nt.data = talloc_steal(user_info, ntlmssp_state->nt_resp.data);
446 if (auth_context->check_ntlm_password) {
447 nt_status = auth_context->check_ntlm_password(auth_context,
448 gensec_ntlmssp,
449 user_info,
450 &gensec_ntlmssp->server_returned_info,
451 user_session_key, lm_session_key);
454 if (!NT_STATUS_IS_OK(nt_status)) {
455 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)));
457 TALLOC_FREE(user_info);
459 NT_STATUS_NOT_OK_RETURN(nt_status);
461 talloc_steal(mem_ctx, user_session_key->data);
462 talloc_steal(mem_ctx, lm_session_key->data);
464 return nt_status;
468 * Next state function for the Authenticate packet
469 * (after authentication - figures out the session keys etc)
471 * @param ntlmssp_state NTLMSSP State
472 * @return Errors or NT_STATUS_OK.
475 static NTSTATUS ntlmssp_server_postauth(struct gensec_security *gensec_security,
476 struct gensec_ntlmssp_context *gensec_ntlmssp,
477 struct ntlmssp_server_auth_state *state)
479 struct ntlmssp_state *ntlmssp_state = gensec_ntlmssp->ntlmssp_state;
480 DATA_BLOB user_session_key = state->user_session_key;
481 DATA_BLOB lm_session_key = state->lm_session_key;
482 NTSTATUS nt_status = NT_STATUS_OK;
483 DATA_BLOB session_key = data_blob(NULL, 0);
485 dump_data_pw("NT session key:\n", user_session_key.data, user_session_key.length);
486 dump_data_pw("LM first-8:\n", lm_session_key.data, lm_session_key.length);
488 /* Handle the different session key derivation for NTLM2 */
489 if (state->doing_ntlm2) {
490 if (user_session_key.data && user_session_key.length == 16) {
491 session_key = data_blob_talloc(ntlmssp_state,
492 NULL, 16);
493 hmac_md5(user_session_key.data, state->session_nonce,
494 sizeof(state->session_nonce), session_key.data);
495 DEBUG(10,("ntlmssp_server_auth: Created NTLM2 session key.\n"));
496 dump_data_pw("NTLM2 session key:\n", session_key.data, session_key.length);
498 } else {
499 DEBUG(10,("ntlmssp_server_auth: Failed to create NTLM2 session key.\n"));
500 session_key = data_blob_null;
502 } else if ((ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_LM_KEY)
503 /* Ensure we can never get here on NTLMv2 */
504 && (ntlmssp_state->nt_resp.length == 0 || ntlmssp_state->nt_resp.length == 24)) {
506 if (lm_session_key.data && lm_session_key.length >= 8) {
507 if (ntlmssp_state->lm_resp.data && ntlmssp_state->lm_resp.length == 24) {
508 session_key = data_blob_talloc(ntlmssp_state,
509 NULL, 16);
510 if (session_key.data == NULL) {
511 return NT_STATUS_NO_MEMORY;
513 SMBsesskeygen_lm_sess_key(lm_session_key.data, ntlmssp_state->lm_resp.data,
514 session_key.data);
515 DEBUG(10,("ntlmssp_server_auth: Created NTLM session key.\n"));
516 } else {
517 static const uint8_t zeros[24] = {0, };
518 session_key = data_blob_talloc(
519 ntlmssp_state, NULL, 16);
520 if (session_key.data == NULL) {
521 return NT_STATUS_NO_MEMORY;
523 SMBsesskeygen_lm_sess_key(zeros, zeros,
524 session_key.data);
525 DEBUG(10,("ntlmssp_server_auth: Created NTLM session key.\n"));
527 dump_data_pw("LM session key:\n", session_key.data,
528 session_key.length);
529 } else {
530 /* LM Key not selected */
531 ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_LM_KEY;
533 DEBUG(10,("ntlmssp_server_auth: Failed to create NTLM session key.\n"));
534 session_key = data_blob_null;
537 } else if (user_session_key.data) {
538 session_key = user_session_key;
539 DEBUG(10,("ntlmssp_server_auth: Using unmodified nt session key.\n"));
540 dump_data_pw("unmodified session key:\n", session_key.data, session_key.length);
542 /* LM Key not selected */
543 ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_LM_KEY;
545 } else if (lm_session_key.data) {
546 /* Very weird to have LM key, but no user session key, but anyway.. */
547 session_key = lm_session_key;
548 DEBUG(10,("ntlmssp_server_auth: Using unmodified lm session key.\n"));
549 dump_data_pw("unmodified session key:\n", session_key.data, session_key.length);
551 /* LM Key not selected */
552 ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_LM_KEY;
554 } else {
555 DEBUG(10,("ntlmssp_server_auth: Failed to create unmodified session key.\n"));
556 session_key = data_blob_null;
558 /* LM Key not selected */
559 ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_LM_KEY;
562 /* With KEY_EXCH, the client supplies the proposed session key,
563 but encrypts it with the long-term key */
564 if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_KEY_EXCH) {
565 if (!state->encrypted_session_key.data
566 || state->encrypted_session_key.length != 16) {
567 DEBUG(1, ("Client-supplied KEY_EXCH session key was of invalid length (%u)!\n",
568 (unsigned)state->encrypted_session_key.length));
569 return NT_STATUS_INVALID_PARAMETER;
570 } else if (!session_key.data || session_key.length != 16) {
571 DEBUG(5, ("server session key is invalid (len == %u), cannot do KEY_EXCH!\n",
572 (unsigned int)session_key.length));
573 ntlmssp_state->session_key = session_key;
574 talloc_steal(ntlmssp_state, session_key.data);
575 } else {
576 dump_data_pw("KEY_EXCH session key (enc):\n",
577 state->encrypted_session_key.data,
578 state->encrypted_session_key.length);
579 arcfour_crypt(state->encrypted_session_key.data,
580 session_key.data,
581 state->encrypted_session_key.length);
582 ntlmssp_state->session_key = data_blob_talloc(ntlmssp_state,
583 state->encrypted_session_key.data,
584 state->encrypted_session_key.length);
585 dump_data_pw("KEY_EXCH session key:\n",
586 state->encrypted_session_key.data,
587 state->encrypted_session_key.length);
589 } else {
590 ntlmssp_state->session_key = session_key;
591 talloc_steal(ntlmssp_state, session_key.data);
594 if (ntlmssp_state->session_key.length) {
595 nt_status = ntlmssp_sign_init(ntlmssp_state);
598 ntlmssp_state->expected_state = NTLMSSP_DONE;
600 return nt_status;
605 * Next state function for the NTLMSSP Authenticate packet
607 * @param gensec_security GENSEC state
608 * @param out_mem_ctx Memory context for *out
609 * @param in The request, as a DATA_BLOB. reply.data must be NULL
610 * @param out The reply, as an allocated DATA_BLOB, caller to free.
611 * @return Errors or NT_STATUS_OK if authentication sucessful
614 NTSTATUS gensec_ntlmssp_server_auth(struct gensec_security *gensec_security,
615 TALLOC_CTX *out_mem_ctx,
616 const DATA_BLOB in, DATA_BLOB *out)
618 struct gensec_ntlmssp_context *gensec_ntlmssp =
619 talloc_get_type_abort(gensec_security->private_data,
620 struct gensec_ntlmssp_context);
621 struct ntlmssp_server_auth_state *state;
622 NTSTATUS nt_status;
624 /* zero the outbound NTLMSSP packet */
625 *out = data_blob_null;
627 state = talloc_zero(gensec_ntlmssp, struct ntlmssp_server_auth_state);
628 if (state == NULL) {
629 return NT_STATUS_NO_MEMORY;
632 nt_status = ntlmssp_server_preauth(gensec_security, gensec_ntlmssp, state, in);
633 if (!NT_STATUS_IS_OK(nt_status)) {
634 TALLOC_FREE(state);
635 return nt_status;
639 * Note we don't check here for NTLMv2 auth settings. If NTLMv2 auth
640 * is required (by "ntlm auth = no" and "lm auth = no" being set in the
641 * smb.conf file) and no NTLMv2 response was sent then the password check
642 * will fail here. JRA.
645 /* Finally, actually ask if the password is OK */
646 nt_status = ntlmssp_server_check_password(gensec_security, gensec_ntlmssp,
647 state,
648 &state->user_session_key,
649 &state->lm_session_key);
650 if (!NT_STATUS_IS_OK(nt_status)) {
651 TALLOC_FREE(state);
652 return nt_status;
655 /* When we get more async in the auth code behind
656 ntlmssp_state->check_password, the ntlmssp_server_postpath
657 can be done in a callback */
659 nt_status = ntlmssp_server_postauth(gensec_security, gensec_ntlmssp, state);
660 TALLOC_FREE(state);
661 return nt_status;