packaging(RHEL-CTDB): package the fake-acls vfs module
[Samba/gbeck.git] / auth / ntlmssp / ntlmssp_server.c
blobd9bea1cde4b97734ff8e2bc7e2e0b93789b49ee9
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/common_auth.h"
33 /**
34 * Determine correct target name flags for reply, given server role
35 * and negotiated flags
37 * @param ntlmssp_state NTLMSSP State
38 * @param neg_flags The flags from the packet
39 * @param chal_flags The flags to be set in the reply packet
40 * @return The 'target name' string.
43 const char *ntlmssp_target_name(struct ntlmssp_state *ntlmssp_state,
44 uint32_t neg_flags, uint32_t *chal_flags)
46 if (neg_flags & NTLMSSP_REQUEST_TARGET) {
47 *chal_flags |= NTLMSSP_NEGOTIATE_TARGET_INFO;
48 *chal_flags |= NTLMSSP_REQUEST_TARGET;
49 if (ntlmssp_state->server.is_standalone) {
50 *chal_flags |= NTLMSSP_TARGET_TYPE_SERVER;
51 return ntlmssp_state->server.netbios_name;
52 } else {
53 *chal_flags |= NTLMSSP_TARGET_TYPE_DOMAIN;
54 return ntlmssp_state->server.netbios_domain;
56 } else {
57 return "";
61 /**
62 * Next state function for the NTLMSSP Negotiate packet
64 * @param gensec_security GENSEC state
65 * @param out_mem_ctx Memory context for *out
66 * @param in The request, as a DATA_BLOB. reply.data must be NULL
67 * @param out The reply, as an allocated DATA_BLOB, caller to free.
68 * @return Errors or MORE_PROCESSING_REQUIRED if (normal) a reply is required.
71 NTSTATUS gensec_ntlmssp_server_negotiate(struct gensec_security *gensec_security,
72 TALLOC_CTX *out_mem_ctx,
73 const DATA_BLOB request, DATA_BLOB *reply)
75 struct gensec_ntlmssp_context *gensec_ntlmssp =
76 talloc_get_type_abort(gensec_security->private_data,
77 struct gensec_ntlmssp_context);
78 struct ntlmssp_state *ntlmssp_state = gensec_ntlmssp->ntlmssp_state;
79 struct auth4_context *auth_context = gensec_security->auth_context;
80 DATA_BLOB struct_blob;
81 uint32_t neg_flags = 0;
82 uint32_t ntlmssp_command, chal_flags;
83 uint8_t cryptkey[8];
84 const char *target_name;
85 NTSTATUS status;
87 /* parse the NTLMSSP packet */
88 #if 0
89 file_save("ntlmssp_negotiate.dat", request.data, request.length);
90 #endif
92 if (request.length) {
93 if ((request.length < 16) || !msrpc_parse(ntlmssp_state, &request, "Cdd",
94 "NTLMSSP",
95 &ntlmssp_command,
96 &neg_flags)) {
97 DEBUG(1, ("ntlmssp_server_negotiate: failed to parse NTLMSSP Negotiate of length %u\n",
98 (unsigned int)request.length));
99 dump_data(2, request.data, request.length);
100 return NT_STATUS_INVALID_PARAMETER;
102 debug_ntlmssp_flags(neg_flags);
104 if (DEBUGLEVEL >= 10) {
105 struct NEGOTIATE_MESSAGE *negotiate = talloc(
106 ntlmssp_state, struct NEGOTIATE_MESSAGE);
107 if (negotiate != NULL) {
108 status = ntlmssp_pull_NEGOTIATE_MESSAGE(
109 &request, negotiate, negotiate);
110 if (NT_STATUS_IS_OK(status)) {
111 NDR_PRINT_DEBUG(NEGOTIATE_MESSAGE,
112 negotiate);
114 TALLOC_FREE(negotiate);
119 ntlmssp_handle_neg_flags(ntlmssp_state, neg_flags, ntlmssp_state->allow_lm_key);
121 /* Ask our caller what challenge they would like in the packet */
122 if (auth_context->get_ntlm_challenge) {
123 status = auth_context->get_ntlm_challenge(auth_context, cryptkey);
124 if (!NT_STATUS_IS_OK(status)) {
125 DEBUG(1, ("gensec_ntlmssp_server_negotiate: failed to get challenge: %s\n",
126 nt_errstr(status)));
127 return status;
129 } else {
130 DEBUG(1, ("gensec_ntlmssp_server_negotiate: backend doesn't give a challenge\n"));
131 return NT_STATUS_NOT_IMPLEMENTED;
134 /* The flags we send back are not just the negotiated flags,
135 * they are also 'what is in this packet'. Therfore, we
136 * operate on 'chal_flags' from here on
139 chal_flags = ntlmssp_state->neg_flags;
141 /* get the right name to fill in as 'target' */
142 target_name = ntlmssp_target_name(ntlmssp_state,
143 neg_flags, &chal_flags);
144 if (target_name == NULL)
145 return NT_STATUS_INVALID_PARAMETER;
147 ntlmssp_state->chal = data_blob_talloc(ntlmssp_state, cryptkey, 8);
148 ntlmssp_state->internal_chal = data_blob_talloc(ntlmssp_state,
149 cryptkey, 8);
151 /* This creates the 'blob' of names that appears at the end of the packet */
152 if (chal_flags & NTLMSSP_NEGOTIATE_TARGET_INFO)
154 status = msrpc_gen(ntlmssp_state, &struct_blob, "aaaaa",
155 MsvAvNbDomainName, target_name,
156 MsvAvNbComputerName, ntlmssp_state->server.netbios_name,
157 MsvAvDnsDomainName, ntlmssp_state->server.dns_domain,
158 MsvAvDnsComputerName, ntlmssp_state->server.dns_name,
159 MsvAvEOL, "");
160 if (!NT_STATUS_IS_OK(status)) {
161 return status;
163 } else {
164 struct_blob = data_blob_null;
168 /* Marshal the packet in the right format, be it unicode or ASCII */
169 const char *gen_string;
170 DATA_BLOB version_blob = data_blob_null;
172 if (chal_flags & NTLMSSP_NEGOTIATE_VERSION) {
173 enum ndr_err_code err;
174 struct ntlmssp_VERSION vers;
176 /* "What Windows returns" as a version number. */
177 ZERO_STRUCT(vers);
178 vers.ProductMajorVersion = NTLMSSP_WINDOWS_MAJOR_VERSION_6;
179 vers.ProductMinorVersion = NTLMSSP_WINDOWS_MINOR_VERSION_1;
180 vers.ProductBuild = 0;
181 vers.NTLMRevisionCurrent = NTLMSSP_REVISION_W2K3;
183 err = ndr_push_struct_blob(&version_blob,
184 ntlmssp_state,
185 &vers,
186 (ndr_push_flags_fn_t)ndr_push_ntlmssp_VERSION);
188 if (!NDR_ERR_CODE_IS_SUCCESS(err)) {
189 data_blob_free(&struct_blob);
190 return NT_STATUS_NO_MEMORY;
194 if (ntlmssp_state->unicode) {
195 gen_string = "CdUdbddBb";
196 } else {
197 gen_string = "CdAdbddBb";
200 status = msrpc_gen(out_mem_ctx, reply, gen_string,
201 "NTLMSSP",
202 NTLMSSP_CHALLENGE,
203 target_name,
204 chal_flags,
205 cryptkey, 8,
206 0, 0,
207 struct_blob.data, struct_blob.length,
208 version_blob.data, version_blob.length);
210 if (!NT_STATUS_IS_OK(status)) {
211 data_blob_free(&version_blob);
212 data_blob_free(&struct_blob);
213 return status;
216 data_blob_free(&version_blob);
218 if (DEBUGLEVEL >= 10) {
219 struct CHALLENGE_MESSAGE *challenge = talloc(
220 ntlmssp_state, struct CHALLENGE_MESSAGE);
221 if (challenge != NULL) {
222 challenge->NegotiateFlags = chal_flags;
223 status = ntlmssp_pull_CHALLENGE_MESSAGE(
224 reply, challenge, challenge);
225 if (NT_STATUS_IS_OK(status)) {
226 NDR_PRINT_DEBUG(CHALLENGE_MESSAGE,
227 challenge);
229 TALLOC_FREE(challenge);
234 data_blob_free(&struct_blob);
236 ntlmssp_state->expected_state = NTLMSSP_AUTH;
238 return NT_STATUS_MORE_PROCESSING_REQUIRED;
241 struct ntlmssp_server_auth_state {
242 DATA_BLOB user_session_key;
243 DATA_BLOB lm_session_key;
244 /* internal variables used by KEY_EXCH (client-supplied user session key */
245 DATA_BLOB encrypted_session_key;
246 bool doing_ntlm2;
247 /* internal variables used by NTLM2 */
248 uint8_t session_nonce[16];
252 * Next state function for the Authenticate packet
254 * @param ntlmssp_state NTLMSSP State
255 * @param request The request, as a DATA_BLOB
256 * @return Errors or NT_STATUS_OK.
259 static NTSTATUS ntlmssp_server_preauth(struct gensec_security *gensec_security,
260 struct gensec_ntlmssp_context *gensec_ntlmssp,
261 struct ntlmssp_server_auth_state *state,
262 const DATA_BLOB request)
264 struct ntlmssp_state *ntlmssp_state = gensec_ntlmssp->ntlmssp_state;
265 struct auth4_context *auth_context = gensec_security->auth_context;
266 uint32_t ntlmssp_command, auth_flags;
267 NTSTATUS nt_status;
269 uint8_t session_nonce_hash[16];
271 const char *parse_string;
273 #if 0
274 file_save("ntlmssp_auth.dat", request.data, request.length);
275 #endif
277 if (ntlmssp_state->unicode) {
278 parse_string = "CdBBUUUBd";
279 } else {
280 parse_string = "CdBBAAABd";
283 /* zero these out */
284 data_blob_free(&ntlmssp_state->session_key);
285 data_blob_free(&ntlmssp_state->lm_resp);
286 data_blob_free(&ntlmssp_state->nt_resp);
288 ntlmssp_state->user = NULL;
289 ntlmssp_state->domain = NULL;
290 ntlmssp_state->client.netbios_name = NULL;
292 /* now the NTLMSSP encoded auth hashes */
293 if (!msrpc_parse(ntlmssp_state, &request, parse_string,
294 "NTLMSSP",
295 &ntlmssp_command,
296 &ntlmssp_state->lm_resp,
297 &ntlmssp_state->nt_resp,
298 &ntlmssp_state->domain,
299 &ntlmssp_state->user,
300 &ntlmssp_state->client.netbios_name,
301 &state->encrypted_session_key,
302 &auth_flags)) {
303 DEBUG(10, ("ntlmssp_server_auth: failed to parse NTLMSSP (nonfatal):\n"));
304 dump_data(10, request.data, request.length);
306 /* zero this out */
307 data_blob_free(&state->encrypted_session_key);
308 auth_flags = 0;
310 /* Try again with a shorter string (Win9X truncates this packet) */
311 if (ntlmssp_state->unicode) {
312 parse_string = "CdBBUUU";
313 } else {
314 parse_string = "CdBBAAA";
317 /* now the NTLMSSP encoded auth hashes */
318 if (!msrpc_parse(ntlmssp_state, &request, parse_string,
319 "NTLMSSP",
320 &ntlmssp_command,
321 &ntlmssp_state->lm_resp,
322 &ntlmssp_state->nt_resp,
323 &ntlmssp_state->domain,
324 &ntlmssp_state->user,
325 &ntlmssp_state->client.netbios_name)) {
326 DEBUG(1, ("ntlmssp_server_auth: failed to parse NTLMSSP (tried both formats):\n"));
327 dump_data(2, request.data, request.length);
329 return NT_STATUS_INVALID_PARAMETER;
333 talloc_steal(state, state->encrypted_session_key.data);
335 if (auth_flags)
336 ntlmssp_handle_neg_flags(ntlmssp_state, auth_flags, ntlmssp_state->allow_lm_key);
338 if (DEBUGLEVEL >= 10) {
339 struct AUTHENTICATE_MESSAGE *authenticate = talloc(
340 ntlmssp_state, struct AUTHENTICATE_MESSAGE);
341 if (authenticate != NULL) {
342 NTSTATUS status;
343 authenticate->NegotiateFlags = auth_flags;
344 status = ntlmssp_pull_AUTHENTICATE_MESSAGE(
345 &request, authenticate, authenticate);
346 if (NT_STATUS_IS_OK(status)) {
347 NDR_PRINT_DEBUG(AUTHENTICATE_MESSAGE,
348 authenticate);
350 TALLOC_FREE(authenticate);
354 DEBUG(3,("Got user=[%s] domain=[%s] workstation=[%s] len1=%lu len2=%lu\n",
355 ntlmssp_state->user, ntlmssp_state->domain,
356 ntlmssp_state->client.netbios_name,
357 (unsigned long)ntlmssp_state->lm_resp.length,
358 (unsigned long)ntlmssp_state->nt_resp.length));
360 #if 0
361 file_save("nthash1.dat", &ntlmssp_state->nt_resp.data, &ntlmssp_state->nt_resp.length);
362 file_save("lmhash1.dat", &ntlmssp_state->lm_resp.data, &ntlmssp_state->lm_resp.length);
363 #endif
365 /* NTLM2 uses a 'challenge' that is made of up both the server challenge, and a
366 client challenge
368 However, the NTLM2 flag may still be set for the real NTLMv2 logins, be careful.
370 if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_NTLM2) {
371 if (ntlmssp_state->nt_resp.length == 24 && ntlmssp_state->lm_resp.length == 24) {
372 struct MD5Context md5_session_nonce_ctx;
373 state->doing_ntlm2 = true;
375 memcpy(state->session_nonce, ntlmssp_state->internal_chal.data, 8);
376 memcpy(&state->session_nonce[8], ntlmssp_state->lm_resp.data, 8);
378 SMB_ASSERT(ntlmssp_state->internal_chal.data && ntlmssp_state->internal_chal.length == 8);
380 MD5Init(&md5_session_nonce_ctx);
381 MD5Update(&md5_session_nonce_ctx, state->session_nonce, 16);
382 MD5Final(session_nonce_hash, &md5_session_nonce_ctx);
384 /* LM response is no longer useful */
385 data_blob_free(&ntlmssp_state->lm_resp);
387 /* We changed the effective challenge - set it */
388 if (auth_context->set_ntlm_challenge) {
389 nt_status = auth_context->set_ntlm_challenge(auth_context,
390 session_nonce_hash,
391 "NTLMSSP callback (NTLM2)");
392 if (!NT_STATUS_IS_OK(nt_status)) {
393 DEBUG(1, ("gensec_ntlmssp_server_negotiate: failed to get challenge: %s\n",
394 nt_errstr(nt_status)));
395 return nt_status;
397 } else {
398 DEBUG(1, ("gensec_ntlmssp_server_negotiate: backend doesn't have facility for challenge to be set\n"));
400 return NT_STATUS_NOT_IMPLEMENTED;
403 /* LM Key is incompatible. */
404 ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_LM_KEY;
407 return NT_STATUS_OK;
411 * Check the password on an NTLMSSP login.
413 * Return the session keys used on the connection.
416 static NTSTATUS ntlmssp_server_check_password(struct gensec_security *gensec_security,
417 struct gensec_ntlmssp_context *gensec_ntlmssp,
418 TALLOC_CTX *mem_ctx,
419 DATA_BLOB *user_session_key, DATA_BLOB *lm_session_key)
421 struct ntlmssp_state *ntlmssp_state = gensec_ntlmssp->ntlmssp_state;
422 struct auth4_context *auth_context = gensec_security->auth_context;
423 NTSTATUS nt_status = NT_STATUS_NOT_IMPLEMENTED;
424 struct auth_usersupplied_info *user_info;
426 user_info = talloc_zero(ntlmssp_state, struct auth_usersupplied_info);
427 if (!user_info) {
428 return NT_STATUS_NO_MEMORY;
431 user_info->logon_parameters = MSV1_0_ALLOW_SERVER_TRUST_ACCOUNT | MSV1_0_ALLOW_WORKSTATION_TRUST_ACCOUNT;
432 user_info->flags = 0;
433 user_info->mapped_state = false;
434 user_info->client.account_name = ntlmssp_state->user;
435 user_info->client.domain_name = ntlmssp_state->domain;
436 user_info->workstation_name = ntlmssp_state->client.netbios_name;
437 user_info->remote_host = gensec_get_remote_address(gensec_security);
439 user_info->password_state = AUTH_PASSWORD_RESPONSE;
440 user_info->password.response.lanman = ntlmssp_state->lm_resp;
441 user_info->password.response.lanman.data = talloc_steal(user_info, ntlmssp_state->lm_resp.data);
442 user_info->password.response.nt = ntlmssp_state->nt_resp;
443 user_info->password.response.nt.data = talloc_steal(user_info, ntlmssp_state->nt_resp.data);
445 if (auth_context->check_ntlm_password) {
446 nt_status = auth_context->check_ntlm_password(auth_context,
447 gensec_ntlmssp,
448 user_info,
449 &gensec_ntlmssp->server_returned_info,
450 user_session_key, lm_session_key);
452 talloc_free(user_info);
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)));
458 NT_STATUS_NOT_OK_RETURN(nt_status);
460 talloc_steal(mem_ctx, user_session_key->data);
461 talloc_steal(mem_ctx, lm_session_key->data);
463 return nt_status;
467 * Next state function for the Authenticate packet
468 * (after authentication - figures out the session keys etc)
470 * @param ntlmssp_state NTLMSSP State
471 * @return Errors or NT_STATUS_OK.
474 static NTSTATUS ntlmssp_server_postauth(struct gensec_security *gensec_security,
475 struct gensec_ntlmssp_context *gensec_ntlmssp,
476 struct ntlmssp_server_auth_state *state)
478 struct ntlmssp_state *ntlmssp_state = gensec_ntlmssp->ntlmssp_state;
479 DATA_BLOB user_session_key = state->user_session_key;
480 DATA_BLOB lm_session_key = state->lm_session_key;
481 NTSTATUS nt_status = NT_STATUS_OK;
482 DATA_BLOB session_key = data_blob(NULL, 0);
484 dump_data_pw("NT session key:\n", user_session_key.data, user_session_key.length);
485 dump_data_pw("LM first-8:\n", lm_session_key.data, lm_session_key.length);
487 /* Handle the different session key derivation for NTLM2 */
488 if (state->doing_ntlm2) {
489 if (user_session_key.data && user_session_key.length == 16) {
490 session_key = data_blob_talloc(ntlmssp_state,
491 NULL, 16);
492 hmac_md5(user_session_key.data, state->session_nonce,
493 sizeof(state->session_nonce), session_key.data);
494 DEBUG(10,("ntlmssp_server_auth: Created NTLM2 session key.\n"));
495 dump_data_pw("NTLM2 session key:\n", session_key.data, session_key.length);
497 } else {
498 DEBUG(10,("ntlmssp_server_auth: Failed to create NTLM2 session key.\n"));
499 session_key = data_blob_null;
501 } else if ((ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_LM_KEY)
502 /* Ensure we can never get here on NTLMv2 */
503 && (ntlmssp_state->nt_resp.length == 0 || ntlmssp_state->nt_resp.length == 24)) {
505 if (lm_session_key.data && lm_session_key.length >= 8) {
506 if (ntlmssp_state->lm_resp.data && ntlmssp_state->lm_resp.length == 24) {
507 session_key = data_blob_talloc(ntlmssp_state,
508 NULL, 16);
509 if (session_key.data == NULL) {
510 return NT_STATUS_NO_MEMORY;
512 SMBsesskeygen_lm_sess_key(lm_session_key.data, ntlmssp_state->lm_resp.data,
513 session_key.data);
514 DEBUG(10,("ntlmssp_server_auth: Created NTLM session key.\n"));
515 } else {
516 static const uint8_t zeros[24] = {0, };
517 session_key = data_blob_talloc(
518 ntlmssp_state, NULL, 16);
519 if (session_key.data == NULL) {
520 return NT_STATUS_NO_MEMORY;
522 SMBsesskeygen_lm_sess_key(zeros, zeros,
523 session_key.data);
524 DEBUG(10,("ntlmssp_server_auth: Created NTLM session key.\n"));
526 dump_data_pw("LM session key:\n", session_key.data,
527 session_key.length);
528 } else {
529 /* LM Key not selected */
530 ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_LM_KEY;
532 DEBUG(10,("ntlmssp_server_auth: Failed to create NTLM session key.\n"));
533 session_key = data_blob_null;
536 } else if (user_session_key.data) {
537 session_key = user_session_key;
538 DEBUG(10,("ntlmssp_server_auth: Using unmodified nt session key.\n"));
539 dump_data_pw("unmodified session key:\n", session_key.data, session_key.length);
541 /* LM Key not selected */
542 ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_LM_KEY;
544 } else if (lm_session_key.data) {
545 /* Very weird to have LM key, but no user session key, but anyway.. */
546 session_key = lm_session_key;
547 DEBUG(10,("ntlmssp_server_auth: Using unmodified lm session key.\n"));
548 dump_data_pw("unmodified session key:\n", session_key.data, session_key.length);
550 /* LM Key not selected */
551 ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_LM_KEY;
553 } else {
554 DEBUG(10,("ntlmssp_server_auth: Failed to create unmodified session key.\n"));
555 session_key = data_blob_null;
557 /* LM Key not selected */
558 ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_LM_KEY;
561 /* With KEY_EXCH, the client supplies the proposed session key,
562 but encrypts it with the long-term key */
563 if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_KEY_EXCH) {
564 if (!state->encrypted_session_key.data
565 || state->encrypted_session_key.length != 16) {
566 DEBUG(1, ("Client-supplied KEY_EXCH session key was of invalid length (%u)!\n",
567 (unsigned)state->encrypted_session_key.length));
568 return NT_STATUS_INVALID_PARAMETER;
569 } else if (!session_key.data || session_key.length != 16) {
570 DEBUG(5, ("server session key is invalid (len == %u), cannot do KEY_EXCH!\n",
571 (unsigned int)session_key.length));
572 ntlmssp_state->session_key = session_key;
573 talloc_steal(ntlmssp_state, session_key.data);
574 } else {
575 dump_data_pw("KEY_EXCH session key (enc):\n",
576 state->encrypted_session_key.data,
577 state->encrypted_session_key.length);
578 arcfour_crypt(state->encrypted_session_key.data,
579 session_key.data,
580 state->encrypted_session_key.length);
581 ntlmssp_state->session_key = data_blob_talloc(ntlmssp_state,
582 state->encrypted_session_key.data,
583 state->encrypted_session_key.length);
584 dump_data_pw("KEY_EXCH session key:\n",
585 state->encrypted_session_key.data,
586 state->encrypted_session_key.length);
588 } else {
589 ntlmssp_state->session_key = session_key;
590 talloc_steal(ntlmssp_state, session_key.data);
593 if (ntlmssp_state->session_key.length) {
594 nt_status = ntlmssp_sign_init(ntlmssp_state);
597 ntlmssp_state->expected_state = NTLMSSP_DONE;
599 return nt_status;
604 * Next state function for the NTLMSSP Authenticate packet
606 * @param gensec_security GENSEC state
607 * @param out_mem_ctx Memory context for *out
608 * @param in The request, as a DATA_BLOB. reply.data must be NULL
609 * @param out The reply, as an allocated DATA_BLOB, caller to free.
610 * @return Errors or NT_STATUS_OK if authentication sucessful
613 NTSTATUS gensec_ntlmssp_server_auth(struct gensec_security *gensec_security,
614 TALLOC_CTX *out_mem_ctx,
615 const DATA_BLOB in, DATA_BLOB *out)
617 struct gensec_ntlmssp_context *gensec_ntlmssp =
618 talloc_get_type_abort(gensec_security->private_data,
619 struct gensec_ntlmssp_context);
620 struct ntlmssp_server_auth_state *state;
621 NTSTATUS nt_status;
623 /* zero the outbound NTLMSSP packet */
624 *out = data_blob_null;
626 state = talloc_zero(gensec_ntlmssp, struct ntlmssp_server_auth_state);
627 if (state == NULL) {
628 return NT_STATUS_NO_MEMORY;
631 nt_status = ntlmssp_server_preauth(gensec_security, gensec_ntlmssp, state, in);
632 if (!NT_STATUS_IS_OK(nt_status)) {
633 TALLOC_FREE(state);
634 return nt_status;
638 * Note we don't check here for NTLMv2 auth settings. If NTLMv2 auth
639 * is required (by "ntlm auth = no" and "lm auth = no" being set in the
640 * smb.conf file) and no NTLMv2 response was sent then the password check
641 * will fail here. JRA.
644 /* Finally, actually ask if the password is OK */
645 nt_status = ntlmssp_server_check_password(gensec_security, gensec_ntlmssp,
646 state,
647 &state->user_session_key,
648 &state->lm_session_key);
649 if (!NT_STATUS_IS_OK(nt_status)) {
650 TALLOC_FREE(state);
651 return nt_status;
654 /* When we get more async in the auth code behind
655 ntlmssp_state->check_password, the ntlmssp_server_postpath
656 can be done in a callback */
658 nt_status = ntlmssp_server_postauth(gensec_security, gensec_ntlmssp, state);
659 TALLOC_FREE(state);
660 return nt_status;