python:tests: Store keys as bytes rather than as lists of ints
[samba.git] / source3 / lib / util_cmdline.c
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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 */
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 */
383 void set_cmdline_auth_info_smb_encrypt(struct user_auth_info *auth_info)
384 {
385         auth_info->smb_encrypt = true;
386 }
387
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
395 bool get_cmdline_auth_info_got_pass(const struct user_auth_info *auth_info)
396 {
397         return auth_info->got_pass;
398 }
399
400 bool get_cmdline_auth_info_smb_encrypt(const struct user_auth_info *auth_info)
401 {
402         return auth_info->smb_encrypt;
403 }
404
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
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
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
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
492 struct cli_credentials *get_cmdline_auth_info_creds(
493         const struct user_auth_info *auth_info)
494 {
495         return auth_info->creds;
496 }