diff options
Diffstat (limited to 'source/utils/smbpasswd.c')
-rw-r--r-- | source/utils/smbpasswd.c | 463 |
1 files changed, 244 insertions, 219 deletions
diff --git a/source/utils/smbpasswd.c b/source/utils/smbpasswd.c index 24185114f13..5bd8b421b1d 100644 --- a/source/utils/smbpasswd.c +++ b/source/utils/smbpasswd.c @@ -33,6 +33,21 @@ extern int optind; /* forced running in root-mode */ static BOOL local_mode; +static BOOL joining_domain = False, got_pass = False, got_username = 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 @@ -54,34 +69,172 @@ static char *strdup_x(const char *s) **********************************************************/ static void usage(void) { - if (getuid() == 0) { - printf("smbpasswd [options] [username] [password]\n"); - } else { - printf("smbpasswd [options] [password]\n"); - } + printf("When run by root:\n"); + printf(" smbpasswd [options] [username] [password]\n"); + printf("otherwise:\n"); + printf(" smbpasswd [options] [password]\n\n"); + printf("options:\n"); + printf(" -L local mode (must be first option)\n"); + printf(" -h print this usage message\n"); printf(" -s use stdin for password prompt\n"); + printf(" -c smb.conf file Use the given path to the smb.conf file\n"); printf(" -D LEVEL debug level\n"); - printf(" -U USER remote username\n"); printf(" -r MACHINE remote machine\n"); + printf(" -U USER remote username\n"); - if (getuid() == 0 || local_mode) { - printf(" -L local mode (must be first option)\n"); - printf(" -R ORDER name resolve order\n"); - printf(" -j DOMAIN join domain name\n"); - printf(" -a add user\n"); - printf(" -x delete user\n"); - printf(" -d disable user\n"); - printf(" -e enable user\n"); - printf(" -n set no password\n"); - printf(" -m machine trust account\n"); + printf("extra options when run by root or in local mode:\n"); + printf(" -a add user\n"); + printf(" -d disable user\n"); + printf(" -e enable user\n"); + printf(" -m machine trust account\n"); + printf(" -n set no password\n"); #ifdef WITH_LDAP_SAM - printf(" -w ldap admin password\n"); + printf(" -w ldap admin password\n"); #endif - } + printf(" -x delete user\n"); + printf(" -j DOMAIN join domain name\n"); + printf(" -R ORDER name resolve order\n"); + exit(1); } +static void set_line_buffering(FILE *f) +{ + setvbuf(f, NULL, _IOLBF, 0); +} + +/******************************************************************* + Process command line options + ******************************************************************/ +static void process_options(int argc, char **argv, BOOL amroot) +{ + int ch; + + user_name[0] = '\0'; + + while ((ch = getopt(argc, argv, "c:axdehmnj:r:sw:R:D:U:L")) != EOF) { + switch(ch) { + case 'L': + local_mode = amroot = True; + break; + case 'c': + 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; + new_passwd = strdup_x("XXXXXX"); + break; + case 'd': + if (!amroot) goto bad_args; + local_flags |= LOCAL_DISABLE_USER; + new_passwd = strdup_x("XXXXXX"); + break; + case 'e': + if (!amroot) goto bad_args; + local_flags |= LOCAL_ENABLE_USER; + break; + case 'm': + if (!amroot) goto bad_args; + local_flags |= LOCAL_TRUST_ACCOUNT; + break; + case 'n': + if (!amroot) goto bad_args; + local_flags |= LOCAL_SET_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 'r': + remote_machine = optarg; + break; + case 's': + set_line_buffering(stdin); + set_line_buffering(stdout); + set_line_buffering(stderr); + 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-ldap\n"); + goto bad_args; +#endif + case 'R': + if (!amroot) goto bad_args; + lp_set_name_resolve_order(optarg); + break; + case 'D': + DEBUGLEVEL = atoi(optarg); + break; + case 'U': { + char *lp; + + got_username = True; + fstrcpy(user_name, optarg); + + if ((lp = strchr(user_name, '%'))) { + *lp = 0; + fstrcpy(user_password, lp + 1); + got_pass = True; + memset(strchr(optarg, '%') + 1, 'X', + strlen(user_password)); + } + + break; + } + case 'h': + default: +bad_args: + usage(); + } + } + + argc -= optind; + argv += optind; + + if (joining_domain && (argc != 0)) + usage(); + + switch(argc) { + case 0: + if (!got_username) + fstrcpy(user_name, ""); + break; + case 1: + if (!amroot == 1) { + new_passwd = argv[0]; + break; + } + if (got_username) + usage(); + fstrcpy(user_name, argv[0]); + break; + case 2: + if (!amroot || got_username || got_pass) + usage(); + fstrcpy(user_name, argv[0]); + new_passwd = strdup_x(argv[1]); + break; + default: + usage(); + } + +} + /* Initialise client credentials for authenticated pipe access */ void init_rpcclient_creds(struct ntuser_creds *creds, char* username, @@ -117,15 +270,16 @@ Join a domain using the administrator username and password goto done; \ } -static int join_domain_byuser(char *domain, char *remote_machine, +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 dest_host, acct_name; + fstring acct_name; struct in_addr dest_ip; TALLOC_CTX *mem_ctx; @@ -149,6 +303,8 @@ static int join_domain_byuser(char *domain, char *remote_machine, NTSTATUS result; int retval = 1; + pstrcpy(pdc_name, remote ? remote : ""); + /* Connect to remote machine */ ZERO_STRUCT(cli); @@ -167,17 +323,39 @@ static int join_domain_byuser(char *domain, char *remote_machine, init_rpcclient_creds(&creds, username, domain, password); cli_init_creds(&cli, &creds); - if (!resolve_srv_name(remote_machine, dest_host, &dest_ip)) { - DEBUG(0, ("Could not resolve name %s\n", remote_machine)); - goto done; + /* + * 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, dns_to_netbios_name(dest_host), 0x20); + make_nmb_name(&called, pdc_name, 0x20); make_nmb_name(&calling, dns_to_netbios_name(global_myname), 0); - if (!cli_establish_connection(&cli, dest_host, &dest_ip, &calling, + if (!cli_establish_connection(&cli, pdc_name, &dest_ip, &calling, &called, "IPC$", "IPC", False, True)) { - DEBUG(0, ("Error connecting to %s\n", dest_host)); + 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; } @@ -301,7 +479,7 @@ static int join_domain_byuser(char *domain, char *remote_machine, encode_pw_buffer((char *)pwbuf, machine_pwd, plen, False); - nt_owf_genW(&upw, ntpw); + mdfour( ntpw, (unsigned char *)upw.buffer, plen); } /* Set password on machine account */ @@ -381,13 +559,13 @@ Join a domain. Old server manager method. static int join_domain(char *domain, char *remote) { - pstring remote_machine; + pstring pdc_name; fstring trust_passwd; unsigned char orig_trust_passwd_hash[16]; DOM_SID domain_sid; BOOL ret; - pstrcpy(remote_machine, remote ? remote : ""); + pstrcpy(pdc_name, remote ? remote : ""); fstrcpy(trust_passwd, global_myname); strlower(trust_passwd); E_md4hash( (uchar *)trust_passwd, orig_trust_passwd_hash); @@ -415,23 +593,31 @@ machine %s in domain %s.\n", global_myname, domain); * If we are given a remote machine assume this is the PDC. */ - if(remote == NULL) { - pstrcpy(remote_machine, lp_passwordserver()); - } + 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(!*remote_machine) { - fprintf(stderr, "No password server list given in smb.conf - \ -unable to join domain.\n"); - 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, remote_machine, &domain_sid) || + 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, remote_machine); + ret = change_trust_account_password( domain, pdc_name); if(!ret) { trust_password_delete(domain); @@ -444,11 +630,6 @@ unable to join domain.\n"); return 0; } -static void set_line_buffering(FILE *f) -{ - setvbuf(f, NULL, _IOLBF, 0); -} - /************************************************************* Utility function to prompt for passwords from stdin. Each password entered must end with a newline. @@ -537,7 +718,7 @@ static BOOL password_change(const char *remote_machine, char *user_name, return False; } ret = remote_password_change(remote_machine, user_name, - old_passwd, new_passwd, err_str, sizeof(err_str)); + old_passwd, new_passwd, err_str, sizeof(err_str)); if(*err_str) fprintf(stderr, err_str); return ret; @@ -570,107 +751,15 @@ static BOOL store_ldap_admin_pw (char* pw) } #endif + /************************************************************* Handle password changing for root. *************************************************************/ -static int process_root(int argc, char *argv[]) +static int process_root(void) { struct passwd *pwd; - int result = 0, ch; - BOOL joining_domain = False, got_pass = False, got_username = False; - int local_flags = 0; - BOOL stdin_passwd_get = False; - fstring user_name, user_password; -#ifdef WITH_LDAP_SAM - fstring ldap_secret; -#endif - char *new_domain = NULL; - char *new_passwd = NULL; - char *old_passwd = NULL; - char *remote_machine = NULL; - - user_name[0] = '\0'; - - while ((ch = getopt(argc, argv, "axdehmnj:r:sw:R:D:U:L")) != EOF) { - switch(ch) { - case 'L': - local_mode = True; - break; - case 'a': - local_flags |= LOCAL_ADD_USER; - break; - case 'x': - local_flags |= LOCAL_DELETE_USER; - new_passwd = strdup_x("XXXXXX"); - break; - case 'd': - local_flags |= LOCAL_DISABLE_USER; - new_passwd = strdup_x("XXXXXX"); - break; - case 'e': - local_flags |= LOCAL_ENABLE_USER; - break; - case 'm': - local_flags |= LOCAL_TRUST_ACCOUNT; - break; - case 'n': - local_flags |= LOCAL_SET_NO_PASSWORD; - new_passwd = strdup_x("NO PASSWORD"); - break; - case 'j': - new_domain = optarg; - strupper(new_domain); - joining_domain = True; - break; - case 'r': - remote_machine = optarg; - break; - case 's': - set_line_buffering(stdin); - set_line_buffering(stdout); - set_line_buffering(stderr); - stdin_passwd_get = True; - break; - case 'w': -#ifdef WITH_LDAP_SAM - local_flags |= LOCAL_SET_LDAP_ADMIN_PW; - fstrcpy(ldap_secret, optarg); - break; -#else - printf("-w not available unless configured --with-ldap\n"); - goto done; -#endif - case 'R': - lp_set_name_resolve_order(optarg); - break; - case 'D': - DEBUGLEVEL = atoi(optarg); - break; - case 'U': { - char *lp; - - got_username = True; - fstrcpy(user_name, optarg); - - if ((lp = strchr(user_name, '%'))) { - *lp = 0; - fstrcpy(user_password, lp + 1); - got_pass = True; - memset(strchr(optarg, '%') + 1, 'X', - strlen(user_password)); - } - - break; - } - case 'h': - default: - usage(); - } - } - - argc -= optind; - argv += optind; + int result = 0; #ifdef WITH_LDAP_SAM if (local_flags & LOCAL_SET_LDAP_ADMIN_PW) @@ -704,9 +793,6 @@ static int process_root(int argc, char *argv[]) if (joining_domain) { - if (argc != 0) - usage(); - /* Are we joining by specifing an admin username and password? */ @@ -735,26 +821,6 @@ static int process_root(int argc, char *argv[]) * Deal with root - can add a user, but only locally. */ - switch(argc) { - case 0: - if (!got_username) - fstrcpy(user_name, ""); - break; - case 1: - if (got_username) - usage(); - fstrcpy(user_name, argv[0]); - break; - case 2: - if (got_username || got_pass) - usage(); - fstrcpy(user_name, argv[0]); - new_passwd = strdup_x(argv[1]); - break; - default: - usage(); - } - if (!user_name[0] && (pwd = sys_getpwuid(0))) { fstrcpy(user_name, pwd->pw_name); } @@ -840,7 +906,9 @@ static int process_root(int argc, char *argv[]) goto done; } - if(!(local_flags & (LOCAL_ADD_USER|LOCAL_DISABLE_USER|LOCAL_ENABLE_USER|LOCAL_DELETE_USER|LOCAL_SET_NO_PASSWORD))) { + 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))) { SAM_ACCOUNT *sampass = NULL; uint16 acct_ctrl; @@ -871,55 +939,18 @@ static int process_root(int argc, char *argv[]) /************************************************************* -handle password changing for non-root + Handle password changing for non-root. *************************************************************/ -static int process_nonroot(int argc, char *argv[]) + +static int process_nonroot(void) { struct passwd *pwd = NULL; - int result = 0, ch; - BOOL stdin_passwd_get = False; - char *old_passwd = NULL; - char *remote_machine = NULL; - char *user_name = NULL; - char *new_passwd = NULL; - - while ((ch = getopt(argc, argv, "hD:r:sU:")) != EOF) { - switch(ch) { - case 'D': - DEBUGLEVEL = atoi(optarg); - break; - case 'r': - remote_machine = optarg; - break; - case 's': - set_line_buffering(stdin); - set_line_buffering(stdout); - set_line_buffering(stderr); - stdin_passwd_get = True; - break; - case 'U': - user_name = optarg; - break; - default: - usage(); - } - } - - argc -= optind; - argv += optind; + int result = 0; - if(argc > 1) { - usage(); - } - - if (argc == 1) { - new_passwd = argv[0]; - } - - if (!user_name) { + if (!user_name[0]) { pwd = sys_getpwuid(getuid()); if (pwd) { - user_name = strdup_x(pwd->pw_name); + fstrcpy(user_name,pwd->pw_name); } else { fprintf(stderr,"you don't exist - go away\n"); exit(1); @@ -973,7 +1004,7 @@ static int process_nonroot(int argc, char *argv[]) **********************************************************/ int main(int argc, char **argv) { - static pstring servicesf = CONFIGFILE; + BOOL amroot = getuid() == 0; AllowDebugChange = False; @@ -981,12 +1012,13 @@ int main(int argc, char **argv) set_auth_parameters(argc, argv); #endif /* HAVE_SET_AUTH_PARAMETERS */ + charset_initialise(); + + process_options(argc, argv, amroot); TimeInit(); setup_logging("smbpasswd", True); - charset_initialise(); - if(!initialize_password_db(False)) { fprintf(stderr, "Can't setup password database vectors.\n"); exit(1); @@ -1019,17 +1051,10 @@ int main(int argc, char **argv) exit(1); } - /* pre-check for local mode option as first option. We can't - do this via normal getopt as getopt can't be called - twice. */ - if (argc > 1 && strcmp(argv[1], "-L") == 0) { - local_mode = True; - } - - if (local_mode || getuid() == 0) { + if (local_mode || amroot) { secrets_init(); - return process_root(argc, argv); + return process_root(); } - return process_nonroot(argc, argv); + return process_nonroot(); } |