diff options
author | Denis Vlasenko <vda.linux@googlemail.com> | 2007-07-21 01:28:41 +0400 |
---|---|---|
committer | Denis Vlasenko <vda.linux@googlemail.com> | 2007-07-21 01:28:41 +0400 |
commit | 21d1014b5b91d1a1319273945291b7a9f4717827 (patch) | |
tree | b84eadba35d31f923ef62579652e4e5d76678c38 /loginutils | |
parent | 2f6ae43b9c74d393a139007377895e8c50b8af9a (diff) |
chpasswd: new applet by Alexander Shishkin <virtuoso@slind.org>
Diffstat (limited to 'loginutils')
-rw-r--r-- | loginutils/Config.in | 8 | ||||
-rw-r--r-- | loginutils/Kbuild | 1 | ||||
-rw-r--r-- | loginutils/cryptpw.c | 4 | ||||
-rw-r--r-- | loginutils/passwd.c | 121 |
4 files changed, 17 insertions, 117 deletions
diff --git a/loginutils/Config.in b/loginutils/Config.in index f9ae122e4..63ae9b4db 100644 --- a/loginutils/Config.in +++ b/loginutils/Config.in @@ -180,6 +180,14 @@ config CRYPTPW help Applet for crypting a string. +config CHPASSWD + bool "chpasswd" + default n + help + chpasswd reads a file of user name and password pairs from + standard input and uses this information to update a group of + existing users. + config SU bool "su" default n diff --git a/loginutils/Kbuild b/loginutils/Kbuild index 1b1165a6e..3d0d777e8 100644 --- a/loginutils/Kbuild +++ b/loginutils/Kbuild @@ -8,6 +8,7 @@ lib-y:= lib-$(CONFIG_ADDGROUP) += addgroup.o lib-$(CONFIG_ADDUSER) += adduser.o lib-$(CONFIG_CRYPTPW) += cryptpw.o +lib-$(CONFIG_CHPASSWD) += chpasswd.o lib-$(CONFIG_GETTY) += getty.o lib-$(CONFIG_LOGIN) += login.o lib-$(CONFIG_PASSWD) += passwd.o diff --git a/loginutils/cryptpw.c b/loginutils/cryptpw.c index dd7304613..1c3059198 100644 --- a/loginutils/cryptpw.c +++ b/loginutils/cryptpw.c @@ -17,9 +17,9 @@ int cryptpw_main(int argc, char **argv) /* Too ugly, and needs even more magic to handle endianness: */ //((uint32_t*)&salt)[0] = '$' + '1'*0x100 + '$'*0x10000; /* Hope one day gcc will do it itself (inlining strcpy) */ - crypt_make_salt(salt + 3, 4); /* md5 */ + crypt_make_salt(salt + 3, 4, 0); /* md5 */ } else { - crypt_make_salt(salt, 1); /* des */ + crypt_make_salt(salt, 1, 0); /* des */ } puts(pw_encrypt(argv[optind] ? argv[optind] : xmalloc_getline(stdin), salt)); diff --git a/loginutils/passwd.c b/loginutils/passwd.c index 8f65c3d0b..cd98d4101 100644 --- a/loginutils/passwd.c +++ b/loginutils/passwd.c @@ -52,10 +52,10 @@ static char* new_password(const struct passwd *pw, uid_t myuid, int algo) } /*memset(salt, 0, sizeof(salt)); - why?*/ - crypt_make_salt(salt, 1); /* des */ + crypt_make_salt(salt, 1, 0); /* des */ if (algo) { /* MD5 */ strcpy(salt, "$1$"); - crypt_make_salt(salt + 3, 4); + crypt_make_salt(salt + 3, 4, 0); } ret = xstrdup(pw_encrypt(newp, salt)); /* returns ptr to static */ /* whee, success! */ @@ -70,115 +70,6 @@ static char* new_password(const struct passwd *pw, uid_t myuid, int algo) return ret; } - -static int update_passwd(const char *filename, const char *username, - const char *new_pw) -{ - struct stat sb; - struct flock lock; - FILE *old_fp; - FILE *new_fp; - char *new_name; - char *last_char; - unsigned user_len; - int old_fd; - int new_fd; - int i; - int ret = 1; /* failure */ - - logmode = LOGMODE_STDIO; - /* New passwd file, "/etc/passwd+" for now */ - new_name = xasprintf("%s+", filename); - last_char = &new_name[strlen(new_name)-1]; - username = xasprintf("%s:", username); - user_len = strlen(username); - - old_fp = fopen(filename, "r+"); - if (!old_fp) - goto free_mem; - old_fd = fileno(old_fp); - - /* Try to create "/etc/passwd+". Wait if it exists. */ - i = 30; - do { - // FIXME: on last iteration try w/o O_EXCL but with O_TRUNC? - new_fd = open(new_name, O_WRONLY|O_CREAT|O_EXCL,0600); - if (new_fd >= 0) goto created; - if (errno != EEXIST) break; - usleep(100000); /* 0.1 sec */ - } while (--i); - bb_perror_msg("cannot create '%s'", new_name); - goto close_old_fp; - created: - if (!fstat(old_fd, &sb)) { - fchmod(new_fd, sb.st_mode & 0777); /* ignore errors */ - fchown(new_fd, sb.st_uid, sb.st_gid); - } - new_fp = fdopen(new_fd, "w"); - if (!new_fp) { - close(new_fd); - goto unlink_new; - } - - /* Backup file is "/etc/passwd-" */ - last_char[0] = '-'; - /* Delete old one, create new as a hardlink to current */ - i = (unlink(new_name) && errno != ENOENT); - if (i || link(filename, new_name)) - bb_perror_msg("warning: cannot create backup copy '%s'", new_name); - last_char[0] = '+'; - - /* Lock the password file before updating */ - lock.l_type = F_WRLCK; - lock.l_whence = SEEK_SET; - lock.l_start = 0; - lock.l_len = 0; - if (fcntl(old_fd, F_SETLK, &lock) < 0) - bb_perror_msg("warning: cannot lock '%s'", filename); - lock.l_type = F_UNLCK; - - /* Read current password file, write updated one */ - while (1) { - char *line = xmalloc_fgets(old_fp); - if (!line) break; /* EOF/error */ - if (strncmp(username, line, user_len) == 0) { - /* we have a match with "username:"... */ - const char *cp = line + user_len; - /* now cp -> old passwd, skip it: */ - cp = strchr(cp, ':'); - if (!cp) cp = ""; - /* now cp -> ':' after old passwd or -> "" */ - fprintf(new_fp, "%s%s%s", username, new_pw, cp); - /* Erase password in memory */ - } else - fputs(line, new_fp); - free(line); - } - fcntl(old_fd, F_SETLK, &lock); - - /* We do want all of them to execute, thus | instead of || */ - if ((ferror(old_fp) | fflush(new_fp) | fsync(new_fd) | fclose(new_fp)) - || rename(new_name, filename) - ) { - /* At least one of those failed */ - goto unlink_new; - } - ret = 0; /* whee, success! */ - - unlink_new: - if (ret) unlink(new_name); - - close_old_fp: - fclose(old_fp); - - free_mem: - if (ENABLE_FEATURE_CLEAN_UP) free(new_name); - if (ENABLE_FEATURE_CLEAN_UP) free((char*)username); - logmode = LOGMODE_BOTH; - return ret; -} - - int passwd_main(int argc, char **argv); int passwd_main(int argc, char **argv) { @@ -192,6 +83,7 @@ int passwd_main(int argc, char **argv) /*STATE_ALGO_des = 0x20, not needed yet */ }; unsigned opt; + int rc; const char *opt_a = ""; const char *filename; char *myname; @@ -278,12 +170,11 @@ int passwd_main(int argc, char **argv) signal(SIGQUIT, SIG_IGN); umask(077); xsetuid(0); - if (update_passwd(filename, name, newp) != 0) { - /* LOGMODE_BOTH */ + rc = update_passwd(filename, name, newp); + logmode = LOGMODE_BOTH; + if (rc < 0) bb_error_msg_and_die("cannot update password file %s", filename); - } - /* LOGMODE_BOTH */ bb_info_msg("Password for %s changed by %s", name, myname); if (ENABLE_FEATURE_CLEAN_UP) free(newp); |