diff options
Diffstat (limited to 'source/utils/smbpasswd.c')
-rw-r--r-- | source/utils/smbpasswd.c | 271 |
1 files changed, 198 insertions, 73 deletions
diff --git a/source/utils/smbpasswd.c b/source/utils/smbpasswd.c index 167eb2ed5f3..a4c25417ca2 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. + * (C) Jeremy Allison 1995-1997. * * 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,7 +18,6 @@ */ #include "includes.h" -#include "des.h" /* Static buffers we will return. */ static struct smb_passwd pw_buf; @@ -152,8 +149,8 @@ _my_get_smbpwnam(FILE * fp, char *name, BOOL * valid_old_pwd, /* NT Entry was valid - even if 'X' or '*', can be overwritten */ *got_valid_nt_entry = True; if (*p != '*' && *p != 'X') { - if(gethexpwd(p,smbntpwd)) - pw_buf.smb_nt_passwd = smbntpwd; + if (gethexpwd((char *)p,(char *)smbntpwd)) + pw_buf.smb_nt_passwd = smbntpwd; } } pw_buf.smb_name = user_name; @@ -167,12 +164,12 @@ _my_get_smbpwnam(FILE * fp, char *name, BOOL * valid_old_pwd, if (p[32] != ':') return (False); - if (!strncasecmp(p, "NO PASSWORD", 11)) { - pw_buf.smb_passwd = NULL; /* No password */ + if (!strncasecmp((char *)p, "NO PASSWORD", 11)) { + pw_buf.smb_passwd = NULL; /* No password */ } else { - if(!gethexpwd(p,smbpwd)) - return False; - pw_buf.smb_passwd = smbpwd; + if(!gethexpwd((char *)p,(char *)smbpwd)) + return False; + pw_buf.smb_passwd = smbpwd; } pw_buf.smb_name = user_name; @@ -189,8 +186,8 @@ _my_get_smbpwnam(FILE * fp, char *name, BOOL * valid_old_pwd, /* NT Entry was valid - even if 'X' or '*', can be overwritten */ *got_valid_nt_entry = True; if (*p != '*' && *p != 'X') { - if(gethexpwd(p,smbntpwd)) - pw_buf.smb_nt_passwd = smbntpwd; + if (gethexpwd((char *)p,(char *)smbntpwd)) + pw_buf.smb_nt_passwd = smbntpwd; } } return &pw_buf; @@ -201,14 +198,13 @@ _my_get_smbpwnam(FILE * fp, char *name, BOOL * valid_old_pwd, /* * Print command usage on stderr and die. */ -void -usage(char *name) +static void usage(char *name) { - fprintf(stderr, "Usage is : %s [username]\n", name); + fprintf(stderr, "Usage is : %s [-add] [username] [password]\n", name); exit(1); } -int main(int argc, char **argv) + int main(int argc, char **argv) { int real_uid; struct passwd *pwd; @@ -223,6 +219,8 @@ int main(int argc, char **argv) FILE *fp; BOOL valid_old_pwd = False; BOOL got_valid_nt_entry = False; + BOOL add_user = False; + int add_pass = 0; long seekpos; int pwfd; char ascii_p16[66]; @@ -232,6 +230,8 @@ int main(int argc, char **argv) char *pfile = SMB_PASSWD_FILE; char readbuf[16 * 1024]; + TimeInit(); + setup_logging(argv[0],True); charset_initialise(); @@ -248,20 +248,51 @@ int main(int argc, char **argv) real_uid = getuid(); /* Deal with usage problems */ - if (real_uid == 0) { - /* As root we can change anothers password. */ - if (argc != 1 && argc != 2) + if (real_uid == 0) + { + /* As root we can change anothers password and add a user. */ + if (argc > 4 ) usage(argv[0]); - } else if (argc != 1) + } + else if (argc == 2 || argc > 3) + { + fprintf(stderr, "%s: Only root can set anothers password.\n", argv[0]); usage(argv[0]); + } - - if (real_uid == 0 && argc == 2) { - /* If we are root we can change anothers password. */ - strncpy(user_name, argv[1], sizeof(user_name) - 1); + 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 <= 2 || argc > 4)) + usage(argv[0]); + + /* root can specify password on command-line */ + if (argc == (add_user ? 4 : 3)) + { + /* -a argument (add_user): new password is 3rd argument. */ + /* no -a argument (add_user): new password is 2nd argument */ + + add_pass = add_user ? 3 : 2; + } + + /* If we are root we can change another's 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 { + } + else + { + /* non-root can specify old pass / new pass on command-line */ + if (argc == 3) + { + /* non-root specifies new password as 2nd argument */ + add_pass = 2; + } + pwd = getpwuid(real_uid); } @@ -269,24 +300,50 @@ int main(int argc, char **argv) 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)); + if (real_uid != 0) + { + if (add_pass) + { + /* old password, as non-root, is 1st argument */ + strncpy(old_passwd, argv[1], sizeof(fstring)); + } + else + { + 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 (add_pass) + { + /* new password is specified on the command line */ + strncpy(new_passwd, argv[add_user ? 3 : 2], sizeof(new_passwd) - 1); + new_passwd[sizeof(new_passwd) - 1] = '\0'; + } + else + { + 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 (strncmp(p, new_passwd, sizeof(fstring)-1)) + { + fprintf(stderr, "%s: Mismatch - password unchanged.\n", argv[0]); + exit(1); + } } - if (new_passwd[0] == '\0') { + if (new_passwd[0] == '\0') + { printf("Password not set\n"); exit(0); } @@ -318,20 +375,30 @@ int main(int argc, char **argv) * 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); + fp = fopen(pfile, "r+"); + if (!fp && errno == ENOENT) { + fp = fopen(pfile, "w"); + if (fp) { + fprintf(fp, "# Samba SMB password file\n"); + fclose(fp); + fp = fopen(pfile, "r+"); + } } + if (!fp) { + 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; @@ -346,26 +413,95 @@ int main(int argc, char **argv) smb_pwent = _my_get_smbpwnam(fp, pwd->pw_name, &valid_old_pwd, &got_valid_nt_entry, &seekpos); if (smb_pwent == NULL) { - 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); - } - /* If we are root we don't need to check the old password. */ - if (real_uid != 0) { - if ((valid_old_pwd == False) || (smb_pwent->smb_passwd == NULL)) { - fprintf(stderr, "%s: User %s is disabled, plase contact your administrator to enable it.\n", argv[0], pwd->pw_name); + 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); } - /* Check the old Lanman password */ - 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); + + /* Create a new smb passwd entry and set it to the given password. */ + { + int fd; + int new_entry_length; + char *new_entry; + 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 %s\n", argv[0], pwd->pw_name, pfile, strerror(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 %s\n", argv[0], pwd->pw_name, pfile, strerror(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 %s\n", argv[0], pwd->pw_name, pfile, strerror(errno)); + /* Remove the entry we just wrote. */ + if(ftruncate(fd, offpos) == -1) { + fprintf(stderr, "%s: ERROR failed to ftruncate file %s. \ +Error was %s. Password file may be corrupt ! Please examine by hand !\n", + argv[0], pwd->pw_name, strerror(errno)); + } + fclose(fp); + pw_file_unlock(lockfd); + exit(1); + } + + fclose(fp); + pw_file_unlock(lockfd); + exit(0); + } + } else { + /* the entry already existed */ + add_user = False; + } + + /* 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 has no old SMB password.\n", argv[0], pwd->pw_name); + } + /* 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) { @@ -443,14 +579,3 @@ int main(int argc, char **argv) return 0; } -#else - -#include "includes.h" - -int -main(int argc, char **argv) -{ - printf("smb password encryption not selected in Makefile\n"); - return 0; -} -#endif |