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