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