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