96dc1fb6aa9e14bb0c7fe0744103ef9c1bc48dab
[mat/samba.git] / source3 / libsmb / ntlmssp.c
1 /*
2    Unix SMB/Netbios implementation.
3    Version 3.0
4    handle NLTMSSP, server side
5
6    Copyright (C) Andrew Tridgell      2001
7    Copyright (C) Andrew Bartlett 2001-2010
8    Copyright (C) Stefan Metzmacher 2005
9
10    This program is free software; you can redistribute it and/or modify
11    it under the terms of the GNU General Public License as published by
12    the Free Software Foundation; either version 3 of the License, or
13    (at your option) any later version.
14
15    This program is distributed in the hope that it will be useful,
16    but WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18    GNU General Public License for more details.
19
20    You should have received a copy of the GNU General Public License
21    along with this program.  If not, see <http://www.gnu.org/licenses/>.
22 */
23
24 #include "includes.h"
25 #include "../auth/ntlmssp/ntlmssp.h"
26 #include "../auth/ntlmssp/ntlmssp_private.h"
27 #include "../libcli/auth/libcli_auth.h"
28 #include "../librpc/gen_ndr/ndr_ntlmssp.h"
29 #include "../auth/ntlmssp/ntlmssp_ndr.h"
30 #include "../lib/crypto/md5.h"
31 #include "../lib/crypto/arcfour.h"
32 #include "../lib/crypto/hmacmd5.h"
33 #include "../nsswitch/libwbclient/wbclient.h"
34
35 static NTSTATUS ntlmssp3_client_initial(struct ntlmssp_state *ntlmssp_state,
36                                        TALLOC_CTX *out_mem_ctx,
37                                        DATA_BLOB reply, DATA_BLOB *next_request);
38 static NTSTATUS ntlmssp3_client_challenge(struct ntlmssp_state *ntlmssp_state,
39                                          TALLOC_CTX *out_mem_ctx, /* Unused at this time */
40                                          const DATA_BLOB reply, DATA_BLOB *next_request);
41 /**
42  * Callbacks for NTLMSSP - for both client and server operating modes
43  *
44  */
45
46 static const struct ntlmssp_callbacks {
47         enum ntlmssp_role role;
48         enum ntlmssp_message_type ntlmssp_command;
49         NTSTATUS (*fn)(struct ntlmssp_state *ntlmssp_state,
50                        TALLOC_CTX *out_mem_ctx,
51                        DATA_BLOB in, DATA_BLOB *out);
52 } ntlmssp_callbacks[] = {
53         {NTLMSSP_CLIENT, NTLMSSP_INITIAL, ntlmssp3_client_initial},
54         {NTLMSSP_CLIENT, NTLMSSP_CHALLENGE, ntlmssp3_client_challenge},
55         {NTLMSSP_CLIENT, NTLMSSP_UNKNOWN, NULL},
56         {NTLMSSP_SERVER, NTLMSSP_UNKNOWN, NULL}
57 };
58
59 /**
60  * Set a username on an NTLMSSP context - ensures it is talloc()ed
61  *
62  */
63
64 NTSTATUS ntlmssp_set_username(struct ntlmssp_state *ntlmssp_state, const char *user)
65 {
66         ntlmssp_state->user = talloc_strdup(ntlmssp_state, user ? user : "" );
67         if (!ntlmssp_state->user) {
68                 return NT_STATUS_NO_MEMORY;
69         }
70         return NT_STATUS_OK;
71 }
72
73 /**
74  * Converts a password to the hashes on an NTLMSSP context.
75  *
76  */
77 NTSTATUS ntlmssp_set_password(struct ntlmssp_state *ntlmssp_state, const char *password)
78 {
79         uint8_t lm_hash[16];
80         uint8_t nt_hash[16];
81
82         TALLOC_FREE(ntlmssp_state->lm_hash);
83         TALLOC_FREE(ntlmssp_state->nt_hash);
84
85         if (password == NULL) {
86                 return NT_STATUS_OK;
87         }
88
89         if (E_deshash(password, lm_hash)) {
90                 ntlmssp_state->lm_hash = (uint8_t *)
91                         talloc_memdup(ntlmssp_state, lm_hash, 16);
92                 if (!ntlmssp_state->lm_hash) {
93                         return NT_STATUS_NO_MEMORY;
94                 }
95         }
96
97         E_md4hash(password, nt_hash);
98
99         ntlmssp_state->nt_hash = (uint8_t *)
100                 talloc_memdup(ntlmssp_state, nt_hash, 16);
101         if (!ntlmssp_state->nt_hash) {
102                 TALLOC_FREE(ntlmssp_state->lm_hash);
103                 return NT_STATUS_NO_MEMORY;
104         }
105
106         return NT_STATUS_OK;
107 }
108
109 /**
110  * Set a domain on an NTLMSSP context - ensures it is talloc()ed
111  *
112  */
113 NTSTATUS ntlmssp_set_domain(struct ntlmssp_state *ntlmssp_state, const char *domain)
114 {
115         ntlmssp_state->domain = talloc_strdup(ntlmssp_state,
116                                               domain ? domain : "" );
117         if (!ntlmssp_state->domain) {
118                 return NT_STATUS_NO_MEMORY;
119         }
120         return NT_STATUS_OK;
121 }
122
123 /**
124  * Request features for the NTLMSSP negotiation
125  *
126  * @param ntlmssp_state NTLMSSP state
127  * @param feature_list List of space seperated features requested from NTLMSSP.
128  */
129 void ntlmssp_want_feature_list(struct ntlmssp_state *ntlmssp_state, char *feature_list)
130 {
131         /*
132          * We need to set this to allow a later SetPassword
133          * via the SAMR pipe to succeed. Strange.... We could
134          * also add  NTLMSSP_NEGOTIATE_SEAL here. JRA.
135          */
136         if (in_list("NTLMSSP_FEATURE_SESSION_KEY", feature_list, True)) {
137                 ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SIGN;
138         }
139         if (in_list("NTLMSSP_FEATURE_SIGN", feature_list, True)) {
140                 ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SIGN;
141         }
142         if(in_list("NTLMSSP_FEATURE_SEAL", feature_list, True)) {
143                 ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SEAL;
144         }
145         if (in_list("NTLMSSP_FEATURE_CCACHE", feature_list, true)) {
146                 ntlmssp_state->use_ccache = true;
147         }
148 }
149
150 /**
151  * Request a feature for the NTLMSSP negotiation
152  *
153  * @param ntlmssp_state NTLMSSP state
154  * @param feature Bit flag specifying the requested feature
155  */
156 void ntlmssp_want_feature(struct ntlmssp_state *ntlmssp_state, uint32_t feature)
157 {
158         /* As per JRA's comment above */
159         if (feature & NTLMSSP_FEATURE_SESSION_KEY) {
160                 ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SIGN;
161         }
162         if (feature & NTLMSSP_FEATURE_SIGN) {
163                 ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SIGN;
164         }
165         if (feature & NTLMSSP_FEATURE_SEAL) {
166                 ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SIGN;
167                 ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SEAL;
168         }
169         if (feature & NTLMSSP_FEATURE_CCACHE) {
170                 ntlmssp_state->use_ccache = true;
171         }
172 }
173
174 /**
175  * Next state function for the NTLMSSP state machine
176  *
177  * @param ntlmssp_state NTLMSSP State
178  * @param in The packet in from the NTLMSSP partner, as a DATA_BLOB
179  * @param out The reply, as an allocated DATA_BLOB, caller to free.
180  * @return Errors, NT_STATUS_MORE_PROCESSING_REQUIRED or NT_STATUS_OK.
181  */
182
183 NTSTATUS ntlmssp_update(struct ntlmssp_state *ntlmssp_state,
184                         const DATA_BLOB input, DATA_BLOB *out)
185 {
186         uint32_t ntlmssp_command;
187         int i;
188
189         if (ntlmssp_state->expected_state == NTLMSSP_DONE) {
190                 /* Called update after negotiations finished. */
191                 DEBUG(1, ("Called NTLMSSP after state machine was 'done'\n"));
192                 return NT_STATUS_INVALID_PARAMETER;
193         }
194
195         *out = data_blob_null;
196
197         if (!input.length) {
198                 switch (ntlmssp_state->role) {
199                 case NTLMSSP_CLIENT:
200                         ntlmssp_command = NTLMSSP_INITIAL;
201                         break;
202                 case NTLMSSP_SERVER:
203                         /* 'datagram' mode - no neg packet */
204                         ntlmssp_command = NTLMSSP_NEGOTIATE;
205                         break;
206                 default:
207                         DEBUG(1, ("Invalid role: %d\n", ntlmssp_state->role));
208                         return NT_STATUS_INVALID_PARAMETER;
209                 }
210         } else {
211                 if (!msrpc_parse(ntlmssp_state, &input, "Cd",
212                                  "NTLMSSP",
213                                  &ntlmssp_command)) {
214                         DEBUG(1, ("Failed to parse NTLMSSP packet, could not extract NTLMSSP command\n"));
215                         dump_data(2, input.data, input.length);
216                         return NT_STATUS_INVALID_PARAMETER;
217                 }
218         }
219
220         if (ntlmssp_command != ntlmssp_state->expected_state) {
221                 DEBUG(1, ("got NTLMSSP command %u, expected %u\n", ntlmssp_command, ntlmssp_state->expected_state));
222                 return NT_STATUS_INVALID_PARAMETER;
223         }
224
225         for (i=0; ntlmssp_callbacks[i].fn; i++) {
226                 if (ntlmssp_callbacks[i].role == ntlmssp_state->role
227                     && ntlmssp_callbacks[i].ntlmssp_command == ntlmssp_command) {
228                         return ntlmssp_callbacks[i].fn(ntlmssp_state, ntlmssp_state, input, out);
229                 }
230         }
231
232         DEBUG(1, ("failed to find NTLMSSP callback for NTLMSSP mode %u, command %u\n",
233                   ntlmssp_state->role, ntlmssp_command));
234
235         return NT_STATUS_INVALID_PARAMETER;
236 }
237
238 /*********************************************************************
239  Client side NTLMSSP
240 *********************************************************************/
241
242 /**
243  * Next state function for the Initial packet
244  *
245  * @param ntlmssp_state NTLMSSP State
246  * @param request The request, as a DATA_BLOB.  reply.data must be NULL
247  * @param request The reply, as an allocated DATA_BLOB, caller to free.
248  * @return Errors or NT_STATUS_OK.
249  */
250
251 static NTSTATUS ntlmssp3_client_initial(struct ntlmssp_state *ntlmssp_state,
252                                        TALLOC_CTX *out_mem_ctx,
253                                        DATA_BLOB in, DATA_BLOB *out)
254 {
255         const char *domain = ntlmssp_state->client.netbios_domain;
256         const char *workstation = ntlmssp_state->client.netbios_name;
257         NTSTATUS status;
258
259         /* These don't really matter in the initial packet, so don't panic if they are not set */
260         if (!domain) {
261                 domain = "";
262         }
263
264         if (!workstation) {
265                 workstation = "";
266         }
267
268         if (ntlmssp_state->unicode) {
269                 ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_UNICODE;
270         } else {
271                 ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_OEM;
272         }
273
274         if (ntlmssp_state->use_ntlmv2) {
275                 ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_NTLM2;
276         }
277
278         /* generate the ntlmssp negotiate packet */
279         status = msrpc_gen(out_mem_ctx,
280                   out, "CddAA",
281                   "NTLMSSP",
282                   NTLMSSP_NEGOTIATE,
283                   ntlmssp_state->neg_flags,
284                   domain,
285                   workstation);
286
287         if (!NT_STATUS_IS_OK(status)) {
288                 DEBUG(0, ("ntlmssp_client_initial: failed to generate "
289                           "ntlmssp negotiate packet\n"));
290                 return status;
291         }
292
293         if (DEBUGLEVEL >= 10) {
294                 struct NEGOTIATE_MESSAGE *negotiate = talloc(
295                         talloc_tos(), struct NEGOTIATE_MESSAGE);
296                 if (negotiate != NULL) {
297                         status = ntlmssp_pull_NEGOTIATE_MESSAGE(
298                                 out, negotiate, negotiate);
299                         if (NT_STATUS_IS_OK(status)) {
300                                 NDR_PRINT_DEBUG(NEGOTIATE_MESSAGE,
301                                                 negotiate);
302                         }
303                         TALLOC_FREE(negotiate);
304                 }
305         }
306
307         ntlmssp_state->expected_state = NTLMSSP_CHALLENGE;
308
309         return NT_STATUS_MORE_PROCESSING_REQUIRED;
310 }
311
312 /**
313  * Next state function for the Challenge Packet.  Generate an auth packet.
314  *
315  * @param ntlmssp_state NTLMSSP State
316  * @param request The request, as a DATA_BLOB.  reply.data must be NULL
317  * @param request The reply, as an allocated DATA_BLOB, caller to free.
318  * @return Errors or NT_STATUS_OK.
319  */
320
321 static NTSTATUS ntlmssp3_client_challenge(struct ntlmssp_state *ntlmssp_state,
322                                          TALLOC_CTX *out_mem_ctx, /* Unused at this time */
323                                          const DATA_BLOB reply, DATA_BLOB *next_request)
324 {
325         uint32_t chal_flags, ntlmssp_command, unkn1, unkn2;
326         DATA_BLOB server_domain_blob;
327         DATA_BLOB challenge_blob;
328         DATA_BLOB struct_blob = data_blob_null;
329         char *server_domain;
330         const char *chal_parse_string;
331         const char *auth_gen_string;
332         DATA_BLOB lm_response = data_blob_null;
333         DATA_BLOB nt_response = data_blob_null;
334         DATA_BLOB session_key = data_blob_null;
335         DATA_BLOB encrypted_session_key = data_blob_null;
336         NTSTATUS nt_status = NT_STATUS_OK;
337
338         if (ntlmssp_state->use_ccache) {
339                 struct wbcCredentialCacheParams params;
340                 struct wbcCredentialCacheInfo *info = NULL;
341                 struct wbcAuthErrorInfo *error = NULL;
342                 struct wbcNamedBlob auth_blob;
343                 struct wbcBlob *wbc_next = NULL;
344                 struct wbcBlob *wbc_session_key = NULL;
345                 wbcErr wbc_status;
346                 int i;
347
348                 params.account_name = ntlmssp_state->user;
349                 params.domain_name = ntlmssp_state->domain;
350                 params.level = WBC_CREDENTIAL_CACHE_LEVEL_NTLMSSP;
351
352                 auth_blob.name = "challenge_blob";
353                 auth_blob.flags = 0;
354                 auth_blob.blob.data = reply.data;
355                 auth_blob.blob.length = reply.length;
356                 params.num_blobs = 1;
357                 params.blobs = &auth_blob;
358
359                 wbc_status = wbcCredentialCache(&params, &info, &error);
360                 wbcFreeMemory(error);
361                 if (!WBC_ERROR_IS_OK(wbc_status)) {
362                         goto noccache;
363                 }
364
365                 for (i=0; i<info->num_blobs; i++) {
366                         if (strequal(info->blobs[i].name, "auth_blob")) {
367                                 wbc_next = &info->blobs[i].blob;
368                         }
369                         if (strequal(info->blobs[i].name, "session_key")) {
370                                 wbc_session_key = &info->blobs[i].blob;
371                         }
372                 }
373                 if ((wbc_next == NULL) || (wbc_session_key == NULL)) {
374                         wbcFreeMemory(info);
375                         goto noccache;
376                 }
377
378                 *next_request = data_blob(wbc_next->data, wbc_next->length);
379                 ntlmssp_state->session_key = data_blob(
380                         wbc_session_key->data, wbc_session_key->length);
381
382                 wbcFreeMemory(info);
383                 goto done;
384         }
385
386 noccache:
387
388         if (!msrpc_parse(ntlmssp_state, &reply, "CdBd",
389                          "NTLMSSP",
390                          &ntlmssp_command,
391                          &server_domain_blob,
392                          &chal_flags)) {
393                 DEBUG(1, ("Failed to parse the NTLMSSP Challenge: (#1)\n"));
394                 dump_data(2, reply.data, reply.length);
395
396                 return NT_STATUS_INVALID_PARAMETER;
397         }
398
399         if (DEBUGLEVEL >= 10) {
400                 struct CHALLENGE_MESSAGE *challenge = talloc(
401                         talloc_tos(), struct CHALLENGE_MESSAGE);
402                 if (challenge != NULL) {
403                         NTSTATUS status;
404                         challenge->NegotiateFlags = chal_flags;
405                         status = ntlmssp_pull_CHALLENGE_MESSAGE(
406                                 &reply, challenge, challenge);
407                         if (NT_STATUS_IS_OK(status)) {
408                                 NDR_PRINT_DEBUG(CHALLENGE_MESSAGE,
409                                                 challenge);
410                         }
411                         TALLOC_FREE(challenge);
412                 }
413         }
414
415         data_blob_free(&server_domain_blob);
416
417         DEBUG(3, ("Got challenge flags:\n"));
418         debug_ntlmssp_flags(chal_flags);
419
420         ntlmssp_handle_neg_flags(ntlmssp_state, chal_flags, lp_client_lanman_auth());
421
422         if (ntlmssp_state->unicode) {
423                 if (chal_flags & NTLMSSP_NEGOTIATE_TARGET_INFO) {
424                         chal_parse_string = "CdUdbddB";
425                 } else {
426                         chal_parse_string = "CdUdbdd";
427                 }
428                 auth_gen_string = "CdBBUUUBd";
429         } else {
430                 if (chal_flags & NTLMSSP_NEGOTIATE_TARGET_INFO) {
431                         chal_parse_string = "CdAdbddB";
432                 } else {
433                         chal_parse_string = "CdAdbdd";
434                 }
435
436                 auth_gen_string = "CdBBAAABd";
437         }
438
439         DEBUG(3, ("NTLMSSP: Set final flags:\n"));
440         debug_ntlmssp_flags(ntlmssp_state->neg_flags);
441
442         if (!msrpc_parse(ntlmssp_state, &reply, chal_parse_string,
443                          "NTLMSSP",
444                          &ntlmssp_command,
445                          &server_domain,
446                          &chal_flags,
447                          &challenge_blob, 8,
448                          &unkn1, &unkn2,
449                          &struct_blob)) {
450                 DEBUG(1, ("Failed to parse the NTLMSSP Challenge: (#2)\n"));
451                 dump_data(2, reply.data, reply.length);
452                 return NT_STATUS_INVALID_PARAMETER;
453         }
454
455         if (chal_flags & NTLMSSP_TARGET_TYPE_SERVER) {
456                 ntlmssp_state->server.is_standalone = true;
457         } else {
458                 ntlmssp_state->server.is_standalone = false;
459         }
460         /* TODO: parse struct_blob and fill in the rest */
461         ntlmssp_state->server.netbios_name = "";
462         ntlmssp_state->server.netbios_domain = server_domain;
463         ntlmssp_state->server.dns_name = "";
464         ntlmssp_state->server.dns_domain = "";
465
466         if (challenge_blob.length != 8) {
467                 data_blob_free(&struct_blob);
468                 return NT_STATUS_INVALID_PARAMETER;
469         }
470
471         if (!ntlmssp_state->nt_hash) {
472                 static const uint8_t zeros[16] = {0, };
473                 /* do nothing - blobs are zero length */
474
475                 /* session key is all zeros */
476                 session_key = data_blob_talloc(ntlmssp_state, zeros, 16);
477
478                 /* not doing NLTM2 without a password */
479                 ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_NTLM2;
480         } else if (ntlmssp_state->use_ntlmv2) {
481                 if (!struct_blob.length) {
482                         /* be lazy, match win2k - we can't do NTLMv2 without it */
483                         DEBUG(1, ("Server did not provide 'target information', required for NTLMv2\n"));
484                         return NT_STATUS_INVALID_PARAMETER;
485                 }
486
487                 /* TODO: if the remote server is standalone, then we should replace 'domain'
488                    with the server name as supplied above */
489
490                 if (!SMBNTLMv2encrypt_hash(ntlmssp_state,
491                                            ntlmssp_state->user,
492                                            ntlmssp_state->domain,
493                                            ntlmssp_state->nt_hash, &challenge_blob,
494                                            &struct_blob,
495                                            &lm_response, &nt_response, NULL,
496                                            &session_key)) {
497                         data_blob_free(&challenge_blob);
498                         data_blob_free(&struct_blob);
499                         return NT_STATUS_NO_MEMORY;
500                 }
501         } else if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_NTLM2) {
502                 struct MD5Context md5_session_nonce_ctx;
503                 uint8_t session_nonce[16];
504                 uint8_t session_nonce_hash[16];
505                 uint8_t user_session_key[16];
506
507                 lm_response = data_blob_talloc(ntlmssp_state, NULL, 24);
508                 generate_random_buffer(lm_response.data, 8);
509                 memset(lm_response.data+8, 0, 16);
510
511                 memcpy(session_nonce, challenge_blob.data, 8);
512                 memcpy(&session_nonce[8], lm_response.data, 8);
513
514                 MD5Init(&md5_session_nonce_ctx);
515                 MD5Update(&md5_session_nonce_ctx, challenge_blob.data, 8);
516                 MD5Update(&md5_session_nonce_ctx, lm_response.data, 8);
517                 MD5Final(session_nonce_hash, &md5_session_nonce_ctx);
518
519                 DEBUG(5, ("NTLMSSP challenge set by NTLM2\n"));
520                 DEBUG(5, ("challenge is: \n"));
521                 dump_data(5, session_nonce_hash, 8);
522
523                 nt_response = data_blob_talloc(ntlmssp_state, NULL, 24);
524                 SMBNTencrypt_hash(ntlmssp_state->nt_hash,
525                                   session_nonce_hash,
526                                   nt_response.data);
527
528                 session_key = data_blob_talloc(ntlmssp_state, NULL, 16);
529
530                 SMBsesskeygen_ntv1(ntlmssp_state->nt_hash, user_session_key);
531                 hmac_md5(user_session_key, session_nonce, sizeof(session_nonce), session_key.data);
532                 dump_data_pw("NTLM2 session key:\n", session_key.data, session_key.length);
533         } else {
534                 /* lanman auth is insecure, it may be disabled */
535                 if (lp_client_lanman_auth() && ntlmssp_state->lm_hash) {
536                         lm_response = data_blob_talloc(ntlmssp_state,
537                                                        NULL, 24);
538                         SMBencrypt_hash(ntlmssp_state->lm_hash,challenge_blob.data,
539                                    lm_response.data);
540                 }
541
542                 nt_response = data_blob_talloc(ntlmssp_state, NULL, 24);
543                 SMBNTencrypt_hash(ntlmssp_state->nt_hash,challenge_blob.data,
544                              nt_response.data);
545
546                 session_key = data_blob_talloc(ntlmssp_state, NULL, 16);
547                 if ((ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_LM_KEY)
548                     && lp_client_lanman_auth() && ntlmssp_state->lm_hash) {
549                         SMBsesskeygen_lm_sess_key(ntlmssp_state->lm_hash, lm_response.data,
550                                         session_key.data);
551                         dump_data_pw("LM session key\n", session_key.data, session_key.length);
552                 } else {
553                         SMBsesskeygen_ntv1(ntlmssp_state->nt_hash, session_key.data);
554                         dump_data_pw("NT session key:\n", session_key.data, session_key.length);
555                 }
556         }
557         data_blob_free(&struct_blob);
558
559         /* Key exchange encryptes a new client-generated session key with
560            the password-derived key */
561         if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_KEY_EXCH) {
562                 /* Make up a new session key */
563                 uint8_t client_session_key[16];
564                 generate_random_buffer(client_session_key, sizeof(client_session_key));
565
566                 /* Encrypt the new session key with the old one */
567                 encrypted_session_key = data_blob(client_session_key, sizeof(client_session_key));
568                 dump_data_pw("KEY_EXCH session key:\n", encrypted_session_key.data, encrypted_session_key.length);
569                 arcfour_crypt_blob(encrypted_session_key.data, encrypted_session_key.length, &session_key);
570                 dump_data_pw("KEY_EXCH session key (enc):\n", encrypted_session_key.data, encrypted_session_key.length);
571
572                 /* Mark the new session key as the 'real' session key */
573                 data_blob_free(&session_key);
574                 session_key = data_blob_talloc(ntlmssp_state,
575                                                client_session_key,
576                                                sizeof(client_session_key));
577         }
578
579         /* this generates the actual auth packet */
580         nt_status = msrpc_gen(ntlmssp_state, next_request, auth_gen_string,
581                        "NTLMSSP",
582                        NTLMSSP_AUTH,
583                        lm_response.data, lm_response.length,
584                        nt_response.data, nt_response.length,
585                        ntlmssp_state->domain,
586                        ntlmssp_state->user,
587                        ntlmssp_state->client.netbios_name,
588                        encrypted_session_key.data, encrypted_session_key.length,
589                        ntlmssp_state->neg_flags);
590
591         if (!NT_STATUS_IS_OK(nt_status)) {
592                 return NT_STATUS_NO_MEMORY;
593         }
594
595         if (DEBUGLEVEL >= 10) {
596                 struct AUTHENTICATE_MESSAGE *authenticate = talloc(
597                         talloc_tos(), struct AUTHENTICATE_MESSAGE);
598                 if (authenticate != NULL) {
599                         NTSTATUS status;
600                         authenticate->NegotiateFlags =
601                                 ntlmssp_state->neg_flags;
602                         status = ntlmssp_pull_AUTHENTICATE_MESSAGE(
603                                 next_request, authenticate, authenticate);
604                         if (NT_STATUS_IS_OK(status)) {
605                                 NDR_PRINT_DEBUG(AUTHENTICATE_MESSAGE,
606                                                 authenticate);
607                         }
608                         TALLOC_FREE(authenticate);
609                 }
610         }
611
612         data_blob_free(&encrypted_session_key);
613
614         data_blob_free(&ntlmssp_state->chal);
615
616         ntlmssp_state->session_key = session_key;
617
618         ntlmssp_state->chal = challenge_blob;
619         ntlmssp_state->lm_resp = lm_response;
620         ntlmssp_state->nt_resp = nt_response;
621
622 done:
623
624         ntlmssp_state->expected_state = NTLMSSP_DONE;
625
626         if (!NT_STATUS_IS_OK(nt_status = ntlmssp_sign_init(ntlmssp_state))) {
627                 DEBUG(1, ("Could not setup NTLMSSP signing/sealing system (error was: %s)\n", nt_errstr(nt_status)));
628         }
629
630         return nt_status;
631 }
632
633 NTSTATUS ntlmssp_client_start(TALLOC_CTX *mem_ctx,
634                               const char *netbios_name,
635                               const char *netbios_domain,
636                               bool use_ntlmv2,
637                               struct ntlmssp_state **_ntlmssp_state)
638 {
639         struct ntlmssp_state *ntlmssp_state;
640
641         if (!netbios_name) {
642                 netbios_name = "";
643         }
644
645         if (!netbios_domain) {
646                 netbios_domain = "";
647         }
648
649         ntlmssp_state = talloc_zero(mem_ctx, struct ntlmssp_state);
650         if (!ntlmssp_state) {
651                 return NT_STATUS_NO_MEMORY;
652         }
653
654         ntlmssp_state->role = NTLMSSP_CLIENT;
655
656         ntlmssp_state->unicode = True;
657
658         ntlmssp_state->use_ntlmv2 = use_ntlmv2;
659
660         ntlmssp_state->expected_state = NTLMSSP_INITIAL;
661
662         ntlmssp_state->neg_flags =
663                 NTLMSSP_NEGOTIATE_128 |
664                 NTLMSSP_NEGOTIATE_ALWAYS_SIGN |
665                 NTLMSSP_NEGOTIATE_NTLM |
666                 NTLMSSP_NEGOTIATE_NTLM2 |
667                 NTLMSSP_NEGOTIATE_KEY_EXCH |
668                 NTLMSSP_REQUEST_TARGET;
669
670         ntlmssp_state->client.netbios_name = talloc_strdup(ntlmssp_state, netbios_name);
671         if (!ntlmssp_state->client.netbios_name) {
672                 talloc_free(ntlmssp_state);
673                 return NT_STATUS_NO_MEMORY;
674         }
675         ntlmssp_state->client.netbios_domain = talloc_strdup(ntlmssp_state, netbios_domain);
676         if (!ntlmssp_state->client.netbios_domain) {
677                 talloc_free(ntlmssp_state);
678                 return NT_STATUS_NO_MEMORY;
679         }
680
681         *_ntlmssp_state = ntlmssp_state;
682         return NT_STATUS_OK;
683 }