From 673e304012909e3fb7f4ae873c28d13185690413 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 4 Dec 2015 15:05:00 +0100 Subject: [PATCH] Adds possibility to change another user password --- source3/include/proto.h | 3 +- source3/libsmb/passchange.c | 13 ++-- source3/utils/smbpasswd.c | 144 ++++++++++++++++++++++++++++++++++++-------- 3 files changed, 131 insertions(+), 29 deletions(-) diff --git a/source3/include/proto.h b/source3/include/proto.h index 9dd08fb..f529b12 100644 --- a/source3/include/proto.h +++ b/source3/include/proto.h @@ -922,7 +922,8 @@ NTSTATUS ntlmssp_client_start(TALLOC_CTX *mem_ctx, /* The following definitions come from libsmb/passchange.c */ -NTSTATUS remote_password_change(const char *remote_machine, const char *user_name, +NTSTATUS remote_password_change(const char *remote_machine, const char *user_to_connect, + const char *user_to_connect_password, const char *user_name, const char *old_passwd, const char *new_passwd, char **err_str); diff --git a/source3/libsmb/passchange.c b/source3/libsmb/passchange.c index 4676b72..3b8d3c7 100644 --- a/source3/libsmb/passchange.c +++ b/source3/libsmb/passchange.c @@ -30,7 +30,10 @@ Change a password on a remote machine using IPC calls. *************************************************************/ -NTSTATUS remote_password_change(const char *remote_machine, const char *user_name, +NTSTATUS remote_password_change(const char *remote_machine, + const char *user_to_connect, + const char *user_to_connect_password, + const char *user_name, const char *old_passwd, const char *new_passwd, char **err_str) { @@ -82,9 +85,11 @@ NTSTATUS remote_password_change(const char *remote_machine, const char *user_nam /* Given things like SMB signing, restrict anonymous and the like, try an authenticated connection first */ - result = cli_session_setup(cli, user_name, - old_passwd, strlen(old_passwd)+1, - old_passwd, strlen(old_passwd)+1, ""); + result = cli_session_setup(cli, user_to_connect, + user_to_connect_password, + strlen(user_to_connect_password)+1, + user_to_connect_password, + strlen(user_to_connect_password)+1, ""); if (!NT_STATUS_IS_OK(result)) { diff --git a/source3/utils/smbpasswd.c b/source3/utils/smbpasswd.c index 437a5e5..e8ae844 100644 --- a/source3/utils/smbpasswd.c +++ b/source3/utils/smbpasswd.c @@ -39,6 +39,8 @@ static const char *remote_machine = NULL; static fstring ldap_secret; +/* additional information to change another account password */ +static fstring user_to_connect; /********************************************************* Print command usage on stderr and die. @@ -57,7 +59,8 @@ static void usage(void) printf(" -c smb.conf file Use the given path to the smb.conf file\n"); printf(" -D LEVEL debug level\n"); printf(" -r MACHINE remote machine\n"); - printf(" -U USER remote username\n"); + printf(" -U USER remote username to change password\n"); + printf(" -C USER remote username with which you'll connect\n"); printf("extra options when run by root or in local mode:\n"); printf(" -a add user\n"); @@ -91,10 +94,12 @@ static int process_options(int argc, char **argv, int local_flags) local_flags |= LOCAL_SET_PASSWORD; ZERO_STRUCT(user_name); + ZERO_STRUCT(user_to_connect); user_name[0] = '\0'; + user_to_connect[0] = '\0'; - while ((ch = getopt(argc, argv, "c:axdehminjr:sw:R:D:U:LW")) != EOF) { + while ((ch = getopt(argc, argv, "c:axdehminjr:sw:R:D:U:C:LW")) != EOF) { switch(ch) { case 'L': if (getuid() != 0) { @@ -161,6 +166,10 @@ static int process_options(int argc, char **argv, int local_flags) got_username = True; fstrcpy(user_name, optarg); break; + case 'C': { + fstrcpy(user_to_connect, optarg); + break; + } case 'W': local_flags |= LOCAL_SET_LDAP_ADMIN_PW; *ldap_secret = '\0'; @@ -242,7 +251,10 @@ static char *prompt_for_new_password(bool stdin_get) Change a password either locally or remotely. *************************************************************/ -static NTSTATUS password_change(const char *remote_mach, char *username, +static NTSTATUS password_change(const char *remote_mach, + const char *user_to_connect, + const char *user_to_connect_password, + char *username, char *old_passwd, char *new_pw, int local_flags) { @@ -258,8 +270,17 @@ static NTSTATUS password_change(const char *remote_mach, char *username, fprintf(stderr, "Invalid remote operation!\n"); return NT_STATUS_UNSUCCESSFUL; } - ret = remote_password_change(remote_mach, username, - old_passwd, new_pw, &err_str); + if (user_to_connect[0] && user_to_connect_password != NULL) { + ret = remote_password_change(remote_mach, + user_to_connect, user_to_connect_password, + username, old_passwd, new_pw, + &err_str); + } else { + ret = remote_password_change(remote_mach, + username, old_passwd, + username, old_passwd, new_pw, + &err_str); + } } else { ret = local_password_change(username, local_flags, new_pw, &err_str, &msg_str); @@ -284,7 +305,7 @@ static NTSTATUS password_change(const char *remote_mach, char *username, Store the LDAP admin password in secrets.tdb ******************************************************************/ static bool store_ldap_admin_pw (char* pw) -{ +{ if (!pw) return False; @@ -295,6 +316,56 @@ static bool store_ldap_admin_pw (char* pw) } +/********************************************************** + Utilities functions + **********************************************************/ + +static char *alloc_prompt(const char *text, const char *username) { + int prompt_length = strlen(text) + strlen(username); + char *prompt = malloc((prompt_length + 1) * sizeof(*prompt)); + + int wrote = snprintf(prompt, prompt_length, text, username); + prompt[wrote] = 0; + return prompt; +} + +static bool alloc_passwords(char **old_pw, char **user_to_connect_password) { + if (user_to_connect[0]) { + char *prompt = alloc_prompt("SMB password for %s:", user_to_connect); + + if (prompt == NULL) { + fprintf(stderr, "Unable to get '%s' password\n", user_to_connect); + return False; + } + *user_to_connect_password = get_pass(prompt, stdin_passwd_get); + free(prompt); + if (*user_to_connect_password == NULL) { + fprintf(stderr, "Unable to get '%s' password.\n", user_to_connect); + return False; + } + prompt = alloc_prompt("Old SMB password for %s:", user_name); + if (prompt == NULL) { + fprintf(stderr, "Unable to get '%s' old password\n", user_name); + SAFE_FREE(*user_to_connect_password); + return False; + } + *old_pw = get_pass(prompt, stdin_passwd_get); + free(prompt); + if (*old_pw == NULL) { + fprintf(stderr, "Unable to get old password.\n"); + SAFE_FREE(*user_to_connect_password); + return False; + } + } else { + *old_pw = get_pass("Old SMB password:",stdin_passwd_get); + if (*old_pw == NULL) { + fprintf(stderr, "Unable to get old password.\n"); + return False; + } + } + return True; +} + /************************************************************* Handle password changing for root. *************************************************************/ @@ -304,6 +375,7 @@ static int process_root(int local_flags) struct passwd *pwd; int result = 0; char *old_passwd = NULL; + char *user_to_connect_password = NULL; if (local_flags & LOCAL_SET_LDAP_ADMIN_PW) { char *ldap_admin_dn = lp_ldap_admin_dn(talloc_tos()); @@ -356,7 +428,7 @@ static int process_root(int local_flags) if (!user_name[0] && (pwd = getpwuid_alloc(talloc_tos(), geteuid()))) { fstrcpy(user_name, pwd->pw_name); TALLOC_FREE(pwd); - } + } if (!user_name[0]) { fprintf(stderr,"You must specify a username\n"); @@ -414,9 +486,7 @@ static int process_root(int local_flags) } else { if (remote_machine != NULL) { - old_passwd = get_pass("Old SMB password:",stdin_passwd_get); - if(!old_passwd) { - fprintf(stderr, "Unable to get old password.\n"); + if (alloc_passwords(&old_passwd, &user_to_connect_password) != True) { exit(1); } } @@ -463,12 +533,23 @@ static int process_root(int local_flags) } } - if (!NT_STATUS_IS_OK(password_change(remote_machine, user_name, - old_passwd, new_passwd, - local_flags))) { - result = 1; - goto done; - } + if (user_to_connect[0]) { + if (!NT_STATUS_IS_OK(password_change(remote_machine, + user_to_connect, user_to_connect_password, + user_name, old_passwd, + new_passwd, 0))) { + result = 1; + goto done; + } + } else { + if (!NT_STATUS_IS_OK(password_change(remote_machine, + user_name, old_passwd, + user_name, old_passwd, + new_passwd, 0))) { + result = 1; + goto done; + } + } if(remote_machine) { printf("Password changed for user %s on %s.\n", user_name, remote_machine ); @@ -499,6 +580,8 @@ static int process_root(int local_flags) } done: + if (remote_machine && user_to_connect[0]) + SAFE_FREE(user_to_connect_password); SAFE_FREE(old_passwd); SAFE_FREE(new_passwd); return result; @@ -515,6 +598,7 @@ static int process_nonroot(int local_flags) int result = 0; char *old_pw = NULL; char *new_pw = NULL; + char *user_to_connect_password = NULL; if (local_flags & ~(LOCAL_AM_ROOT | LOCAL_SET_PASSWORD)) { /* Extra flags that we can't honor non-root */ @@ -545,9 +629,7 @@ static int process_nonroot(int local_flags) } if (remote_machine != NULL) { - old_pw = get_pass("Old SMB password:",stdin_passwd_get); - if (old_pw == NULL) { - fprintf(stderr, "Unable to get old password.\n"); + if (alloc_passwords(&old_pw, &user_to_connect_password) != True) { exit(1); } } @@ -563,15 +645,29 @@ static int process_nonroot(int local_flags) exit(1); } - if (!NT_STATUS_IS_OK(password_change(remote_machine, user_name, old_pw, - new_pw, 0))) { - result = 1; - goto done; + if (user_to_connect[0]) { + if (!NT_STATUS_IS_OK(password_change(remote_machine, + user_to_connect, user_to_connect_password, + user_name, old_pw, + new_pw, 0))) { + result = 1; + goto done; + } + } else { + if (!NT_STATUS_IS_OK(password_change(remote_machine, + user_name, old_pw, + user_name, old_pw, + new_pw, 0))) { + result = 1; + goto done; + } } printf("Password changed for user %s\n", user_name); done: + if (user_to_connect[0]) + SAFE_FREE(user_to_connect_password); SAFE_FREE(old_pw); SAFE_FREE(new_pw); @@ -584,7 +680,7 @@ static int process_nonroot(int local_flags) Start here. **********************************************************/ int main(int argc, char **argv) -{ +{ TALLOC_CTX *frame = talloc_stackframe(); int local_flags = 0; int ret;