X-Git-Url: http://git.samba.org/samba.git/?p=kai%2Fsamba.git;a=blobdiff_plain;f=source%2Futils%2Fsmbpasswd.c;h=e9d0e3d313c530f07aabea4130757ef34afd0ba3;hp=6088263bccd9d216ff5be9ff64ac7fe479ae990e;hb=fa068a6db8da154903fb97a843f261592fcb684a;hpb=aabb18953b5d026af3548610aa1ffd6ea2fd72e5 diff --git a/source/utils/smbpasswd.c b/source/utils/smbpasswd.c index 6088263bccd..e9d0e3d313c 100644 --- a/source/utils/smbpasswd.c +++ b/source/utils/smbpasswd.c @@ -1,8 +1,6 @@ -#ifdef SMB_PASSWD - /* * Unix SMB/Netbios implementation. Version 1.9. smbpasswd module. Copyright - * (C) Jeremy Allison 1995-1997. + * (C) Jeremy Allison 1995-1998 * * This program is free software; you can redistribute it and/or modify it under * the terms of the GNU General Public License as published by the Free @@ -20,517 +18,544 @@ */ #include "includes.h" -#include "des.h" -/* Static buffers we will return. */ -static struct smb_passwd pw_buf; -static pstring user_name; -static unsigned char smbpwd[16]; -static unsigned char smbntpwd[16]; +extern pstring myhostname; +extern pstring global_myname; +extern int DEBUGLEVEL; + -static int gethexpwd(char *p, char *pwd) +/********************************************************* +a strdup with exit +**********************************************************/ +static char *xstrdup(char *s) { - int i; - unsigned char lonybble, hinybble; - char *hexchars = "0123456789ABCDEF"; - char *p1, *p2; - for (i = 0; i < 32; i += 2) { - hinybble = toupper(p[i]); - lonybble = toupper(p[i + 1]); + s = strdup(s); + if (!s) { + fprintf(stderr,"out of memory\n"); + exit(1); + } + return s; +} + + +/********************************************************* + Print command usage on stderr and die. +**********************************************************/ +static void usage(void) +{ + if (getuid() == 0) { + printf("smbpasswd [options] [username] [password]\n"); + } else { + printf("smbpasswd [options] [password]\n"); + } + printf("options:\n"); + printf(" -s use stdin for password prompt\n"); + printf(" -D LEVEL debug level\n"); + printf(" -U USER remote username\n"); + printf(" -r MACHINE remote machine\n"); + + if (getuid() == 0) { + printf(" -R ORDER name resolve order\n"); + printf(" -j DOMAIN join domain name\n"); + printf(" -a add user\n"); + printf(" -d disable user\n"); + printf(" -e enable user\n"); + printf(" -n set no password\n"); + printf(" -m machine trust account\n"); + } + exit(1); +} + +/********************************************************* +Join a domain. +**********************************************************/ +static int join_domain(char *domain, char *remote) +{ + pstring remote_machine; + fstring trust_passwd; + unsigned char orig_trust_passwd_hash[16]; + BOOL ret; + + pstrcpy(remote_machine, remote ? remote : ""); + fstrcpy(trust_passwd, global_myname); + strlower(trust_passwd); + 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; + } + + /* + * Create the machine account password file. + */ + if(!trust_password_lock( domain, global_myname, True)) { + fprintf(stderr, "unable to open the machine account password file for \ +machine %s in domain %s.\n", global_myname, domain); + return 1; + } - p1 = strchr(hexchars, hinybble); - p2 = strchr(hexchars, lonybble); - if (!p1 || !p2) - return (False); + /* + * Write the old machine account password. + */ + + if(!set_trust_account_password( orig_trust_passwd_hash)) { + fprintf(stderr, "unable to write the machine account password for \ +machine %s in domain %s.\n", global_myname, domain); + trust_password_unlock(); + return 1; + } + + /* + * If we are given a remote machine assume this is the PDC. + */ + + if(remote == NULL) { + pstrcpy(remote_machine, lp_passwordserver()); + } - hinybble = PTR_DIFF(p1, hexchars); - lonybble = PTR_DIFF(p2, hexchars); + if(!*remote_machine) { + fprintf(stderr, "No password server list given in smb.conf - \ +unable to join domain.\n"); + trust_password_unlock(); + return 1; + } - pwd[i / 2] = (hinybble << 4) | lonybble; + ret = change_trust_account_password( domain, remote_machine); + trust_password_unlock(); + + if(!ret) { + trust_password_delete( domain, global_myname); + fprintf(stderr,"Unable to join domain %s.\n",domain); + } else { + printf("Joined domain %s.\n",domain); } - return (True); + + return (int)ret; } -struct smb_passwd * -_my_get_smbpwnam(FILE * fp, char *name, BOOL * valid_old_pwd, - BOOL *got_valid_nt_entry, long *pwd_seekpos) + +static void set_line_buffering(FILE *f) { - char linebuf[256]; - unsigned char c; - unsigned char *p; - long uidval; - long linebuf_len; + setvbuf(f, NULL, _IOLBF, 0); +} + +/************************************************************* + Utility function to prompt for passwords from stdin. Each + password entered must end with a newline. +*************************************************************/ +static char *stdin_new_passwd(void) +{ + static fstring new_passwd; + size_t len; + + ZERO_STRUCT(new_passwd); /* - * Scan the file, a line at a time and check if the name matches. + * 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. */ - while (!feof(fp)) { - linebuf[0] = '\0'; - *pwd_seekpos = ftell(fp); + 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_passwd); +} - fgets(linebuf, 256, fp); - if (ferror(fp)) - return NULL; - /* - * Check if the string is terminated with a newline - if not - * then we must keep reading and discard until we get one. - */ - linebuf_len = strlen(linebuf); - if (linebuf[linebuf_len - 1] != '\n') { - c = '\0'; - while (!ferror(fp) && !feof(fp)) { - c = fgetc(fp); - if (c == '\n') - break; - } - } else - linebuf[linebuf_len - 1] = '\0'; +/************************************************************* + Utility function to get passwords via tty or stdin + Used if the '-s' option is set to silently get passwords + to enable scripting. +*************************************************************/ +static char *get_pass( char *prompt, BOOL stdin_get) +{ + char *p; + if (stdin_get) { + p = stdin_new_passwd(); + } else { + p = getpass(prompt); + } + return xstrdup(p); +} + +/************************************************************* + Utility function to prompt for new password. +*************************************************************/ +static char *prompt_for_new_password(BOOL stdin_get) +{ + char *p; + fstring new_passwd; + + ZERO_STRUCT(new_passwd); + + p = get_pass("New SMB password:", stdin_get); + + fstrcpy(new_passwd, p); + + p = get_pass("Retype new SMB password:", stdin_get); + + if (strcmp(p, new_passwd)) { + fprintf(stderr, "Mismatch - password unchanged.\n"); + return NULL; + } + + return xstrdup(p); +} + + +/************************************************************* +change a password either locally or remotely +*************************************************************/ +static BOOL password_change(const char *remote_machine, char *user_name, + char *old_passwd, char *new_passwd, + BOOL add_user, BOOL enable_user, + BOOL disable_user, BOOL set_no_password, + BOOL trust_account) +{ + if (remote_machine != NULL) { + if (add_user || enable_user || disable_user || set_no_password || trust_account) { + /* these things can't be done remotely yet */ + return False; + } + return remote_password_change(remote_machine, user_name, old_passwd, new_passwd); + } + + return local_password_change(user_name, trust_account, add_user, enable_user, + disable_user, set_no_password, new_passwd); +} - if ((linebuf[0] == 0) && feof(fp)) + +/************************************************************* +handle password changing for root +*************************************************************/ +static int process_root(int argc, char *argv[]) +{ + struct passwd *pwd; + int ch; + BOOL joining_domain = False; + BOOL trust_account = False; + BOOL add_user = False; + BOOL disable_user = False; + BOOL enable_user = False; + BOOL set_no_password = False; + BOOL stdin_passwd_get = False; + char *user_name = NULL; + char *new_domain = NULL; + char *new_passwd = NULL; + char *old_passwd = NULL; + char *remote_machine = NULL; + + while ((ch = getopt(argc, argv, "adehmnj:r:sR:D:U:")) != EOF) { + switch(ch) { + case 'a': + add_user = True; break; - /* - * The line we have should be of the form :- - * - * username:uid:[32hex bytes]:....other flags presently - * ignored.... - * - * or, - * - * username:uid:[32hex bytes]:[32hex bytes]:....ignored.... - * - * if Windows NT compatible passwords are also present. - */ + case 'd': + disable_user = True; + new_passwd = "XXXXXX"; + break; + case 'e': + enable_user = True; + break; + case 'D': + DEBUGLEVEL = atoi(optarg); + break; + case 'n': + set_no_password = True; + new_passwd = "NO PASSWORD"; + 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 'R': + lp_set_name_resolve_order(optarg); + break; + case 'm': + trust_account = True; + break; + case 'j': + new_domain = optarg; + strupper(new_domain); + joining_domain = True; + break; + case 'U': + user_name = optarg; + break; + default: + usage(); + } + } + + argc -= optind; + argv += optind; - if (linebuf[0] == '#' || linebuf[0] == '\0') - continue; - p = (unsigned char *) strchr(linebuf, ':'); - if (p == NULL) - continue; - /* - * As 256 is shorter than a pstring we don't need to check - * length here - if this ever changes.... - */ - strncpy(user_name, linebuf, PTR_DIFF(p, linebuf)); - user_name[PTR_DIFF(p, linebuf)] = '\0'; - if (!strequal(user_name, name)) - continue; - /* User name matches - get uid and password */ - p++; /* Go past ':' */ - if (!isdigit(*p)) - return (False); + /* + * Ensure add_user and either remote machine or join domain are + * not both set. + */ + if(add_user && ((remote_machine != NULL) || joining_domain)) { + usage(); + } + + if(joining_domain) { + if (argc != 0) usage(); + return join_domain(new_domain, remote_machine); + } + + /* + * Deal with root - can add a user, but only locally. + */ + + switch(argc) { + case 0: + break; + case 1: + user_name = argv[0]; + break; + case 2: + user_name = argv[0]; + new_passwd = argv[1]; + break; + default: + usage(); + } + + if (!user_name && (pwd = getpwuid(0))) { + user_name = xstrdup(pwd->pw_name); + } + + if (!user_name) { + fprintf(stderr,"You must specify a username\n"); + exit(1); + } + + if (!remote_machine && !Get_Pwnam(user_name, True)) { + fprintf(stderr, "User \"%s\" was not found in system password file.\n", + user_name); + exit(1); + } + + if (user_name[strlen(user_name)-1] == '$') { + user_name[strlen(user_name)-1] = 0; + } - uidval = atoi((char *) p); - while (*p && isdigit(*p)) - p++; + if (trust_account) { + /* add the $ automatically */ + static fstring buf; - if (*p != ':') - return (False); + if (add_user) { + new_passwd = xstrdup(user_name); + strlower(new_passwd); + } + + slprintf(buf, sizeof(buf)-1, "%s$", user_name); + user_name = buf; + } + + if (remote_machine != NULL) { + old_passwd = get_pass("Old SMB password:",stdin_passwd_get); + } + + if (!new_passwd) { /* - * Now get the password value - this should be 32 hex digits - * which are the ascii representations of a 16 byte string. - * Get two at a time and put them into the password. + * 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. */ - p++; - *pwd_seekpos += PTR_DIFF(p, linebuf); /* Save exact position - * of passwd in file - - * this is used by - * smbpasswd.c */ - if (*p == '*' || *p == 'X') { - /* Password deliberately invalid - end here. */ - *valid_old_pwd = False; - *got_valid_nt_entry = False; - pw_buf.smb_nt_passwd = NULL; /* No NT password (yet)*/ - - /* Now check if the NT compatible password is - available. */ - p += 33; /* Move to the first character of the line after - the lanman password. */ - if ((linebuf_len >= (PTR_DIFF(p, linebuf) + 33)) && (p[32] == ':')) { - /* NT Entry was valid - even if 'X' or '*', can be overwritten */ - *got_valid_nt_entry = True; - if (*p != '*' && *p != 'X') { - if (gethexpwd((char *)p,(char *)smbntpwd)) - pw_buf.smb_nt_passwd = smbntpwd; - } + + if(enable_user) { + struct smb_passwd *smb_pass = getsmbpwnam(user_name); + if((smb_pass != NULL) && (smb_pass->smb_passwd != NULL)) { + new_passwd = "XXXX"; /* Don't care. */ } - pw_buf.smb_name = user_name; - pw_buf.smb_userid = uidval; - pw_buf.smb_passwd = NULL; /* No password */ - return (&pw_buf); } - if (linebuf_len < (PTR_DIFF(p, linebuf) + 33)) - return (False); - if (p[32] != ':') - return (False); + if(!new_passwd) + new_passwd = prompt_for_new_password(stdin_passwd_get); + } + + if (!password_change(remote_machine, user_name, old_passwd, new_passwd, + add_user, enable_user, disable_user, set_no_password, + trust_account)) { + fprintf(stderr,"Failed to change password entry for %s\n", user_name); + return 1; + } + + if(disable_user) { + printf("User %s disabled.\n", user_name); + } else if(enable_user) { + printf("User %s enabled.\n", user_name); + } else if (set_no_password) { + printf("User %s - set to no password.\n", user_name); + } else { + printf("Password changed for user %s\n", user_name); + } + return 0; +} - if (!strncasecmp((char *)p, "NO PASSWORD", 11)) { - pw_buf.smb_passwd = NULL; /* No password */ - } else { - if(!gethexpwd((char *)p,(char *)smbpwd)) - return False; - pw_buf.smb_passwd = smbpwd; + +/************************************************************* +handle password changing for non-root +*************************************************************/ +static int process_nonroot(int argc, char *argv[]) +{ + struct passwd *pwd = NULL; + int 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; - pw_buf.smb_name = user_name; - pw_buf.smb_userid = uidval; - pw_buf.smb_nt_passwd = NULL; - *got_valid_nt_entry = False; - *valid_old_pwd = True; - - /* Now check if the NT compatible password is - available. */ - p += 33; /* Move to the first character of the line after - the lanman password. */ - if ((linebuf_len >= (PTR_DIFF(p, linebuf) + 33)) && (p[32] == ':')) { - /* NT Entry was valid - even if 'X' or '*', can be overwritten */ - *got_valid_nt_entry = True; - if (*p != '*' && *p != 'X') { - if (gethexpwd((char *)p,(char *)smbntpwd)) - pw_buf.smb_nt_passwd = smbntpwd; - } + if(argc > 1) { + usage(); + } + + if (argc == 1) { + new_passwd = argv[0]; + } + + if (!user_name) { + pwd = getpwuid(getuid()); + if (pwd) { + user_name = xstrdup(pwd->pw_name); + } else { + fprintf(stderr,"you don't exist - go away\n"); + exit(1); } - return &pw_buf; } - return NULL; -} + + /* + * A non-root user is always setting a password + * via a remote machine (even if that machine is + * localhost). + */ + if (remote_machine == NULL) { + remote_machine = "127.0.0.1"; + } -/* - * Print command usage on stderr and die. - */ -static void usage(char *name) -{ - fprintf(stderr, "Usage is : %s [-add] [username]\n", name); - exit(1); -} - int main(int argc, char **argv) -{ - int real_uid; - struct passwd *pwd; - fstring old_passwd; - uchar old_p16[16]; - uchar old_nt_p16[16]; - fstring new_passwd; - uchar new_p16[16]; - uchar new_nt_p16[16]; - char *p; - struct smb_passwd *smb_pwent; - FILE *fp; - BOOL valid_old_pwd = False; - BOOL got_valid_nt_entry = False; - BOOL add_user = False; - long seekpos; - int pwfd; - char ascii_p16[66]; - char c; - int ret, i, err, writelen; - int lockfd = -1; - char *pfile = SMB_PASSWD_FILE; - char readbuf[16 * 1024]; - - TimeInit(); - - setup_logging(argv[0],True); - - charset_initialise(); - -#ifndef DEBUG_PASSWORD - /* Check the effective uid */ - if (geteuid() != 0) { - fprintf(stderr, "%s: Must be setuid root.\n", argv[0]); - exit(1); - } -#endif - - /* Get the real uid */ - real_uid = getuid(); - - /* Deal with usage problems */ - if (real_uid == 0) { - /* As root we can change anothers password and add a user. */ - if (argc > 3 ) - usage(argv[0]); - } else if (argc != 1) { - fprintf(stderr, "%s: Only root can set anothers password.\n", argv[0]); - usage(argv[0]); - } - - if (real_uid == 0 && (argc > 1)) { - /* We are root - check if we should add the user */ - if ((argv[1][0] == '-') && (argv[1][1] == 'a')) - add_user = True; - if(add_user && (argc != 3)) - usage(argv[0]); - - /* If we are root we can change anothers password. */ - strncpy(user_name, add_user ? argv[2] : argv[1], sizeof(user_name) - 1); - user_name[sizeof(user_name) - 1] = '\0'; - pwd = getpwnam(user_name); - } else { - pwd = getpwuid(real_uid); - } - - if (pwd == 0) { - fprintf(stderr, "%s: Unable to get UNIX password entry for user.\n", argv[0]); - exit(1); - } - /* If we are root we don't ask for the old password. */ - old_passwd[0] = '\0'; - if (real_uid != 0) { - p = getpass("Old SMB password:"); - strncpy(old_passwd, p, sizeof(fstring)); - old_passwd[sizeof(fstring)-1] = '\0'; - } - new_passwd[0] = '\0'; - p = getpass("New SMB password:"); - strncpy(new_passwd, p, sizeof(fstring)); - new_passwd[sizeof(fstring)-1] = '\0'; - p = getpass("Retype new SMB password:"); - if (strcmp(p, new_passwd)) { - fprintf(stderr, "%s: Mismatch - password unchanged.\n", argv[0]); - exit(1); - } - - if (new_passwd[0] == '\0') { - printf("Password not set\n"); - exit(0); - } - - /* Calculate the MD4 hash (NT compatible) of the old and new passwords */ - memset(old_nt_p16, '\0', 16); - E_md4hash((uchar *)old_passwd, old_nt_p16); - - memset(new_nt_p16, '\0', 16); - E_md4hash((uchar *) new_passwd, new_nt_p16); - - /* Mangle the passwords into Lanman format */ - old_passwd[14] = '\0'; - strupper(old_passwd); - new_passwd[14] = '\0'; - strupper(new_passwd); - - /* - * Calculate the SMB (lanman) hash functions of both old and new passwords. - */ - - memset(old_p16, '\0', 16); - E_P16((uchar *) old_passwd, old_p16); - - memset(new_p16, '\0', 16); - E_P16((uchar *) new_passwd, new_p16); - - /* - * Open the smbpaswd file XXXX - we need to parse smb.conf to get the - * filename - */ - if ((fp = fopen(pfile, "r+")) == NULL) { - err = errno; - fprintf(stderr, "%s: Failed to open password file %s.\n", - argv[0], pfile); - errno = err; - perror(argv[0]); - exit(err); - } - /* Set read buffer to 16k for effiecient reads */ - setvbuf(fp, readbuf, _IOFBF, sizeof(readbuf)); - - /* make sure it is only rw by the owner */ - chmod(pfile, 0600); - - /* Lock the smbpasswd file for write. */ - if ((lockfd = pw_file_lock(pfile, F_WRLCK, 5)) < 0) { - err = errno; - fprintf(stderr, "%s: Failed to lock password file %s.\n", - argv[0], pfile); - fclose(fp); - errno = err; - perror(argv[0]); - exit(err); - } - /* Get the smb passwd entry for this user */ - smb_pwent = _my_get_smbpwnam(fp, pwd->pw_name, &valid_old_pwd, - &got_valid_nt_entry, &seekpos); - if (smb_pwent == NULL) { - if(add_user == False) { - fprintf(stderr, "%s: Failed to find entry for user %s in file %s.\n", - argv[0], pwd->pw_name, pfile); - fclose(fp); - pw_file_unlock(lockfd); - exit(1); - } - - /* Create a new smb passwd entry and set it to the given password. */ - { - int fd; - int i; - int new_entry_length; - char *new_entry; - char *p; - long offpos; - - /* The add user write needs to be atomic - so get the fd from - the fp and do a raw write() call. - */ - fd = fileno(fp); - - if((offpos = lseek(fd, 0, SEEK_END)) == -1) { - fprintf(stderr, "%s: Failed to add entry for user %s to file %s. \ -Error was %d\n", argv[0], pwd->pw_name, pfile, errno); - fclose(fp); - pw_file_unlock(lockfd); - exit(1); - } - - new_entry_length = strlen(pwd->pw_name) + 1 + 15 + 1 + - 32 + 1 + 32 + 1 + strlen(pwd->pw_gecos) + - 1 + strlen(pwd->pw_dir) + 1 + - strlen(pwd->pw_shell) + 1; - if((new_entry = (char *)malloc( new_entry_length )) == 0) { - fprintf(stderr, "%s: Failed to add entry for user %s to file %s. \ -Error was %d\n", argv[0], pwd->pw_name, pfile, errno); - fclose(fp); - pw_file_unlock(lockfd); - exit(1); - } - - sprintf(new_entry, "%s:%u:", pwd->pw_name, pwd->pw_uid); - p = &new_entry[strlen(new_entry)]; - for( i = 0; i < 16; i++) - sprintf(&p[i*2], "%02X", new_p16[i]); - p += 32; - *p++ = ':'; - for( i = 0; i < 16; i++) - sprintf(&p[i*2], "%02X", new_nt_p16[i]); - p += 32; - *p++ = ':'; - sprintf(p, "%s:%s:%s\n", pwd->pw_gecos, - pwd->pw_dir, pwd->pw_shell); - if(write(fd, new_entry, strlen(new_entry)) != strlen(new_entry)) { - fprintf(stderr, "%s: Failed to add entry for user %s to file %s. \ -Error was %d\n", argv[0], pwd->pw_name, pfile, errno); - /* Remove the entry we just wrote. */ - if(ftruncate(fd, offpos) == -1) { - fprintf(stderr, "%s: ERROR failed to ftruncate file %s. \ -Error was %d. Password file may be corrupt ! Please examine by hand !\n", - argv[0], pwd->pw_name, errno); - } - fclose(fp); - pw_file_unlock(lockfd); - exit(1); - } - - fclose(fp); - pw_file_unlock(lockfd); - exit(0); - } - } - - /* If we are root or the password is 'NO PASSWORD' then - we don't need to check the old password. */ - if (real_uid != 0) { - if (valid_old_pwd == False) { - fprintf(stderr, "%s: User %s is disabled, plase contact your administrator to enable it.\n", argv[0], pwd->pw_name); - fclose(fp); - pw_file_unlock(lockfd); - exit(1); - } - /* Check the old Lanman password - NULL means 'NO PASSWORD' */ - if (smb_pwent->smb_passwd != NULL) { - if (memcmp(old_p16, smb_pwent->smb_passwd, 16)) { - fprintf(stderr, "%s: Couldn't change password.\n", argv[0]); - fclose(fp); - pw_file_unlock(lockfd); - exit(1); - } - } - /* Check the NT password if it exists */ - if (smb_pwent->smb_nt_passwd != NULL) { - if (memcmp(old_nt_p16, smb_pwent->smb_nt_passwd, 16)) { - fprintf(stderr, "%s: Couldn't change password.\n", argv[0]); - fclose(fp); - pw_file_unlock(lockfd); - exit(1); - } - } - } - /* - * If we get here either we were root or the old password checked out - * ok. - */ - /* Create the 32 byte representation of the new p16 */ - for (i = 0; i < 16; i++) { - sprintf(&ascii_p16[i * 2], "%02X", (uchar) new_p16[i]); - } - if(got_valid_nt_entry) { - /* Add on the NT md4 hash */ - ascii_p16[32] = ':'; - for (i = 0; i < 16; i++) { - sprintf(&ascii_p16[(i * 2)+33], "%02X", (uchar) new_nt_p16[i]); - } - } - /* - * Do an atomic write into the file at the position defined by - * seekpos. - */ - pwfd = fileno(fp); - ret = lseek(pwfd, seekpos - 1, SEEK_SET); - if (ret != seekpos - 1) { - err = errno; - fprintf(stderr, "%s: seek fail on file %s.\n", - argv[0], pfile); - fclose(fp); - errno = err; - perror(argv[0]); - pw_file_unlock(lockfd); - exit(1); - } - /* Sanity check - ensure the character is a ':' */ - if (read(pwfd, &c, 1) != 1) { - err = errno; - fprintf(stderr, "%s: read fail on file %s.\n", - argv[0], pfile); - fclose(fp); - errno = err; - perror(argv[0]); - pw_file_unlock(lockfd); - exit(1); - } - if (c != ':') { - fprintf(stderr, "%s: sanity check on passwd file %s failed.\n", - argv[0], pfile); - fclose(fp); - pw_file_unlock(lockfd); - exit(1); - } - writelen = (got_valid_nt_entry) ? 65 : 32; - if (write(pwfd, ascii_p16, writelen) != writelen) { - err = errno; - fprintf(stderr, "%s: write fail in file %s.\n", - argv[0], pfile); - fclose(fp); - errno = err; - perror(argv[0]); - pw_file_unlock(lockfd); - exit(err); - } - fclose(fp); - pw_file_unlock(lockfd); - printf("Password changed\n"); - return 0; + if (remote_machine != NULL) { + old_passwd = get_pass("Old SMB password:",stdin_passwd_get); + } + + if (!new_passwd) { + new_passwd = prompt_for_new_password(stdin_passwd_get); + } + + if (!new_passwd) { + printf("unable to get new password\n"); + exit(0); + } + + if (!password_change(remote_machine, user_name, old_passwd, new_passwd, + False, False, False, False, False)) { + fprintf(stderr,"Failed to change password for %s\n", user_name); + return 1; + } + + printf("Password changed for user %s\n", user_name); + return 0; } -#else -#include "includes.h" -int -main(int argc, char **argv) -{ - printf("smb password encryption not selected in Makefile\n"); - return 0; +/********************************************************* + Start here. +**********************************************************/ +int main(int argc, char **argv) +{ + static pstring servicesf = CONFIGFILE; + + TimeInit(); + + setup_logging("smbpasswd", True); + + charset_initialise(); + + if(!initialize_password_db()) { + fprintf(stderr, "Can't setup password database vectors.\n"); + exit(1); + } + + if (!lp_load(servicesf,True,False,False)) { + fprintf(stderr, "Can't load %s - run testparm to debug it\n", + servicesf); + exit(1); + } + + if(!get_myname(myhostname,NULL)) { + fprintf(stderr, "unable to get my hostname.\n"); + exit(1); + } + + /* + * Set the machine NETBIOS name if not already + * set from the config file. + */ + + if (!*global_myname) { + char *p; + fstrcpy(global_myname, myhostname); + 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 ((geteuid() == (uid_t)0) && (getuid() != (uid_t)0)) { + fprintf(stderr, "smbpasswd must *NOT* be setuid root.\n"); + exit(1); + } + + if (getuid() == 0) { + return process_root(argc, argv); + } + + return process_nonroot(argc, argv); } -#endif