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