1 /*
2    Unix SMB/CIFS implementation.
3    Samba utility functions
4    Copyright (C) Andrew Tridgell 1992-1998
5    Copyright (C) Jeremy Allison 2001-2007
6    Copyright (C) Simo Sorce 2001
7    Copyright (C) Jim McDonough <jmcd@us.ibm.com> 2003
8    Copyright (C) James Peach 2006
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 "auth_info.h"
26 #include "secrets.h"
27 #include "param/param.h"
28 #include "librpc/gen_ndr/samr.h"
29 #include "auth/credentials/credentials.h"
30 #include "auth/gensec/gensec.h"
31 
32 /**************************************************************************n
33   Code to cope with username/password auth options from the commandline.
34   Used mainly in client tools.
35 ****************************************************************************/
36 
37 struct user_auth_info {
38 	struct cli_credentials *creds;
39 	struct loadparm_context *lp_ctx;
40 	bool got_username;
41 	bool got_pass;
42 	int signing_state;
43 	bool smb_encrypt;
44 	bool use_machine_account;
45 	bool use_pw_nt_hash;
46 	char *pw_nt_hash;
47 };
48 
user_auth_info_init(TALLOC_CTX * mem_ctx)49 struct user_auth_info *user_auth_info_init(TALLOC_CTX *mem_ctx)
50 {
51 	struct user_auth_info *result = NULL;
52 
53 	result = talloc_zero(mem_ctx, struct user_auth_info);
54 	if (result == NULL) {
55 		return NULL;
56 	}
57 
58 	result->lp_ctx = loadparm_init_s3(result, loadparm_s3_helpers());
59 	if (result->lp_ctx == NULL) {
60 		TALLOC_FREE(result);
61 		return NULL;
62 	}
63 
64 	result->creds = cli_credentials_init(result);
65 	if (result->creds == NULL) {
66 		TALLOC_FREE(result);
67 		return NULL;
68 	}
69 
70 	cli_credentials_set_conf(result->creds, result->lp_ctx);
71 
72 	result->signing_state = SMB_SIGNING_DEFAULT;
73 	return result;
74 }
75 
set_cmdline_auth_info_guess(struct user_auth_info * auth_info)76 void set_cmdline_auth_info_guess(struct user_auth_info *auth_info)
77 {
78 	/*
79 	 * Note that cli_credentials_guess() calls
80 	 * cli_credentials_set_conf() again, which will
81 	 * hopefully cope with a reloaded smb.conf.
82 	 */
83 	cli_credentials_set_username(auth_info->creds, "GUEST", CRED_GUESS_ENV);
84 	cli_credentials_guess(auth_info->creds, auth_info->lp_ctx);
85 }
86 
set_cmdline_auth_info_from_file(struct user_auth_info * auth_info,const char * filename)87 void set_cmdline_auth_info_from_file(struct user_auth_info *auth_info,
88 				     const char *filename)
89 {
90 	bool ok;
91 
92 	ok = cli_credentials_parse_file(auth_info->creds, filename,
93 					CRED_SPECIFIED);
94 	if (!ok) {
95 		exit(EIO);
96 	}
97 	auth_info->got_username = true;
98 }
99 
get_cmdline_auth_info_username(const struct user_auth_info * auth_info)100 const char *get_cmdline_auth_info_username(const struct user_auth_info *auth_info)
101 {
102 	const char *username = NULL;
103 
104 	username = cli_credentials_get_username(auth_info->creds);
105 	if (username == NULL) {
106 		return "";
107 	}
108 
109 	return username;
110 }
111 
set_cmdline_auth_info_username(struct user_auth_info * auth_info,const char * username)112 void set_cmdline_auth_info_username(struct user_auth_info *auth_info,
113 				    const char *username)
114 {
115 	const char *new_val = NULL;
116 
117 	if (username == NULL) {
118 		return;
119 	}
120 	cli_credentials_parse_string(auth_info->creds,
121 				     username,
122 				     CRED_SPECIFIED);
123 	new_val = cli_credentials_get_username(auth_info->creds);
124 	if (new_val == NULL) {
125 		exit(ENOMEM);
126 	}
127 
128 	auth_info->got_username = true;
129 	if (strchr_m(username, '%') != NULL) {
130 		auth_info->got_pass = true;
131 	}
132 }
133 
reset_cmdline_auth_info_username(struct user_auth_info * auth_info)134 void reset_cmdline_auth_info_username(struct user_auth_info *auth_info)
135 {
136 	const char *username = NULL;
137 	const char *new_val = NULL;
138 
139 	if (!auth_info->got_username) {
140 		return;
141 	}
142 
143 	username = cli_credentials_get_username(auth_info->creds);
144 	if (username == NULL) {
145 		return;
146 	}
147 	if (username[0] == '\0') {
148 		return;
149 	}
150 
151 	cli_credentials_parse_string(auth_info->creds,
152 				     username,
153 				     CRED_SPECIFIED);
154 	new_val = cli_credentials_get_username(auth_info->creds);
155 	if (new_val == NULL) {
156 		exit(ENOMEM);
157 	}
158 }
159 
get_cmdline_auth_info_domain(const struct user_auth_info * auth_info)160 const char *get_cmdline_auth_info_domain(const struct user_auth_info *auth_info)
161 {
162 	const char *domain = NULL;
163 
164 	domain = cli_credentials_get_domain(auth_info->creds);
165 	if (domain == NULL) {
166 		return "";
167 	}
168 
169 	return domain;
170 }
171 
set_cmdline_auth_info_domain(struct user_auth_info * auth_info,const char * domain)172 void set_cmdline_auth_info_domain(struct user_auth_info *auth_info,
173 				  const char *domain)
174 {
175 	bool ok;
176 
177 	ok = cli_credentials_set_domain(auth_info->creds, domain, CRED_SPECIFIED);
178 	if (!ok) {
179 		exit(ENOMEM);
180 	}
181 }
182 
get_cmdline_auth_info_password(const struct user_auth_info * auth_info)183 const char *get_cmdline_auth_info_password(const struct user_auth_info *auth_info)
184 {
185 	const char *password = NULL;
186 
187 	if (auth_info->pw_nt_hash != NULL) {
188 		return auth_info->pw_nt_hash;
189 	}
190 
191 	if (auth_info->use_pw_nt_hash) {
192 		struct user_auth_info *ai =
193 			discard_const_p(struct user_auth_info, auth_info);
194 		struct samr_Password *nt_hash = NULL;
195 
196 		nt_hash = cli_credentials_get_nt_hash(ai->creds,
197 						      ai);
198 		if (nt_hash == NULL) {
199 			return "";
200 		}
201 
202 		ai->pw_nt_hash = hex_encode_talloc(ai,
203 						   nt_hash->hash,
204 						   sizeof(nt_hash->hash));
205 		TALLOC_FREE(nt_hash);
206 		if (ai->pw_nt_hash == NULL) {
207 			return "";
208 		}
209 
210 		return auth_info->pw_nt_hash;
211 	}
212 
213 	password = cli_credentials_get_password(auth_info->creds);
214 	if (password == NULL) {
215 		return "";
216 	}
217 
218 	return password;
219 }
220 
set_cmdline_auth_info_password(struct user_auth_info * auth_info,const char * password)221 void set_cmdline_auth_info_password(struct user_auth_info *auth_info,
222 				    const char *password)
223 {
224 	bool ok;
225 
226 	auth_info->got_pass = true;
227 
228 	if (password != NULL && strlen(password) == 0) {
229 		password = NULL;
230 	}
231 
232 	ok = cli_credentials_set_password(auth_info->creds,
233 					  password,
234 					  CRED_SPECIFIED);
235 	if (!ok) {
236 		exit(ENOMEM);
237 	}
238 }
239 
set_cmdline_auth_info_signing_state(struct user_auth_info * auth_info,const char * arg)240 bool set_cmdline_auth_info_signing_state(struct user_auth_info *auth_info,
241 					 const char *arg)
242 {
243 	auth_info->signing_state = SMB_SIGNING_DEFAULT;
244 	if (strequal(arg, "off") || strequal(arg, "no") ||
245 			strequal(arg, "false")) {
246 		auth_info->signing_state = SMB_SIGNING_OFF;
247 	} else if (strequal(arg, "on") || strequal(arg, "yes") ||
248 			strequal(arg, "if_required") ||
249 			strequal(arg, "true") || strequal(arg, "auto")) {
250 		auth_info->signing_state = SMB_SIGNING_IF_REQUIRED;
251 	} else if (strequal(arg, "force") || strequal(arg, "required") ||
252 			strequal(arg, "forced")) {
253 		auth_info->signing_state = SMB_SIGNING_REQUIRED;
254 	} else {
255 		return false;
256 	}
257 	return true;
258 }
259 
set_cmdline_auth_info_signing_state_raw(struct user_auth_info * auth_info,int signing_state)260 void set_cmdline_auth_info_signing_state_raw(struct user_auth_info *auth_info,
261 					     int signing_state)
262 {
263 	auth_info->signing_state = signing_state;
264 }
265 
get_cmdline_auth_info_signing_state(const struct user_auth_info * auth_info)266 int get_cmdline_auth_info_signing_state(const struct user_auth_info *auth_info)
267 {
268 	if (auth_info->smb_encrypt) {
269 		return SMB_SIGNING_REQUIRED;
270 	}
271 	return auth_info->signing_state;
272 }
273 
set_cmdline_auth_info_use_ccache(struct user_auth_info * auth_info,bool b)274 void set_cmdline_auth_info_use_ccache(struct user_auth_info *auth_info, bool b)
275 {
276 	uint32_t gensec_features;
277 
278 	gensec_features = cli_credentials_get_gensec_features(auth_info->creds);
279 	gensec_features |= GENSEC_FEATURE_NTLM_CCACHE;
280 	cli_credentials_set_gensec_features(auth_info->creds, gensec_features);
281 }
282 
get_cmdline_auth_info_use_ccache(const struct user_auth_info * auth_info)283 bool get_cmdline_auth_info_use_ccache(const struct user_auth_info *auth_info)
284 {
285 	uint32_t gensec_features;
286 
287 	gensec_features = cli_credentials_get_gensec_features(auth_info->creds);
288 	if (gensec_features & GENSEC_FEATURE_NTLM_CCACHE) {
289 		return true;
290 	}
291 
292 	return false;
293 }
294 
set_cmdline_auth_info_use_pw_nt_hash(struct user_auth_info * auth_info,bool b)295 void set_cmdline_auth_info_use_pw_nt_hash(struct user_auth_info *auth_info,
296 					  bool b)
297 {
298 	TALLOC_FREE(auth_info->pw_nt_hash);
299 	auth_info->use_pw_nt_hash = b;
300 	cli_credentials_set_password_will_be_nt_hash(auth_info->creds, b);
301 }
302 
get_cmdline_auth_info_use_pw_nt_hash(const struct user_auth_info * auth_info)303 bool get_cmdline_auth_info_use_pw_nt_hash(
304 	const struct user_auth_info *auth_info)
305 {
306 	return auth_info->use_pw_nt_hash;
307 }
308 
set_cmdline_auth_info_use_kerberos(struct user_auth_info * auth_info,bool b)309 void set_cmdline_auth_info_use_kerberos(struct user_auth_info *auth_info,
310 					bool b)
311 {
312 	enum credentials_use_kerberos krb5_state;
313 
314 	if (b) {
315 		krb5_state = CRED_MUST_USE_KERBEROS;
316 	} else {
317 		krb5_state = CRED_DONT_USE_KERBEROS;
318 	}
319 
320 	cli_credentials_set_kerberos_state(auth_info->creds, krb5_state);
321 }
322 
get_cmdline_auth_info_use_kerberos(const struct user_auth_info * auth_info)323 bool get_cmdline_auth_info_use_kerberos(const struct user_auth_info *auth_info)
324 {
325 	enum credentials_use_kerberos krb5_state;
326 
327 	krb5_state = cli_credentials_get_kerberos_state(auth_info->creds);
328 
329 	if (krb5_state == CRED_MUST_USE_KERBEROS) {
330 		return true;
331 	}
332 
333 	return false;
334 }
335 
set_cmdline_auth_info_fallback_after_kerberos(struct user_auth_info * auth_info,bool b)336 void set_cmdline_auth_info_fallback_after_kerberos(struct user_auth_info *auth_info,
337 					bool b)
338 {
339 	enum credentials_use_kerberos krb5_state;
340 
341 	krb5_state = cli_credentials_get_kerberos_state(auth_info->creds);
342 
343 	switch (krb5_state) {
344 	case CRED_MUST_USE_KERBEROS:
345 		if (b) {
346 			krb5_state = CRED_AUTO_USE_KERBEROS;
347 		}
348 		break;
349 	case CRED_AUTO_USE_KERBEROS:
350 		if (!b) {
351 			krb5_state = CRED_MUST_USE_KERBEROS;
352 		}
353 		break;
354 	case CRED_DONT_USE_KERBEROS:
355 		/* nothing to do */
356 		break;
357 	}
358 
359 	cli_credentials_set_kerberos_state(auth_info->creds, krb5_state);
360 }
361 
get_cmdline_auth_info_fallback_after_kerberos(const struct user_auth_info * auth_info)362 bool get_cmdline_auth_info_fallback_after_kerberos(const struct user_auth_info *auth_info)
363 {
364 	enum credentials_use_kerberos krb5_state;
365 
366 	krb5_state = cli_credentials_get_kerberos_state(auth_info->creds);
367 
368 	if (krb5_state == CRED_AUTO_USE_KERBEROS) {
369 		return true;
370 	}
371 
372 	return false;
373 }
374 
375 /* This should only be used by lib/popt_common.c JRA */
set_cmdline_auth_info_use_krb5_ticket(struct user_auth_info * auth_info)376 void set_cmdline_auth_info_use_krb5_ticket(struct user_auth_info *auth_info)
377 {
378 	set_cmdline_auth_info_use_kerberos(auth_info, true);
379 	auth_info->got_pass = true;
380 }
381 
382 /* This should only be used by lib/popt_common.c JRA */
set_cmdline_auth_info_smb_encrypt(struct user_auth_info * auth_info)383 void set_cmdline_auth_info_smb_encrypt(struct user_auth_info *auth_info)
384 {
385 	auth_info->smb_encrypt = true;
386 }
387 
set_cmdline_auth_info_use_machine_account(struct user_auth_info * auth_info)388 void set_cmdline_auth_info_use_machine_account(struct user_auth_info *auth_info)
389 {
390 	cli_credentials_set_machine_account_pending(auth_info->creds,
391 						    auth_info->lp_ctx);
392 	auth_info->use_machine_account = true;
393 }
394 
get_cmdline_auth_info_got_pass(const struct user_auth_info * auth_info)395 bool get_cmdline_auth_info_got_pass(const struct user_auth_info *auth_info)
396 {
397 	return auth_info->got_pass;
398 }
399 
get_cmdline_auth_info_smb_encrypt(const struct user_auth_info * auth_info)400 bool get_cmdline_auth_info_smb_encrypt(const struct user_auth_info *auth_info)
401 {
402 	return auth_info->smb_encrypt;
403 }
404 
get_cmdline_auth_info_use_machine_account(const struct user_auth_info * auth_info)405 bool get_cmdline_auth_info_use_machine_account(const struct user_auth_info *auth_info)
406 {
407 	return auth_info->use_machine_account;
408 }
409 
set_cmdline_auth_info_machine_account_creds(struct user_auth_info * auth_info)410 bool set_cmdline_auth_info_machine_account_creds(struct user_auth_info *auth_info)
411 {
412 	struct db_context *db_ctx = NULL;
413 	NTSTATUS status;
414 
415 	if (!get_cmdline_auth_info_use_machine_account(auth_info)) {
416 		return false;
417 	}
418 
419 	db_ctx = secrets_db_ctx();
420 	if (db_ctx == NULL) {
421 		d_printf("ERROR: Unable to open secrets database\n");
422 		return false;
423 	}
424 
425 	cli_credentials_set_domain(auth_info->creds, lpcfg_workgroup(auth_info->lp_ctx),
426 				   CRED_SPECIFIED);
427 
428 	status = cli_credentials_set_machine_account_db_ctx(auth_info->creds,
429 							    auth_info->lp_ctx,
430 							    db_ctx);
431 	if (!NT_STATUS_IS_OK(status)) {
432 		d_printf("ERROR: Unable to fetch machine password for "
433 			 "%s in domain %s - %s\n",
434 			 lpcfg_netbios_name(auth_info->lp_ctx),
435 			 lpcfg_workgroup(auth_info->lp_ctx),
436 			 nt_errstr(status));
437 		return false;
438 	}
439 
440 	return true;
441 }
442 
cmdline_auth_info_pw_callback(struct cli_credentials * creds)443 static const char *cmdline_auth_info_pw_callback(struct cli_credentials *creds)
444 {
445 	TALLOC_CTX *frame = talloc_stackframe();
446 	const char *name = NULL;
447 	char *label = NULL;
448 	char *ret = NULL;
449 	char pwd[256] = {0};
450 	int rc;
451 
452 	name = cli_credentials_get_unparsed_name(creds, frame);
453 	if (name == NULL) {
454 		goto fail;
455 	}
456 	label = talloc_asprintf(frame, "Enter %s's password: ", name);
457 	if (label == NULL) {
458 		goto fail;
459 	}
460 	rc = samba_getpass(label, pwd, sizeof(pwd), false, false);
461 	if (rc != 0) {
462 		goto fail;
463 	}
464 	ret = talloc_strdup(creds, pwd);
465 	if (ret == NULL) {
466 		goto fail;
467 	}
468 	talloc_set_name_const(ret, __location__);
469 fail:
470 	ZERO_STRUCT(pwd);
471 	TALLOC_FREE(frame);
472 	return ret;
473 }
474 
475 /****************************************************************************
476  Ensure we have a password if one not given.
477 ****************************************************************************/
478 
set_cmdline_auth_info_getpass(struct user_auth_info * auth_info)479 void set_cmdline_auth_info_getpass(struct user_auth_info *auth_info)
480 {
481 	if (get_cmdline_auth_info_got_pass(auth_info) ||
482 	    get_cmdline_auth_info_use_ccache(auth_info) ||
483 	    get_cmdline_auth_info_use_kerberos(auth_info)) {
484 		/* Already got one... */
485 		return;
486 	}
487 
488 	cli_credentials_set_password_callback(auth_info->creds,
489 					cmdline_auth_info_pw_callback);
490 }
491 
get_cmdline_auth_info_creds(const struct user_auth_info * auth_info)492 struct cli_credentials *get_cmdline_auth_info_creds(
493 	const struct user_auth_info *auth_info)
494 {
495 	return auth_info->creds;
496 }
497