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