use global_myname and not domain for storing domain sid
[Samba.git] / source / utils / smbpasswd.c
blob527e2a38f68062e98cb31201483dd122998f1f9c
1 /*
2 * Unix SMB/Netbios implementation.
3 * Version 1.9.
4 * smbpasswd module.
5 * Copyright (C) Jeremy Allison 1995-1998
6 * Copyright (C) Tim Potter 2001
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation; either version 2 of the License, or (at your
11 * option) any later version.
13 * This program is distributed in the hope that it will be useful, but WITHOUT
14 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
16 * more details.
18 * You should have received a copy of the GNU General Public License along with
19 * this program; if not, write to the Free Software Foundation, Inc., 675
20 * Mass Ave, Cambridge, MA 02139, USA. */
22 #include "includes.h"
24 extern pstring global_myname;
25 extern BOOL AllowDebugChange;
28 * Next two lines needed for SunOS and don't
29 * hurt anything else...
31 extern char *optarg;
32 extern int optind;
34 /* forced running in root-mode */
35 static BOOL local_mode;
36 static BOOL joining_domain = False, got_pass = False, got_username = False;
37 static int local_flags = 0;
38 static BOOL stdin_passwd_get = False;
39 static fstring user_name, user_password;
40 static char *new_domain = NULL;
41 static char *new_passwd = NULL;
42 static char *old_passwd = NULL;
43 static char *remote_machine = NULL;
44 static pstring servicesf = CONFIGFILE;
46 #ifdef WITH_LDAP_SAM
47 static fstring ldap_secret;
48 #endif
52 /*********************************************************
53 A strdup with exit
54 **********************************************************/
56 static char *strdup_x(const char *s)
58 char *new_s = strdup(s);
59 if (!new_s) {
60 fprintf(stderr,"out of memory\n");
61 exit(1);
63 return new_s;
67 /*********************************************************
68 Print command usage on stderr and die.
69 **********************************************************/
70 static void usage(void)
72 printf("When run by root:\n");
73 printf(" smbpasswd [options] [username] [password]\n");
74 printf("otherwise:\n");
75 printf(" smbpasswd [options] [password]\n\n");
77 printf("options:\n");
78 printf(" -L local mode (must be first option)\n");
79 printf(" -h print this usage message\n");
80 printf(" -s use stdin for password prompt\n");
81 printf(" -c smb.conf file Use the given path to the smb.conf file\n");
82 printf(" -D LEVEL debug level\n");
83 printf(" -r MACHINE remote machine\n");
84 printf(" -U USER remote username\n");
86 printf("extra options when run by root or in local mode:\n");
87 printf(" -a add user\n");
88 printf(" -d disable user\n");
89 printf(" -e enable user\n");
90 printf(" -m machine trust account\n");
91 printf(" -n set no password\n");
92 #ifdef WITH_LDAP_SAM
93 printf(" -w ldap admin password\n");
94 #endif
95 printf(" -x delete user\n");
96 printf(" -j DOMAIN join domain name\n");
97 printf(" -S DOMAIN Retrieve the domain SID for DOMAIN\n");
98 printf(" -R ORDER name resolve order\n");
100 exit(1);
103 static void set_line_buffering(FILE *f)
105 setvbuf(f, NULL, _IOLBF, 0);
108 /*******************************************************************
109 Process command line options
110 ******************************************************************/
111 static void process_options(int argc, char **argv, BOOL amroot)
113 int ch;
115 user_name[0] = '\0';
117 while ((ch = getopt(argc, argv, "c:axdehmnj:r:sw:R:D:U:LS")) != EOF) {
118 switch(ch) {
119 case 'L':
120 local_mode = amroot = True;
121 break;
122 case 'c':
123 pstrcpy(servicesf,optarg);
124 break;
125 case 'a':
126 if (!amroot) goto bad_args;
127 local_flags |= LOCAL_ADD_USER;
128 break;
129 case 'x':
130 if (!amroot) goto bad_args;
131 local_flags |= LOCAL_DELETE_USER;
132 new_passwd = strdup_x("XXXXXX");
133 break;
134 case 'd':
135 if (!amroot) goto bad_args;
136 local_flags |= LOCAL_DISABLE_USER;
137 new_passwd = strdup_x("XXXXXX");
138 break;
139 case 'e':
140 if (!amroot) goto bad_args;
141 local_flags |= LOCAL_ENABLE_USER;
142 break;
143 case 'm':
144 if (!amroot) goto bad_args;
145 local_flags |= LOCAL_TRUST_ACCOUNT;
146 break;
147 case 'n':
148 if (!amroot) goto bad_args;
149 local_flags |= LOCAL_SET_NO_PASSWORD;
150 new_passwd = strdup_x("NO PASSWORD");
151 break;
152 case 'j':
153 if (!amroot) goto bad_args;
154 new_domain = optarg;
155 strupper(new_domain);
156 joining_domain = True;
157 break;
158 case 'r':
159 remote_machine = optarg;
160 break;
161 case 'S':
162 if (!amroot) goto bad_args;
163 local_flags |= LOCAL_GET_DOM_SID;
164 break;
165 case 's':
166 set_line_buffering(stdin);
167 set_line_buffering(stdout);
168 set_line_buffering(stderr);
169 stdin_passwd_get = True;
170 break;
171 case 'w':
172 if (!amroot) goto bad_args;
173 #ifdef WITH_LDAP_SAM
174 local_flags |= LOCAL_SET_LDAP_ADMIN_PW;
175 fstrcpy(ldap_secret, optarg);
176 break;
177 #else
178 printf("-w not available unless configured --with-ldapsam\n");
179 goto bad_args;
180 #endif
181 case 'R':
182 if (!amroot) goto bad_args;
183 lp_set_name_resolve_order(optarg);
184 break;
185 case 'D':
186 DEBUGLEVEL = atoi(optarg);
187 break;
188 case 'U': {
189 char *lp;
191 got_username = True;
192 fstrcpy(user_name, optarg);
194 if ((lp = strchr(user_name, '%'))) {
195 *lp = 0;
196 fstrcpy(user_password, lp + 1);
197 got_pass = True;
198 memset(strchr(optarg, '%') + 1, 'X',
199 strlen(user_password));
202 break;
204 case 'h':
205 default:
206 bad_args:
207 usage();
211 argc -= optind;
212 argv += optind;
214 if (joining_domain && (argc != 0))
215 usage();
217 switch(argc) {
218 case 0:
219 if (!got_username)
220 fstrcpy(user_name, "");
221 break;
222 case 1:
223 if (!amroot == 1) {
224 new_passwd = argv[0];
225 break;
227 if (got_username)
228 usage();
229 fstrcpy(user_name, argv[0]);
230 break;
231 case 2:
232 if (!amroot || got_username || got_pass)
233 usage();
234 fstrcpy(user_name, argv[0]);
235 new_passwd = strdup_x(argv[1]);
236 break;
237 default:
238 usage();
243 /* Initialise client credentials for authenticated pipe access */
245 void init_rpcclient_creds(struct ntuser_creds *creds, char* username,
246 char* domain, char* password)
248 ZERO_STRUCTP(creds);
250 if (lp_encrypted_passwords()) {
251 pwd_make_lm_nt_16(&creds->pwd, password);
252 } else {
253 pwd_set_cleartext(&creds->pwd, password);
256 fstrcpy(creds->user_name, username);
257 fstrcpy(creds->domain, domain);
260 /*********************************************************
261 Join a domain using the administrator username and password
262 **********************************************************/
264 /* Macro for checking RPC error codes to make things more readable */
266 #define CHECK_RPC_ERR(rpc, msg) \
267 if (!NT_STATUS_IS_OK(result = rpc)) { \
268 DEBUG(0, (msg ": %s\n", get_nt_error_msg(result))); \
269 goto done; \
272 #define CHECK_RPC_ERR_DEBUG(rpc, debug_args) \
273 if (!NT_STATUS_IS_OK(result = rpc)) { \
274 DEBUG(0, debug_args); \
275 goto done; \
278 static int join_domain_byuser(char *domain, char *remote,
279 char *username, char *password)
281 /* libsmb variables */
283 pstring pdc_name;
284 struct nmb_name calling, called;
285 struct ntuser_creds creds;
286 struct cli_state cli;
287 fstring acct_name;
288 struct in_addr dest_ip;
289 TALLOC_CTX *mem_ctx;
291 /* rpc variables */
293 POLICY_HND lsa_pol, sam_pol, domain_pol, user_pol;
294 DOM_SID domain_sid;
295 uint32 user_rid;
297 /* Password stuff */
299 char *machine_pwd;
300 int plen = 0;
301 uchar pwbuf[516], ntpw[16], sess_key[16];
302 SAM_USERINFO_CTR ctr;
303 SAM_USER_INFO_24 p24;
304 SAM_USER_INFO_10 p10;
306 /* Misc */
308 NTSTATUS result;
309 int retval = 1;
311 pstrcpy(pdc_name, remote ? remote : "");
313 /* Connect to remote machine */
315 ZERO_STRUCT(cli);
316 ZERO_STRUCT(creds);
317 ZERO_STRUCT(dest_ip); /* Make sure no nasty surprises */
319 if (!(mem_ctx = talloc_init())) {
320 DEBUG(0, ("Could not initialise talloc context\n"));
321 goto done;
324 if (!cli_initialise(&cli)) {
325 DEBUG(0, ("Could not initialise client structure\n"));
326 goto done;
329 init_rpcclient_creds(&creds, username, domain, password);
330 cli_init_creds(&cli, &creds);
333 * If we are given a remote machine assume this is the PDC.
336 if(remote == NULL || !strcmp(remote, "*")) {
337 struct in_addr *ip_list;
338 int addr_count;
339 if (!get_dc_list(True /* PDC only*/, domain, &ip_list, &addr_count)) {
340 fprintf(stderr, "Unable to find the domain controller for domain %s.\n", domain);
341 return 1;
343 if ((addr_count < 1) || (is_zero_ip(ip_list[0]))) {
344 fprintf(stderr, "Incorrect entries returned when finding the domain controller for domain %s.\n", domain);
345 return 1;
348 if (!lookup_dc_name(global_myname, domain, &ip_list[0], pdc_name)) {
349 fprintf(stderr, "Unable to lookup the name for the domain controller for domain %s.\n", domain);
350 return 1;
352 dest_ip = ip_list[0];
355 make_nmb_name(&called, pdc_name, 0x20);
356 make_nmb_name(&calling, dns_to_netbios_name(global_myname), 0);
358 if (!cli_establish_connection(&cli, pdc_name, &dest_ip, &calling,
359 &called, "IPC$", "IPC", False, True)) {
360 if (!NT_STATUS_IS_OK(cli_nt_error(&cli))) {
361 DEBUG(0, ("Error connecting to %s - %s\n", pdc_name,cli_errstr(&cli)));
362 } else {
363 DEBUG(0, ("Error connecting to %s\n", pdc_name));
365 goto done;
368 /* Fetch domain sid */
370 if (!cli_nt_session_open(&cli, PIPE_LSARPC)) {
371 DEBUG(0, ("Error connecting to SAM pipe\n"));
372 goto done;
376 CHECK_RPC_ERR(cli_lsa_open_policy(&cli, mem_ctx, True,
377 SEC_RIGHTS_MAXIMUM_ALLOWED,
378 &lsa_pol),
379 "error opening lsa policy handle");
381 CHECK_RPC_ERR(cli_lsa_query_info_policy(&cli, mem_ctx, &lsa_pol,
382 5, domain, &domain_sid),
383 "error querying info policy");
385 cli_lsa_close(&cli, mem_ctx, &lsa_pol);
387 cli_nt_session_close(&cli); /* Done with this pipe */
389 /* Create domain user */
391 if (!cli_nt_session_open(&cli, PIPE_SAMR)) {
392 DEBUG(0, ("Error connecting to SAM pipe\n"));
393 goto done;
396 CHECK_RPC_ERR(cli_samr_connect(&cli, mem_ctx,
397 SEC_RIGHTS_MAXIMUM_ALLOWED,
398 &sam_pol),
399 "could not connect to SAM database");
402 CHECK_RPC_ERR(cli_samr_open_domain(&cli, mem_ctx, &sam_pol,
403 SEC_RIGHTS_MAXIMUM_ALLOWED,
404 &domain_sid, &domain_pol),
405 "could not open domain");
407 /* Create domain user */
409 fstrcpy(acct_name, global_myname);
410 fstrcat(acct_name, "$");
412 strlower(acct_name);
415 uint32 unknown = 0xe005000b;
417 result = cli_samr_create_dom_user(&cli, mem_ctx, &domain_pol,
418 acct_name, ACB_WSTRUST,
419 unknown, &user_pol,
420 &user_rid);
424 if (NT_STATUS_IS_OK(result)) {
426 /* We *must* do this.... don't ask... */
428 CHECK_RPC_ERR_DEBUG(cli_samr_close(&cli, mem_ctx, &user_pol), ("error closing user policy"));
429 result = NT_STATUS_USER_EXISTS;
432 if (NT_STATUS_V(result) == NT_STATUS_V(NT_STATUS_USER_EXISTS)) {
433 uint32 num_rids, *name_types, *user_rids;
434 uint32 flags = 0x3e8;
435 char *names;
437 /* Look up existing rid */
439 names = (char *)&acct_name[0];
441 CHECK_RPC_ERR_DEBUG(
442 cli_samr_lookup_names(&cli, mem_ctx,
443 &domain_pol, flags,
444 1, &names, &num_rids,
445 &user_rids, &name_types),
446 ("error looking up rid for user %s: %s\n",
447 acct_name, get_nt_error_msg(result)));
449 if (name_types[0] != SID_NAME_USER) {
450 DEBUG(0, ("%s is not a user account\n", acct_name));
451 goto done;
454 user_rid = user_rids[0];
456 /* Open handle on user */
458 CHECK_RPC_ERR_DEBUG(
459 cli_samr_open_user(&cli, mem_ctx, &domain_pol,
460 SEC_RIGHTS_MAXIMUM_ALLOWED,
461 user_rid, &user_pol),
462 ("could not re-open existing user %s: %s\n",
463 acct_name, get_nt_error_msg(result)));
465 } else if (!NT_STATUS_IS_OK(result)) {
466 DEBUG(0, ("error creating domain user: %s\n",
467 get_nt_error_msg(result)));
468 goto done;
471 /* Create a random machine account password */
474 UNISTR2 upw; /* Unicode password */
476 upw.buffer = (uint16 *)talloc_zero(mem_ctx, 0xc *
477 sizeof(uint16));
479 upw.uni_str_len = 0xc;
480 upw.uni_max_len = 0xc;
482 machine_pwd = (char *)upw.buffer;
483 plen = upw.uni_str_len * 2;
484 generate_random_buffer((unsigned char *)machine_pwd, plen, True);
486 encode_pw_buffer((char *)pwbuf, machine_pwd, plen, False);
488 mdfour( ntpw, (unsigned char *)upw.buffer, plen);
491 /* Set password on machine account */
493 ZERO_STRUCT(ctr);
494 ZERO_STRUCT(p24);
496 init_sam_user_info24(&p24, (char *)pwbuf,24);
498 ctr.switch_value = 24;
499 ctr.info.id24 = &p24;
501 /* I don't think this is quite the right place for this
502 calculation. It should be moved somewhere where the credentials
503 are calculated. )-: */
505 mdfour(sess_key, cli.pwd.smb_nt_pwd, 16);
507 CHECK_RPC_ERR(cli_samr_set_userinfo(&cli, mem_ctx, &user_pol, 24,
508 sess_key, &ctr),
509 "error setting trust account password");
511 /* Why do we have to try to (re-)set the ACB to be the same as what
512 we passed in the samr_create_dom_user() call? When a NT
513 workstation is joined to a domain by an administrator the
514 acb_info is set to 0x80. For a normal user with "Add
515 workstations to the domain" rights the acb_info is 0x84. I'm
516 not sure whether it is supposed to make a difference or not. NT
517 seems to cope with either value so don't bomb out if the set
518 userinfo2 level 0x10 fails. -tpot */
520 ZERO_STRUCT(ctr);
521 ctr.switch_value = 0x10;
522 ctr.info.id10 = &p10;
524 init_sam_user_info10(&p10, ACB_WSTRUST);
526 /* Ignoring the return value is necessary for joining a domain
527 as a normal user with "Add workstation to domain" privilege. */
529 result = cli_samr_set_userinfo2(&cli, mem_ctx, &user_pol, 0x10,
530 sess_key, &ctr);
532 /* Now store the secret in the secrets database */
534 strupper(domain);
536 if (!secrets_store_domain_sid(domain, &domain_sid) ||
537 !secrets_store_trust_account_password(domain, ntpw)) {
538 DEBUG(0, ("error storing domain secrets\n"));
539 goto done;
542 retval = 0; /* Success! */
544 done:
545 /* Close down pipe - this will clean up open policy handles */
547 if (cli.nt_pipe_fnum)
548 cli_nt_session_close(&cli);
550 /* Display success or failure */
552 if (retval != 0) {
553 trust_password_delete(domain);
554 fprintf(stderr,"Unable to join domain %s.\n",domain);
555 } else {
556 printf("Joined domain %s.\n",domain);
559 return retval;
562 /*********************************************************
563 Join a domain. Old server manager method.
564 **********************************************************/
566 static int join_domain(char *domain, char *remote)
568 pstring pdc_name;
569 fstring trust_passwd;
570 unsigned char orig_trust_passwd_hash[16];
571 DOM_SID domain_sid;
572 BOOL ret;
574 pstrcpy(pdc_name, remote ? remote : "");
575 fstrcpy(trust_passwd, global_myname);
576 strlower(trust_passwd);
579 * Machine names can be 15 characters, but the max length on
580 * a password is 14. --jerry
582 trust_passwd[14] = '\0';
584 E_md4hash( (uchar *)trust_passwd, orig_trust_passwd_hash);
586 /* Ensure that we are not trying to join a
587 domain if we are locally set up as a domain
588 controller. */
590 if(strequal(remote, global_myname)) {
591 fprintf(stderr, "Cannot join domain %s as the domain controller name is our own. We cannot be a domain controller for a domain and also be a domain member.\n", domain);
592 return 1;
596 * Write the old machine account password.
599 if(!secrets_store_trust_account_password(domain, orig_trust_passwd_hash)) {
600 fprintf(stderr, "Unable to write the machine account password for \
601 machine %s in domain %s.\n", global_myname, domain);
602 return 1;
606 * If we are given a remote machine assume this is the PDC.
609 if(remote == NULL || !strcmp(remote, "*")) {
610 struct in_addr *ip_list = NULL;
611 int addr_count;
612 if (!get_dc_list(True /* PDC only*/, domain, &ip_list, &addr_count)) {
613 fprintf(stderr, "Unable to find the domain controller for domain %s.\n", domain);
614 return 1;
616 if ((addr_count < 1) || (is_zero_ip(ip_list[0]))) {
617 fprintf(stderr, "Incorrect entries returned when finding the domain controller for domain %s.\n", domain);
618 return 1;
621 if (!lookup_dc_name(global_myname, domain, &ip_list[0], pdc_name)) {
622 fprintf(stderr, "Unable to lookup the name for the domain controller for domain %s.\n", domain);
623 return 1;
627 if (!fetch_domain_sid( domain, pdc_name, &domain_sid) ||
628 !secrets_store_domain_sid(domain, &domain_sid)) {
629 fprintf(stderr,"Failed to get domain SID. Unable to join domain %s.\n",domain);
630 return 1;
633 ret = change_trust_account_password( domain, pdc_name);
635 if(!ret) {
636 trust_password_delete(domain);
637 fprintf(stderr,"Unable to join domain %s.\n",domain);
638 return 1;
639 } else {
640 printf("Joined domain %s.\n",domain);
643 return 0;
646 static int set_domain_sid_from_dc( char *domain, char *remote )
648 pstring pdc_name;
649 DOM_SID domain_sid;
650 fstring sid_str;
652 pstrcpy(pdc_name, remote ? remote : "");
654 if(strequal(pdc_name, global_myname)) {
655 fprintf(stderr, "Cannot fetch domain sid for %s as the domain controller name is our own.\n", domain);
656 return 1;
659 if(remote == NULL || !strcmp(remote, "*")) {
660 struct in_addr *ip_list = NULL;
661 int addr_count;
662 if (!get_dc_list(False , domain, &ip_list, &addr_count)) {
663 fprintf(stderr, "Unable to find the domain controller for domain %s.\n", domain);
664 return 1;
666 if ((addr_count < 1) || (is_zero_ip(ip_list[0]))) {
667 fprintf(stderr, "Incorrect entries returned when finding the domain controller for domain %s.\n", domain);
668 return 1;
671 if (!lookup_dc_name(global_myname, domain, &ip_list[0], pdc_name)) {
672 fprintf(stderr, "Unable to lookup the name for the domain controller for domain %s.\n", domain);
673 return 1;
677 if (!fetch_domain_sid( domain, pdc_name, &domain_sid)
678 || !secrets_store_domain_sid(global_myname, &domain_sid))
680 fprintf(stderr,"Failed to get domain SID for %s.\n",domain);
681 return 1;
684 sid_to_string(sid_str, &domain_sid);
685 printf("Successfully set domain SID to %s.\n", sid_str);
687 return 0;
691 /*************************************************************
692 Utility function to prompt for passwords from stdin. Each
693 password entered must end with a newline.
694 *************************************************************/
695 static char *stdin_new_passwd(void)
697 static fstring new_passwd;
698 size_t len;
700 ZERO_ARRAY(new_passwd);
703 * if no error is reported from fgets() and string at least contains
704 * the newline that ends the password, then replace the newline with
705 * a null terminator.
707 if ( fgets(new_passwd, sizeof(new_passwd), stdin) != NULL) {
708 if ((len = strlen(new_passwd)) > 0) {
709 if(new_passwd[len-1] == '\n')
710 new_passwd[len - 1] = 0;
713 return(new_passwd);
717 /*************************************************************
718 Utility function to get passwords via tty or stdin
719 Used if the '-s' option is set to silently get passwords
720 to enable scripting.
721 *************************************************************/
722 static char *get_pass( char *prompt, BOOL stdin_get)
724 char *p;
725 if (stdin_get) {
726 p = stdin_new_passwd();
727 } else {
728 p = getpass(prompt);
730 return strdup_x(p);
733 /*************************************************************
734 Utility function to prompt for new password.
735 *************************************************************/
736 static char *prompt_for_new_password(BOOL stdin_get)
738 char *p;
739 fstring new_passwd;
741 ZERO_ARRAY(new_passwd);
743 p = get_pass("New SMB password:", stdin_get);
745 fstrcpy(new_passwd, p);
746 safe_free(p);
748 p = get_pass("Retype new SMB password:", stdin_get);
750 if (strcmp(p, new_passwd)) {
751 fprintf(stderr, "Mismatch - password unchanged.\n");
752 ZERO_ARRAY(new_passwd);
753 safe_free(p);
754 return NULL;
757 return p;
761 /*************************************************************
762 Change a password either locally or remotely.
763 *************************************************************/
765 static BOOL password_change(const char *remote_machine, char *user_name,
766 char *old_passwd, char *new_passwd, int local_flags)
768 BOOL ret;
769 pstring err_str;
770 pstring msg_str;
772 if (remote_machine != NULL) {
773 if (local_flags & (LOCAL_ADD_USER|LOCAL_DELETE_USER|LOCAL_DISABLE_USER|LOCAL_ENABLE_USER|
774 LOCAL_TRUST_ACCOUNT|LOCAL_SET_NO_PASSWORD)) {
775 /* these things can't be done remotely yet */
776 return False;
778 ret = remote_password_change(remote_machine, user_name,
779 old_passwd, new_passwd, err_str, sizeof(err_str));
780 if(*err_str)
781 fprintf(stderr, err_str);
782 return ret;
785 ret = local_password_change(user_name, local_flags, new_passwd,
786 err_str, sizeof(err_str), msg_str, sizeof(msg_str));
788 if(*msg_str)
789 printf(msg_str);
790 if(*err_str)
791 fprintf(stderr, err_str);
793 return ret;
796 #ifdef WITH_LDAP_SAM
797 /*******************************************************************
798 Store the LDAP admin password in secrets.tdb
799 ******************************************************************/
800 static BOOL store_ldap_admin_pw (char* pw)
802 if (!pw)
803 return False;
805 if (!secrets_init())
806 return False;
808 return secrets_store_ldap_pw(lp_ldap_admin_dn(), pw);
810 #endif
813 /*************************************************************
814 Handle password changing for root.
815 *************************************************************/
817 static int process_root(void)
819 struct passwd *pwd;
820 int result = 0;
822 #ifdef WITH_LDAP_SAM
823 if (local_flags & LOCAL_SET_LDAP_ADMIN_PW)
825 printf("Setting stored password for \"%s\" in secrets.tdb\n",
826 lp_ldap_admin_dn());
827 if (!store_ldap_admin_pw(ldap_secret))
828 DEBUG(0,("ERROR: Failed to store the ldap admin password!\n"));
829 goto done;
831 #endif
834 * Ensure both add/delete user are not set
835 * Ensure add/delete user and either remote machine or join domain are
836 * not both set.
838 if ( ((local_flags & (LOCAL_ADD_USER|LOCAL_DELETE_USER)) == (LOCAL_ADD_USER|LOCAL_DELETE_USER))
839 || ( (local_flags & (LOCAL_ADD_USER|LOCAL_DELETE_USER))
840 && ((remote_machine != NULL) || joining_domain) ) )
842 usage();
845 /* Only load interfaces if we are doing network operations. */
847 if ( joining_domain || remote_machine || (local_flags & LOCAL_GET_DOM_SID) ) {
848 load_interfaces();
851 /* Join a domain */
853 if (joining_domain) {
855 /* Are we joining by specifing an admin username and
856 password? */
858 if (user_name[0]) {
860 /* Get administrator password if not specified */
862 if (!got_pass) {
863 char *pass = getpass("Password: ");
865 if (pass)
866 pstrcpy(user_password, pass);
869 return join_domain_byuser(new_domain, remote_machine,
870 user_name, user_password);
871 } else {
873 /* Or just with the server manager? */
875 return join_domain(new_domain, remote_machine);
880 * get the domain sid from a PDC and store it in secrets.tdb
881 * Used for Samba PDC/BDC installations.
884 if (local_flags & LOCAL_GET_DOM_SID) {
885 return set_domain_sid_from_dc(lp_workgroup(), remote_machine);
889 * Deal with root - can add a user, but only locally.
892 if (!user_name[0] && (pwd = sys_getpwuid(0))) {
893 fstrcpy(user_name, pwd->pw_name);
896 if (!user_name[0]) {
897 fprintf(stderr,"You must specify a username\n");
898 exit(1);
901 if (local_flags & LOCAL_TRUST_ACCOUNT) {
902 /* add the $ automatically */
903 static fstring buf;
906 * Remove any trailing '$' before we
907 * generate the initial machine password.
910 if (user_name[strlen(user_name)-1] == '$') {
911 user_name[strlen(user_name)-1] = 0;
914 if (local_flags & LOCAL_ADD_USER) {
915 safe_free(new_passwd);
916 new_passwd = strdup_x(user_name);
917 strlower(new_passwd);
921 * Now ensure the username ends in '$' for
922 * the machine add.
925 slprintf(buf, sizeof(buf)-1, "%s$", user_name);
926 fstrcpy(user_name, buf);
929 if (remote_machine != NULL) {
930 old_passwd = get_pass("Old SMB password:",stdin_passwd_get);
933 if (!new_passwd) {
936 * If we are trying to enable a user, first we need to find out
937 * if they are using a modern version of the smbpasswd file that
938 * disables a user by just writing a flag into the file. If so
939 * then we can re-enable a user without prompting for a new
940 * password. If not (ie. they have a no stored password in the
941 * smbpasswd file) then we need to prompt for a new password.
944 if(local_flags & LOCAL_ENABLE_USER) {
946 SAM_ACCOUNT *sampass = NULL;
948 pdb_init_sam(&sampass);
949 if (!pdb_getsampwnam(sampass, user_name)) {
950 printf("ERROR: Unable to locate %s in passdb!\n", user_name);
951 pdb_free_sam(sampass);
952 result = 1;
953 goto done;
955 if((sampass != NULL) && (pdb_get_lanman_passwd(sampass) != NULL)) {
956 new_passwd = strdup_x("XXXX"); /* Don't care. */
959 pdb_free_sam(sampass);
962 if(!new_passwd)
963 new_passwd = prompt_for_new_password(stdin_passwd_get);
965 if(!new_passwd) {
966 fprintf(stderr, "Unable to get new password.\n");
967 exit(1);
971 if (!password_change(remote_machine, user_name, old_passwd, new_passwd, local_flags)) {
972 fprintf(stderr,"Failed to modify password entry for user %s\n", user_name);
973 result = 1;
974 goto done;
977 if(remote_machine) {
978 printf("Password changed for user %s on %s.\n", user_name, remote_machine );
979 } else if(!(local_flags & (LOCAL_ADD_USER|LOCAL_DISABLE_USER|LOCAL_ENABLE_USER|LOCAL_DELETE_USER|LOCAL_SET_NO_PASSWORD))) {
980 SAM_ACCOUNT *sampass = NULL;
981 uint16 acct_ctrl;
983 pdb_init_sam(&sampass);
985 if (!pdb_getsampwnam(sampass, user_name)) {
986 printf("ERROR: Unable to locate %s in passdb!\n", user_name);
987 pdb_free_sam(sampass);
988 result = 1;
989 goto done;
992 printf("Password changed for user %s.", user_name );
993 acct_ctrl = pdb_get_acct_ctrl(sampass);
994 if(acct_ctrl & ACB_DISABLED)
995 printf(" User has disabled flag set.");
996 if(acct_ctrl & ACB_PWNOTREQ)
997 printf(" User has no password flag set.");
998 printf("\n");
1000 pdb_free_sam(sampass);
1003 done:
1004 safe_free(new_passwd);
1005 return result;
1009 /*************************************************************
1010 Handle password changing for non-root.
1011 *************************************************************/
1013 static int process_nonroot(void)
1015 struct passwd *pwd = NULL;
1016 int result = 0;
1018 if (!user_name[0]) {
1019 pwd = sys_getpwuid(getuid());
1020 if (pwd) {
1021 fstrcpy(user_name,pwd->pw_name);
1022 } else {
1023 fprintf(stderr,"you don't exist - go away\n");
1024 exit(1);
1029 * A non-root user is always setting a password
1030 * via a remote machine (even if that machine is
1031 * localhost).
1034 load_interfaces(); /* Delayed from main() */
1036 if (remote_machine == NULL) {
1037 remote_machine = "127.0.0.1";
1040 if (remote_machine != NULL) {
1041 old_passwd = get_pass("Old SMB password:",stdin_passwd_get);
1044 if (!new_passwd) {
1045 new_passwd = prompt_for_new_password(stdin_passwd_get);
1048 if (!new_passwd) {
1049 fprintf(stderr, "Unable to get new password.\n");
1050 exit(1);
1053 if (!password_change(remote_machine, user_name, old_passwd, new_passwd, 0)) {
1054 fprintf(stderr,"Failed to change password for %s\n", user_name);
1055 result = 1;
1056 goto done;
1059 printf("Password changed for user %s\n", user_name);
1061 done:
1062 safe_free(old_passwd);
1063 safe_free(new_passwd);
1065 return result;
1070 /*********************************************************
1071 Start here.
1072 **********************************************************/
1073 int main(int argc, char **argv)
1075 BOOL amroot = getuid() == 0;
1077 DEBUGLEVEL = 0;
1078 AllowDebugChange = False;
1080 #if defined(HAVE_SET_AUTH_PARAMETERS)
1081 set_auth_parameters(argc, argv);
1082 #endif /* HAVE_SET_AUTH_PARAMETERS */
1084 charset_initialise();
1086 process_options(argc, argv, amroot);
1087 TimeInit();
1089 setup_logging("smbpasswd", True);
1091 if(!initialize_password_db(False)) {
1092 fprintf(stderr, "Can't setup password database vectors.\n");
1093 exit(1);
1096 if (!lp_load(servicesf,True,False,False)) {
1097 fprintf(stderr, "Can't load %s - run testparm to debug it\n",
1098 servicesf);
1099 exit(1);
1103 * Set the machine NETBIOS name if not already
1104 * set from the config file.
1107 if (!*global_myname) {
1108 char *p;
1109 fstrcpy(global_myname, myhostname());
1110 p = strchr(global_myname, '.' );
1111 if (p) *p = 0;
1113 strupper(global_myname);
1115 codepage_initialise(lp_client_code_page());
1117 /* Check the effective uid - make sure we are not setuid */
1118 if ((geteuid() == (uid_t)0) && (getuid() != (uid_t)0)) {
1119 fprintf(stderr, "smbpasswd must *NOT* be setuid root.\n");
1120 exit(1);
1123 if (local_mode || amroot) {
1124 secrets_init();
1125 return process_root();
1128 return process_nonroot();