smbd: Correct PATH_ vs NAME_NOT_FOUND for not following lcomp
[Samba.git] / auth / credentials / credentials_ntlm.c
bloba018be14c56b2377013573e1d330eabe7191ceb7
1 /*
2 Unix SMB/CIFS implementation.
4 User credentials handling
6 Copyright (C) Andrew Tridgell 2001
7 Copyright (C) Andrew Bartlett <abartlet@samba.org> 2001-2005
8 Copyright (C) Stefan Metzmacher 2005
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.
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.
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/>.
24 #include "includes.h"
25 #include "librpc/gen_ndr/samr.h" /* for struct samrPassword */
26 #include "../lib/crypto/crypto.h"
27 #include "libcli/auth/libcli_auth.h"
28 #include "auth/credentials/credentials.h"
29 #include "auth/credentials/credentials_internal.h"
31 #include "lib/crypto/gnutls_helpers.h"
32 #include <gnutls/gnutls.h>
33 #include <gnutls/crypto.h>
35 #undef DBGC_CLASS
36 #define DBGC_CLASS DBGC_AUTH
38 _PUBLIC_ NTSTATUS cli_credentials_get_ntlm_response(struct cli_credentials *cred, TALLOC_CTX *mem_ctx,
39 int *flags,
40 DATA_BLOB challenge,
41 const NTTIME *server_timestamp,
42 DATA_BLOB target_info,
43 DATA_BLOB *_lm_response, DATA_BLOB *_nt_response,
44 DATA_BLOB *_lm_session_key, DATA_BLOB *_session_key)
46 TALLOC_CTX *frame = talloc_stackframe();
47 const char *user = NULL;
48 const char *domain = NULL;
49 DATA_BLOB lm_response = data_blob_null;
50 DATA_BLOB nt_response = data_blob_null;
51 DATA_BLOB lm_session_key = data_blob_null;
52 DATA_BLOB session_key = data_blob_null;
53 const struct samr_Password *nt_hash = NULL;
54 int rc;
56 if (cred->kerberos_state == CRED_USE_KERBEROS_REQUIRED) {
57 TALLOC_FREE(frame);
58 return NT_STATUS_INVALID_PARAMETER_MIX;
61 /* We may already have an NTLM response we prepared earlier.
62 * This is used for NTLM pass-though authentication */
63 if (cred->nt_response.data || cred->lm_response.data) {
64 if (cred->nt_response.length != 0) {
65 nt_response = data_blob_dup_talloc(frame,
66 cred->nt_response);
67 if (nt_response.data == NULL) {
68 TALLOC_FREE(frame);
69 return NT_STATUS_NO_MEMORY;
72 if (cred->nt_session_key.length != 0) {
73 session_key = data_blob_dup_talloc(frame,
74 cred->nt_session_key);
75 if (session_key.data == NULL) {
76 TALLOC_FREE(frame);
77 return NT_STATUS_NO_MEMORY;
80 if (cred->lm_response.length != 0) {
81 lm_response = data_blob_dup_talloc(frame,
82 cred->lm_response);
83 if (lm_response.data == NULL) {
84 TALLOC_FREE(frame);
85 return NT_STATUS_NO_MEMORY;
88 if (cred->lm_session_key.length != 0) {
89 lm_session_key = data_blob_dup_talloc(frame,
90 cred->lm_session_key);
91 if (lm_session_key.data == NULL) {
92 TALLOC_FREE(frame);
93 return NT_STATUS_NO_MEMORY;
97 if (cred->lm_response.data == NULL) {
98 *flags = *flags & ~CLI_CRED_LANMAN_AUTH;
100 goto done;
103 nt_hash = cli_credentials_get_nt_hash(cred, frame);
105 cli_credentials_get_ntlm_username_domain(cred, frame, &user, &domain);
106 if (user == NULL) {
107 TALLOC_FREE(frame);
108 return NT_STATUS_NO_MEMORY;
110 if (domain == NULL) {
111 TALLOC_FREE(frame);
112 return NT_STATUS_NO_MEMORY;
115 /* If we are sending a username@realm login (see function
116 * above), then we will not send LM, it will not be
117 * accepted */
118 if (cred->principal_obtained > cred->username_obtained) {
119 *flags = *flags & ~CLI_CRED_LANMAN_AUTH;
122 /* Likewise if we are a machine account (avoid protocol downgrade attacks) */
123 if (cred->machine_account) {
124 *flags = *flags & ~CLI_CRED_LANMAN_AUTH;
127 if (!nt_hash) {
128 /* do nothing - blobs are zero length */
130 /* session key is all zeros */
131 session_key = data_blob_talloc_zero(frame, 16);
132 if (session_key.data == NULL) {
133 TALLOC_FREE(frame);
134 return NT_STATUS_NO_MEMORY;
136 lm_session_key = data_blob_talloc_zero(frame, 16);
137 if (lm_session_key.data == NULL) {
138 TALLOC_FREE(frame);
139 return NT_STATUS_NO_MEMORY;
142 /* not doing NTLM2 without a password */
143 *flags &= ~CLI_CRED_NTLM2;
144 } else if (*flags & CLI_CRED_NTLMv2_AUTH) {
146 if (!target_info.length) {
147 /* be lazy, match win2k - we can't do NTLMv2 without it */
148 DEBUG(1, ("Server did not provide 'target information', required for NTLMv2\n"));
149 TALLOC_FREE(frame);
150 return NT_STATUS_INVALID_PARAMETER;
153 /* TODO: if the remote server is standalone, then we should replace 'domain'
154 with the server name as supplied above */
156 if (!SMBNTLMv2encrypt_hash(frame,
157 user,
158 domain,
159 nt_hash->hash, &challenge,
160 server_timestamp, &target_info,
161 &lm_response, &nt_response,
162 NULL, &session_key)) {
163 TALLOC_FREE(frame);
164 return NT_STATUS_NO_MEMORY;
167 /* LM Key is incompatible... */
168 *flags &= ~CLI_CRED_LANMAN_AUTH;
169 if (lm_response.length != 0) {
171 * We should not expose the lm key.
173 memset(lm_response.data, 0, lm_response.length);
175 } else if (*flags & CLI_CRED_NTLM2) {
176 uint8_t session_nonce[16];
177 uint8_t session_nonce_hash[16];
178 uint8_t user_session_key[16];
180 lm_response = data_blob_talloc_zero(frame, 24);
181 if (lm_response.data == NULL) {
182 TALLOC_FREE(frame);
183 return NT_STATUS_NO_MEMORY;
185 generate_random_buffer(lm_response.data, 8);
187 memcpy(session_nonce, challenge.data, 8);
188 memcpy(&session_nonce[8], lm_response.data, 8);
190 rc = gnutls_hash_fast(GNUTLS_DIG_MD5,
191 session_nonce,
192 sizeof(session_nonce),
193 session_nonce_hash);
194 if (rc < 0) {
195 return gnutls_error_to_ntstatus(rc, NT_STATUS_NTLM_BLOCKED);
198 DEBUG(5, ("NTLMSSP challenge set by NTLM2\n"));
199 DEBUG(5, ("challenge is: \n"));
200 dump_data(5, session_nonce_hash, 8);
202 nt_response = data_blob_talloc_zero(frame, 24);
203 if (nt_response.data == NULL) {
204 TALLOC_FREE(frame);
205 return NT_STATUS_NO_MEMORY;
207 rc = SMBOWFencrypt(nt_hash->hash,
208 session_nonce_hash,
209 nt_response.data);
210 if (rc != 0) {
211 TALLOC_FREE(frame);
212 return gnutls_error_to_ntstatus(rc, NT_STATUS_ACCESS_DISABLED_BY_POLICY_OTHER);
215 ZERO_ARRAY(session_nonce_hash);
217 session_key = data_blob_talloc_zero(frame, 16);
218 if (session_key.data == NULL) {
219 TALLOC_FREE(frame);
220 return NT_STATUS_NO_MEMORY;
223 SMBsesskeygen_ntv1(nt_hash->hash, user_session_key);
225 rc = gnutls_hmac_fast(GNUTLS_MAC_MD5,
226 user_session_key,
227 sizeof(user_session_key),
228 session_nonce,
229 sizeof(session_nonce),
230 session_key.data);
231 if (rc < 0) {
232 return gnutls_error_to_ntstatus(rc, NT_STATUS_NTLM_BLOCKED);
235 ZERO_ARRAY(user_session_key);
237 dump_data_pw("NTLM2 session key:\n", session_key.data, session_key.length);
239 /* LM Key is incompatible... */
240 *flags &= ~CLI_CRED_LANMAN_AUTH;
241 } else {
242 const char *password = cli_credentials_get_password(cred);
243 uint8_t lm_hash[16];
244 bool do_lm = false;
246 nt_response = data_blob_talloc_zero(frame, 24);
247 if (nt_response.data == NULL) {
248 TALLOC_FREE(frame);
249 return NT_STATUS_NO_MEMORY;
251 rc = SMBOWFencrypt(nt_hash->hash, challenge.data,
252 nt_response.data);
253 if (rc != 0) {
254 TALLOC_FREE(frame);
255 return gnutls_error_to_ntstatus(rc, NT_STATUS_ACCESS_DISABLED_BY_POLICY_OTHER);
258 session_key = data_blob_talloc_zero(frame, 16);
259 if (session_key.data == NULL) {
260 TALLOC_FREE(frame);
261 return NT_STATUS_NO_MEMORY;
263 SMBsesskeygen_ntv1(nt_hash->hash, session_key.data);
264 dump_data_pw("NT session key:\n", session_key.data, session_key.length);
266 /* lanman auth is insecure, it may be disabled.
267 We may also not have a password */
269 if (password != NULL) {
270 do_lm = E_deshash(password, lm_hash);
273 if (*flags & CLI_CRED_LANMAN_AUTH && do_lm) {
274 lm_response = data_blob_talloc_zero(frame, 24);
275 if (lm_response.data == NULL) {
276 ZERO_STRUCT(lm_hash);
277 TALLOC_FREE(frame);
278 return NT_STATUS_NO_MEMORY;
281 rc = SMBencrypt_hash(lm_hash,
282 challenge.data,
283 lm_response.data);
284 if (rc != 0) {
285 ZERO_STRUCT(lm_hash);
286 TALLOC_FREE(frame);
287 return gnutls_error_to_ntstatus(rc, NT_STATUS_ACCESS_DISABLED_BY_POLICY_OTHER);
289 } else {
290 /* just copy the nt_response */
291 lm_response = data_blob_dup_talloc(frame, nt_response);
292 if (lm_response.data == NULL) {
293 ZERO_STRUCT(lm_hash);
294 TALLOC_FREE(frame);
295 return NT_STATUS_NO_MEMORY;
299 if (do_lm) {
300 lm_session_key = data_blob_talloc_zero(frame, 16);
301 if (lm_session_key.data == NULL) {
302 ZERO_STRUCT(lm_hash);
303 TALLOC_FREE(frame);
304 return NT_STATUS_NO_MEMORY;
306 memcpy(lm_session_key.data, lm_hash, 8);
308 if (!(*flags & CLI_CRED_NTLM_AUTH)) {
309 memcpy(session_key.data, lm_session_key.data, 16);
311 ZERO_STRUCT(lm_hash);
315 done:
316 if (_lm_response != NULL) {
317 talloc_steal(mem_ctx, lm_response.data);
318 *_lm_response = lm_response;
319 } else {
320 data_blob_clear(&lm_response);
322 if (_nt_response != NULL) {
323 talloc_steal(mem_ctx, nt_response.data);
324 *_nt_response = nt_response;
325 } else {
326 data_blob_clear(&nt_response);
328 if (_lm_session_key != NULL) {
329 talloc_steal(mem_ctx, lm_session_key.data);
330 *_lm_session_key = lm_session_key;
331 } else {
332 data_blob_clear(&lm_session_key);
334 if (_session_key != NULL) {
335 talloc_steal(mem_ctx, session_key.data);
336 *_session_key = session_key;
337 } else {
338 data_blob_clear(&session_key);
340 TALLOC_FREE(frame);
341 return NT_STATUS_OK;
345 * Set a utf16 password on the credentials context, including an indication
346 * of 'how' the password was obtained
348 * This is required because the nt_hash is calculated over the raw utf16 blob,
349 * which might not be completely valid utf16, which means the conversion
350 * from CH_UTF16MUNGED to CH_UTF8 might lose information.
352 _PUBLIC_ bool cli_credentials_set_utf16_password(struct cli_credentials *cred,
353 const DATA_BLOB *password_utf16,
354 enum credentials_obtained obtained)
356 cred->password_will_be_nt_hash = false;
358 if (password_utf16 == NULL) {
359 return cli_credentials_set_password(cred, NULL, obtained);
362 if (obtained >= cred->password_obtained) {
363 struct samr_Password *nt_hash = NULL;
364 char *password_talloc = NULL;
365 size_t password_len = 0;
366 bool ok;
368 nt_hash = talloc(cred, struct samr_Password);
369 if (nt_hash == NULL) {
370 return false;
373 ok = convert_string_talloc(cred,
374 CH_UTF16MUNGED, CH_UTF8,
375 password_utf16->data,
376 password_utf16->length,
377 &password_talloc,
378 &password_len);
379 if (!ok) {
380 TALLOC_FREE(nt_hash);
381 return false;
384 ok = cli_credentials_set_password(cred, password_talloc, obtained);
385 TALLOC_FREE(password_talloc);
386 if (!ok) {
387 TALLOC_FREE(nt_hash);
388 return false;
391 mdfour(nt_hash->hash, password_utf16->data, password_utf16->length);
392 cred->nt_hash = nt_hash;
393 return true;
396 return false;
400 * Set a old utf16 password on the credentials context.
402 * This is required because the nt_hash is calculated over the raw utf16 blob,
403 * which might not be completely valid utf16, which means the conversion
404 * from CH_UTF16MUNGED to CH_UTF8 might lose information.
406 _PUBLIC_ bool cli_credentials_set_old_utf16_password(struct cli_credentials *cred,
407 const DATA_BLOB *password_utf16)
409 struct samr_Password *nt_hash = NULL;
410 char *password_talloc = NULL;
411 size_t password_len = 0;
412 bool ok;
414 if (password_utf16 == NULL) {
415 return cli_credentials_set_old_password(cred, NULL, CRED_SPECIFIED);
418 nt_hash = talloc(cred, struct samr_Password);
419 if (nt_hash == NULL) {
420 return false;
423 ok = convert_string_talloc(cred,
424 CH_UTF16MUNGED, CH_UTF8,
425 password_utf16->data,
426 password_utf16->length,
427 &password_talloc,
428 &password_len);
429 if (!ok) {
430 TALLOC_FREE(nt_hash);
431 return false;
434 ok = cli_credentials_set_old_password(cred, password_talloc, CRED_SPECIFIED);
435 TALLOC_FREE(password_talloc);
436 if (!ok) {
437 TALLOC_FREE(nt_hash);
438 return false;
441 mdfour(nt_hash->hash, password_utf16->data, password_utf16->length);
442 cred->old_nt_hash = nt_hash;
443 return true;
446 _PUBLIC_ void cli_credentials_set_password_will_be_nt_hash(struct cli_credentials *cred,
447 bool val)
450 * We set this here and the next cli_credentials_set_password()
451 * that resets the password or password callback
452 * will pick this up.
454 * cli_credentials_set_nt_hash() and
455 * cli_credentials_set_utf16_password() will reset this
456 * to false.
458 cred->password_will_be_nt_hash = val;
461 _PUBLIC_ bool cli_credentials_is_password_nt_hash(struct cli_credentials *cred)
463 return cred->password_will_be_nt_hash;
466 _PUBLIC_ bool cli_credentials_set_nt_hash(struct cli_credentials *cred,
467 const struct samr_Password *nt_hash,
468 enum credentials_obtained obtained)
470 cred->password_will_be_nt_hash = false;
472 if (obtained >= cred->password_obtained) {
473 cli_credentials_set_password(cred, NULL, obtained);
474 if (nt_hash) {
475 cred->nt_hash = talloc(cred, struct samr_Password);
476 if (cred->nt_hash == NULL) {
477 return false;
479 *cred->nt_hash = *nt_hash;
480 } else {
481 cred->nt_hash = NULL;
483 return true;
486 return false;
489 _PUBLIC_ bool cli_credentials_set_old_nt_hash(struct cli_credentials *cred,
490 const struct samr_Password *nt_hash)
492 cli_credentials_set_old_password(cred, NULL, CRED_SPECIFIED);
493 if (nt_hash) {
494 cred->old_nt_hash = talloc(cred, struct samr_Password);
495 if (cred->old_nt_hash == NULL) {
496 return false;
498 *cred->old_nt_hash = *nt_hash;
499 } else {
500 cred->old_nt_hash = NULL;
503 return true;
506 _PUBLIC_ bool cli_credentials_set_ntlm_response(struct cli_credentials *cred,
507 const DATA_BLOB *lm_response,
508 const DATA_BLOB *lm_session_key,
509 const DATA_BLOB *nt_response,
510 const DATA_BLOB *nt_session_key,
511 enum credentials_obtained obtained)
513 if (obtained >= cred->password_obtained) {
514 cli_credentials_set_password(cred, NULL, obtained);
516 data_blob_clear_free(&cred->lm_response);
517 data_blob_clear_free(&cred->lm_session_key);
518 data_blob_clear_free(&cred->nt_response);
519 data_blob_clear_free(&cred->nt_session_key);
521 if (lm_response != NULL && lm_response->length != 0) {
522 cred->lm_response = data_blob_talloc(cred,
523 lm_response->data,
524 lm_response->length);
525 if (cred->lm_response.data == NULL) {
526 return false;
529 if (lm_session_key != NULL && lm_session_key->length != 0) {
530 cred->lm_session_key = data_blob_talloc(cred,
531 lm_session_key->data,
532 lm_session_key->length);
533 if (cred->lm_session_key.data == NULL) {
534 return false;
538 if (nt_response != NULL && nt_response->length != 0) {
539 cred->nt_response = data_blob_talloc(cred,
540 nt_response->data,
541 nt_response->length);
542 if (cred->nt_response.data == NULL) {
543 return false;
546 if (nt_session_key != NULL && nt_session_key->length != 0) {
547 cred->nt_session_key = data_blob_talloc(cred,
548 nt_session_key->data,
549 nt_session_key->length);
550 if (cred->nt_session_key.data == NULL) {
551 return false;
555 return true;
558 return false;