2 Unix SMB/Netbios implementation.
4 handle NLTMSSP, server side
6 Copyright (C) Andrew Tridgell 2001
7 Copyright (C) Andrew Bartlett 2001-2003
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 2 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, write to the Free Software
21 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
27 /* we currently do not know how to get the right session key for this, so
28 we cannot enable it by default... :-( */
33 * Print out the NTLMSSP flags for debugging
34 * @param neg_flags The flags from the packet
37 void debug_ntlmssp_flags(uint32 neg_flags
)
39 DEBUG(3,("Got NTLMSSP neg_flags=0x%08x\n", neg_flags
));
41 if (neg_flags
& NTLMSSP_NEGOTIATE_UNICODE
)
42 DEBUGADD(4, (" NTLMSSP_NEGOTIATE_UNICODE\n"));
43 if (neg_flags
& NTLMSSP_NEGOTIATE_OEM
)
44 DEBUGADD(4, (" NTLMSSP_NEGOTIATE_OEM\n"));
45 if (neg_flags
& NTLMSSP_REQUEST_TARGET
)
46 DEBUGADD(4, (" NTLMSSP_REQUEST_TARGET\n"));
47 if (neg_flags
& NTLMSSP_NEGOTIATE_SIGN
)
48 DEBUGADD(4, (" NTLMSSP_NEGOTIATE_SIGN\n"));
49 if (neg_flags
& NTLMSSP_NEGOTIATE_SEAL
)
50 DEBUGADD(4, (" NTLMSSP_NEGOTIATE_SEAL\n"));
51 if (neg_flags
& NTLMSSP_NEGOTIATE_LM_KEY
)
52 DEBUGADD(4, (" NTLMSSP_NEGOTIATE_LM_KEY\n"));
53 if (neg_flags
& NTLMSSP_NEGOTIATE_NETWARE
)
54 DEBUGADD(4, (" NTLMSSP_NEGOTIATE_NETWARE\n"));
55 if (neg_flags
& NTLMSSP_NEGOTIATE_NTLM
)
56 DEBUGADD(4, (" NTLMSSP_NEGOTIATE_NTLM\n"));
57 if (neg_flags
& NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED
)
58 DEBUGADD(4, (" NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED\n"));
59 if (neg_flags
& NTLMSSP_NEGOTIATE_WORKSTATION_SUPPLIED
)
60 DEBUGADD(4, (" NTLMSSP_NEGOTIATE_WORKSTATION_SUPPLIED\n"));
61 if (neg_flags
& NTLMSSP_NEGOTIATE_THIS_IS_LOCAL_CALL
)
62 DEBUGADD(4, (" NTLMSSP_NEGOTIATE_THIS_IS_LOCAL_CALL\n"));
63 if (neg_flags
& NTLMSSP_NEGOTIATE_ALWAYS_SIGN
)
64 DEBUGADD(4, (" NTLMSSP_NEGOTIATE_ALWAYS_SIGN\n"));
65 if (neg_flags
& NTLMSSP_NEGOTIATE_NTLM2
)
66 DEBUGADD(4, (" NTLMSSP_NEGOTIATE_NTLM2\n"));
67 if (neg_flags
& NTLMSSP_CHAL_TARGET_INFO
)
68 DEBUGADD(4, (" NTLMSSP_CHAL_TARGET_INFO\n"));
69 if (neg_flags
& NTLMSSP_NEGOTIATE_128
)
70 DEBUGADD(4, (" NTLMSSP_NEGOTIATE_128\n"));
71 if (neg_flags
& NTLMSSP_NEGOTIATE_KEY_EXCH
)
72 DEBUGADD(4, (" NTLMSSP_NEGOTIATE_KEY_EXCH\n"));
76 * Default challenge generation code.
80 static const uint8
*get_challenge(struct ntlmssp_state
*ntlmssp_state
)
83 generate_random_buffer(chal
, sizeof(chal
), False
);
89 * Determine correct target name flags for reply, given server role
90 * and negotiated flags
92 * @param ntlmssp_state NTLMSSP State
93 * @param neg_flags The flags from the packet
94 * @param chal_flags The flags to be set in the reply packet
95 * @return The 'target name' string.
98 static const char *ntlmssp_target_name(struct ntlmssp_state
*ntlmssp_state
,
99 uint32 neg_flags
, uint32
*chal_flags
)
101 if (neg_flags
& NTLMSSP_REQUEST_TARGET
) {
102 *chal_flags
|= NTLMSSP_CHAL_TARGET_INFO
;
103 *chal_flags
|= NTLMSSP_REQUEST_TARGET
;
104 if (ntlmssp_state
->server_role
== ROLE_STANDALONE
) {
105 *chal_flags
|= NTLMSSP_TARGET_TYPE_SERVER
;
106 return ntlmssp_state
->get_global_myname();
108 *chal_flags
|= NTLMSSP_TARGET_TYPE_DOMAIN
;
109 return ntlmssp_state
->get_domain();
117 * Next state function for the Negotiate packet
119 * @param ntlmssp_state NTLMSSP State
120 * @param request The request, as a DATA_BLOB
121 * @param request The reply, as an allocated DATA_BLOB, caller to free.
122 * @return Errors or MORE_PROCESSING_REQUIRED if a reply is sent.
125 static NTSTATUS
ntlmssp_server_negotiate(struct ntlmssp_state
*ntlmssp_state
,
126 const DATA_BLOB request
, DATA_BLOB
*reply
)
128 DATA_BLOB struct_blob
;
129 fstring dnsname
, dnsdomname
;
130 uint32 neg_flags
= 0;
131 uint32 ntlmssp_command
, chal_flags
;
132 char *cliname
=NULL
, *domname
=NULL
;
133 const uint8
*cryptkey
;
134 const char *target_name
;
136 /* parse the NTLMSSP packet */
138 file_save("ntlmssp_negotiate.dat", request
.data
, request
.length
);
141 if (request
.length
) {
142 if (!msrpc_parse(&request
, "CddAA",
148 DEBUG(1, ("ntlmssp_server_negotiate: failed to parse NTLMSSP:\n"));
149 dump_data(2, (const char *)request
.data
, request
.length
);
150 return NT_STATUS_INVALID_PARAMETER
;
156 debug_ntlmssp_flags(neg_flags
);
159 cryptkey
= ntlmssp_state
->get_challenge(ntlmssp_state
);
161 data_blob_free(&ntlmssp_state
->chal
);
162 ntlmssp_state
->chal
= data_blob(cryptkey
, 8);
164 /* Give them the challenge. For now, ignore neg_flags and just
165 return the flags we want. Obviously this is not correct */
168 NTLMSSP_NEGOTIATE_128
|
169 NTLMSSP_NEGOTIATE_NTLM
;
171 if (neg_flags
& NTLMSSP_NEGOTIATE_UNICODE
) {
172 chal_flags
|= NTLMSSP_NEGOTIATE_UNICODE
;
173 ntlmssp_state
->unicode
= True
;
175 chal_flags
|= NTLMSSP_NEGOTIATE_OEM
;
178 target_name
= ntlmssp_target_name(ntlmssp_state
,
179 neg_flags
, &chal_flags
);
181 if (target_name
== NULL
)
182 return NT_STATUS_INVALID_PARAMETER
;
184 /* This should be a 'netbios domain -> DNS domain' mapping */
185 dnsdomname
[0] = '\0';
186 get_mydomname(dnsdomname
);
187 strlower_m(dnsdomname
);
190 get_myfullname(dnsname
);
193 if (chal_flags
& NTLMSSP_CHAL_TARGET_INFO
)
195 const char *target_name_dns
= "";
196 if (chal_flags
|= NTLMSSP_TARGET_TYPE_DOMAIN
) {
197 target_name_dns
= dnsdomname
;
198 } else if (chal_flags
|= NTLMSSP_TARGET_TYPE_SERVER
) {
199 target_name_dns
= dnsname
;
202 msrpc_gen(&struct_blob
, "aaaaa",
203 ntlmssp_state
->unicode
, NTLMSSP_NAME_TYPE_DOMAIN
, target_name
,
204 ntlmssp_state
->unicode
, NTLMSSP_NAME_TYPE_SERVER
, ntlmssp_state
->get_global_myname(),
205 ntlmssp_state
->unicode
, NTLMSSP_NAME_TYPE_DOMAIN_DNS
, target_name_dns
,
206 ntlmssp_state
->unicode
, NTLMSSP_NAME_TYPE_SERVER_DNS
, dnsdomname
,
207 ntlmssp_state
->unicode
, 0, "");
209 struct_blob
= data_blob(NULL
, 0);
213 const char *gen_string
;
214 if (ntlmssp_state
->unicode
) {
215 gen_string
= "CdUdbddB";
217 gen_string
= "CdAdbddB";
220 msrpc_gen(reply
, gen_string
,
227 struct_blob
.data
, struct_blob
.length
);
230 data_blob_free(&struct_blob
);
232 ntlmssp_state
->expected_state
= NTLMSSP_AUTH
;
234 return NT_STATUS_MORE_PROCESSING_REQUIRED
;
238 * Next state function for the Authenticate packet
240 * @param ntlmssp_state NTLMSSP State
241 * @param request The request, as a DATA_BLOB
242 * @param request The reply, as an allocated DATA_BLOB, caller to free.
243 * @return Errors or NT_STATUS_OK.
246 static NTSTATUS
ntlmssp_server_auth(struct ntlmssp_state
*ntlmssp_state
,
247 const DATA_BLOB request
, DATA_BLOB
*reply
)
250 uint32 ntlmssp_command
, neg_flags
;
253 const char *parse_string
;
255 /* parse the NTLMSSP packet */
257 file_save("ntlmssp_auth.dat", request
.data
, request
.length
);
260 if (ntlmssp_state
->unicode
) {
261 parse_string
= "CdBBUUUBd";
263 parse_string
= "CdBBAAABd";
266 data_blob_free(&ntlmssp_state
->lm_resp
);
267 data_blob_free(&ntlmssp_state
->nt_resp
);
269 SAFE_FREE(ntlmssp_state
->user
);
270 SAFE_FREE(ntlmssp_state
->domain
);
271 SAFE_FREE(ntlmssp_state
->workstation
);
273 /* now the NTLMSSP encoded auth hashes */
274 if (!msrpc_parse(&request
, parse_string
,
277 &ntlmssp_state
->lm_resp
,
278 &ntlmssp_state
->nt_resp
,
279 &ntlmssp_state
->domain
,
280 &ntlmssp_state
->user
,
281 &ntlmssp_state
->workstation
,
284 DEBUG(1, ("ntlmssp_server_auth: failed to parse NTLMSSP:\n"));
285 dump_data(2, (const char *)request
.data
, request
.length
);
286 return NT_STATUS_INVALID_PARAMETER
;
289 data_blob_free(&sess_key
);
291 DEBUG(3,("Got user=[%s] domain=[%s] workstation=[%s] len1=%lu len2=%lu\n",
292 ntlmssp_state
->user
, ntlmssp_state
->domain
, ntlmssp_state
->workstation
, (unsigned long)ntlmssp_state
->lm_resp
.length
, (unsigned long)ntlmssp_state
->nt_resp
.length
));
295 file_save("nthash1.dat", &ntlmssp_state
->nt_resp
.data
, &ntlmssp_state
->nt_resp
.length
);
296 file_save("lmhash1.dat", &ntlmssp_state
->lm_resp
.data
, &ntlmssp_state
->lm_resp
.length
);
299 nt_status
= ntlmssp_state
->check_password(ntlmssp_state
);
301 *reply
= data_blob(NULL
, 0);
307 * Create an NTLMSSP state machine
309 * @param ntlmssp_state NTLMSSP State, allocated by this function
312 NTSTATUS
ntlmssp_server_start(NTLMSSP_STATE
**ntlmssp_state
)
316 mem_ctx
= talloc_init("NTLMSSP context");
318 *ntlmssp_state
= talloc_zero(mem_ctx
, sizeof(**ntlmssp_state
));
319 if (!*ntlmssp_state
) {
320 DEBUG(0,("ntlmssp_server_start: talloc failed!\n"));
321 talloc_destroy(mem_ctx
);
322 return NT_STATUS_NO_MEMORY
;
325 (*ntlmssp_state
)->mem_ctx
= mem_ctx
;
326 (*ntlmssp_state
)->get_challenge
= get_challenge
;
328 (*ntlmssp_state
)->get_global_myname
= global_myname
;
329 (*ntlmssp_state
)->get_domain
= lp_workgroup
;
330 (*ntlmssp_state
)->server_role
= ROLE_DOMAIN_MEMBER
; /* a good default */
332 (*ntlmssp_state
)->expected_state
= NTLMSSP_NEGOTIATE
;
338 * End an NTLMSSP state machine
340 * @param ntlmssp_state NTLMSSP State, free()ed by this function
343 NTSTATUS
ntlmssp_server_end(NTLMSSP_STATE
**ntlmssp_state
)
345 TALLOC_CTX
*mem_ctx
= (*ntlmssp_state
)->mem_ctx
;
347 data_blob_free(&(*ntlmssp_state
)->chal
);
348 data_blob_free(&(*ntlmssp_state
)->lm_resp
);
349 data_blob_free(&(*ntlmssp_state
)->nt_resp
);
351 SAFE_FREE((*ntlmssp_state
)->user
);
352 SAFE_FREE((*ntlmssp_state
)->domain
);
353 SAFE_FREE((*ntlmssp_state
)->workstation
);
355 talloc_destroy(mem_ctx
);
356 *ntlmssp_state
= NULL
;
361 * Next state function for the NTLMSSP state machine
363 * @param ntlmssp_state NTLMSSP State
364 * @param request The request, as a DATA_BLOB
365 * @param request The reply, as an allocated DATA_BLOB, caller to free.
366 * @return Errors, NT_STATUS_MORE_PROCESSING_REQUIRED or NT_STATUS_OK.
369 NTSTATUS
ntlmssp_server_update(NTLMSSP_STATE
*ntlmssp_state
,
370 const DATA_BLOB request
, DATA_BLOB
*reply
)
372 uint32 ntlmssp_command
;
373 *reply
= data_blob(NULL
, 0);
375 if (request
.length
) {
376 if (!msrpc_parse(&request
, "Cd",
379 return NT_STATUS_INVALID_PARAMETER
;
382 /* 'datagram' mode - no neg packet */
383 ntlmssp_command
= NTLMSSP_NEGOTIATE
;
386 if (ntlmssp_command
!= ntlmssp_state
->expected_state
) {
387 DEBUG(1, ("got NTLMSSP command %u, expected %u\n", ntlmssp_command
, ntlmssp_state
->expected_state
));
388 return NT_STATUS_INVALID_PARAMETER
;
391 if (ntlmssp_command
== NTLMSSP_NEGOTIATE
) {
392 return ntlmssp_server_negotiate(ntlmssp_state
, request
, reply
);
393 } else if (ntlmssp_command
== NTLMSSP_AUTH
) {
394 return ntlmssp_server_auth(ntlmssp_state
, request
, reply
);
396 DEBUG(1, ("unknown NTLMSSP command %u, expected %u\n", ntlmssp_command
, ntlmssp_state
->expected_state
));
397 return NT_STATUS_INVALID_PARAMETER
;
401 /*********************************************************************
403 *********************************************************************/
406 * Next state function for the Initial packet
408 * @param ntlmssp_state NTLMSSP State
409 * @param request The request, as a DATA_BLOB. reply.data must be NULL
410 * @param request The reply, as an allocated DATA_BLOB, caller to free.
411 * @return Errors or NT_STATUS_OK.
414 static NTSTATUS
ntlmssp_client_initial(struct ntlmssp_client_state
*ntlmssp_state
,
415 DATA_BLOB reply
, DATA_BLOB
*next_request
)
417 if (ntlmssp_state
->unicode
) {
418 ntlmssp_state
->neg_flags
|= NTLMSSP_NEGOTIATE_UNICODE
;
421 if (ntlmssp_state
->use_ntlmv2
) {
422 ntlmssp_state
->neg_flags
|= NTLMSSP_NEGOTIATE_NTLM2
;
426 ntlmssp_state
->neg_flags
|= NTLMSSP_NEGOTIATE_NTLM2
;
429 /* generate the ntlmssp negotiate packet */
430 msrpc_gen(next_request
, "CddAA",
433 ntlmssp_state
->neg_flags
,
434 ntlmssp_state
->get_domain(),
435 ntlmssp_state
->get_global_myname());
437 return NT_STATUS_MORE_PROCESSING_REQUIRED
;
441 * Next state function for the Challenge Packet. Generate an auth packet.
443 * @param ntlmssp_state NTLMSSP State
444 * @param request The request, as a DATA_BLOB. reply.data must be NULL
445 * @param request The reply, as an allocated DATA_BLOB, caller to free.
446 * @return Errors or NT_STATUS_OK.
449 static NTSTATUS
ntlmssp_client_challenge(struct ntlmssp_client_state
*ntlmssp_state
,
450 const DATA_BLOB reply
, DATA_BLOB
*next_request
)
452 uint32 chal_flags
, ntlmssp_command
, unkn1
, unkn2
;
453 DATA_BLOB server_domain_blob
;
454 DATA_BLOB challenge_blob
;
455 DATA_BLOB struct_blob
= data_blob(NULL
, 0);
457 const char *chal_parse_string
;
458 const char *auth_gen_string
;
459 DATA_BLOB lm_response
= data_blob(NULL
, 0);
460 DATA_BLOB nt_response
= data_blob(NULL
, 0);
461 DATA_BLOB session_key
= data_blob(NULL
, 0);
462 uint8 datagram_sess_key
[16];
463 size_t datagram_sess_key_len
;
465 #if 0 /* until we know what flag to tigger it on */
466 generate_random_buffer(datagram_sess_key
, sizeof(datagram_sess_key
), False
);
467 datagram_sess_key_len
= sizeof(datagram_sess_key
);
469 ZERO_STRUCT(datagram_sess_key
);
470 datagram_sess_key_len
= 0;
473 if (!msrpc_parse(&reply
, "CdBd",
478 DEBUG(1, ("Failed to parse the NTLMSSP Challenge: (#1)\n"));
479 dump_data(2, (const char *)reply
.data
, reply
.length
);
481 return NT_STATUS_INVALID_PARAMETER
;
484 data_blob_free(&server_domain_blob
);
486 DEBUG(3, ("Got challenge flags:\n"));
487 debug_ntlmssp_flags(chal_flags
);
489 if (chal_flags
& NTLMSSP_NEGOTIATE_UNICODE
) {
490 if (chal_flags
& NTLMSSP_CHAL_TARGET_INFO
) {
491 chal_parse_string
= "CdUdbddB";
493 chal_parse_string
= "CdUdbdd";
495 auth_gen_string
= "CdBBUUUBd";
496 ntlmssp_state
->unicode
= True
;
497 ntlmssp_state
->neg_flags
|= NTLMSSP_NEGOTIATE_UNICODE
;
498 ntlmssp_state
->neg_flags
&= ~NTLMSSP_NEGOTIATE_OEM
;
499 } else if (chal_flags
& NTLMSSP_NEGOTIATE_OEM
) {
500 if (chal_flags
& NTLMSSP_CHAL_TARGET_INFO
) {
501 chal_parse_string
= "CdAdbddB";
503 chal_parse_string
= "CdAdbdd";
505 auth_gen_string
= "CdBBAAABd";
506 ntlmssp_state
->unicode
= False
;
507 ntlmssp_state
->neg_flags
&= ~NTLMSSP_NEGOTIATE_UNICODE
;
508 ntlmssp_state
->neg_flags
|= NTLMSSP_NEGOTIATE_OEM
;
510 return NT_STATUS_INVALID_PARAMETER
;
513 if (chal_flags
& NTLMSSP_NEGOTIATE_LM_KEY
&& lp_client_lanman_auth()) {
514 /* server forcing us to use LM */
515 ntlmssp_state
->neg_flags
|= NTLMSSP_NEGOTIATE_LM_KEY
;
516 ntlmssp_state
->use_ntlmv2
= False
;
518 ntlmssp_state
->neg_flags
&= ~NTLMSSP_NEGOTIATE_LM_KEY
;
521 if (!(chal_flags
& NTLMSSP_NEGOTIATE_NTLM2
)) {
522 ntlmssp_state
->neg_flags
&= ~NTLMSSP_NEGOTIATE_NTLM2
;
525 if (!(chal_flags
& NTLMSSP_NEGOTIATE_128
)) {
526 ntlmssp_state
->neg_flags
&= ~NTLMSSP_NEGOTIATE_128
;
529 DEBUG(3, ("NTLMSSP: Set final flags:\n"));
530 debug_ntlmssp_flags(ntlmssp_state
->neg_flags
);
532 if (!msrpc_parse(&reply
, chal_parse_string
,
540 DEBUG(1, ("Failed to parse the NTLMSSP Challenge: (#2)\n"));
541 dump_data(2, (const char *)reply
.data
, reply
.length
);
542 return NT_STATUS_INVALID_PARAMETER
;
545 ntlmssp_state
->server_domain
= talloc_strdup(ntlmssp_state
->mem_ctx
,
548 SAFE_FREE(server_domain
);
549 if (challenge_blob
.length
!= 8) {
550 data_blob_free(&struct_blob
);
551 return NT_STATUS_INVALID_PARAMETER
;
554 if (!ntlmssp_state
->password
) {
555 /* do nothing - blobs are zero length */
556 } else if (ntlmssp_state
->use_ntlmv2
) {
558 if (!struct_blob
.length
) {
559 /* be lazy, match win2k - we can't do NTLMv2 without it */
560 return NT_STATUS_INVALID_PARAMETER
;
563 /* TODO: if the remote server is standalone, then we should replace 'domain'
564 with the server name as supplied above */
566 if (!SMBNTLMv2encrypt(ntlmssp_state
->user
,
567 ntlmssp_state
->domain
,
568 ntlmssp_state
->password
, &challenge_blob
,
570 &lm_response
, &nt_response
, &session_key
)) {
571 data_blob_free(&challenge_blob
);
572 data_blob_free(&struct_blob
);
573 return NT_STATUS_NO_MEMORY
;
576 } else if (ntlmssp_state
->neg_flags
& NTLMSSP_NEGOTIATE_NTLM2
) {
577 struct MD5Context md5_session_nonce_ctx
;
579 uchar session_nonce
[16];
580 E_md4hash(ntlmssp_state
->password
, nt_hash
);
582 generate_random_buffer(lm_response
.data
, 8, False
);
583 memset(lm_response
.data
+8, 0, 16);
585 MD5Init(&md5_session_nonce_ctx
);
586 MD5Update(&md5_session_nonce_ctx
, challenge_blob
.data
, 8);
587 MD5Update(&md5_session_nonce_ctx
, lm_response
.data
, 8);
588 MD5Final(session_nonce
, &md5_session_nonce_ctx
);
590 nt_response
= data_blob(NULL
, 24);
591 SMBNTencrypt(ntlmssp_state
->password
,
595 /* This is *NOT* the correct session key algorithm - just
596 fill in the bytes with something... */
597 session_key
= data_blob(NULL
, 16);
598 SMBsesskeygen_ntv1(nt_hash
, NULL
, session_key
.data
);
605 E_deshash(ntlmssp_state
->password
, lm_hash
);
606 E_md4hash(ntlmssp_state
->password
, nt_hash
);
608 /* lanman auth is insecure, it may be disabled */
609 if (lp_client_lanman_auth()) {
610 lm_response
= data_blob(NULL
, 24);
611 SMBencrypt(ntlmssp_state
->password
,challenge_blob
.data
,
615 nt_response
= data_blob(NULL
, 24);
616 SMBNTencrypt(ntlmssp_state
->password
,challenge_blob
.data
,
619 session_key
= data_blob(NULL
, 16);
620 if ((ntlmssp_state
->neg_flags
& NTLMSSP_NEGOTIATE_LM_KEY
)
621 && lp_client_lanman_auth()) {
622 SMBsesskeygen_lmv1(lm_hash
, lm_response
.data
,
625 SMBsesskeygen_ntv1(nt_hash
, NULL
, session_key
.data
);
628 data_blob_free(&struct_blob
);
630 /* this generates the actual auth packet */
631 if (!msrpc_gen(next_request
, auth_gen_string
,
634 lm_response
.data
, lm_response
.length
,
635 nt_response
.data
, nt_response
.length
,
636 ntlmssp_state
->domain
,
638 ntlmssp_state
->get_global_myname(),
639 datagram_sess_key
, datagram_sess_key_len
,
640 ntlmssp_state
->neg_flags
)) {
642 data_blob_free(&lm_response
);
643 data_blob_free(&nt_response
);
644 data_blob_free(&session_key
);
645 return NT_STATUS_NO_MEMORY
;
648 data_blob_free(&ntlmssp_state
->chal
);
649 data_blob_free(&ntlmssp_state
->lm_resp
);
650 data_blob_free(&ntlmssp_state
->nt_resp
);
651 data_blob_free(&ntlmssp_state
->session_key
);
653 ntlmssp_state
->chal
= challenge_blob
;
654 ntlmssp_state
->lm_resp
= lm_response
;
655 ntlmssp_state
->nt_resp
= nt_response
;
656 ntlmssp_state
->session_key
= session_key
;
658 return NT_STATUS_MORE_PROCESSING_REQUIRED
;
661 NTSTATUS
ntlmssp_client_start(NTLMSSP_CLIENT_STATE
**ntlmssp_state
)
665 mem_ctx
= talloc_init("NTLMSSP Client context");
667 *ntlmssp_state
= talloc_zero(mem_ctx
, sizeof(**ntlmssp_state
));
668 if (!*ntlmssp_state
) {
669 DEBUG(0,("ntlmssp_server_start: talloc failed!\n"));
670 talloc_destroy(mem_ctx
);
671 return NT_STATUS_NO_MEMORY
;
674 (*ntlmssp_state
)->mem_ctx
= mem_ctx
;
676 (*ntlmssp_state
)->get_global_myname
= global_myname
;
677 (*ntlmssp_state
)->get_domain
= lp_workgroup
;
679 (*ntlmssp_state
)->unicode
= True
;
681 (*ntlmssp_state
)->use_ntlmv2
= lp_client_ntlmv2_auth();
683 (*ntlmssp_state
)->neg_flags
=
684 NTLMSSP_NEGOTIATE_128
|
685 NTLMSSP_NEGOTIATE_NTLM
|
686 NTLMSSP_REQUEST_TARGET
;
688 (*ntlmssp_state
)->ref_count
= 1;
693 NTSTATUS
ntlmssp_client_end(NTLMSSP_CLIENT_STATE
**ntlmssp_state
)
695 TALLOC_CTX
*mem_ctx
= (*ntlmssp_state
)->mem_ctx
;
697 (*ntlmssp_state
)->ref_count
--;
699 if ((*ntlmssp_state
)->ref_count
== 0) {
700 data_blob_free(&(*ntlmssp_state
)->chal
);
701 data_blob_free(&(*ntlmssp_state
)->lm_resp
);
702 data_blob_free(&(*ntlmssp_state
)->nt_resp
);
703 data_blob_free(&(*ntlmssp_state
)->session_key
);
704 data_blob_free(&(*ntlmssp_state
)->stored_response
);
705 talloc_destroy(mem_ctx
);
708 *ntlmssp_state
= NULL
;
712 NTSTATUS
ntlmssp_client_update(NTLMSSP_CLIENT_STATE
*ntlmssp_state
,
713 DATA_BLOB reply
, DATA_BLOB
*next_request
)
715 NTSTATUS nt_status
= NT_STATUS_INVALID_PARAMETER
;
716 uint32 ntlmssp_command
;
717 *next_request
= data_blob(NULL
, 0);
720 /* If there is a cached reply, use it - otherwise this is the first packet */
721 if (!ntlmssp_state
->stored_response
.length
) {
722 return ntlmssp_client_initial(ntlmssp_state
, reply
, next_request
);
725 reply
= ntlmssp_state
->stored_response
;
728 if (!msrpc_parse(&reply
, "Cd",
731 return NT_STATUS_INVALID_PARAMETER
;
734 if (ntlmssp_command
== NTLMSSP_CHALLENGE
) {
735 nt_status
= ntlmssp_client_challenge(ntlmssp_state
, reply
, next_request
);
737 if (ntlmssp_state
->stored_response
.length
) {
738 data_blob_free(&ntlmssp_state
->stored_response
);
743 NTSTATUS
ntlmssp_set_username(NTLMSSP_CLIENT_STATE
*ntlmssp_state
, const char *user
)
745 ntlmssp_state
->user
= talloc_strdup(ntlmssp_state
->mem_ctx
, user
);
746 if (!ntlmssp_state
->user
) {
747 return NT_STATUS_NO_MEMORY
;
752 NTSTATUS
ntlmssp_set_password(NTLMSSP_CLIENT_STATE
*ntlmssp_state
, const char *password
)
755 ntlmssp_state
->password
= NULL
;
757 ntlmssp_state
->password
= talloc_strdup(ntlmssp_state
->mem_ctx
, password
);
758 if (!ntlmssp_state
->password
) {
759 return NT_STATUS_NO_MEMORY
;
765 NTSTATUS
ntlmssp_set_domain(NTLMSSP_CLIENT_STATE
*ntlmssp_state
, const char *domain
)
767 ntlmssp_state
->domain
= talloc_strdup(ntlmssp_state
->mem_ctx
, domain
);
768 if (!ntlmssp_state
->domain
) {
769 return NT_STATUS_NO_MEMORY
;
775 * Store a DATA_BLOB containing an NTLMSSP response, for use later.
776 * This 'keeps' the data blob - the caller must *not* free it.
779 NTSTATUS
ntlmssp_client_store_response(NTLMSSP_CLIENT_STATE
*ntlmssp_state
,
782 data_blob_free(&ntlmssp_state
->stored_response
);
783 ntlmssp_state
->stored_response
= response
;