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