diff options
Diffstat (limited to 'source/utils/smbpasswd.c')
-rw-r--r-- | source/utils/smbpasswd.c | 854 |
1 files changed, 697 insertions, 157 deletions
diff --git a/source/utils/smbpasswd.c b/source/utils/smbpasswd.c index 75a4319cb96..df2d2d7ef6d 100644 --- a/source/utils/smbpasswd.c +++ b/source/utils/smbpasswd.c @@ -1,5 +1,8 @@ + /* - * Unix SMB/CIFS implementation. + * Unix SMB/Netbios implementation. + * Version 1.9. + * smbpasswd module. * Copyright (C) Jeremy Allison 1995-1998 * Copyright (C) Tim Potter 2001 * @@ -30,13 +33,37 @@ extern char *optarg; extern int optind; /* forced running in root-mode */ -static BOOL got_pass = False, got_username = False; +static BOOL local_mode; +static BOOL joining_domain = False, got_pass = False, got_username = False, changing_trust_pw = FALSE; +static int local_flags = 0; static BOOL stdin_passwd_get = False; static fstring user_name, user_password; +static char *new_domain = NULL; static char *new_passwd = NULL; +static char *old_passwd = NULL; static char *remote_machine = NULL; +static pstring servicesf = CONFIGFILE; +#ifdef WITH_LDAP_SAM static fstring ldap_secret; +#endif + + + +/********************************************************* + A strdup with exit +**********************************************************/ + +static char *strdup_x(const char *s) +{ + char *new_s = strdup(s); + if (!new_s) { + fprintf(stderr,"out of memory\n"); + exit(1); + } + return new_s; +} + /********************************************************* Print command usage on stderr and die. @@ -61,11 +88,15 @@ static void usage(void) printf(" -a add user\n"); printf(" -d disable user\n"); printf(" -e enable user\n"); - printf(" -i interdomain trust account\n"); printf(" -m machine trust account\n"); printf(" -n set no password\n"); +#ifdef WITH_LDAP_SAM printf(" -w ldap admin password\n"); +#endif printf(" -x delete user\n"); + printf(" -j DOMAIN join domain name\n"); + printf(" -t DOMAIN change trust account password on domain\n"); + printf(" -S DOMAIN Retrieve the domain SID for DOMAIN\n"); printf(" -R ORDER name resolve order\n"); exit(1); @@ -79,60 +110,66 @@ static void set_line_buffering(FILE *f) /******************************************************************* Process command line options ******************************************************************/ -static int process_options(int argc, char **argv, int local_flags) +static void process_options(int argc, char **argv, BOOL amroot) { int ch; - pstring configfile; - pstrcpy(configfile, dyn_CONFIGFILE); - - local_flags |= LOCAL_SET_PASSWORD; - - ZERO_STRUCT(user_name); - ZERO_STRUCT(user_password); user_name[0] = '\0'; - while ((ch = getopt(argc, argv, "c:axdehminjr:sw:R:D:U:L")) != EOF) { + while ((ch = getopt(argc, argv, "c:axdehmnj:t:r:sw:R:D:U:LS")) != EOF) { switch(ch) { case 'L': - local_flags |= LOCAL_AM_ROOT; + local_mode = amroot = True; break; case 'c': - pstrcpy(configfile,optarg); + pstrcpy(servicesf,optarg); break; case 'a': + if (!amroot) goto bad_args; local_flags |= LOCAL_ADD_USER; break; case 'x': + if (!amroot) goto bad_args; local_flags |= LOCAL_DELETE_USER; - local_flags &= ~LOCAL_SET_PASSWORD; + new_passwd = strdup_x("XXXXXX"); break; case 'd': + if (!amroot) goto bad_args; local_flags |= LOCAL_DISABLE_USER; - local_flags &= ~LOCAL_SET_PASSWORD; + new_passwd = strdup_x("XXXXXX"); break; case 'e': + if (!amroot) goto bad_args; local_flags |= LOCAL_ENABLE_USER; - local_flags &= ~LOCAL_SET_PASSWORD; break; case 'm': + if (!amroot) goto bad_args; local_flags |= LOCAL_TRUST_ACCOUNT; break; - case 'i': - local_flags |= LOCAL_INTERDOM_ACCOUNT; - break; - case 'j': - d_printf("See 'net rpc join' for this functionality\n"); - exit(1); - break; case 'n': + if (!amroot) goto bad_args; local_flags |= LOCAL_SET_NO_PASSWORD; - local_flags &= ~LOCAL_SET_PASSWORD; - new_passwd = smb_xstrdup("NO PASSWORD"); + new_passwd = strdup_x("NO PASSWORD"); break; + case 'j': + if (!amroot) goto bad_args; + new_domain = optarg; + strupper(new_domain); + joining_domain = True; + break; + case 't': + if (!amroot) goto bad_args; + new_domain = optarg; + strupper(new_domain); + changing_trust_pw = True; + break; case 'r': remote_machine = optarg; break; + case 'S': + if (!amroot) goto bad_args; + local_flags |= LOCAL_GET_DOM_SID; + break; case 's': set_line_buffering(stdin); set_line_buffering(stdout); @@ -140,10 +177,17 @@ static int process_options(int argc, char **argv, int local_flags) stdin_passwd_get = True; break; case 'w': + if (!amroot) goto bad_args; +#ifdef WITH_LDAP_SAM local_flags |= LOCAL_SET_LDAP_ADMIN_PW; fstrcpy(ldap_secret, optarg); break; +#else + printf("-w not available unless configured --with-ldapsam\n"); + goto bad_args; +#endif case 'R': + if (!amroot) goto bad_args; lp_set_name_resolve_order(optarg); break; case 'D': @@ -159,7 +203,7 @@ static int process_options(int argc, char **argv, int local_flags) *lp = 0; fstrcpy(user_password, lp + 1); got_pass = True; - memset(strchr_m(optarg, '%') + 1, 'X', + memset(strchr(optarg, '%') + 1, 'X', strlen(user_password)); } @@ -167,6 +211,7 @@ static int process_options(int argc, char **argv, int local_flags) } case 'h': default: +bad_args: usage(); } } @@ -174,41 +219,481 @@ static int process_options(int argc, char **argv, int local_flags) argc -= optind; argv += optind; + if (joining_domain && (argc != 0)) + usage(); + switch(argc) { case 0: if (!got_username) fstrcpy(user_name, ""); break; case 1: - if (!(local_flags & LOCAL_AM_ROOT)) { + if (!amroot == 1) { new_passwd = argv[0]; - } else { - if (got_username) { - usage(); - } else { - fstrcpy(user_name, argv[0]); - } + break; } + if (got_username) + usage(); + fstrcpy(user_name, argv[0]); break; case 2: - if (!(local_flags & LOCAL_AM_ROOT) || got_username || got_pass) { + if (!amroot || got_username || got_pass) usage(); - } - fstrcpy(user_name, argv[0]); - new_passwd = smb_xstrdup(argv[1]); + new_passwd = strdup_x(argv[1]); break; default: usage(); } - if (!lp_load(configfile,True,False,False)) { - fprintf(stderr, "Can't load %s - run testparm to debug it\n", - dyn_CONFIGFILE); - exit(1); +} + +/* Initialise client credentials for authenticated pipe access */ + +void init_rpcclient_creds(struct ntuser_creds *creds, char* username, + char* domain, char* password) +{ + ZERO_STRUCTP(creds); + + if (lp_encrypted_passwords()) { + pwd_make_lm_nt_16(&creds->pwd, password); + } else { + pwd_set_cleartext(&creds->pwd, password); } - return local_flags; + fstrcpy(creds->user_name, username); + fstrcpy(creds->domain, domain); +} + +/********************************************************* +Join a domain using the administrator username and password +**********************************************************/ + +/* Macro for checking RPC error codes to make things more readable */ + +#define CHECK_RPC_ERR(rpc, msg) \ + if (!NT_STATUS_IS_OK(result = rpc)) { \ + DEBUG(0, (msg ": %s\n", get_nt_error_msg(result))); \ + goto done; \ + } + +#define CHECK_RPC_ERR_DEBUG(rpc, debug_args) \ + if (!NT_STATUS_IS_OK(result = rpc)) { \ + DEBUG(0, debug_args); \ + goto done; \ + } + +static int join_domain_byuser(char *domain, char *remote, + char *username, char *password) +{ + /* libsmb variables */ + + pstring pdc_name; + struct nmb_name calling, called; + struct ntuser_creds creds; + struct cli_state cli; + fstring acct_name; + struct in_addr dest_ip; + TALLOC_CTX *mem_ctx; + + /* rpc variables */ + + POLICY_HND lsa_pol, sam_pol, domain_pol, user_pol; + DOM_SID domain_sid; + uint32 user_rid; + + /* Password stuff */ + + char *machine_pwd; + int plen = 0; + uchar pwbuf[516], ntpw[16], sess_key[16]; + SAM_USERINFO_CTR ctr; + SAM_USER_INFO_24 p24; + SAM_USER_INFO_10 p10; + + /* Misc */ + + NTSTATUS result; + int retval = 1; + + pstrcpy(pdc_name, remote ? remote : ""); + + /* Connect to remote machine */ + + ZERO_STRUCT(cli); + ZERO_STRUCT(creds); + ZERO_STRUCT(dest_ip); /* Make sure no nasty surprises */ + + if (!(mem_ctx = talloc_init())) { + DEBUG(0, ("Could not initialise talloc context\n")); + goto done; + } + + if (!cli_initialise(&cli)) { + DEBUG(0, ("Could not initialise client structure\n")); + goto done; + } + + init_rpcclient_creds(&creds, username, domain, password); + cli_init_creds(&cli, &creds); + + /* + * If we are given a remote machine assume this is the PDC. + */ + + if(remote == NULL || !strcmp(remote, "*")) { + struct in_addr *ip_list; + int addr_count; + if (!get_dc_list(True /* PDC only*/, domain, &ip_list, &addr_count)) { + fprintf(stderr, "Unable to find the domain controller for domain %s.\n", domain); + return 1; + } + if ((addr_count < 1) || (is_zero_ip(ip_list[0]))) { + fprintf(stderr, "Incorrect entries returned when finding the domain controller for domain %s.\n", domain); + return 1; + } + + if (!lookup_dc_name(global_myname, domain, &ip_list[0], pdc_name)) { + fprintf(stderr, "Unable to lookup the name for the domain controller for domain %s.\n", domain); + return 1; + } + dest_ip = ip_list[0]; + } + + make_nmb_name(&called, pdc_name, 0x20); + make_nmb_name(&calling, dns_to_netbios_name(global_myname), 0); + + if (!cli_establish_connection(&cli, pdc_name, &dest_ip, &calling, + &called, "IPC$", "IPC", False, True)) { + if (!NT_STATUS_IS_OK(cli_nt_error(&cli))) { + DEBUG(0, ("Error connecting to %s - %s\n", pdc_name,cli_errstr(&cli))); + } else { + DEBUG(0, ("Error connecting to %s\n", pdc_name)); + } + goto done; + } + + /* Fetch domain sid */ + + if (!cli_nt_session_open(&cli, PIPE_LSARPC)) { + DEBUG(0, ("Error connecting to SAM pipe\n")); + goto done; + } + + + CHECK_RPC_ERR(cli_lsa_open_policy(&cli, mem_ctx, True, + SEC_RIGHTS_MAXIMUM_ALLOWED, + &lsa_pol), + "error opening lsa policy handle"); + + CHECK_RPC_ERR(cli_lsa_query_info_policy(&cli, mem_ctx, &lsa_pol, + 5, domain, &domain_sid), + "error querying info policy"); + + cli_lsa_close(&cli, mem_ctx, &lsa_pol); + + cli_nt_session_close(&cli); /* Done with this pipe */ + + /* Create domain user */ + + if (!cli_nt_session_open(&cli, PIPE_SAMR)) { + DEBUG(0, ("Error connecting to SAM pipe\n")); + goto done; + } + + CHECK_RPC_ERR(cli_samr_connect(&cli, mem_ctx, + SEC_RIGHTS_MAXIMUM_ALLOWED, + &sam_pol), + "could not connect to SAM database"); + + + CHECK_RPC_ERR(cli_samr_open_domain(&cli, mem_ctx, &sam_pol, + SEC_RIGHTS_MAXIMUM_ALLOWED, + &domain_sid, &domain_pol), + "could not open domain"); + + /* Create domain user */ + + fstrcpy(acct_name, global_myname); + fstrcat(acct_name, "$"); + + strlower(acct_name); + + { + uint32 unknown = 0xe005000b; + + result = cli_samr_create_dom_user(&cli, mem_ctx, &domain_pol, + acct_name, ACB_WSTRUST, + unknown, &user_pol, + &user_rid); + } + + + if (NT_STATUS_IS_OK(result)) { + + /* We *must* do this.... don't ask... */ + + CHECK_RPC_ERR_DEBUG(cli_samr_close(&cli, mem_ctx, &user_pol), ("error closing user policy")); + result = NT_STATUS_USER_EXISTS; + } + + if (NT_STATUS_V(result) == NT_STATUS_V(NT_STATUS_USER_EXISTS)) { + uint32 num_rids, *name_types, *user_rids; + uint32 flags = 0x3e8; + char *names; + + /* Look up existing rid */ + + names = (char *)&acct_name[0]; + + CHECK_RPC_ERR_DEBUG( + cli_samr_lookup_names(&cli, mem_ctx, + &domain_pol, flags, + 1, &names, &num_rids, + &user_rids, &name_types), + ("error looking up rid for user %s: %s\n", + acct_name, get_nt_error_msg(result))); + + if (name_types[0] != SID_NAME_USER) { + DEBUG(0, ("%s is not a user account\n", acct_name)); + goto done; + } + + user_rid = user_rids[0]; + + /* Open handle on user */ + + CHECK_RPC_ERR_DEBUG( + cli_samr_open_user(&cli, mem_ctx, &domain_pol, + SEC_RIGHTS_MAXIMUM_ALLOWED, + user_rid, &user_pol), + ("could not re-open existing user %s: %s\n", + acct_name, get_nt_error_msg(result))); + + } else if (!NT_STATUS_IS_OK(result)) { + DEBUG(0, ("error creating domain user: %s\n", + get_nt_error_msg(result))); + goto done; + } + + /* Create a random machine account password */ + + { + UNISTR2 upw; /* Unicode password */ + + upw.buffer = (uint16 *)talloc_zero(mem_ctx, 0xc * + sizeof(uint16)); + + upw.uni_str_len = 0xc; + upw.uni_max_len = 0xc; + + machine_pwd = (char *)upw.buffer; + plen = upw.uni_str_len * 2; + generate_random_buffer((unsigned char *)machine_pwd, plen, True); + + encode_pw_buffer((char *)pwbuf, machine_pwd, plen, False); + + mdfour( ntpw, (unsigned char *)upw.buffer, plen); + } + + /* Set password on machine account */ + + ZERO_STRUCT(ctr); + ZERO_STRUCT(p24); + + init_sam_user_info24(&p24, (char *)pwbuf,24); + + ctr.switch_value = 24; + ctr.info.id24 = &p24; + + /* I don't think this is quite the right place for this + calculation. It should be moved somewhere where the credentials + are calculated. )-: */ + + mdfour(sess_key, cli.pwd.smb_nt_pwd, 16); + + CHECK_RPC_ERR(cli_samr_set_userinfo(&cli, mem_ctx, &user_pol, 24, + sess_key, &ctr), + "error setting trust account password"); + + /* Why do we have to try to (re-)set the ACB to be the same as what + we passed in the samr_create_dom_user() call? When a NT + workstation is joined to a domain by an administrator the + acb_info is set to 0x80. For a normal user with "Add + workstations to the domain" rights the acb_info is 0x84. I'm + not sure whether it is supposed to make a difference or not. NT + seems to cope with either value so don't bomb out if the set + userinfo2 level 0x10 fails. -tpot */ + + ZERO_STRUCT(ctr); + ctr.switch_value = 0x10; + ctr.info.id10 = &p10; + + init_sam_user_info10(&p10, ACB_WSTRUST); + + /* Ignoring the return value is necessary for joining a domain + as a normal user with "Add workstation to domain" privilege. */ + + result = cli_samr_set_userinfo2(&cli, mem_ctx, &user_pol, 0x10, + sess_key, &ctr); + + /* Now store the secret in the secrets database */ + + strupper(domain); + + if (!secrets_store_domain_sid(domain, &domain_sid) || + !secrets_store_trust_account_password(domain, ntpw)) { + DEBUG(0, ("error storing domain secrets\n")); + goto done; + } + + retval = 0; /* Success! */ + + done: + /* Close down pipe - this will clean up open policy handles */ + + if (cli.nt_pipe_fnum) + cli_nt_session_close(&cli); + + /* Display success or failure */ + + if (retval != 0) { + trust_password_delete(domain); + fprintf(stderr,"Unable to join domain %s.\n",domain); + } else { + printf("Joined domain %s.\n",domain); + } + + return retval; +} + +/********************************************************* +Join a domain. Old server manager method. +**********************************************************/ + +static int join_domain(char *domain, char *remote) +{ + pstring pdc_name; + fstring trust_passwd; + unsigned char orig_trust_passwd_hash[16]; + DOM_SID domain_sid; + BOOL ret; + + pstrcpy(pdc_name, remote ? remote : ""); + fstrcpy(trust_passwd, global_myname); + strlower(trust_passwd); + + /* + * Machine names can be 15 characters, but the max length on + * a password is 14. --jerry + */ + trust_passwd[14] = '\0'; + + E_md4hash( (uchar *)trust_passwd, orig_trust_passwd_hash); + + /* Ensure that we are not trying to join a + domain if we are locally set up as a domain + controller. */ + + if(strequal(remote, global_myname)) { + 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); + return 1; + } + + /* + * Write the old machine account password. + */ + + if(!secrets_store_trust_account_password(domain, orig_trust_passwd_hash)) { + fprintf(stderr, "Unable to write the machine account password for \ +machine %s in domain %s.\n", global_myname, domain); + return 1; + } + + /* + * If we are given a remote machine assume this is the PDC. + */ + + if(remote == NULL || !strcmp(remote, "*")) { + struct in_addr *ip_list = NULL; + int addr_count; + if (!get_dc_list(True /* PDC only*/, domain, &ip_list, &addr_count)) { + fprintf(stderr, "Unable to find the domain controller for domain %s.\n", domain); + return 1; + } + if ((addr_count < 1) || (is_zero_ip(ip_list[0]))) { + fprintf(stderr, "Incorrect entries returned when finding the domain controller for domain %s.\n", domain); + return 1; + } + + if (!lookup_dc_name(global_myname, domain, &ip_list[0], pdc_name)) { + fprintf(stderr, "Unable to lookup the name for the domain controller for domain %s.\n", domain); + return 1; + } + } + + if (!fetch_domain_sid( domain, pdc_name, &domain_sid) || + !secrets_store_domain_sid(domain, &domain_sid)) { + fprintf(stderr,"Failed to get domain SID. Unable to join domain %s.\n",domain); + return 1; + } + + ret = change_trust_account_password( domain, pdc_name); + + if(!ret) { + trust_password_delete(domain); + fprintf(stderr,"Unable to join domain %s.\n",domain); + return 1; + } else { + printf("Joined domain %s.\n",domain); + } + + return 0; +} + +static int set_domain_sid_from_dc( char *domain, char *remote ) +{ + pstring pdc_name; + DOM_SID domain_sid; + fstring sid_str; + + pstrcpy(pdc_name, remote ? remote : ""); + + if(strequal(pdc_name, global_myname)) { + fprintf(stderr, "Cannot fetch domain sid for %s as the domain controller name is our own.\n", domain); + return 1; + } + + if(remote == NULL || !strcmp(remote, "*")) { + struct in_addr *ip_list = NULL; + int addr_count; + if (!get_dc_list(False , domain, &ip_list, &addr_count)) { + fprintf(stderr, "Unable to find the domain controller for domain %s.\n", domain); + return 1; + } + if ((addr_count < 1) || (is_zero_ip(ip_list[0]))) { + fprintf(stderr, "Incorrect entries returned when finding the domain controller for domain %s.\n", domain); + return 1; + } + + if (!lookup_dc_name(global_myname, domain, &ip_list[0], pdc_name)) { + fprintf(stderr, "Unable to lookup the name for the domain controller for domain %s.\n", domain); + return 1; + } + } + + if (!fetch_domain_sid( domain, pdc_name, &domain_sid) + || !secrets_store_domain_sid(global_myname, &domain_sid)) + { + fprintf(stderr,"Failed to get domain SID for %s.\n",domain); + return 1; + } + + sid_to_string(sid_str, &domain_sid); + printf("Successfully set domain SID to %s.\n", sid_str); + + return 0; + } /************************************************************* @@ -217,23 +702,23 @@ static int process_options(int argc, char **argv, int local_flags) *************************************************************/ static char *stdin_new_passwd(void) { - static fstring new_pw; + static fstring new_passwd; size_t len; - ZERO_ARRAY(new_pw); + ZERO_ARRAY(new_passwd); /* * if no error is reported from fgets() and string at least contains * the newline that ends the password, then replace the newline with * a null terminator. */ - if ( fgets(new_pw, sizeof(new_pw), stdin) != NULL) { - if ((len = strlen(new_pw)) > 0) { - if(new_pw[len-1] == '\n') - new_pw[len - 1] = 0; + if ( fgets(new_passwd, sizeof(new_passwd), stdin) != NULL) { + if ((len = strlen(new_passwd)) > 0) { + if(new_passwd[len-1] == '\n') + new_passwd[len - 1] = 0; } } - return(new_pw); + return(new_passwd); } @@ -250,7 +735,7 @@ static char *get_pass( char *prompt, BOOL stdin_get) } else { p = getpass(prompt); } - return smb_xstrdup(p); + return strdup_x(p); } /************************************************************* @@ -259,21 +744,21 @@ static char *get_pass( char *prompt, BOOL stdin_get) static char *prompt_for_new_password(BOOL stdin_get) { char *p; - fstring new_pw; + fstring new_passwd; - ZERO_ARRAY(new_pw); + ZERO_ARRAY(new_passwd); p = get_pass("New SMB password:", stdin_get); - fstrcpy(new_pw, p); - SAFE_FREE(p); + fstrcpy(new_passwd, p); + safe_free(p); p = get_pass("Retype new SMB password:", stdin_get); - if (strcmp(p, new_pw)) { + if (strcmp(p, new_passwd)) { fprintf(stderr, "Mismatch - password unchanged.\n"); - ZERO_ARRAY(new_pw); - SAFE_FREE(p); + ZERO_ARRAY(new_passwd); + safe_free(p); return NULL; } @@ -285,27 +770,27 @@ static char *prompt_for_new_password(BOOL stdin_get) Change a password either locally or remotely. *************************************************************/ -static BOOL password_change(const char *remote_mach, char *username, - char *old_passwd, char *new_pw, int local_flags) +static BOOL password_change(const char *remote_machine, char *user_name, + char *old_passwd, char *new_passwd, int local_flags) { BOOL ret; pstring err_str; pstring msg_str; - if (remote_mach != NULL) { + if (remote_machine != NULL) { if (local_flags & (LOCAL_ADD_USER|LOCAL_DELETE_USER|LOCAL_DISABLE_USER|LOCAL_ENABLE_USER| LOCAL_TRUST_ACCOUNT|LOCAL_SET_NO_PASSWORD)) { /* these things can't be done remotely yet */ return False; } - ret = remote_password_change(remote_mach, username, - old_passwd, new_pw, err_str, sizeof(err_str)); + ret = remote_password_change(remote_machine, user_name, + old_passwd, new_passwd, err_str, sizeof(err_str)); if(*err_str) fprintf(stderr, err_str); return ret; } - ret = local_password_change(username, local_flags, new_pw, + ret = local_password_change(user_name, local_flags, new_passwd, err_str, sizeof(err_str), msg_str, sizeof(msg_str)); if(*msg_str) @@ -316,11 +801,12 @@ static BOOL password_change(const char *remote_mach, char *username, return ret; } +#ifdef WITH_LDAP_SAM /******************************************************************* Store the LDAP admin password in secrets.tdb ******************************************************************/ static BOOL store_ldap_admin_pw (char* pw) -{ +{ if (!pw) return False; @@ -329,18 +815,19 @@ static BOOL store_ldap_admin_pw (char* pw) return secrets_store_ldap_pw(lp_ldap_admin_dn(), pw); } +#endif /************************************************************* Handle password changing for root. *************************************************************/ -static int process_root(int local_flags) +static int process_root(void) { struct passwd *pwd; int result = 0; - char *old_passwd = NULL; +#ifdef WITH_LDAP_SAM if (local_flags & LOCAL_SET_LDAP_ADMIN_PW) { printf("Setting stored password for \"%s\" in secrets.tdb\n", @@ -349,27 +836,80 @@ static int process_root(int local_flags) DEBUG(0,("ERROR: Failed to store the ldap admin password!\n")); goto done; } +#endif /* * Ensure both add/delete user are not set * Ensure add/delete user and either remote machine or join domain are * not both set. */ - if(((local_flags & (LOCAL_ADD_USER|LOCAL_DELETE_USER)) == (LOCAL_ADD_USER|LOCAL_DELETE_USER)) || - ((local_flags & (LOCAL_ADD_USER|LOCAL_DELETE_USER)) && - (remote_machine != NULL))) { + if ( ((local_flags & (LOCAL_ADD_USER|LOCAL_DELETE_USER)) == (LOCAL_ADD_USER|LOCAL_DELETE_USER)) + || ( (local_flags & (LOCAL_ADD_USER|LOCAL_DELETE_USER)) + && ((remote_machine != NULL) || joining_domain || changing_trust_pw) ) ) + { usage(); } /* Only load interfaces if we are doing network operations. */ - if (remote_machine) { + if ( joining_domain || remote_machine || (local_flags & LOCAL_GET_DOM_SID) ) { load_interfaces(); } - if (!user_name[0] && (pwd = getpwuid_alloc(geteuid()))) { + /* Join a domain */ + + if (joining_domain) { + + /* Are we joining by specifing an admin username and + password? */ + + if (user_name[0]) { + + /* Get administrator password if not specified */ + + if (!got_pass) { + char *pass = getpass("Password: "); + + if (pass) + pstrcpy(user_password, pass); + } + + return join_domain_byuser(new_domain, remote_machine, + user_name, user_password); + } else { + + /* Or just with the server manager? */ + + return join_domain(new_domain, remote_machine); + } + } + + + /* Change Trust Password */ + + if (changing_trust_pw) { + if (change_trust_account_password(new_domain, remote_machine)) { + return 0; + } + return 1; + } + + + /* + * get the domain sid from a PDC and store it in secrets.tdb + * Used for Samba PDC/BDC installations. + */ + + if (local_flags & LOCAL_GET_DOM_SID) { + return set_domain_sid_from_dc(lp_workgroup(), remote_machine); + } + + /* + * Deal with root - can add a user, but only locally. + */ + + if (!user_name[0] && (pwd = sys_getpwuid(0))) { fstrcpy(user_name, pwd->pw_name); - passwd_free(&pwd); } if (!user_name[0]) { @@ -391,8 +931,8 @@ static int process_root(int local_flags) } if (local_flags & LOCAL_ADD_USER) { - SAFE_FREE(new_passwd); - new_passwd = smb_xstrdup(user_name); + safe_free(new_passwd); + new_passwd = strdup_x(user_name); strlower(new_passwd); } @@ -403,64 +943,50 @@ static int process_root(int local_flags) slprintf(buf, sizeof(buf)-1, "%s$", user_name); fstrcpy(user_name, buf); - } else if (local_flags & LOCAL_INTERDOM_ACCOUNT) { - static fstring buf; + } - if (local_flags & LOCAL_ADD_USER) { - /* - * Prompt for trusting domain's account password - */ - new_passwd = prompt_for_new_password(stdin_passwd_get); - if(!new_passwd) { - fprintf(stderr, "Unable to get newpassword.\n"); - exit(1); - } - } - - /* prepare uppercased and '$' terminated username */ - slprintf(buf, sizeof(buf) - 1, "%s$", user_name); - fstrcpy(user_name, buf); - - } else { - - if (remote_machine != NULL) { - old_passwd = get_pass("Old SMB password:",stdin_passwd_get); - } - - if (!(local_flags & LOCAL_SET_PASSWORD)) { + if (remote_machine != NULL) { + old_passwd = get_pass("Old SMB password:",stdin_passwd_get); + } + + if (!new_passwd) { + + /* + * If we are trying to enable a user, first we need to find out + * if they are using a modern version of the smbpasswd file that + * disables a user by just writing a flag into the file. If so + * then we can re-enable a user without prompting for a new + * password. If not (ie. they have a no stored password in the + * smbpasswd file) then we need to prompt for a new password. + */ + + if(local_flags & LOCAL_ENABLE_USER) { - /* - * If we are trying to enable a user, first we need to find out - * if they are using a modern version of the smbpasswd file that - * disables a user by just writing a flag into the file. If so - * then we can re-enable a user without prompting for a new - * password. If not (ie. they have a no stored password in the - * smbpasswd file) then we need to prompt for a new password. - */ + SAM_ACCOUNT *sampass = NULL; - if(local_flags & LOCAL_ENABLE_USER) { - SAM_ACCOUNT *sampass = NULL; - BOOL ret; - - pdb_init_sam(&sampass); - ret = pdb_getsampwnam(sampass, user_name); - if((sampass != False) && (pdb_get_lanman_passwd(sampass) == NULL)) { - local_flags |= LOCAL_SET_PASSWORD; - } - pdb_free_sam(&sampass); + pdb_init_sam(&sampass); + if (!pdb_getsampwnam(sampass, user_name)) { + printf("ERROR: Unable to locate %s in passdb!\n", user_name); + pdb_free_sam(sampass); + result = 1; + goto done; + } + if((sampass != NULL) && (pdb_get_lanman_passwd(sampass) != NULL)) { + new_passwd = strdup_x("XXXX"); /* Don't care. */ } + + pdb_free_sam(sampass); } - - if(local_flags & LOCAL_SET_PASSWORD) { + + if(!new_passwd) new_passwd = prompt_for_new_password(stdin_passwd_get); - - if(!new_passwd) { - fprintf(stderr, "Unable to get new password.\n"); - exit(1); - } + + if(!new_passwd) { + fprintf(stderr, "Unable to get new password.\n"); + exit(1); } } - + if (!password_change(remote_machine, user_name, old_passwd, new_passwd, local_flags)) { fprintf(stderr,"Failed to modify password entry for user %s\n", user_name); result = 1; @@ -469,24 +995,32 @@ static int process_root(int local_flags) if(remote_machine) { printf("Password changed for user %s on %s.\n", user_name, remote_machine ); - } else if(!(local_flags & (LOCAL_ADD_USER|LOCAL_DISABLE_USER|LOCAL_ENABLE_USER|LOCAL_DELETE_USER|LOCAL_SET_NO_PASSWORD|LOCAL_SET_PASSWORD))) { + } else if(!(local_flags & (LOCAL_ADD_USER|LOCAL_DISABLE_USER|LOCAL_ENABLE_USER|LOCAL_DELETE_USER|LOCAL_SET_NO_PASSWORD))) { SAM_ACCOUNT *sampass = NULL; - BOOL ret; + uint16 acct_ctrl; pdb_init_sam(&sampass); - ret = pdb_getsampwnam(sampass, user_name); - + + if (!pdb_getsampwnam(sampass, user_name)) { + printf("ERROR: Unable to locate %s in passdb!\n", user_name); + pdb_free_sam(sampass); + result = 1; + goto done; + } + printf("Password changed for user %s.", user_name ); - if( (ret != False) && (pdb_get_acct_ctrl(sampass)&ACB_DISABLED) ) + acct_ctrl = pdb_get_acct_ctrl(sampass); + if(acct_ctrl & ACB_DISABLED) printf(" User has disabled flag set."); - if((ret != False) && (pdb_get_acct_ctrl(sampass) & ACB_PWNOTREQ) ) + if(acct_ctrl & ACB_PWNOTREQ) printf(" User has no password flag set."); printf("\n"); - pdb_free_sam(&sampass); + + pdb_free_sam(sampass); } done: - SAFE_FREE(new_passwd); + safe_free(new_passwd); return result; } @@ -495,24 +1029,17 @@ static int process_root(int local_flags) Handle password changing for non-root. *************************************************************/ -static int process_nonroot(int local_flags) +static int process_nonroot(void) { struct passwd *pwd = NULL; int result = 0; - char *old_passwd = NULL; - - if (local_flags & ~(LOCAL_AM_ROOT | LOCAL_SET_PASSWORD)) { - /* Extra flags that we can't honor non-root */ - usage(); - } if (!user_name[0]) { - pwd = getpwuid_alloc(getuid()); + pwd = sys_getpwuid(getuid()); if (pwd) { fstrcpy(user_name,pwd->pw_name); - passwd_free(&pwd); } else { - fprintf(stderr, "smbpasswd: you don't exist - go away\n"); + fprintf(stderr,"you don't exist - go away\n"); exit(1); } } @@ -551,8 +1078,8 @@ static int process_nonroot(int local_flags) printf("Password changed for user %s\n", user_name); done: - SAFE_FREE(old_passwd); - SAFE_FREE(new_passwd); + safe_free(old_passwd); + safe_free(new_passwd); return result; } @@ -564,22 +1091,33 @@ static int process_nonroot(int local_flags) **********************************************************/ int main(int argc, char **argv) { - int local_flags = 0; - + BOOL amroot = getuid() == 0; + + DEBUGLEVEL = 0; AllowDebugChange = False; #if defined(HAVE_SET_AUTH_PARAMETERS) set_auth_parameters(argc, argv); #endif /* HAVE_SET_AUTH_PARAMETERS */ - if (getuid() == 0) { - local_flags = LOCAL_AM_ROOT; + charset_initialise(); + + process_options(argc, argv, amroot); + TimeInit(); + + setup_logging("smbpasswd", True); + + if(!initialize_password_db(False)) { + fprintf(stderr, "Can't setup password database vectors.\n"); + exit(1); } - local_flags = process_options(argc, argv, local_flags); + if (!lp_load(servicesf,True,False,False)) { + fprintf(stderr, "Can't load %s - run testparm to debug it\n", + servicesf); + exit(1); + } - setup_logging("smbpasswd", True); - /* * Set the machine NETBIOS name if not already * set from the config file. @@ -588,21 +1126,23 @@ int main(int argc, char **argv) if (!*global_myname) { char *p; fstrcpy(global_myname, myhostname()); - p = strchr_m(global_myname, '.' ); + p = strchr(global_myname, '.' ); if (p) *p = 0; } strupper(global_myname); + codepage_initialise(lp_client_code_page()); + /* Check the effective uid - make sure we are not setuid */ - if (is_setuid_root()) { + if ((geteuid() == (uid_t)0) && (getuid() != (uid_t)0)) { fprintf(stderr, "smbpasswd must *NOT* be setuid root.\n"); exit(1); } - if (local_flags & LOCAL_AM_ROOT) { + if (local_mode || amroot) { secrets_init(); - return process_root(local_flags); + return process_root(); } - return process_nonroot(local_flags); + return process_nonroot(); } |