s4-loadparm: 2nd half of lp_ to lpcfg_ conversion
[kamenim/samba.git] / source4 / 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 "librpc/gen_ndr/samr.h" /* for struct samrPassword */
26 #include "auth/credentials/credentials.h"
27 #include "auth/credentials/credentials_krb5.h"
28 #include "auth/credentials/credentials_proto.h"
29 #include "libcli/auth/libcli_auth.h"
30 #include "lib/events/events.h"
31 #include "param/param.h"
32
33 /**
34  * Create a new credentials structure
35  * @param mem_ctx TALLOC_CTX parent for credentials structure 
36  */
37 _PUBLIC_ struct cli_credentials *cli_credentials_init(TALLOC_CTX *mem_ctx) 
38 {
39         struct cli_credentials *cred = talloc(mem_ctx, struct cli_credentials);
40         if (cred == NULL) {
41                 return cred;
42         }
43
44         cred->workstation_obtained = CRED_UNINITIALISED;
45         cred->username_obtained = CRED_UNINITIALISED;
46         cred->password_obtained = CRED_UNINITIALISED;
47         cred->domain_obtained = CRED_UNINITIALISED;
48         cred->realm_obtained = CRED_UNINITIALISED;
49         cred->ccache_obtained = CRED_UNINITIALISED;
50         cred->client_gss_creds_obtained = CRED_UNINITIALISED;
51         cred->principal_obtained = CRED_UNINITIALISED;
52         cred->keytab_obtained = CRED_UNINITIALISED;
53         cred->server_gss_creds_obtained = CRED_UNINITIALISED;
54
55         cred->ccache_threshold = CRED_UNINITIALISED;
56         cred->client_gss_creds_threshold = CRED_UNINITIALISED;
57
58         cred->workstation = NULL;
59         cred->username = NULL;
60         cred->password = NULL;
61         cred->old_password = NULL;
62         cred->domain = NULL;
63         cred->realm = NULL;
64         cred->principal = NULL;
65         cred->salt_principal = NULL;
66         cred->impersonate_principal = NULL;
67         cred->target_service = NULL;
68
69         cred->bind_dn = NULL;
70
71         cred->nt_hash = NULL;
72
73         cred->lm_response.data = NULL;
74         cred->lm_response.length = 0;
75         cred->nt_response.data = NULL;
76         cred->nt_response.length = 0;
77
78         cred->ccache = NULL;
79         cred->client_gss_creds = NULL;
80         cred->keytab = NULL;
81         cred->server_gss_creds = NULL;
82
83         cred->workstation_cb = NULL;
84         cred->password_cb = NULL;
85         cred->username_cb = NULL;
86         cred->domain_cb = NULL;
87         cred->realm_cb = NULL;
88         cred->principal_cb = NULL;
89
90         cred->priv_data = NULL;
91
92         cred->netlogon_creds = NULL;
93         cred->secure_channel_type = SEC_CHAN_NULL;
94
95         cred->kvno = 0;
96
97         cred->password_last_changed_time = 0;
98
99         cred->smb_krb5_context = NULL;
100
101         cred->machine_account_pending = false;
102         cred->machine_account_pending_lp_ctx = NULL;
103
104         cred->machine_account = false;
105
106         cred->tries = 3;
107
108         cred->callback_running = false;
109
110         cli_credentials_set_kerberos_state(cred, CRED_AUTO_USE_KERBEROS);
111         cli_credentials_set_gensec_features(cred, 0);
112
113         return cred;
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_ void cli_credentials_set_kerberos_state(struct cli_credentials *creds, 
131                                         enum credentials_use_kerberos use_kerberos)
132 {
133         creds->use_kerberos = use_kerberos;
134 }
135
136 _PUBLIC_ enum credentials_use_kerberos cli_credentials_get_kerberos_state(struct cli_credentials *creds)
137 {
138         return creds->use_kerberos;
139 }
140
141 _PUBLIC_ void cli_credentials_set_gensec_features(struct cli_credentials *creds, uint32_t gensec_features)
142 {
143         creds->gensec_features = gensec_features;
144 }
145
146 _PUBLIC_ uint32_t cli_credentials_get_gensec_features(struct cli_credentials *creds)
147 {
148         return creds->gensec_features;
149 }
150
151
152 /**
153  * Obtain the username for this credentials context.
154  * @param cred credentials context
155  * @retval The username set on this context.
156  * @note Return value will never be NULL except by programmer error.
157  */
158 _PUBLIC_ const char *cli_credentials_get_username(struct cli_credentials *cred)
159 {
160         if (cred->machine_account_pending) {
161                 cli_credentials_set_machine_account(cred, 
162                                         cred->machine_account_pending_lp_ctx);
163         }
164
165         if (cred->username_obtained == CRED_CALLBACK && 
166             !cred->callback_running) {
167                 cred->callback_running = true;
168                 cred->username = cred->username_cb(cred);
169                 cred->callback_running = false;
170                 cred->username_obtained = CRED_SPECIFIED;
171                 cli_credentials_invalidate_ccache(cred, cred->username_obtained);
172         }
173
174         return cred->username;
175 }
176
177 _PUBLIC_ bool cli_credentials_set_username(struct cli_credentials *cred, 
178                                   const char *val, enum credentials_obtained obtained)
179 {
180         if (obtained >= cred->username_obtained) {
181                 cred->username = talloc_strdup(cred, val);
182                 cred->username_obtained = obtained;
183                 cli_credentials_invalidate_ccache(cred, cred->username_obtained);
184                 return true;
185         }
186
187         return false;
188 }
189
190 bool cli_credentials_set_username_callback(struct cli_credentials *cred,
191                                   const char *(*username_cb) (struct cli_credentials *))
192 {
193         if (cred->username_obtained < CRED_CALLBACK) {
194                 cred->username_cb = username_cb;
195                 cred->username_obtained = CRED_CALLBACK;
196                 return true;
197         }
198
199         return false;
200 }
201
202 _PUBLIC_ bool cli_credentials_set_bind_dn(struct cli_credentials *cred, 
203                                  const char *bind_dn)
204 {
205         cred->bind_dn = talloc_strdup(cred, bind_dn);
206         return true;
207 }
208
209 /**
210  * Obtain the BIND DN for this credentials context.
211  * @param cred credentials context
212  * @retval The username set on this context.
213  * @note Return value will be NULL if not specified explictly
214  */
215 _PUBLIC_ const char *cli_credentials_get_bind_dn(struct cli_credentials *cred)
216 {
217         return cred->bind_dn;
218 }
219
220
221 /**
222  * Obtain the client principal for this credentials context.
223  * @param cred credentials context
224  * @retval The username set on this context.
225  * @note Return value will never be NULL except by programmer error.
226  */
227 const char *cli_credentials_get_principal_and_obtained(struct cli_credentials *cred, TALLOC_CTX *mem_ctx, enum credentials_obtained *obtained)
228 {
229         if (cred->machine_account_pending) {
230                 cli_credentials_set_machine_account(cred,
231                                         cred->machine_account_pending_lp_ctx);
232         }
233
234         if (cred->principal_obtained == CRED_CALLBACK && 
235             !cred->callback_running) {
236                 cred->callback_running = true;
237                 cred->principal = cred->principal_cb(cred);
238                 cred->callback_running = false;
239                 cred->principal_obtained = CRED_SPECIFIED;
240                 cli_credentials_invalidate_ccache(cred, cred->principal_obtained);
241         }
242
243         if (cred->principal_obtained < cred->username_obtained
244             || cred->principal_obtained < MAX(cred->domain_obtained, cred->realm_obtained)) {
245                 if (cred->domain_obtained > cred->realm_obtained) {
246                         *obtained = MIN(cred->domain_obtained, cred->username_obtained);
247                         return talloc_asprintf(mem_ctx, "%s@%s", 
248                                                cli_credentials_get_username(cred),
249                                                cli_credentials_get_domain(cred));
250                 } else {
251                         *obtained = MIN(cred->domain_obtained, cred->username_obtained);
252                         return talloc_asprintf(mem_ctx, "%s@%s", 
253                                                cli_credentials_get_username(cred),
254                                                cli_credentials_get_realm(cred));
255                 }
256         }
257         *obtained = cred->principal_obtained;
258         return talloc_reference(mem_ctx, cred->principal);
259 }
260
261 /**
262  * Obtain the client principal for this credentials context.
263  * @param cred credentials context
264  * @retval The username set on this context.
265  * @note Return value will never be NULL except by programmer error.
266  */
267 _PUBLIC_ const char *cli_credentials_get_principal(struct cli_credentials *cred, TALLOC_CTX *mem_ctx)
268 {
269         enum credentials_obtained obtained;
270         return cli_credentials_get_principal_and_obtained(cred, mem_ctx, &obtained);
271 }
272
273 bool cli_credentials_set_principal(struct cli_credentials *cred, 
274                                    const char *val, 
275                                    enum credentials_obtained obtained)
276 {
277         if (obtained >= cred->principal_obtained) {
278                 cred->principal = talloc_strdup(cred, val);
279                 cred->principal_obtained = obtained;
280                 cli_credentials_invalidate_ccache(cred, cred->principal_obtained);
281                 return true;
282         }
283
284         return false;
285 }
286
287 /* Set a callback to get the principal.  This could be a popup dialog,
288  * a terminal prompt or similar.  */
289 bool cli_credentials_set_principal_callback(struct cli_credentials *cred,
290                                   const char *(*principal_cb) (struct cli_credentials *))
291 {
292         if (cred->principal_obtained < CRED_CALLBACK) {
293                 cred->principal_cb = principal_cb;
294                 cred->principal_obtained = CRED_CALLBACK;
295                 return true;
296         }
297
298         return false;
299 }
300
301 /* Some of our tools are 'anonymous by default'.  This is a single
302  * function to determine if authentication has been explicitly
303  * requested */
304
305 _PUBLIC_ bool cli_credentials_authentication_requested(struct cli_credentials *cred) 
306 {
307         if (cred->bind_dn) {
308                 return true;
309         }
310
311         if (cli_credentials_is_anonymous(cred)){
312                 return false;
313         }
314
315         if (cred->principal_obtained >= CRED_SPECIFIED) {
316                 return true;
317         }
318         if (cred->username_obtained >= CRED_SPECIFIED) {
319                 return true;
320         }
321
322         if (cli_credentials_get_kerberos_state(cred) == CRED_MUST_USE_KERBEROS) {
323                 return true;
324         }
325
326         return false;
327 }
328
329 /**
330  * Obtain the password for this credentials context.
331  * @param cred credentials context
332  * @retval If set, the cleartext password, otherwise NULL
333  */
334 _PUBLIC_ const char *cli_credentials_get_password(struct cli_credentials *cred)
335 {
336         if (cred->machine_account_pending) {
337                 cli_credentials_set_machine_account(cred,
338                                                     cred->machine_account_pending_lp_ctx);
339         }
340
341         if (cred->password_obtained == CRED_CALLBACK && 
342             !cred->callback_running) {
343                 cred->callback_running = true;
344                 cred->password = cred->password_cb(cred);
345                 cred->callback_running = false;
346                 cred->password_obtained = CRED_CALLBACK_RESULT;
347                 cli_credentials_invalidate_ccache(cred, cred->password_obtained);
348         }
349
350         return cred->password;
351 }
352
353 /* Set a password on the credentials context, including an indication
354  * of 'how' the password was obtained */
355
356 _PUBLIC_ bool cli_credentials_set_password(struct cli_credentials *cred, 
357                                   const char *val, 
358                                   enum credentials_obtained obtained)
359 {
360         if (obtained >= cred->password_obtained) {
361                 cred->password = talloc_strdup(cred, val);
362                 cred->password_obtained = obtained;
363                 cli_credentials_invalidate_ccache(cred, cred->password_obtained);
364
365                 cred->nt_hash = NULL;
366                 cred->lm_response = data_blob(NULL, 0);
367                 cred->nt_response = data_blob(NULL, 0);
368                 return true;
369         }
370
371         return false;
372 }
373
374 _PUBLIC_ bool cli_credentials_set_password_callback(struct cli_credentials *cred,
375                                            const char *(*password_cb) (struct cli_credentials *))
376 {
377         if (cred->password_obtained < CRED_CALLBACK) {
378                 cred->password_cb = password_cb;
379                 cred->password_obtained = CRED_CALLBACK;
380                 cli_credentials_invalidate_ccache(cred, cred->password_obtained);
381                 return true;
382         }
383
384         return false;
385 }
386
387 /**
388  * Obtain the 'old' password for this credentials context (used for join accounts).
389  * @param cred credentials context
390  * @retval If set, the cleartext password, otherwise NULL
391  */
392 const char *cli_credentials_get_old_password(struct cli_credentials *cred)
393 {
394         if (cred->machine_account_pending) {
395                 cli_credentials_set_machine_account(cred,
396                                                     cred->machine_account_pending_lp_ctx);
397         }
398
399         return cred->old_password;
400 }
401
402 bool cli_credentials_set_old_password(struct cli_credentials *cred, 
403                                       const char *val, 
404                                       enum credentials_obtained obtained)
405 {
406         cred->old_password = talloc_strdup(cred, val);
407         return true;
408 }
409
410 /**
411  * Obtain the password, in the form MD4(unicode(password)) for this credentials context.
412  *
413  * Sometimes we only have this much of the password, while the rest of
414  * the time this call avoids calling E_md4hash themselves.
415  *
416  * @param cred credentials context
417  * @retval If set, the cleartext password, otherwise NULL
418  */
419 _PUBLIC_ const struct samr_Password *cli_credentials_get_nt_hash(struct cli_credentials *cred, 
420                                                         TALLOC_CTX *mem_ctx)
421 {
422         const char *password = cli_credentials_get_password(cred);
423
424         if (password) {
425                 struct samr_Password *nt_hash = talloc(mem_ctx, struct samr_Password);
426                 if (!nt_hash) {
427                         return NULL;
428                 }
429                 
430                 E_md4hash(password, nt_hash->hash);    
431
432                 return nt_hash;
433         } else {
434                 return cred->nt_hash;
435         }
436 }
437
438 /**
439  * Obtain the 'short' or 'NetBIOS' domain for this credentials context.
440  * @param cred credentials context
441  * @retval The domain set on this context. 
442  * @note Return value will never be NULL except by programmer error.
443  */
444 _PUBLIC_ const char *cli_credentials_get_domain(struct cli_credentials *cred)
445 {
446         if (cred->machine_account_pending) {
447                 cli_credentials_set_machine_account(cred,
448                                                     cred->machine_account_pending_lp_ctx);
449         }
450
451         if (cred->domain_obtained == CRED_CALLBACK && 
452             !cred->callback_running) {
453                 cred->callback_running = true;
454                 cred->domain = cred->domain_cb(cred);
455                 cred->callback_running = false;
456                 cred->domain_obtained = CRED_SPECIFIED;
457                 cli_credentials_invalidate_ccache(cred, cred->domain_obtained);
458         }
459
460         return cred->domain;
461 }
462
463
464 _PUBLIC_ bool cli_credentials_set_domain(struct cli_credentials *cred, 
465                                 const char *val, 
466                                 enum credentials_obtained obtained)
467 {
468         if (obtained >= cred->domain_obtained) {
469                 /* it is important that the domain be in upper case,
470                  * particularly for the sensitive NTLMv2
471                  * calculations */
472                 cred->domain = strupper_talloc(cred, val);
473                 cred->domain_obtained = obtained;
474                 cli_credentials_invalidate_ccache(cred, cred->domain_obtained);
475                 return true;
476         }
477
478         return false;
479 }
480
481 bool cli_credentials_set_domain_callback(struct cli_credentials *cred,
482                                          const char *(*domain_cb) (struct cli_credentials *))
483 {
484         if (cred->domain_obtained < CRED_CALLBACK) {
485                 cred->domain_cb = domain_cb;
486                 cred->domain_obtained = CRED_CALLBACK;
487                 return true;
488         }
489
490         return false;
491 }
492
493 /**
494  * Obtain the Kerberos realm for this credentials context.
495  * @param cred credentials context
496  * @retval The realm set on this context. 
497  * @note Return value will never be NULL except by programmer error.
498  */
499 _PUBLIC_ const char *cli_credentials_get_realm(struct cli_credentials *cred)
500 {       
501         if (cred->machine_account_pending) {
502                 cli_credentials_set_machine_account(cred,
503                                                     cred->machine_account_pending_lp_ctx);
504         }
505
506         if (cred->realm_obtained == CRED_CALLBACK && 
507             !cred->callback_running) {
508                 cred->callback_running = true;
509                 cred->realm = cred->realm_cb(cred);
510                 cred->callback_running = false;
511                 cred->realm_obtained = CRED_SPECIFIED;
512                 cli_credentials_invalidate_ccache(cred, cred->realm_obtained);
513         }
514
515         return cred->realm;
516 }
517
518 /**
519  * Set the realm for this credentials context, and force it to
520  * uppercase for the sainity of our local kerberos libraries 
521  */
522 _PUBLIC_ bool cli_credentials_set_realm(struct cli_credentials *cred, 
523                                const char *val, 
524                                enum credentials_obtained obtained)
525 {
526         if (obtained >= cred->realm_obtained) {
527                 cred->realm = strupper_talloc(cred, val);
528                 cred->realm_obtained = obtained;
529                 cli_credentials_invalidate_ccache(cred, cred->realm_obtained);
530                 return true;
531         }
532
533         return false;
534 }
535
536 bool cli_credentials_set_realm_callback(struct cli_credentials *cred,
537                                         const char *(*realm_cb) (struct cli_credentials *))
538 {
539         if (cred->realm_obtained < CRED_CALLBACK) {
540                 cred->realm_cb = realm_cb;
541                 cred->realm_obtained = CRED_CALLBACK;
542                 return true;
543         }
544
545         return false;
546 }
547
548 /**
549  * Obtain the 'short' or 'NetBIOS' workstation name for this credentials context.
550  *
551  * @param cred credentials context
552  * @retval The workstation name set on this context. 
553  * @note Return value will never be NULL except by programmer error.
554  */
555 _PUBLIC_ const char *cli_credentials_get_workstation(struct cli_credentials *cred)
556 {
557         if (cred->workstation_obtained == CRED_CALLBACK && 
558             !cred->callback_running) {
559                 cred->callback_running = true;
560                 cred->workstation = cred->workstation_cb(cred);
561                 cred->callback_running = false;
562                 cred->workstation_obtained = CRED_SPECIFIED;
563         }
564
565         return cred->workstation;
566 }
567
568 _PUBLIC_ bool cli_credentials_set_workstation(struct cli_credentials *cred, 
569                                      const char *val, 
570                                      enum credentials_obtained obtained)
571 {
572         if (obtained >= cred->workstation_obtained) {
573                 cred->workstation = talloc_strdup(cred, val);
574                 cred->workstation_obtained = obtained;
575                 return true;
576         }
577
578         return false;
579 }
580
581 bool cli_credentials_set_workstation_callback(struct cli_credentials *cred,
582                                               const char *(*workstation_cb) (struct cli_credentials *))
583 {
584         if (cred->workstation_obtained < CRED_CALLBACK) {
585                 cred->workstation_cb = workstation_cb;
586                 cred->workstation_obtained = CRED_CALLBACK;
587                 return true;
588         }
589
590         return false;
591 }
592
593 /**
594  * Given a string, typically obtained from a -U argument, parse it into domain, username, realm and password fields
595  *
596  * The format accepted is [domain\\]user[%password] or user[@realm][%password]
597  *
598  * @param credentials Credentials structure on which to set the password
599  * @param data the string containing the username, password etc
600  * @param obtained This enum describes how 'specified' this password is
601  */
602
603 _PUBLIC_ void cli_credentials_parse_string(struct cli_credentials *credentials, const char *data, enum credentials_obtained obtained)
604 {
605         char *uname, *p;
606
607         if (strcmp("%",data) == 0) {
608                 cli_credentials_set_anonymous(credentials);
609                 return;
610         }
611
612         uname = talloc_strdup(credentials, data); 
613         if ((p = strchr_m(uname,'%'))) {
614                 *p = 0;
615                 cli_credentials_set_password(credentials, p+1, obtained);
616         }
617
618         if ((p = strchr_m(uname,'@'))) {
619                 cli_credentials_set_principal(credentials, uname, obtained);
620                 *p = 0;
621                 cli_credentials_set_realm(credentials, p+1, obtained);
622                 return;
623         } else if ((p = strchr_m(uname,'\\')) || (p = strchr_m(uname, '/'))) {
624                 *p = 0;
625                 cli_credentials_set_domain(credentials, uname, obtained);
626                 uname = p+1;
627         }
628         cli_credentials_set_username(credentials, uname, obtained);
629 }
630
631 /**
632  * Given a a credentials structure, print it as a string
633  *
634  * The format output is [domain\\]user[%password] or user[@realm][%password]
635  *
636  * @param credentials Credentials structure on which to set the password
637  * @param mem_ctx The memory context to place the result on
638  */
639
640 _PUBLIC_ const char *cli_credentials_get_unparsed_name(struct cli_credentials *credentials, TALLOC_CTX *mem_ctx)
641 {
642         const char *bind_dn = cli_credentials_get_bind_dn(credentials);
643         const char *domain;
644         const char *username;
645         const char *name;
646
647         if (bind_dn) {
648                 name = talloc_reference(mem_ctx, bind_dn);
649         } else {
650                 cli_credentials_get_ntlm_username_domain(credentials, mem_ctx, &username, &domain);
651                 if (domain && domain[0]) {
652                         name = talloc_asprintf(mem_ctx, "%s\\%s", 
653                                                domain, username);
654                 } else {
655                         name = talloc_asprintf(mem_ctx, "%s", 
656                                                username);
657                 }
658         }
659         return name;
660 }
661
662 /**
663  * Specifies default values for domain, workstation and realm
664  * from the smb.conf configuration file
665  *
666  * @param cred Credentials structure to fill in
667  */
668 _PUBLIC_ void cli_credentials_set_conf(struct cli_credentials *cred, 
669                               struct loadparm_context *lp_ctx)
670 {
671         cli_credentials_set_username(cred, "", CRED_UNINITIALISED);
672         cli_credentials_set_domain(cred, lpcfg_workgroup(lp_ctx), CRED_UNINITIALISED);
673         cli_credentials_set_workstation(cred, lpcfg_netbios_name(lp_ctx), CRED_UNINITIALISED);
674         cli_credentials_set_realm(cred, lpcfg_realm(lp_ctx), CRED_UNINITIALISED);
675 }
676
677 /**
678  * Guess defaults for credentials from environment variables, 
679  * and from the configuration file
680  * 
681  * @param cred Credentials structure to fill in
682  */
683 _PUBLIC_ void cli_credentials_guess(struct cli_credentials *cred,
684                            struct loadparm_context *lp_ctx)
685 {
686         char *p;
687         const char *error_string;
688
689         if (lp_ctx != NULL) {
690                 cli_credentials_set_conf(cred, lp_ctx);
691         }
692         
693         if (getenv("LOGNAME")) {
694                 cli_credentials_set_username(cred, getenv("LOGNAME"), CRED_GUESS_ENV);
695         }
696
697         if (getenv("USER")) {
698                 cli_credentials_parse_string(cred, getenv("USER"), CRED_GUESS_ENV);
699                 if ((p = strchr_m(getenv("USER"),'%'))) {
700                         memset(p,0,strlen(cred->password));
701                 }
702         }
703
704         if (getenv("PASSWD")) {
705                 cli_credentials_set_password(cred, getenv("PASSWD"), CRED_GUESS_ENV);
706         }
707
708         if (getenv("PASSWD_FD")) {
709                 cli_credentials_parse_password_fd(cred, atoi(getenv("PASSWD_FD")), 
710                                                   CRED_GUESS_FILE);
711         }
712         
713         p = getenv("PASSWD_FILE");
714         if (p && p[0]) {
715                 cli_credentials_parse_password_file(cred, p, CRED_GUESS_FILE);
716         }
717         
718         if (cli_credentials_get_kerberos_state(cred) != CRED_DONT_USE_KERBEROS) {
719                 cli_credentials_set_ccache(cred, event_context_find(cred), lp_ctx, NULL, CRED_GUESS_FILE,
720                                            &error_string);
721         }
722 }
723
724 /**
725  * Attach NETLOGON credentials for use with SCHANNEL
726  */
727
728 _PUBLIC_ void cli_credentials_set_netlogon_creds(struct cli_credentials *cred, 
729                                                  struct netlogon_creds_CredentialState *netlogon_creds)
730 {
731         cred->netlogon_creds = talloc_reference(cred, netlogon_creds);
732 }
733
734 /**
735  * Return attached NETLOGON credentials 
736  */
737
738 struct netlogon_creds_CredentialState *cli_credentials_get_netlogon_creds(struct cli_credentials *cred)
739 {
740         return cred->netlogon_creds;
741 }
742
743 /** 
744  * Set NETLOGON secure channel type
745  */
746
747 _PUBLIC_ void cli_credentials_set_secure_channel_type(struct cli_credentials *cred,
748                                              enum netr_SchannelType secure_channel_type)
749 {
750         cred->secure_channel_type = secure_channel_type;
751 }
752
753 /**
754  * Return NETLOGON secure chanel type
755  */
756
757 _PUBLIC_ time_t cli_credentials_get_password_last_changed_time(struct cli_credentials *cred)
758 {
759         return cred->password_last_changed_time;
760 }
761
762 /** 
763  * Set NETLOGON secure channel type
764  */
765
766 _PUBLIC_ void cli_credentials_set_password_last_changed_time(struct cli_credentials *cred,
767                                                              time_t last_changed_time)
768 {
769         cred->password_last_changed_time = last_changed_time;
770 }
771
772 /**
773  * Return NETLOGON secure chanel type
774  */
775
776 _PUBLIC_ enum netr_SchannelType cli_credentials_get_secure_channel_type(struct cli_credentials *cred)
777 {
778         return cred->secure_channel_type;
779 }
780
781 /**
782  * Fill in a credentials structure as the anonymous user
783  */
784 _PUBLIC_ void cli_credentials_set_anonymous(struct cli_credentials *cred) 
785 {
786         cli_credentials_set_username(cred, "", CRED_SPECIFIED);
787         cli_credentials_set_domain(cred, "", CRED_SPECIFIED);
788         cli_credentials_set_password(cred, NULL, CRED_SPECIFIED);
789         cli_credentials_set_realm(cred, NULL, CRED_SPECIFIED);
790         cli_credentials_set_workstation(cred, "", CRED_UNINITIALISED);
791 }
792
793 /**
794  * Describe a credentials context as anonymous or authenticated
795  * @retval true if anonymous, false if a username is specified
796  */
797
798 _PUBLIC_ bool cli_credentials_is_anonymous(struct cli_credentials *cred)
799 {
800         const char *username;
801         
802         /* if bind dn is set it's not anonymous */
803         if (cred->bind_dn) {
804                 return false;
805         }
806
807         if (cred->machine_account_pending) {
808                 cli_credentials_set_machine_account(cred,
809                                                     cred->machine_account_pending_lp_ctx);
810         }
811
812         username = cli_credentials_get_username(cred);
813         
814         /* Yes, it is deliberate that we die if we have a NULL pointer
815          * here - anonymous is "", not NULL, which is 'never specified,
816          * never guessed', ie programmer bug */
817         if (!username[0]) {
818                 return true;
819         }
820
821         return false;
822 }
823
824 /**
825  * Mark the current password for a credentials struct as wrong. This will 
826  * cause the password to be prompted again (if a callback is set).
827  *
828  * This will decrement the number of times the password can be tried.
829  *
830  * @retval whether the credentials struct is finished
831  */
832 _PUBLIC_ bool cli_credentials_wrong_password(struct cli_credentials *cred)
833 {
834         if (cred->password_obtained != CRED_CALLBACK_RESULT) {
835                 return false;
836         }
837         
838         cred->password_obtained = CRED_CALLBACK;
839
840         cred->tries--;
841
842         return (cred->tries > 0);
843 }