Line data Source code
1 : /*
2 : Unix SMB/CIFS implementation.
3 :
4 : User credentials handling
5 :
6 : Copyright (C) Jelmer Vernooij 2005
7 : Copyright (C) Tim Potter 2001
8 : Copyright (C) Andrew Bartlett <abartlet@samba.org> 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 "librpc/gen_ndr/samr.h" /* for struct samrPassword */
26 : #include "auth/credentials/credentials.h"
27 : #include "auth/credentials/credentials_internal.h"
28 : #include "auth/gensec/gensec.h"
29 : #include "libcli/auth/libcli_auth.h"
30 : #include "tevent.h"
31 : #include "param/param.h"
32 : #include "system/filesys.h"
33 : #include "system/passwd.h"
34 :
35 : /**
36 : * Create a new credentials structure
37 : * @param mem_ctx TALLOC_CTX parent for credentials structure
38 : */
39 360754 : _PUBLIC_ struct cli_credentials *cli_credentials_init(TALLOC_CTX *mem_ctx)
40 : {
41 360754 : struct cli_credentials *cred = talloc_zero(mem_ctx, struct cli_credentials);
42 360754 : if (cred == NULL) {
43 0 : return cred;
44 : }
45 :
46 360754 : cred->winbind_separator = '\\';
47 :
48 360754 : cred->kerberos_state = CRED_USE_KERBEROS_DESIRED;
49 :
50 360754 : cred->signing_state = SMB_SIGNING_DEFAULT;
51 :
52 : /*
53 : * The default value of lpcfg_client_ipc_signing() is REQUIRED, so use
54 : * the same value here.
55 : */
56 360754 : cred->ipc_signing_state = SMB_SIGNING_REQUIRED;
57 360754 : cred->encryption_state = SMB_ENCRYPTION_DEFAULT;
58 :
59 360754 : return cred;
60 : }
61 :
62 : _PUBLIC_
63 62357 : struct cli_credentials *cli_credentials_init_server(TALLOC_CTX *mem_ctx,
64 : struct loadparm_context *lp_ctx)
65 : {
66 62357 : struct cli_credentials *server_creds = NULL;
67 2633 : NTSTATUS status;
68 2633 : bool ok;
69 :
70 62357 : server_creds = cli_credentials_init(mem_ctx);
71 62357 : if (server_creds == NULL) {
72 0 : return NULL;
73 : }
74 :
75 62357 : ok = cli_credentials_set_conf(server_creds, lp_ctx);
76 62357 : if (!ok) {
77 0 : TALLOC_FREE(server_creds);
78 0 : return NULL;
79 : }
80 :
81 62357 : status = cli_credentials_set_machine_account(server_creds, lp_ctx);
82 62357 : if (!NT_STATUS_IS_OK(status)) {
83 2 : DEBUG(1, ("Failed to obtain server credentials: %s\n",
84 : nt_errstr(status)));
85 2 : TALLOC_FREE(server_creds);
86 2 : return NULL;
87 : }
88 :
89 59722 : return server_creds;
90 : }
91 :
92 0 : _PUBLIC_ void cli_credentials_set_callback_data(struct cli_credentials *cred,
93 : void *callback_data)
94 : {
95 0 : cred->priv_data = callback_data;
96 0 : }
97 :
98 0 : _PUBLIC_ void *_cli_credentials_callback_data(struct cli_credentials *cred)
99 : {
100 0 : return cred->priv_data;
101 : }
102 :
103 : /**
104 : * Create a new anonymous credential
105 : * @param mem_ctx TALLOC_CTX parent for credentials structure
106 : */
107 121786 : _PUBLIC_ struct cli_credentials *cli_credentials_init_anon(TALLOC_CTX *mem_ctx)
108 : {
109 1892 : struct cli_credentials *anon_credentials;
110 :
111 121786 : anon_credentials = cli_credentials_init(mem_ctx);
112 121786 : cli_credentials_set_anonymous(anon_credentials);
113 :
114 121786 : return anon_credentials;
115 : }
116 :
117 283524 : _PUBLIC_ bool cli_credentials_set_kerberos_state(struct cli_credentials *creds,
118 : enum credentials_use_kerberos kerberos_state,
119 : enum credentials_obtained obtained)
120 : {
121 283524 : if (obtained >= creds->kerberos_state_obtained) {
122 283523 : creds->kerberos_state = kerberos_state;
123 283523 : creds->kerberos_state_obtained = obtained;
124 :
125 283523 : return true;
126 : }
127 :
128 0 : return false;
129 : }
130 :
131 0 : _PUBLIC_ void cli_credentials_set_forced_sasl_mech(struct cli_credentials *creds,
132 : const char *sasl_mech)
133 : {
134 0 : TALLOC_FREE(creds->forced_sasl_mech);
135 0 : creds->forced_sasl_mech = talloc_strdup(creds, sasl_mech);
136 0 : }
137 :
138 80 : _PUBLIC_ void cli_credentials_set_krb_forwardable(struct cli_credentials *creds,
139 : enum credentials_krb_forwardable krb_forwardable)
140 : {
141 80 : creds->krb_forwardable = krb_forwardable;
142 80 : }
143 :
144 713630 : _PUBLIC_ enum credentials_use_kerberos cli_credentials_get_kerberos_state(struct cli_credentials *creds)
145 : {
146 713630 : return creds->kerberos_state;
147 : }
148 :
149 414498 : _PUBLIC_ const char *cli_credentials_get_forced_sasl_mech(struct cli_credentials *creds)
150 : {
151 414498 : return creds->forced_sasl_mech;
152 : }
153 :
154 15066 : _PUBLIC_ enum credentials_krb_forwardable cli_credentials_get_krb_forwardable(struct cli_credentials *creds)
155 : {
156 15066 : return creds->krb_forwardable;
157 : }
158 :
159 43136 : _PUBLIC_ bool cli_credentials_set_gensec_features(struct cli_credentials *creds,
160 : uint32_t gensec_features,
161 : enum credentials_obtained obtained)
162 : {
163 43136 : if (obtained >= creds->gensec_features_obtained) {
164 43135 : creds->gensec_features_obtained = obtained;
165 43135 : creds->gensec_features = gensec_features;
166 :
167 43135 : return true;
168 : }
169 :
170 0 : return false;
171 : }
172 :
173 344625 : _PUBLIC_ uint32_t cli_credentials_get_gensec_features(struct cli_credentials *creds)
174 : {
175 344625 : return creds->gensec_features;
176 : }
177 :
178 :
179 : /**
180 : * Obtain the username for this credentials context.
181 : * @param cred credentials context
182 : * @retval The username set on this context.
183 : * @note Return value will never be NULL except by programmer error.
184 : */
185 1553981 : _PUBLIC_ const char *cli_credentials_get_username(struct cli_credentials *cred)
186 : {
187 1553981 : if (cred->machine_account_pending) {
188 0 : cli_credentials_set_machine_account(cred,
189 : cred->machine_account_pending_lp_ctx);
190 : }
191 :
192 1553981 : if (cred->username_obtained == CRED_CALLBACK &&
193 0 : !cred->callback_running) {
194 0 : cred->callback_running = true;
195 0 : cred->username = cred->username_cb(cred);
196 0 : cred->callback_running = false;
197 0 : if (cred->username_obtained == CRED_CALLBACK) {
198 0 : cred->username_obtained = CRED_CALLBACK_RESULT;
199 0 : cli_credentials_invalidate_ccache(cred, cred->username_obtained);
200 : }
201 : }
202 :
203 1553981 : return cred->username;
204 : }
205 :
206 : /**
207 : * @brief Obtain the username for this credentials context.
208 : *
209 : * @param[in] cred The credential context.
210 : *
211 : * @param[in] obtained A pointer to store the obtained information.
212 : *
213 : * return The user name or NULL if an error occurred.
214 : */
215 : _PUBLIC_ const char *
216 24444 : cli_credentials_get_username_and_obtained(struct cli_credentials *cred,
217 : enum credentials_obtained *obtained)
218 : {
219 24444 : if (obtained != NULL) {
220 24444 : *obtained = cred->username_obtained;
221 : }
222 :
223 24444 : return cli_credentials_get_username(cred);
224 : }
225 :
226 813483 : _PUBLIC_ bool cli_credentials_set_username(struct cli_credentials *cred,
227 : const char *val, enum credentials_obtained obtained)
228 : {
229 813483 : if (obtained >= cred->username_obtained) {
230 682294 : cred->username = talloc_strdup(cred, val);
231 682294 : cred->username_obtained = obtained;
232 682294 : cli_credentials_invalidate_ccache(cred, cred->username_obtained);
233 682294 : return true;
234 : }
235 :
236 131013 : return false;
237 : }
238 :
239 0 : _PUBLIC_ bool cli_credentials_set_username_callback(struct cli_credentials *cred,
240 : const char *(*username_cb) (struct cli_credentials *))
241 : {
242 0 : if (cred->username_obtained < CRED_CALLBACK) {
243 0 : cred->username_cb = username_cb;
244 0 : cred->username_obtained = CRED_CALLBACK;
245 0 : return true;
246 : }
247 :
248 0 : return false;
249 : }
250 :
251 605 : _PUBLIC_ bool cli_credentials_set_bind_dn(struct cli_credentials *cred,
252 : const char *bind_dn)
253 : {
254 605 : cred->bind_dn = talloc_strdup(cred, bind_dn);
255 605 : return true;
256 : }
257 :
258 : /**
259 : * Obtain the BIND DN for this credentials context.
260 : * @param cred credentials context
261 : * @retval The username set on this context.
262 : * @note Return value will be NULL if not specified explicitly
263 : */
264 27812 : _PUBLIC_ const char *cli_credentials_get_bind_dn(struct cli_credentials *cred)
265 : {
266 27812 : return cred->bind_dn;
267 : }
268 :
269 :
270 : /**
271 : * Obtain the client principal for this credentials context.
272 : * @param cred credentials context
273 : * @retval The username set on this context.
274 : * @note Return value will never be NULL except by programmer error.
275 : */
276 87741 : _PUBLIC_ char *cli_credentials_get_principal_and_obtained(struct cli_credentials *cred, TALLOC_CTX *mem_ctx, enum credentials_obtained *obtained)
277 : {
278 87741 : if (cred->machine_account_pending) {
279 0 : cli_credentials_set_machine_account(cred,
280 : cred->machine_account_pending_lp_ctx);
281 : }
282 :
283 87741 : if (cred->principal_obtained == CRED_CALLBACK &&
284 0 : !cred->callback_running) {
285 0 : cred->callback_running = true;
286 0 : cred->principal = cred->principal_cb(cred);
287 0 : cred->callback_running = false;
288 0 : if (cred->principal_obtained == CRED_CALLBACK) {
289 0 : cred->principal_obtained = CRED_CALLBACK_RESULT;
290 0 : cli_credentials_invalidate_ccache(cred, cred->principal_obtained);
291 : }
292 : }
293 :
294 87741 : if (cred->principal_obtained < cred->username_obtained
295 5472 : || cred->principal_obtained < MAX(cred->domain_obtained, cred->realm_obtained)) {
296 82277 : const char *effective_username = NULL;
297 82277 : const char *effective_realm = NULL;
298 2754 : enum credentials_obtained effective_obtained;
299 :
300 82277 : effective_username = cli_credentials_get_username(cred);
301 82277 : if (effective_username == NULL || strlen(effective_username) == 0) {
302 7 : *obtained = cred->username_obtained;
303 7 : return NULL;
304 : }
305 :
306 82270 : if (cred->domain_obtained > cred->realm_obtained) {
307 18084 : effective_realm = cli_credentials_get_domain(cred);
308 18084 : effective_obtained = MIN(cred->domain_obtained,
309 : cred->username_obtained);
310 : } else {
311 64186 : effective_realm = cli_credentials_get_realm(cred);
312 64186 : effective_obtained = MIN(cred->realm_obtained,
313 : cred->username_obtained);
314 : }
315 :
316 82270 : if (effective_realm == NULL || strlen(effective_realm) == 0) {
317 95 : effective_realm = cli_credentials_get_domain(cred);
318 95 : effective_obtained = MIN(cred->domain_obtained,
319 : cred->username_obtained);
320 : }
321 :
322 82270 : if (effective_realm != NULL && strlen(effective_realm) != 0) {
323 82208 : *obtained = effective_obtained;
324 82208 : return talloc_asprintf(mem_ctx, "%s@%s",
325 : effective_username,
326 : effective_realm);
327 : }
328 : }
329 5526 : *obtained = cred->principal_obtained;
330 5526 : return talloc_strdup(mem_ctx, cred->principal);
331 : }
332 :
333 : /**
334 : * Obtain the client principal for this credentials context.
335 : * @param cred credentials context
336 : * @retval The username set on this context.
337 : * @note Return value will never be NULL except by programmer error.
338 : */
339 22570 : _PUBLIC_ char *cli_credentials_get_principal(struct cli_credentials *cred, TALLOC_CTX *mem_ctx)
340 : {
341 556 : enum credentials_obtained obtained;
342 22570 : return cli_credentials_get_principal_and_obtained(cred, mem_ctx, &obtained);
343 : }
344 :
345 214982 : _PUBLIC_ bool cli_credentials_set_principal(struct cli_credentials *cred,
346 : const char *val,
347 : enum credentials_obtained obtained)
348 : {
349 214982 : if (obtained >= cred->principal_obtained) {
350 214957 : cred->principal = talloc_strdup(cred, val);
351 214957 : if (cred->principal == NULL) {
352 163420 : return false;
353 : }
354 49198 : cred->principal_obtained = obtained;
355 :
356 49198 : cli_credentials_invalidate_ccache(cred, cred->principal_obtained);
357 49198 : return true;
358 : }
359 :
360 25 : return false;
361 : }
362 :
363 : /* Set a callback to get the principal. This could be a popup dialog,
364 : * a terminal prompt or similar. */
365 0 : _PUBLIC_ bool cli_credentials_set_principal_callback(struct cli_credentials *cred,
366 : const char *(*principal_cb) (struct cli_credentials *))
367 : {
368 0 : if (cred->principal_obtained < CRED_CALLBACK) {
369 0 : cred->principal_cb = principal_cb;
370 0 : cred->principal_obtained = CRED_CALLBACK;
371 0 : return true;
372 : }
373 :
374 0 : return false;
375 : }
376 :
377 : /* Some of our tools are 'anonymous by default'. This is a single
378 : * function to determine if authentication has been explicitly
379 : * requested */
380 :
381 53843 : _PUBLIC_ bool cli_credentials_authentication_requested(struct cli_credentials *cred)
382 : {
383 53843 : uint32_t gensec_features = 0;
384 :
385 53843 : if (cred->bind_dn) {
386 442 : return true;
387 : }
388 :
389 : /*
390 : * If we forced the mech we clearly want authentication. E.g. to use
391 : * SASL/EXTERNAL which has no credentials.
392 : */
393 53401 : if (cred->forced_sasl_mech) {
394 0 : return true;
395 : }
396 :
397 53401 : if (cli_credentials_is_anonymous(cred)){
398 1181 : return false;
399 : }
400 :
401 52218 : if (cred->principal_obtained >= CRED_SPECIFIED) {
402 12644 : return true;
403 : }
404 39479 : if (cred->username_obtained >= CRED_SPECIFIED) {
405 35212 : return true;
406 : }
407 :
408 4225 : if (cli_credentials_get_kerberos_state(cred) == CRED_USE_KERBEROS_REQUIRED) {
409 14 : return true;
410 : }
411 :
412 4211 : gensec_features = cli_credentials_get_gensec_features(cred);
413 4211 : if (gensec_features & GENSEC_FEATURE_NTLM_CCACHE) {
414 0 : return true;
415 : }
416 :
417 4211 : if (gensec_features & GENSEC_FEATURE_SIGN) {
418 0 : return true;
419 : }
420 :
421 4211 : if (gensec_features & GENSEC_FEATURE_SEAL) {
422 0 : return true;
423 : }
424 :
425 4190 : return false;
426 : }
427 :
428 : /**
429 : * Obtain the password for this credentials context.
430 : * @param cred credentials context
431 : * @retval If set, the cleartext password, otherwise NULL
432 : */
433 227555 : _PUBLIC_ const char *cli_credentials_get_password(struct cli_credentials *cred)
434 : {
435 227555 : if (cred->machine_account_pending) {
436 1 : cli_credentials_set_machine_account(cred,
437 : cred->machine_account_pending_lp_ctx);
438 : }
439 :
440 227555 : if (cred->password_obtained == CRED_CALLBACK &&
441 39 : !cred->callback_running &&
442 39 : !cred->password_will_be_nt_hash) {
443 39 : cred->callback_running = true;
444 39 : cred->password = cred->password_cb(cred);
445 39 : cred->callback_running = false;
446 39 : if (cred->password_obtained == CRED_CALLBACK) {
447 39 : cred->password_obtained = CRED_CALLBACK_RESULT;
448 39 : cli_credentials_invalidate_ccache(cred, cred->password_obtained);
449 : }
450 : }
451 :
452 227555 : return cred->password;
453 : }
454 :
455 : /**
456 : * @brief Obtain the password for this credentials context.
457 : *
458 : * @param[in] cred The credential context.
459 : *
460 : * @param[in] obtained A pointer to store the obtained information.
461 : *
462 : * return The user name or NULL if an error occurred.
463 : */
464 : _PUBLIC_ const char *
465 21060 : cli_credentials_get_password_and_obtained(struct cli_credentials *cred,
466 : enum credentials_obtained *obtained)
467 : {
468 21060 : const char *password = cli_credentials_get_password(cred);
469 :
470 21060 : if (obtained != NULL) {
471 21060 : *obtained = cred->password_obtained;
472 : }
473 :
474 21060 : return password;
475 : }
476 :
477 : /* Set a password on the credentials context, including an indication
478 : * of 'how' the password was obtained */
479 :
480 283886 : _PUBLIC_ bool cli_credentials_set_password(struct cli_credentials *cred,
481 : const char *val,
482 : enum credentials_obtained obtained)
483 : {
484 283886 : if (obtained >= cred->password_obtained) {
485 :
486 283843 : cred->lm_response = data_blob_null;
487 283843 : cred->nt_response = data_blob_null;
488 283843 : cred->nt_hash = NULL;
489 283843 : cred->password = NULL;
490 :
491 283843 : cli_credentials_invalidate_ccache(cred, obtained);
492 :
493 283843 : cred->password_tries = 0;
494 :
495 283843 : if (val == NULL) {
496 166105 : cred->password_obtained = obtained;
497 166105 : return true;
498 : }
499 :
500 117738 : if (cred->password_will_be_nt_hash) {
501 3 : struct samr_Password *nt_hash = NULL;
502 3 : size_t val_len = strlen(val);
503 1 : size_t converted;
504 :
505 3 : nt_hash = talloc(cred, struct samr_Password);
506 3 : if (nt_hash == NULL) {
507 0 : return false;
508 : }
509 :
510 3 : converted = strhex_to_str((char *)nt_hash->hash,
511 : sizeof(nt_hash->hash),
512 : val, val_len);
513 3 : if (converted != sizeof(nt_hash->hash)) {
514 0 : TALLOC_FREE(nt_hash);
515 0 : return false;
516 : }
517 :
518 3 : cred->nt_hash = nt_hash;
519 3 : cred->password_obtained = obtained;
520 3 : return true;
521 : }
522 :
523 117735 : cred->password = talloc_strdup(cred, val);
524 117735 : if (cred->password == NULL) {
525 0 : return false;
526 : }
527 :
528 : /* Don't print the actual password in talloc memory dumps */
529 117735 : talloc_set_name_const(cred->password,
530 : "password set via cli_credentials_set_password");
531 117735 : cred->password_obtained = obtained;
532 :
533 117735 : return true;
534 : }
535 :
536 36 : return false;
537 : }
538 :
539 17658 : _PUBLIC_ bool cli_credentials_set_password_callback(struct cli_credentials *cred,
540 : const char *(*password_cb) (struct cli_credentials *))
541 : {
542 17658 : if (cred->password_obtained < CRED_CALLBACK) {
543 11001 : cred->password_tries = 3;
544 11001 : cred->password_cb = password_cb;
545 11001 : cred->password_obtained = CRED_CALLBACK;
546 11001 : cli_credentials_invalidate_ccache(cred, cred->password_obtained);
547 11001 : return true;
548 : }
549 :
550 6657 : return false;
551 : }
552 :
553 : /**
554 : * Obtain the 'old' password for this credentials context (used for join accounts).
555 : * @param cred credentials context
556 : * @retval If set, the cleartext password, otherwise NULL
557 : */
558 321 : _PUBLIC_ const char *cli_credentials_get_old_password(struct cli_credentials *cred)
559 : {
560 321 : if (cred->machine_account_pending) {
561 0 : cli_credentials_set_machine_account(cred,
562 : cred->machine_account_pending_lp_ctx);
563 : }
564 :
565 321 : return cred->old_password;
566 : }
567 :
568 475 : _PUBLIC_ bool cli_credentials_set_old_password(struct cli_credentials *cred,
569 : const char *val,
570 : enum credentials_obtained obtained)
571 : {
572 475 : cred->old_password = talloc_strdup(cred, val);
573 475 : if (cred->old_password) {
574 : /* Don't print the actual password in talloc memory dumps */
575 201 : talloc_set_name_const(cred->old_password, "password set via cli_credentials_set_old_password");
576 : }
577 475 : cred->old_nt_hash = NULL;
578 475 : return true;
579 : }
580 :
581 : /**
582 : * Obtain the password, in the form MD4(unicode(password)) for this credentials context.
583 : *
584 : * Sometimes we only have this much of the password, while the rest of
585 : * the time this call avoids calling E_md4hash themselves.
586 : *
587 : * @param cred credentials context
588 : * @retval If set, the cleartext password, otherwise NULL
589 : */
590 43261 : _PUBLIC_ struct samr_Password *cli_credentials_get_nt_hash(struct cli_credentials *cred,
591 : TALLOC_CTX *mem_ctx)
592 : {
593 705 : enum credentials_obtained password_obtained;
594 705 : enum credentials_obtained ccache_threshold;
595 705 : enum credentials_obtained client_gss_creds_threshold;
596 705 : bool password_is_nt_hash;
597 43261 : const char *password = NULL;
598 43261 : struct samr_Password *nt_hash = NULL;
599 :
600 43261 : if (cred->nt_hash != NULL) {
601 : /*
602 : * If we already have a hash it's easy.
603 : */
604 14234 : goto return_hash;
605 : }
606 :
607 : /*
608 : * This is a bit tricky, with password_will_be_nt_hash
609 : * we still need to get the value via the password_callback
610 : * but if we did that we should not remember it's state
611 : * in the long run so we need to undo it.
612 : */
613 :
614 29027 : password_obtained = cred->password_obtained;
615 29027 : ccache_threshold = cred->ccache_threshold;
616 29027 : client_gss_creds_threshold = cred->client_gss_creds_threshold;
617 29027 : password_is_nt_hash = cred->password_will_be_nt_hash;
618 :
619 29027 : cred->password_will_be_nt_hash = false;
620 29027 : password = cli_credentials_get_password(cred);
621 :
622 29027 : cred->password_will_be_nt_hash = password_is_nt_hash;
623 29027 : if (password_is_nt_hash && password_obtained == CRED_CALLBACK) {
624 : /*
625 : * We got the nt_hash as string via the callback,
626 : * so we need to undo the state change.
627 : *
628 : * And also don't remember it as plaintext password.
629 : */
630 0 : cred->client_gss_creds_threshold = client_gss_creds_threshold;
631 0 : cred->ccache_threshold = ccache_threshold;
632 0 : cred->password_obtained = password_obtained;
633 0 : cred->password = NULL;
634 : }
635 :
636 29027 : if (password == NULL) {
637 999 : return NULL;
638 : }
639 :
640 28018 : nt_hash = talloc(cred, struct samr_Password);
641 28018 : if (nt_hash == NULL) {
642 0 : return NULL;
643 : }
644 :
645 28018 : if (password_is_nt_hash) {
646 0 : size_t password_len = strlen(password);
647 0 : size_t converted;
648 :
649 0 : converted = strhex_to_str((char *)nt_hash->hash,
650 : sizeof(nt_hash->hash),
651 : password, password_len);
652 0 : if (converted != sizeof(nt_hash->hash)) {
653 0 : TALLOC_FREE(nt_hash);
654 0 : return NULL;
655 : }
656 : } else {
657 28018 : E_md4hash(password, nt_hash->hash);
658 : }
659 :
660 28018 : cred->nt_hash = nt_hash;
661 28018 : nt_hash = NULL;
662 :
663 42252 : return_hash:
664 42252 : nt_hash = talloc(mem_ctx, struct samr_Password);
665 42252 : if (nt_hash == NULL) {
666 0 : return NULL;
667 : }
668 :
669 42252 : *nt_hash = *cred->nt_hash;
670 :
671 42252 : return nt_hash;
672 : }
673 :
674 : /**
675 : * Obtain the old password, in the form MD4(unicode(password)) for this credentials context.
676 : *
677 : * Sometimes we only have this much of the password, while the rest of
678 : * the time this call avoids calling E_md4hash themselves.
679 : *
680 : * @param cred credentials context
681 : * @retval If set, the cleartext password, otherwise NULL
682 : */
683 234 : _PUBLIC_ struct samr_Password *cli_credentials_get_old_nt_hash(struct cli_credentials *cred,
684 : TALLOC_CTX *mem_ctx)
685 : {
686 234 : const char *old_password = NULL;
687 :
688 234 : if (cred->old_nt_hash != NULL) {
689 0 : struct samr_Password *nt_hash = talloc(mem_ctx, struct samr_Password);
690 0 : if (!nt_hash) {
691 0 : return NULL;
692 : }
693 :
694 0 : *nt_hash = *cred->old_nt_hash;
695 :
696 0 : return nt_hash;
697 : }
698 :
699 234 : old_password = cli_credentials_get_old_password(cred);
700 234 : if (old_password) {
701 111 : struct samr_Password *nt_hash = talloc(mem_ctx, struct samr_Password);
702 111 : if (!nt_hash) {
703 0 : return NULL;
704 : }
705 :
706 111 : E_md4hash(old_password, nt_hash->hash);
707 :
708 111 : return nt_hash;
709 : }
710 :
711 123 : return NULL;
712 : }
713 :
714 : /**
715 : * Obtain the 'short' or 'NetBIOS' domain for this credentials context.
716 : * @param cred credentials context
717 : * @retval The domain set on this context.
718 : * @note Return value will never be NULL except by programmer error.
719 : */
720 756515 : _PUBLIC_ const char *cli_credentials_get_domain(struct cli_credentials *cred)
721 : {
722 756515 : if (cred->machine_account_pending) {
723 0 : cli_credentials_set_machine_account(cred,
724 : cred->machine_account_pending_lp_ctx);
725 : }
726 :
727 756515 : if (cred->domain_obtained == CRED_CALLBACK &&
728 0 : !cred->callback_running) {
729 0 : cred->callback_running = true;
730 0 : cred->domain = cred->domain_cb(cred);
731 0 : cred->callback_running = false;
732 0 : if (cred->domain_obtained == CRED_CALLBACK) {
733 0 : cred->domain_obtained = CRED_CALLBACK_RESULT;
734 0 : cli_credentials_invalidate_ccache(cred, cred->domain_obtained);
735 : }
736 : }
737 :
738 756515 : return cred->domain;
739 : }
740 :
741 : /**
742 : * @brief Obtain the domain for this credential context.
743 : *
744 : * @param[in] cred The credential context.
745 : *
746 : * @param[out] obtained A pointer to store the obtained information.
747 : *
748 : * @return The domain name or NULL if an error occurred.
749 : */
750 87 : _PUBLIC_ const char *cli_credentials_get_domain_and_obtained(
751 : struct cli_credentials *cred,
752 : enum credentials_obtained *obtained)
753 : {
754 87 : const char *domain = cli_credentials_get_domain(cred);
755 :
756 87 : if (obtained != NULL) {
757 87 : *obtained = cred->domain_obtained;
758 : }
759 :
760 87 : return domain;
761 : }
762 :
763 :
764 576182 : _PUBLIC_ bool cli_credentials_set_domain(struct cli_credentials *cred,
765 : const char *val,
766 : enum credentials_obtained obtained)
767 : {
768 576182 : if (obtained >= cred->domain_obtained) {
769 : /* it is important that the domain be in upper case,
770 : * particularly for the sensitive NTLMv2
771 : * calculations */
772 514731 : cred->domain = strupper_talloc(cred, val);
773 514731 : cred->domain_obtained = obtained;
774 : /* setting domain does not mean we have to invalidate ccache
775 : * because domain in not used for Kerberos operations.
776 : * If ccache invalidation is required, one will anyway specify
777 : * a password to kinit, and that will force invalidation of the ccache
778 : */
779 514731 : return true;
780 : }
781 :
782 61451 : return false;
783 : }
784 :
785 0 : bool cli_credentials_set_domain_callback(struct cli_credentials *cred,
786 : const char *(*domain_cb) (struct cli_credentials *))
787 : {
788 0 : if (cred->domain_obtained < CRED_CALLBACK) {
789 0 : cred->domain_cb = domain_cb;
790 0 : cred->domain_obtained = CRED_CALLBACK;
791 0 : return true;
792 : }
793 :
794 0 : return false;
795 : }
796 :
797 : /**
798 : * Obtain the Kerberos realm for this credentials context.
799 : * @param cred credentials context
800 : * @retval The realm set on this context.
801 : * @note Return value will never be NULL except by programmer error.
802 : */
803 824398 : _PUBLIC_ const char *cli_credentials_get_realm(struct cli_credentials *cred)
804 : {
805 824398 : if (cred->machine_account_pending) {
806 0 : cli_credentials_set_machine_account(cred,
807 : cred->machine_account_pending_lp_ctx);
808 : }
809 :
810 824398 : if (cred->realm_obtained == CRED_CALLBACK &&
811 0 : !cred->callback_running) {
812 0 : cred->callback_running = true;
813 0 : cred->realm = cred->realm_cb(cred);
814 0 : cred->callback_running = false;
815 0 : if (cred->realm_obtained == CRED_CALLBACK) {
816 0 : cred->realm_obtained = CRED_CALLBACK_RESULT;
817 0 : cli_credentials_invalidate_ccache(cred, cred->realm_obtained);
818 : }
819 : }
820 :
821 824398 : return cred->realm;
822 : }
823 :
824 : /**
825 : * Set the realm for this credentials context, and force it to
826 : * uppercase for the sanity of our local kerberos libraries
827 : */
828 457889 : _PUBLIC_ bool cli_credentials_set_realm(struct cli_credentials *cred,
829 : const char *val,
830 : enum credentials_obtained obtained)
831 : {
832 457889 : if (obtained >= cred->realm_obtained) {
833 450883 : cred->realm = strupper_talloc(cred, val);
834 450883 : cred->realm_obtained = obtained;
835 450883 : cli_credentials_invalidate_ccache(cred, cred->realm_obtained);
836 450883 : return true;
837 : }
838 :
839 7006 : return false;
840 : }
841 :
842 0 : bool cli_credentials_set_realm_callback(struct cli_credentials *cred,
843 : const char *(*realm_cb) (struct cli_credentials *))
844 : {
845 0 : if (cred->realm_obtained < CRED_CALLBACK) {
846 0 : cred->realm_cb = realm_cb;
847 0 : cred->realm_obtained = CRED_CALLBACK;
848 0 : return true;
849 : }
850 :
851 0 : return false;
852 : }
853 :
854 : /**
855 : * Obtain the 'short' or 'NetBIOS' workstation name for this credentials context.
856 : *
857 : * @param cred credentials context
858 : * @retval The workstation name set on this context.
859 : * @note Return value will never be NULL except by programmer error.
860 : */
861 123687 : _PUBLIC_ const char *cli_credentials_get_workstation(struct cli_credentials *cred)
862 : {
863 123687 : if (cred->workstation_obtained == CRED_CALLBACK &&
864 0 : !cred->callback_running) {
865 0 : cred->callback_running = true;
866 0 : cred->workstation = cred->workstation_cb(cred);
867 0 : cred->callback_running = false;
868 0 : if (cred->workstation_obtained == CRED_CALLBACK) {
869 0 : cred->workstation_obtained = CRED_CALLBACK_RESULT;
870 : }
871 : }
872 :
873 123687 : return cred->workstation;
874 : }
875 :
876 460819 : _PUBLIC_ bool cli_credentials_set_workstation(struct cli_credentials *cred,
877 : const char *val,
878 : enum credentials_obtained obtained)
879 : {
880 460819 : if (obtained >= cred->workstation_obtained) {
881 419278 : cred->workstation = talloc_strdup(cred, val);
882 419278 : cred->workstation_obtained = obtained;
883 419278 : return true;
884 : }
885 :
886 41121 : return false;
887 : }
888 :
889 0 : bool cli_credentials_set_workstation_callback(struct cli_credentials *cred,
890 : const char *(*workstation_cb) (struct cli_credentials *))
891 : {
892 0 : if (cred->workstation_obtained < CRED_CALLBACK) {
893 0 : cred->workstation_cb = workstation_cb;
894 0 : cred->workstation_obtained = CRED_CALLBACK;
895 0 : return true;
896 : }
897 :
898 0 : return false;
899 : }
900 :
901 : /**
902 : * Given a string, typically obtained from a -U argument, parse it into domain, username, realm and password fields
903 : *
904 : * The format accepted is [domain\\]user[%password] or user[@realm][%password]
905 : *
906 : * @param credentials Credentials structure on which to set the password
907 : * @param data the string containing the username, password etc
908 : * @param obtained This enum describes how 'specified' this password is
909 : */
910 :
911 239360 : _PUBLIC_ void cli_credentials_parse_string(struct cli_credentials *credentials, const char *data, enum credentials_obtained obtained)
912 : {
913 1026 : char *uname, *p;
914 239360 : char *uname_free = NULL;
915 :
916 239360 : if (strcmp("%",data) == 0) {
917 434 : cli_credentials_set_anonymous(credentials);
918 434 : return;
919 : }
920 :
921 238926 : uname = talloc_strdup(credentials, data);
922 238926 : uname_free = uname;
923 :
924 238926 : if ((p = strchr_m(uname,'%'))) {
925 22734 : *p = 0;
926 22734 : cli_credentials_set_password(credentials, p+1, obtained);
927 : }
928 :
929 238926 : if ((p = strchr_m(uname,'@'))) {
930 : /*
931 : * We also need to set username and domain
932 : * in order to undo the effect of
933 : * cli_credentials_guess().
934 : */
935 379 : cli_credentials_set_username(credentials, uname, obtained);
936 379 : cli_credentials_set_domain(credentials, "", obtained);
937 :
938 379 : cli_credentials_set_principal(credentials, uname, obtained);
939 379 : *p = 0;
940 379 : cli_credentials_set_realm(credentials, p+1, obtained);
941 379 : TALLOC_FREE(uname_free);
942 379 : return;
943 238547 : } else if ((p = strchr_m(uname,'\\'))
944 237932 : || (p = strchr_m(uname, '/'))
945 236611 : || (p = strchr_m(uname, credentials->winbind_separator)))
946 : {
947 1964 : const char *domain = NULL;
948 :
949 1964 : domain = uname;
950 1964 : *p = 0;
951 1964 : uname = p+1;
952 :
953 1970 : if (obtained == credentials->realm_obtained &&
954 6 : !strequal_m(credentials->domain, domain))
955 : {
956 : /*
957 : * We need to undo a former set with the same level
958 : * in order to get the expected result from
959 : * cli_credentials_get_principal().
960 : *
961 : * But we only need to do that if the domain
962 : * actually changes.
963 : */
964 5 : cli_credentials_set_realm(credentials, domain, obtained);
965 : }
966 1964 : cli_credentials_set_domain(credentials, domain, obtained);
967 : }
968 238549 : if (obtained == credentials->principal_obtained &&
969 8 : !strequal_m(credentials->username, uname))
970 : {
971 : /*
972 : * We need to undo a former set with the same level
973 : * in order to get the expected result from
974 : * cli_credentials_get_principal().
975 : *
976 : * But we only need to do that if the username
977 : * actually changes.
978 : */
979 2 : credentials->principal_obtained = CRED_UNINITIALISED;
980 2 : credentials->principal = NULL;
981 : }
982 238547 : cli_credentials_set_username(credentials, uname, obtained);
983 :
984 238547 : TALLOC_FREE(uname_free);
985 : }
986 :
987 : /**
988 : * Given a a credentials structure, print it as a string
989 : *
990 : * The format output is [domain\\]user[%password] or user[@realm][%password]
991 : *
992 : * @param credentials Credentials structure on which to set the password
993 : * @param mem_ctx The memory context to place the result on
994 : */
995 :
996 518 : _PUBLIC_ char *cli_credentials_get_unparsed_name(struct cli_credentials *credentials, TALLOC_CTX *mem_ctx)
997 : {
998 518 : const char *bind_dn = cli_credentials_get_bind_dn(credentials);
999 518 : const char *domain = NULL;
1000 518 : const char *username = NULL;
1001 518 : char *name = NULL;
1002 :
1003 518 : if (bind_dn) {
1004 0 : name = talloc_strdup(mem_ctx, bind_dn);
1005 : } else {
1006 518 : cli_credentials_get_ntlm_username_domain(credentials, mem_ctx, &username, &domain);
1007 518 : if (domain && domain[0]) {
1008 414 : name = talloc_asprintf(mem_ctx, "%s\\%s",
1009 : domain, username);
1010 : } else {
1011 104 : name = talloc_asprintf(mem_ctx, "%s",
1012 : username);
1013 : }
1014 : }
1015 518 : return name;
1016 : }
1017 :
1018 :
1019 : /**
1020 : * Specifies default values for domain, workstation and realm
1021 : * from the smb.conf configuration file
1022 : *
1023 : * @param cred Credentials structure to fill in
1024 : *
1025 : * @return true on success, false on error.
1026 : */
1027 274664 : _PUBLIC_ bool cli_credentials_set_conf(struct cli_credentials *cred,
1028 : struct loadparm_context *lp_ctx)
1029 : {
1030 274664 : const char *sep = NULL;
1031 274664 : const char *realm = lpcfg_realm(lp_ctx);
1032 3895 : enum credentials_client_protection protection =
1033 274664 : lpcfg_client_protection(lp_ctx);
1034 274664 : const char *workgroup = lpcfg_workgroup(lp_ctx);
1035 274664 : const char *netbios_name = lpcfg_netbios_name(lp_ctx);
1036 3895 : bool ok;
1037 :
1038 274664 : (void)cli_credentials_set_username(cred, "", CRED_UNINITIALISED);
1039 :
1040 274664 : if (workgroup != NULL && strlen(workgroup) == 0) {
1041 0 : workgroup = NULL;
1042 : }
1043 :
1044 274664 : if (workgroup != NULL) {
1045 274664 : if (lpcfg_parm_is_cmdline(lp_ctx, "workgroup")) {
1046 1500 : ok = cli_credentials_set_domain(cred,
1047 : workgroup,
1048 : CRED_SPECIFIED);
1049 1500 : if (!ok) {
1050 0 : DBG_ERR("Failed to set domain!\n");
1051 0 : return false;
1052 : }
1053 : } else {
1054 273164 : (void)cli_credentials_set_domain(cred,
1055 : workgroup,
1056 : CRED_SMB_CONF);
1057 : }
1058 : }
1059 :
1060 274664 : if (netbios_name != NULL && strlen(netbios_name) == 0) {
1061 0 : netbios_name = NULL;
1062 : }
1063 :
1064 274664 : if (netbios_name != NULL) {
1065 274664 : if (lpcfg_parm_is_cmdline(lp_ctx, "netbios name")) {
1066 285 : ok = cli_credentials_set_workstation(cred,
1067 : netbios_name,
1068 : CRED_SPECIFIED);
1069 285 : if (!ok) {
1070 0 : DBG_ERR("Failed to set workstation!\n");
1071 0 : return false;
1072 : }
1073 : } else {
1074 274379 : (void)cli_credentials_set_workstation(cred,
1075 : netbios_name,
1076 : CRED_SMB_CONF);
1077 : }
1078 : }
1079 :
1080 274664 : if (realm != NULL && strlen(realm) == 0) {
1081 114671 : realm = NULL;
1082 : }
1083 :
1084 274100 : if (realm != NULL) {
1085 159429 : if (lpcfg_parm_is_cmdline(lp_ctx, "realm")) {
1086 248 : ok = cli_credentials_set_realm(cred,
1087 : realm,
1088 : CRED_SPECIFIED);
1089 248 : if (!ok) {
1090 0 : DBG_ERR("Failed to set realm!\n");
1091 0 : return false;
1092 : }
1093 : } else {
1094 159181 : (void)cli_credentials_set_realm(cred,
1095 : realm,
1096 : CRED_SMB_CONF);
1097 : }
1098 : }
1099 :
1100 274664 : sep = lpcfg_winbind_separator(lp_ctx);
1101 274664 : if (sep != NULL && sep[0] != '\0') {
1102 274664 : cred->winbind_separator = *lpcfg_winbind_separator(lp_ctx);
1103 : }
1104 :
1105 274664 : if (cred->signing_state_obtained <= CRED_SMB_CONF) {
1106 : /* Will be set to default for invalid smb.conf values */
1107 273564 : cred->signing_state = lpcfg_client_signing(lp_ctx);
1108 273564 : if (cred->signing_state == SMB_SIGNING_DEFAULT) {
1109 273550 : switch (protection) {
1110 269664 : case CRED_CLIENT_PROTECTION_DEFAULT:
1111 269664 : break;
1112 0 : case CRED_CLIENT_PROTECTION_PLAIN:
1113 0 : cred->signing_state = SMB_SIGNING_OFF;
1114 0 : break;
1115 0 : case CRED_CLIENT_PROTECTION_SIGN:
1116 : case CRED_CLIENT_PROTECTION_ENCRYPT:
1117 0 : cred->signing_state = SMB_SIGNING_REQUIRED;
1118 0 : break;
1119 : }
1120 : }
1121 :
1122 273564 : cred->signing_state_obtained = CRED_SMB_CONF;
1123 : }
1124 :
1125 274664 : if (cred->ipc_signing_state_obtained <= CRED_SMB_CONF) {
1126 : /* Will be set to required for invalid smb.conf values */
1127 274663 : cred->ipc_signing_state = lpcfg_client_ipc_signing(lp_ctx);
1128 274663 : cred->ipc_signing_state_obtained = CRED_SMB_CONF;
1129 : }
1130 :
1131 274664 : if (cred->encryption_state_obtained <= CRED_SMB_CONF) {
1132 : /* Will be set to default for invalid smb.conf values */
1133 273564 : cred->encryption_state = lpcfg_client_smb_encrypt(lp_ctx);
1134 273564 : if (cred->encryption_state == SMB_ENCRYPTION_DEFAULT) {
1135 273468 : switch (protection) {
1136 269582 : case CRED_CLIENT_PROTECTION_DEFAULT:
1137 269582 : break;
1138 0 : case CRED_CLIENT_PROTECTION_PLAIN:
1139 : case CRED_CLIENT_PROTECTION_SIGN:
1140 0 : cred->encryption_state = SMB_ENCRYPTION_OFF;
1141 0 : break;
1142 0 : case CRED_CLIENT_PROTECTION_ENCRYPT:
1143 0 : cred->encryption_state = SMB_ENCRYPTION_REQUIRED;
1144 0 : break;
1145 : }
1146 : }
1147 : }
1148 :
1149 274664 : if (cred->kerberos_state_obtained <= CRED_SMB_CONF) {
1150 : /* Will be set to default for invalid smb.conf values */
1151 212165 : cred->kerberos_state = lpcfg_client_use_kerberos(lp_ctx);
1152 212165 : cred->kerberos_state_obtained = CRED_SMB_CONF;
1153 : }
1154 :
1155 274664 : if (cred->gensec_features_obtained <= CRED_SMB_CONF) {
1156 273517 : switch (protection) {
1157 269630 : case CRED_CLIENT_PROTECTION_DEFAULT:
1158 269630 : break;
1159 0 : case CRED_CLIENT_PROTECTION_PLAIN:
1160 0 : cred->gensec_features = 0;
1161 0 : break;
1162 0 : case CRED_CLIENT_PROTECTION_SIGN:
1163 0 : cred->gensec_features = GENSEC_FEATURE_SIGN;
1164 0 : break;
1165 0 : case CRED_CLIENT_PROTECTION_ENCRYPT:
1166 0 : cred->gensec_features =
1167 : GENSEC_FEATURE_SIGN|GENSEC_FEATURE_SEAL;
1168 0 : break;
1169 : }
1170 273517 : cred->gensec_features_obtained = CRED_SMB_CONF;
1171 : }
1172 :
1173 270769 : return true;
1174 : }
1175 :
1176 : /**
1177 : * Guess defaults for credentials from environment variables,
1178 : * and from the configuration file
1179 : *
1180 : * @param cred Credentials structure to fill in
1181 : */
1182 99618 : _PUBLIC_ bool cli_credentials_guess(struct cli_credentials *cred,
1183 : struct loadparm_context *lp_ctx)
1184 : {
1185 443 : const char *error_string;
1186 99618 : const char *env = NULL;
1187 99618 : struct passwd *pwd = NULL;
1188 443 : bool ok;
1189 :
1190 99618 : if (lp_ctx != NULL) {
1191 99616 : ok = cli_credentials_set_conf(cred, lp_ctx);
1192 99616 : if (!ok) {
1193 0 : return false;
1194 : }
1195 : }
1196 :
1197 99618 : pwd = getpwuid(getuid());
1198 99618 : if (pwd != NULL) {
1199 99079 : size_t len = strlen(pwd->pw_name);
1200 :
1201 99079 : if (len > 0 && len <= 1024) {
1202 99079 : (void)cli_credentials_parse_string(cred,
1203 98636 : pwd->pw_name,
1204 : CRED_GUESS_ENV);
1205 : }
1206 : }
1207 :
1208 99618 : env = getenv("LOGNAME");
1209 99618 : if (env != NULL) {
1210 0 : size_t len = strlen(env);
1211 :
1212 0 : if (len > 0 && len <= 1024) {
1213 0 : (void)cli_credentials_set_username(cred,
1214 : env,
1215 : CRED_GUESS_ENV);
1216 : }
1217 : }
1218 :
1219 99618 : env = getenv("USER");
1220 99618 : if (env != NULL) {
1221 99618 : size_t len = strlen(env);
1222 :
1223 99618 : if (len > 0 && len <= 1024) {
1224 99618 : char *p = NULL;
1225 :
1226 99618 : (void)cli_credentials_parse_string(cred,
1227 : env,
1228 : CRED_GUESS_ENV);
1229 99618 : if ((p = strchr_m(env, '%'))) {
1230 0 : memset(p, '\0', strlen(cred->password));
1231 : }
1232 : }
1233 : }
1234 :
1235 99618 : env = getenv("PASSWD");
1236 99618 : if (env != NULL) {
1237 6 : size_t len = strlen(env);
1238 :
1239 6 : if (len > 0 && len <= 1024) {
1240 6 : (void)cli_credentials_set_password(cred,
1241 : env,
1242 : CRED_GUESS_ENV);
1243 : }
1244 : }
1245 :
1246 99618 : env = getenv("PASSWD_FD");
1247 99618 : if (env != NULL) {
1248 2 : size_t len = strlen(env);
1249 :
1250 2 : if (len > 0 && len <= 1024) {
1251 2 : int fd = atoi(env);
1252 :
1253 2 : (void)cli_credentials_parse_password_fd(cred,
1254 : fd,
1255 : CRED_GUESS_FILE);
1256 : }
1257 : }
1258 :
1259 99618 : env = getenv("PASSWD_FILE");
1260 99618 : if (env != NULL) {
1261 2 : size_t len = strlen(env);
1262 :
1263 2 : if (len > 0 && len <= 4096) {
1264 2 : (void)cli_credentials_parse_password_file(cred,
1265 : env,
1266 : CRED_GUESS_FILE);
1267 : }
1268 : }
1269 :
1270 199234 : if (lp_ctx != NULL &&
1271 99616 : cli_credentials_get_kerberos_state(cred) != CRED_USE_KERBEROS_DISABLED) {
1272 98210 : (void)cli_credentials_set_ccache(cred,
1273 : lp_ctx,
1274 : NULL,
1275 : CRED_GUESS_FILE,
1276 : &error_string);
1277 : }
1278 :
1279 99175 : return true;
1280 : }
1281 :
1282 : /**
1283 : * Attach NETLOGON credentials for use with SCHANNEL
1284 : */
1285 :
1286 1611 : _PUBLIC_ void cli_credentials_set_netlogon_creds(
1287 : struct cli_credentials *cred,
1288 : const struct netlogon_creds_CredentialState *netlogon_creds)
1289 : {
1290 1611 : TALLOC_FREE(cred->netlogon_creds);
1291 1611 : if (netlogon_creds == NULL) {
1292 491 : return;
1293 : }
1294 1080 : cred->netlogon_creds = netlogon_creds_copy(cred, netlogon_creds);
1295 : }
1296 :
1297 : /**
1298 : * Return attached NETLOGON credentials
1299 : */
1300 :
1301 569924 : _PUBLIC_ struct netlogon_creds_CredentialState *cli_credentials_get_netlogon_creds(struct cli_credentials *cred)
1302 : {
1303 569924 : return cred->netlogon_creds;
1304 : }
1305 :
1306 : /**
1307 : * Set NETLOGON secure channel type
1308 : */
1309 :
1310 70920 : _PUBLIC_ void cli_credentials_set_secure_channel_type(struct cli_credentials *cred,
1311 : enum netr_SchannelType secure_channel_type)
1312 : {
1313 70920 : cred->secure_channel_type = secure_channel_type;
1314 70920 : }
1315 :
1316 : /**
1317 : * Return NETLOGON secure channel type
1318 : */
1319 :
1320 133762 : _PUBLIC_ time_t cli_credentials_get_password_last_changed_time(struct cli_credentials *cred)
1321 : {
1322 133762 : return cred->password_last_changed_time;
1323 : }
1324 :
1325 : /**
1326 : * Set NETLOGON secure channel type
1327 : */
1328 :
1329 67146 : _PUBLIC_ void cli_credentials_set_password_last_changed_time(struct cli_credentials *cred,
1330 : time_t last_changed_time)
1331 : {
1332 67146 : cred->password_last_changed_time = last_changed_time;
1333 67146 : }
1334 :
1335 : /**
1336 : * Return NETLOGON secure channel type
1337 : */
1338 :
1339 10548 : _PUBLIC_ enum netr_SchannelType cli_credentials_get_secure_channel_type(struct cli_credentials *cred)
1340 : {
1341 10548 : return cred->secure_channel_type;
1342 : }
1343 :
1344 : /**
1345 : * Fill in a credentials structure as the anonymous user
1346 : */
1347 165759 : _PUBLIC_ void cli_credentials_set_anonymous(struct cli_credentials *cred)
1348 : {
1349 165759 : cli_credentials_set_username(cred, "", CRED_SPECIFIED);
1350 165759 : cli_credentials_set_domain(cred, "", CRED_SPECIFIED);
1351 165759 : cli_credentials_set_password(cred, NULL, CRED_SPECIFIED);
1352 165759 : cli_credentials_set_principal(cred, NULL, CRED_SPECIFIED);
1353 165759 : cli_credentials_set_realm(cred, NULL, CRED_SPECIFIED);
1354 165759 : cli_credentials_set_workstation(cred, "", CRED_UNINITIALISED);
1355 165759 : cli_credentials_set_kerberos_state(cred,
1356 : CRED_USE_KERBEROS_DISABLED,
1357 : CRED_SPECIFIED);
1358 165759 : }
1359 :
1360 : /**
1361 : * Describe a credentials context as anonymous or authenticated
1362 : * @retval true if anonymous, false if a username is specified
1363 : */
1364 :
1365 183799 : _PUBLIC_ bool cli_credentials_is_anonymous(struct cli_credentials *cred)
1366 : {
1367 2618 : const char *username;
1368 :
1369 : /* if bind dn is set it's not anonymous */
1370 183799 : if (cred->bind_dn) {
1371 0 : return false;
1372 : }
1373 :
1374 183799 : if (cred->machine_account_pending) {
1375 14 : cli_credentials_set_machine_account(cred,
1376 : cred->machine_account_pending_lp_ctx);
1377 : }
1378 :
1379 : /* if principal is set, it's not anonymous */
1380 183799 : if ((cred->principal != NULL) && cred->principal_obtained >= cred->username_obtained) {
1381 37527 : return false;
1382 : }
1383 :
1384 145077 : username = cli_credentials_get_username(cred);
1385 :
1386 : /* Yes, it is deliberate that we die if we have a NULL pointer
1387 : * here - anonymous is "", not NULL, which is 'never specified,
1388 : * never guessed', ie programmer bug */
1389 145077 : if (!username[0]) {
1390 9204 : return true;
1391 : }
1392 :
1393 134596 : return false;
1394 : }
1395 :
1396 : /**
1397 : * Mark the current password for a credentials struct as wrong. This will
1398 : * cause the password to be prompted again (if a callback is set).
1399 : *
1400 : * This will decrement the number of times the password can be tried.
1401 : *
1402 : * @retval whether the credentials struct is finished
1403 : */
1404 1728 : _PUBLIC_ bool cli_credentials_wrong_password(struct cli_credentials *cred)
1405 : {
1406 1728 : if (cred->password_obtained != CRED_CALLBACK_RESULT) {
1407 1721 : return false;
1408 : }
1409 :
1410 0 : if (cred->password_tries == 0) {
1411 0 : return false;
1412 : }
1413 :
1414 0 : cred->password_tries--;
1415 :
1416 0 : if (cred->password_tries == 0) {
1417 0 : return false;
1418 : }
1419 :
1420 0 : cred->password_obtained = CRED_CALLBACK;
1421 0 : return true;
1422 : }
1423 :
1424 81736 : _PUBLIC_ void cli_credentials_get_ntlm_username_domain(struct cli_credentials *cred, TALLOC_CTX *mem_ctx,
1425 : const char **username,
1426 : const char **domain)
1427 : {
1428 81736 : if (cred->principal_obtained >= cred->username_obtained) {
1429 4026 : *domain = talloc_strdup(mem_ctx, "");
1430 4026 : *username = cli_credentials_get_principal(cred, mem_ctx);
1431 : } else {
1432 77710 : *domain = cli_credentials_get_domain(cred);
1433 77710 : *username = cli_credentials_get_username(cred);
1434 : }
1435 81736 : }
1436 :
1437 : /**
1438 : * Read a named file, and parse it for username, domain, realm and password
1439 : *
1440 : * @param credentials Credentials structure on which to set the password
1441 : * @param file a named file to read the details from
1442 : * @param obtained This enum describes how 'specified' this password is
1443 : */
1444 :
1445 61 : _PUBLIC_ bool cli_credentials_parse_file(struct cli_credentials *cred, const char *file, enum credentials_obtained obtained)
1446 : {
1447 61 : uint16_t len = 0;
1448 7 : char *ptr, *val, *param;
1449 7 : char **lines;
1450 7 : int i, numlines;
1451 61 : const char *realm = NULL;
1452 61 : const char *domain = NULL;
1453 61 : const char *password = NULL;
1454 61 : const char *username = NULL;
1455 :
1456 61 : lines = file_lines_load(file, &numlines, 0, NULL);
1457 :
1458 61 : if (lines == NULL)
1459 : {
1460 : /* fail if we can't open the credentials file */
1461 0 : d_printf("ERROR: Unable to open credentials file!\n");
1462 0 : return false;
1463 : }
1464 :
1465 249 : for (i = 0; i < numlines; i++) {
1466 188 : len = strlen(lines[i]);
1467 :
1468 188 : if (len == 0)
1469 0 : continue;
1470 :
1471 : /* break up the line into parameter & value.
1472 : * will need to eat a little whitespace possibly */
1473 188 : param = lines[i];
1474 188 : if (!(ptr = strchr_m (lines[i], '=')))
1475 0 : continue;
1476 :
1477 188 : val = ptr+1;
1478 188 : *ptr = '\0';
1479 :
1480 : /* eat leading white space */
1481 192 : while ((*val!='\0') && ((*val==' ') || (*val=='\t')))
1482 4 : val++;
1483 :
1484 188 : if (strwicmp("password", param) == 0) {
1485 54 : password = val;
1486 127 : } else if (strwicmp("username", param) == 0) {
1487 54 : username = val;
1488 66 : } else if (strwicmp("domain", param) == 0) {
1489 52 : domain = val;
1490 7 : } else if (strwicmp("realm", param) == 0) {
1491 7 : realm = val;
1492 : }
1493 :
1494 : /*
1495 : * We need to readd '=' in order to let
1496 : * the strlen() work in the last loop
1497 : * that clears the memory.
1498 : */
1499 188 : *ptr = '=';
1500 : }
1501 :
1502 61 : if (realm != NULL && strlen(realm) != 0) {
1503 : /*
1504 : * only overwrite with a valid string
1505 : */
1506 7 : cli_credentials_set_realm(cred, realm, obtained);
1507 : }
1508 :
1509 61 : if (domain != NULL && strlen(domain) != 0) {
1510 : /*
1511 : * only overwrite with a valid string
1512 : */
1513 59 : cli_credentials_set_domain(cred, domain, obtained);
1514 : }
1515 :
1516 61 : if (password != NULL) {
1517 : /*
1518 : * Here we allow "".
1519 : */
1520 61 : cli_credentials_set_password(cred, password, obtained);
1521 : }
1522 :
1523 61 : if (username != NULL) {
1524 : /*
1525 : * The last "username" line takes preference
1526 : * if the string also contains domain, realm or
1527 : * password.
1528 : */
1529 61 : cli_credentials_parse_string(cred, username, obtained);
1530 : }
1531 :
1532 249 : for (i = 0; i < numlines; i++) {
1533 188 : len = strlen(lines[i]);
1534 188 : memset(lines[i], 0, len);
1535 : }
1536 61 : talloc_free(lines);
1537 :
1538 61 : return true;
1539 : }
1540 :
1541 : /**
1542 : * Read a named file, and parse it for a password
1543 : *
1544 : * @param credentials Credentials structure on which to set the password
1545 : * @param file a named file to read the password from
1546 : * @param obtained This enum describes how 'specified' this password is
1547 : */
1548 :
1549 2 : _PUBLIC_ bool cli_credentials_parse_password_file(struct cli_credentials *credentials, const char *file, enum credentials_obtained obtained)
1550 : {
1551 2 : int fd = open(file, O_RDONLY, 0);
1552 0 : bool ret;
1553 :
1554 2 : if (fd < 0) {
1555 0 : fprintf(stderr, "Error opening password file %s: %s\n",
1556 0 : file, strerror(errno));
1557 0 : return false;
1558 : }
1559 :
1560 2 : ret = cli_credentials_parse_password_fd(credentials, fd, obtained);
1561 :
1562 2 : close(fd);
1563 :
1564 2 : return ret;
1565 : }
1566 :
1567 :
1568 : /**
1569 : * Read a file descriptor, and parse it for a password (eg from a file or stdin)
1570 : *
1571 : * @param credentials Credentials structure on which to set the password
1572 : * @param fd open file descriptor to read the password from
1573 : * @param obtained This enum describes how 'specified' this password is
1574 : */
1575 :
1576 4 : _PUBLIC_ bool cli_credentials_parse_password_fd(struct cli_credentials *credentials,
1577 : int fd, enum credentials_obtained obtained)
1578 : {
1579 0 : char *p;
1580 0 : char pass[128];
1581 :
1582 4 : if (credentials->password_obtained >= obtained) {
1583 0 : return false;
1584 : }
1585 :
1586 4 : for(p = pass, *p = '\0'; /* ensure that pass is null-terminated */
1587 50 : p && p - pass < sizeof(pass) - 1;) {
1588 46 : switch (read(fd, p, 1)) {
1589 46 : case 1:
1590 46 : if (*p != '\n' && *p != '\0') {
1591 42 : *++p = '\0'; /* advance p, and null-terminate pass */
1592 42 : break;
1593 : }
1594 :
1595 0 : FALL_THROUGH;
1596 : case 0:
1597 4 : if (p - pass) {
1598 4 : *p = '\0'; /* null-terminate it, just in case... */
1599 4 : p = NULL; /* then force the loop condition to become false */
1600 4 : break;
1601 : }
1602 :
1603 0 : fprintf(stderr,
1604 : "Error reading password from file descriptor "
1605 : "%d: empty password\n",
1606 : fd);
1607 0 : return false;
1608 :
1609 0 : default:
1610 0 : fprintf(stderr, "Error reading password from file descriptor %d: %s\n",
1611 0 : fd, strerror(errno));
1612 0 : return false;
1613 : }
1614 : }
1615 :
1616 4 : cli_credentials_set_password(credentials, pass, obtained);
1617 4 : return true;
1618 : }
1619 :
1620 : /**
1621 : * @brief Set the SMB signing state to request for a SMB connection.
1622 : *
1623 : * @param[in] creds The credentials structure to update.
1624 : *
1625 : * @param[in] signing_state The signing state to set.
1626 : *
1627 : * @param obtained This way the described signing state was specified.
1628 : *
1629 : * @return true if we could set the signing state, false otherwise.
1630 : */
1631 3533 : _PUBLIC_ bool cli_credentials_set_smb_signing(struct cli_credentials *creds,
1632 : enum smb_signing_setting signing_state,
1633 : enum credentials_obtained obtained)
1634 : {
1635 3533 : if (obtained >= creds->signing_state_obtained) {
1636 3533 : creds->signing_state_obtained = obtained;
1637 3533 : creds->signing_state = signing_state;
1638 3533 : return true;
1639 : }
1640 :
1641 0 : return false;
1642 : }
1643 :
1644 : /**
1645 : * @brief Obtain the SMB signing state from a credentials structure.
1646 : *
1647 : * @param[in] creds The credential structure to obtain the SMB signing state
1648 : * from.
1649 : *
1650 : * @return The SMB signing state.
1651 : */
1652 : _PUBLIC_ enum smb_signing_setting
1653 17091 : cli_credentials_get_smb_signing(struct cli_credentials *creds)
1654 : {
1655 17091 : return creds->signing_state;
1656 : }
1657 :
1658 : /**
1659 : * @brief Set the SMB IPC signing state to request for a SMB connection.
1660 : *
1661 : * @param[in] creds The credentials structure to update.
1662 : *
1663 : * @param[in] signing_state The signing state to set.
1664 : *
1665 : * @param obtained This way the described signing state was specified.
1666 : *
1667 : * @return true if we could set the signing state, false otherwise.
1668 : */
1669 : _PUBLIC_ bool
1670 80 : cli_credentials_set_smb_ipc_signing(struct cli_credentials *creds,
1671 : enum smb_signing_setting ipc_signing_state,
1672 : enum credentials_obtained obtained)
1673 : {
1674 80 : if (obtained >= creds->ipc_signing_state_obtained) {
1675 80 : creds->ipc_signing_state_obtained = obtained;
1676 80 : creds->ipc_signing_state = ipc_signing_state;
1677 80 : return true;
1678 : }
1679 :
1680 0 : return false;
1681 : }
1682 :
1683 : /**
1684 : * @brief Obtain the SMB IPC signing state from a credentials structure.
1685 : *
1686 : * @param[in] creds The credential structure to obtain the SMB IPC signing
1687 : * state from.
1688 : *
1689 : * @return The SMB signing state.
1690 : */
1691 : _PUBLIC_ enum smb_signing_setting
1692 1613 : cli_credentials_get_smb_ipc_signing(struct cli_credentials *creds)
1693 : {
1694 1613 : return creds->ipc_signing_state;
1695 : }
1696 :
1697 : /**
1698 : * @brief Set the SMB encryption state to request for a SMB connection.
1699 : *
1700 : * @param[in] creds The credentials structure to update.
1701 : *
1702 : * @param[in] encryption_state The encryption state to set.
1703 : *
1704 : * @param obtained This way the described encryption state was specified.
1705 : *
1706 : * @return true if we could set the encryption state, false otherwise.
1707 : */
1708 1521 : _PUBLIC_ bool cli_credentials_set_smb_encryption(struct cli_credentials *creds,
1709 : enum smb_encryption_setting encryption_state,
1710 : enum credentials_obtained obtained)
1711 : {
1712 1521 : if (obtained >= creds->encryption_state_obtained) {
1713 1521 : creds->encryption_state_obtained = obtained;
1714 1521 : creds->encryption_state = encryption_state;
1715 1521 : return true;
1716 : }
1717 :
1718 0 : return false;
1719 : }
1720 :
1721 14 : static const char *obtained_to_str(enum credentials_obtained obtained)
1722 : {
1723 14 : switch (obtained) {
1724 0 : case CRED_UNINITIALISED:
1725 0 : return "CRED_UNINITIALISED";
1726 0 : case CRED_SMB_CONF:
1727 0 : return "CRED_SMB_CONF";
1728 0 : case CRED_CALLBACK:
1729 0 : return "CRED_CALLBACK";
1730 0 : case CRED_GUESS_ENV:
1731 0 : return "CRED_GUESS_ENV";
1732 0 : case CRED_GUESS_FILE:
1733 0 : return "CRED_GUESS_FILE";
1734 0 : case CRED_CALLBACK_RESULT:
1735 0 : return "CRED_CALLBACK_RESULT";
1736 3 : case CRED_SPECIFIED:
1737 3 : return "CRED_SPECIFIED";
1738 : }
1739 :
1740 : /* Never reached */
1741 0 : return "";
1742 : }
1743 :
1744 1 : static const char *krb5_state_to_str(enum credentials_use_kerberos krb5_state)
1745 : {
1746 1 : switch (krb5_state) {
1747 0 : case CRED_USE_KERBEROS_DISABLED:
1748 0 : return "CRED_USE_KERBEROS_DISABLED";
1749 1 : case CRED_USE_KERBEROS_DESIRED:
1750 1 : return "CRED_USE_KERBEROS_DESIRED";
1751 0 : case CRED_USE_KERBEROS_REQUIRED:
1752 0 : return "CRED_USE_KERBEROS_REQUIRED";
1753 : }
1754 :
1755 : /* Never reached */
1756 0 : return "";
1757 : }
1758 :
1759 1 : static const char *krb5_fwd_to_str(enum credentials_krb_forwardable krb5_fwd)
1760 : {
1761 1 : switch (krb5_fwd) {
1762 0 : case CRED_AUTO_KRB_FORWARDABLE:
1763 0 : return "CRED_AUTO_KRB_FORWARDABLE";
1764 0 : case CRED_NO_KRB_FORWARDABLE:
1765 0 : return "CRED_NO_KRB_FORWARDABLE";
1766 0 : case CRED_FORCE_KRB_FORWARDABLE:
1767 0 : return "CRED_FORCE_KRB_FORWARDABLE";
1768 : }
1769 :
1770 : /* Never reached */
1771 0 : return "";
1772 : }
1773 :
1774 2 : static const char *signing_state_to_str(enum smb_signing_setting signing_state)
1775 : {
1776 2 : switch(signing_state) {
1777 0 : case SMB_SIGNING_IPC_DEFAULT:
1778 0 : return "SMB_SIGNING_IPC_DEFAULT";
1779 1 : case SMB_SIGNING_DEFAULT:
1780 1 : return "SMB_SIGNING_DEFAULT";
1781 0 : case SMB_SIGNING_OFF:
1782 0 : return "SMB_SIGNING_OFF";
1783 0 : case SMB_SIGNING_IF_REQUIRED:
1784 0 : return "SMB_SIGNING_IF_REQUIRED";
1785 0 : case SMB_SIGNING_DESIRED:
1786 0 : return "SMB_SIGNING_DESIRED";
1787 1 : case SMB_SIGNING_REQUIRED:
1788 1 : return "SMB_SIGNING_REQUIRED";
1789 : }
1790 :
1791 : /* Never reached */
1792 0 : return "";
1793 : }
1794 :
1795 1 : static const char *encryption_state_to_str(enum smb_encryption_setting encryption_state)
1796 : {
1797 1 : switch(encryption_state) {
1798 0 : case SMB_ENCRYPTION_DEFAULT:
1799 0 : return "SMB_ENCRYPTION_DEFAULT";
1800 0 : case SMB_ENCRYPTION_OFF:
1801 0 : return "SMB_ENCRYPTION_OFF";
1802 0 : case SMB_ENCRYPTION_IF_REQUIRED:
1803 0 : return "SMB_ENCRYPTION_IF_REQUIRED";
1804 0 : case SMB_ENCRYPTION_DESIRED:
1805 0 : return "SMB_ENCRYPTION_DESIRED";
1806 0 : case SMB_ENCRYPTION_REQUIRED:
1807 0 : return "SMB_ENCRYPTION_REQUIRED";
1808 : }
1809 :
1810 : /* Never reached */
1811 0 : return "";
1812 : }
1813 :
1814 1 : _PUBLIC_ void cli_credentials_dump(struct cli_credentials *creds)
1815 : {
1816 1 : DBG_ERR("CLI_CREDENTIALS:\n");
1817 1 : DBG_ERR("\n");
1818 2 : DBG_ERR(" Username: %s - %s\n",
1819 : creds->username,
1820 : obtained_to_str(creds->username_obtained));
1821 1 : DBG_ERR(" Workstation: %s - %s\n",
1822 : creds->workstation,
1823 : obtained_to_str(creds->workstation_obtained));
1824 2 : DBG_ERR(" Domain: %s - %s\n",
1825 : creds->domain,
1826 : obtained_to_str(creds->domain_obtained));
1827 2 : DBG_ERR(" Password: %s - %s\n",
1828 : creds->password != NULL ? "*SECRET*" : "NULL",
1829 : obtained_to_str(creds->password_obtained));
1830 2 : DBG_ERR(" Old password: %s\n",
1831 : creds->old_password != NULL ? "*SECRET*" : "NULL");
1832 1 : DBG_ERR(" Password tries: %u\n",
1833 : creds->password_tries);
1834 1 : DBG_ERR(" Realm: %s - %s\n",
1835 : creds->realm,
1836 : obtained_to_str(creds->realm_obtained));
1837 1 : DBG_ERR(" Principal: %s - %s\n",
1838 : creds->principal,
1839 : obtained_to_str(creds->principal_obtained));
1840 1 : DBG_ERR(" Salt principal: %s\n",
1841 : creds->salt_principal);
1842 1 : DBG_ERR(" Impersonate principal: %s\n",
1843 : creds->impersonate_principal);
1844 1 : DBG_ERR(" Self service: %s\n",
1845 : creds->self_service);
1846 1 : DBG_ERR(" Target service: %s\n",
1847 : creds->target_service);
1848 2 : DBG_ERR(" Kerberos state: %s - %s\n",
1849 : krb5_state_to_str(creds->kerberos_state),
1850 : obtained_to_str(creds->kerberos_state_obtained));
1851 1 : DBG_ERR(" Kerberos forwardable ticket: %s\n",
1852 : krb5_fwd_to_str(creds->krb_forwardable));
1853 2 : DBG_ERR(" Signing state: %s - %s\n",
1854 : signing_state_to_str(creds->signing_state),
1855 : obtained_to_str(creds->signing_state_obtained));
1856 2 : DBG_ERR(" IPC signing state: %s - %s\n",
1857 : signing_state_to_str(creds->ipc_signing_state),
1858 : obtained_to_str(creds->ipc_signing_state_obtained));
1859 1 : DBG_ERR(" Encryption state: %s - %s\n",
1860 : encryption_state_to_str(creds->encryption_state),
1861 : obtained_to_str(creds->encryption_state_obtained));
1862 1 : DBG_ERR(" Gensec features: %#X\n",
1863 : creds->gensec_features);
1864 1 : DBG_ERR(" Forced sasl mech: %s\n",
1865 : creds->forced_sasl_mech);
1866 1 : DBG_ERR(" CCACHE: %p - %s\n",
1867 : creds->ccache,
1868 : obtained_to_str(creds->ccache_obtained));
1869 1 : DBG_ERR(" CLIENT_GSS_CREDS: %p - %s\n",
1870 : creds->client_gss_creds,
1871 : obtained_to_str(creds->client_gss_creds_obtained));
1872 1 : DBG_ERR(" SERVER_GSS_CREDS: %p - %s\n",
1873 : creds->server_gss_creds,
1874 : obtained_to_str(creds->server_gss_creds_obtained));
1875 1 : DBG_ERR(" KEYTAB: %p - %s\n",
1876 : creds->keytab,
1877 : obtained_to_str(creds->keytab_obtained));
1878 1 : DBG_ERR(" KVNO: %u\n",
1879 : creds->kvno);
1880 1 : DBG_ERR("\n");
1881 1 : }
1882 :
1883 : /**
1884 : * @brief Obtain the SMB encryption state from a credentials structure.
1885 : *
1886 : * @param[in] creds The credential structure to obtain the SMB encryption state
1887 : * from.
1888 : *
1889 : * @return The SMB signing state.
1890 : */
1891 : _PUBLIC_ enum smb_encryption_setting
1892 68178 : cli_credentials_get_smb_encryption(struct cli_credentials *creds)
1893 : {
1894 68178 : return creds->encryption_state;
1895 : }
1896 :
1897 : /**
1898 : * Encrypt a data blob using the session key and the negotiated encryption
1899 : * algorithm
1900 : *
1901 : * @param state Credential state, contains the session key and algorithm
1902 : * @param data Data blob containing the data to be encrypted.
1903 : *
1904 : */
1905 86 : _PUBLIC_ NTSTATUS netlogon_creds_session_encrypt(
1906 : struct netlogon_creds_CredentialState *state,
1907 : DATA_BLOB data)
1908 : {
1909 0 : NTSTATUS status;
1910 :
1911 86 : if (data.data == NULL || data.length == 0) {
1912 0 : DBG_ERR("Nothing to encrypt "
1913 : "data.data == NULL or data.length == 0\n");
1914 0 : return NT_STATUS_INVALID_PARAMETER;
1915 : }
1916 : /*
1917 : * Don't crypt an all-zero password it will give away the
1918 : * NETLOGON pipe session key .
1919 : */
1920 86 : if (all_zero(data.data, data.length)) {
1921 0 : DBG_ERR("Supplied data all zeros, could leak session key\n");
1922 0 : return NT_STATUS_INVALID_PARAMETER;
1923 : }
1924 86 : if (state->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
1925 86 : status = netlogon_creds_aes_encrypt(state,
1926 : data.data,
1927 : data.length);
1928 0 : } else if (state->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
1929 0 : status = netlogon_creds_arcfour_crypt(state,
1930 : data.data,
1931 : data.length);
1932 : } else {
1933 0 : DBG_ERR("Unsupported encryption option negotiated\n");
1934 0 : status = NT_STATUS_NOT_SUPPORTED;
1935 : }
1936 86 : if (!NT_STATUS_IS_OK(status)) {
1937 0 : return status;
1938 : }
1939 86 : return NT_STATUS_OK;
1940 : }
1941 :
|