ctdb-daemon: Fix signed/unsigned comparison
[samba.git] / source3 / lib / util_cmdline.c
blob90ee67c4cb7663e1a5f28f16092ebebbd4a7fd1e
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
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.
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.
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/>.
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"
32 /**************************************************************************n
33 Code to cope with username/password auth options from the commandline.
34 Used mainly in client tools.
35 ****************************************************************************/
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;
49 struct user_auth_info *user_auth_info_init(TALLOC_CTX *mem_ctx)
51 struct user_auth_info *result = NULL;
53 result = talloc_zero(mem_ctx, struct user_auth_info);
54 if (result == NULL) {
55 return NULL;
58 result->lp_ctx = loadparm_init_s3(result, loadparm_s3_helpers());
59 if (result->lp_ctx == NULL) {
60 TALLOC_FREE(result);
61 return NULL;
64 result->creds = cli_credentials_init(result);
65 if (result->creds == NULL) {
66 TALLOC_FREE(result);
67 return NULL;
70 cli_credentials_set_conf(result->creds, result->lp_ctx);
72 result->signing_state = SMB_SIGNING_DEFAULT;
73 return result;
76 void set_cmdline_auth_info_guess(struct user_auth_info *auth_info)
79 * Note that cli_credentials_guess() calls
80 * cli_credentials_set_conf() again, which will
81 * hopefully cope with a reloaded smb.conf.
83 cli_credentials_set_username(auth_info->creds, "GUEST", CRED_GUESS_ENV);
84 cli_credentials_guess(auth_info->creds, auth_info->lp_ctx);
87 void set_cmdline_auth_info_from_file(struct user_auth_info *auth_info,
88 const char *filename)
90 bool ok;
92 ok = cli_credentials_parse_file(auth_info->creds, filename,
93 CRED_SPECIFIED);
94 if (!ok) {
95 exit(EIO);
97 auth_info->got_username = true;
100 const char *get_cmdline_auth_info_username(const struct user_auth_info *auth_info)
102 const char *username = NULL;
104 username = cli_credentials_get_username(auth_info->creds);
105 if (username == NULL) {
106 return "";
109 return username;
112 void set_cmdline_auth_info_username(struct user_auth_info *auth_info,
113 const char *username)
115 const char *new_val = NULL;
117 if (username == NULL) {
118 return;
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);
128 auth_info->got_username = true;
129 if (strchr_m(username, '%') != NULL) {
130 auth_info->got_pass = true;
134 void reset_cmdline_auth_info_username(struct user_auth_info *auth_info)
136 const char *username = NULL;
137 const char *new_val = NULL;
139 if (!auth_info->got_username) {
140 return;
143 username = cli_credentials_get_username(auth_info->creds);
144 if (username == NULL) {
145 return;
147 if (username[0] == '\0') {
148 return;
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);
160 const char *get_cmdline_auth_info_domain(const struct user_auth_info *auth_info)
162 const char *domain = NULL;
164 domain = cli_credentials_get_domain(auth_info->creds);
165 if (domain == NULL) {
166 return "";
169 return domain;
172 void set_cmdline_auth_info_domain(struct user_auth_info *auth_info,
173 const char *domain)
175 bool ok;
177 ok = cli_credentials_set_domain(auth_info->creds, domain, CRED_SPECIFIED);
178 if (!ok) {
179 exit(ENOMEM);
183 const char *get_cmdline_auth_info_password(const struct user_auth_info *auth_info)
185 const char *password = NULL;
187 if (auth_info->pw_nt_hash != NULL) {
188 return auth_info->pw_nt_hash;
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;
196 nt_hash = cli_credentials_get_nt_hash(ai->creds,
197 ai);
198 if (nt_hash == NULL) {
199 return "";
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 "";
210 return auth_info->pw_nt_hash;
213 password = cli_credentials_get_password(auth_info->creds);
214 if (password == NULL) {
215 return "";
218 return password;
221 void set_cmdline_auth_info_password(struct user_auth_info *auth_info,
222 const char *password)
224 bool ok;
226 auth_info->got_pass = true;
228 if (password != NULL && strlen(password) == 0) {
229 password = NULL;
232 ok = cli_credentials_set_password(auth_info->creds,
233 password,
234 CRED_SPECIFIED);
235 if (!ok) {
236 exit(ENOMEM);
240 bool set_cmdline_auth_info_signing_state(struct user_auth_info *auth_info,
241 const char *arg)
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;
257 return true;
260 void set_cmdline_auth_info_signing_state_raw(struct user_auth_info *auth_info,
261 int signing_state)
263 auth_info->signing_state = signing_state;
266 int get_cmdline_auth_info_signing_state(const struct user_auth_info *auth_info)
268 if (auth_info->smb_encrypt) {
269 return SMB_SIGNING_REQUIRED;
271 return auth_info->signing_state;
274 void set_cmdline_auth_info_use_ccache(struct user_auth_info *auth_info, bool b)
276 uint32_t gensec_features;
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);
283 bool get_cmdline_auth_info_use_ccache(const struct user_auth_info *auth_info)
285 uint32_t gensec_features;
287 gensec_features = cli_credentials_get_gensec_features(auth_info->creds);
288 if (gensec_features & GENSEC_FEATURE_NTLM_CCACHE) {
289 return true;
292 return false;
295 void set_cmdline_auth_info_use_pw_nt_hash(struct user_auth_info *auth_info,
296 bool b)
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);
303 bool get_cmdline_auth_info_use_pw_nt_hash(
304 const struct user_auth_info *auth_info)
306 return auth_info->use_pw_nt_hash;
309 void set_cmdline_auth_info_use_kerberos(struct user_auth_info *auth_info,
310 bool b)
312 enum credentials_use_kerberos krb5_state;
314 if (b) {
315 krb5_state = CRED_MUST_USE_KERBEROS;
316 } else {
317 krb5_state = CRED_DONT_USE_KERBEROS;
320 cli_credentials_set_kerberos_state(auth_info->creds, krb5_state);
323 bool get_cmdline_auth_info_use_kerberos(const struct user_auth_info *auth_info)
325 enum credentials_use_kerberos krb5_state;
327 krb5_state = cli_credentials_get_kerberos_state(auth_info->creds);
329 if (krb5_state == CRED_MUST_USE_KERBEROS) {
330 return true;
333 return false;
336 void set_cmdline_auth_info_fallback_after_kerberos(struct user_auth_info *auth_info,
337 bool b)
339 enum credentials_use_kerberos krb5_state;
341 krb5_state = cli_credentials_get_kerberos_state(auth_info->creds);
343 switch (krb5_state) {
344 case CRED_MUST_USE_KERBEROS:
345 if (b) {
346 krb5_state = CRED_AUTO_USE_KERBEROS;
348 break;
349 case CRED_AUTO_USE_KERBEROS:
350 if (!b) {
351 krb5_state = CRED_MUST_USE_KERBEROS;
353 break;
354 case CRED_DONT_USE_KERBEROS:
355 /* nothing to do */
356 break;
359 cli_credentials_set_kerberos_state(auth_info->creds, krb5_state);
362 bool get_cmdline_auth_info_fallback_after_kerberos(const struct user_auth_info *auth_info)
364 enum credentials_use_kerberos krb5_state;
366 krb5_state = cli_credentials_get_kerberos_state(auth_info->creds);
368 if (krb5_state == CRED_AUTO_USE_KERBEROS) {
369 return true;
372 return false;
375 /* This should only be used by lib/popt_common.c JRA */
376 void set_cmdline_auth_info_use_krb5_ticket(struct user_auth_info *auth_info)
378 set_cmdline_auth_info_use_kerberos(auth_info, true);
379 auth_info->got_pass = true;
382 /* This should only be used by lib/popt_common.c JRA */
383 void set_cmdline_auth_info_smb_encrypt(struct user_auth_info *auth_info)
385 auth_info->smb_encrypt = true;
388 void set_cmdline_auth_info_use_machine_account(struct user_auth_info *auth_info)
390 cli_credentials_set_machine_account_pending(auth_info->creds,
391 auth_info->lp_ctx);
392 auth_info->use_machine_account = true;
395 bool get_cmdline_auth_info_got_pass(const struct user_auth_info *auth_info)
397 return auth_info->got_pass;
400 bool get_cmdline_auth_info_smb_encrypt(const struct user_auth_info *auth_info)
402 return auth_info->smb_encrypt;
405 bool get_cmdline_auth_info_use_machine_account(const struct user_auth_info *auth_info)
407 return auth_info->use_machine_account;
410 bool set_cmdline_auth_info_machine_account_creds(struct user_auth_info *auth_info)
412 struct db_context *db_ctx = NULL;
413 NTSTATUS status;
415 if (!get_cmdline_auth_info_use_machine_account(auth_info)) {
416 return false;
419 db_ctx = secrets_db_ctx();
420 if (db_ctx == NULL) {
421 d_printf("ERROR: Unable to open secrets database\n");
422 return false;
425 cli_credentials_set_domain(auth_info->creds, lpcfg_workgroup(auth_info->lp_ctx),
426 CRED_SPECIFIED);
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;
440 return true;
443 static const char *cmdline_auth_info_pw_callback(struct cli_credentials *creds)
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;
452 name = cli_credentials_get_unparsed_name(creds, frame);
453 if (name == NULL) {
454 goto fail;
456 label = talloc_asprintf(frame, "Enter %s's password: ", name);
457 if (label == NULL) {
458 goto fail;
460 rc = samba_getpass(label, pwd, sizeof(pwd), false, false);
461 if (rc != 0) {
462 goto fail;
464 ret = talloc_strdup(creds, pwd);
465 if (ret == NULL) {
466 goto fail;
468 talloc_set_name_const(ret, __location__);
469 fail:
470 ZERO_STRUCT(pwd);
471 TALLOC_FREE(frame);
472 return ret;
475 /****************************************************************************
476 Ensure we have a password if one not given.
477 ****************************************************************************/
479 void set_cmdline_auth_info_getpass(struct user_auth_info *auth_info)
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;
488 cli_credentials_set_password_callback(auth_info->creds,
489 cmdline_auth_info_pw_callback);
492 struct cli_credentials *get_cmdline_auth_info_creds(
493 const struct user_auth_info *auth_info)
495 return auth_info->creds;