On 7/19/07, Tito <[EMAIL PROTECTED]> wrote:
Hi,
Hi,

attached you will find a drop in replacement
for chpasswd.c with some more busyboxification
(use of getopt32 and syslogging capabilities of
bb_*_msg_* functions) and some things it seems to me that
need to be fixed (this could be done to me being in hurry
and not understanding you code... in this case ignore it).
This code is only compile tested and needs more care and love. ;-)
Thanks for pointing these things out! I've done some more tweaking on
the applet. Attached please find an updated patch.

Regards,
--
Alex
diff -purN busybox.orig/include/applets.h busybox-trybuild/include/applets.h
--- busybox.orig/include/applets.h	2007-07-19 02:03:40.000000000 +0400
+++ busybox-trybuild/include/applets.h	2007-07-20 00:14:36.000000000 +0400
@@ -89,6 +89,7 @@ USE_CHCON(APPLET(chcon, _BB_DIR_USR_BIN,
 USE_CHGRP(APPLET_NOEXEC(chgrp, chgrp, _BB_DIR_BIN, _BB_SUID_NEVER, chgrp))
 USE_CHMOD(APPLET_NOEXEC(chmod, chmod, _BB_DIR_BIN, _BB_SUID_NEVER, chmod))
 USE_CHOWN(APPLET_NOEXEC(chown, chown, _BB_DIR_BIN, _BB_SUID_NEVER, chown))
+USE_CHPASSWD(APPLET(chpasswd, _BB_DIR_USR_SBIN, _BB_SUID_NEVER))
 USE_CHPST(APPLET(chpst, _BB_DIR_USR_BIN, _BB_SUID_NEVER))
 USE_CHROOT(APPLET(chroot, _BB_DIR_USR_SBIN, _BB_SUID_NEVER))
 USE_CHRT(APPLET(chrt, _BB_DIR_USR_BIN, _BB_SUID_NEVER))
diff -purN busybox.orig/include/libbb.h busybox-trybuild/include/libbb.h
--- busybox.orig/include/libbb.h	2007-07-19 02:03:40.000000000 +0400
+++ busybox-trybuild/include/libbb.h	2007-07-20 00:14:36.000000000 +0400
@@ -778,6 +778,9 @@ extern void print_login_prompt(void);
 
 extern void crypt_make_salt(char *p, int cnt);
 
+extern int update_passwd(const char *filename, const char *username,
+			const char *new_pw);
+
 int get_terminal_width_height(const int fd, int *width, int *height);
 
 int ioctl_or_perror(int fd, int request, void *argp, const char *fmt,...) __attribute__ ((format (printf, 4, 5)));
diff -purN busybox.orig/include/usage.h busybox-trybuild/include/usage.h
--- busybox.orig/include/usage.h	2007-07-19 02:03:40.000000000 +0400
+++ busybox-trybuild/include/usage.h	2007-07-20 00:14:36.000000000 +0400
@@ -2520,6 +2520,18 @@
        "	-l	Locks (disables) the specified user account\n" \
        "	-u	Unlocks (re-enables) the specified user account"
 
+#define chpasswd_trivial_usage \
+       "[--md5|--encrypt]"
+#define chpasswd_full_usage \
+       "Read user:password information from stdin\n" \
+       "and update /etc/passwd accordingly." \
+       "\n\nOptions:\n" \
+       "	-e, --encrypt\n" \
+       "               Supplied passwords are in encrypted form.\n" \
+       "	-m, --md5\n" \
+       "               Use MD5 encryption instead DES when the supplied\n" \
+       "               passwords are not encrypted.\n"
+
 #define patch_trivial_usage \
        "[-p<num>] [-i <diff>]"
 #define patch_full_usage \
diff -purN busybox.orig/libbb/Kbuild busybox-trybuild/libbb/Kbuild
--- busybox.orig/libbb/Kbuild	2007-07-19 02:03:40.000000000 +0400
+++ busybox-trybuild/libbb/Kbuild	2007-07-20 00:14:36.000000000 +0400
@@ -104,7 +104,8 @@ lib-y += xreadlink.o
 lib-$(CONFIG_FEATURE_MOUNT_LOOP) += loop.o
 lib-$(CONFIG_LOSETUP) += loop.o
 lib-$(CONFIG_FEATURE_MTAB_SUPPORT) += mtab.o
-lib-$(CONFIG_PASSWD) += pw_encrypt.o crypt_make_salt.o
+lib-$(CONFIG_PASSWD) += pw_encrypt.o crypt_make_salt.o update_passwd.o
+lib-$(CONFIG_CHPASSWD) += pw_encrypt.o crypt_make_salt.o update_passwd.o
 lib-$(CONFIG_CRYPTPW) += pw_encrypt.o crypt_make_salt.o
 lib-$(CONFIG_SULOGIN) += pw_encrypt.o
 lib-$(CONFIG_FEATURE_HTTPD_AUTH_MD5) += pw_encrypt.o
diff -purN busybox.orig/libbb/update_passwd.c busybox-trybuild/libbb/update_passwd.c
--- busybox.orig/libbb/update_passwd.c	1970-01-01 03:00:00.000000000 +0300
+++ busybox-trybuild/libbb/update_passwd.c	2007-07-20 00:14:36.000000000 +0400
@@ -0,0 +1,120 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * update_passwd
+ *
+ * update_passwd is a common function for passwd and chpasswd applets;
+ * it is responsible for updating password file (i.e. /etc/passwd or
+ * /etc/shadow) for a given user and password.
+ *
+ * Moved from loginutils/passwd.c by Alexander Shishkin <[EMAIL PROTECTED]>
+ */
+
+#include "libbb.h"
+
+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;
+}
+
diff -purN busybox.orig/loginutils/chpasswd.c busybox-trybuild/loginutils/chpasswd.c
--- busybox.orig/loginutils/chpasswd.c	1970-01-01 03:00:00.000000000 +0300
+++ busybox-trybuild/loginutils/chpasswd.c	2007-07-20 00:14:36.000000000 +0400
@@ -0,0 +1,104 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * chpasswd.c
+ *
+ * Written for SLIND (from passwd.c) by Alexander Shishkin <[EMAIL PROTECTED]>
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ */
+
+#include "libbb.h"
+
+#if ENABLE_GETOPT_LONG
+#include <getopt.h>
+
+static const struct option chpasswd_opts[] = {
+	{ "encrypted", no_argument, NULL, 'e' },
+	{ "md5", no_argument, NULL, 'm' },
+	{ NULL, 0, NULL, 0 }
+};
+#endif
+
+#define OPT_ENC		1
+#define OPT_MD5		2
+
+int chpasswd_main(int argc, char **argv);
+int chpasswd_main(int argc, char **argv)
+{
+	char *name, *cp, *ret;
+	char buf[80];
+	char salt[sizeof("$N$XXXXXXXX")];
+	int flag;
+	const struct passwd *pw;
+	struct rlimit rlimit_fsize;
+	const char *pwfile = bb_path_passwd_file;;
+
+	if (getuid() != 0)
+		bb_error_msg_and_die("can only run as root.");
+
+#if ENABLE_FEATURE_SHADOWPASSWDS
+	if (access(bb_path_shadow_file, F_OK))
+		pwfile = bb_path_shadow_file;
+#endif
+
+ 	opt_complementary = "m--e";
+
+	USE_GETOPT_LONG(applet_long_options = chpasswd_opts;)
+
+	flag = getopt32(argc, argv, "em");
+
+	rlimit_fsize.rlim_cur = rlimit_fsize.rlim_max = 512L * 30000;
+	setrlimit(RLIMIT_FSIZE, &rlimit_fsize);
+	signal(SIGHUP, SIG_IGN);
+	signal(SIGINT, SIG_IGN);
+	signal(SIGQUIT, SIG_IGN);
+
+	while (fgets(buf, sizeof buf, stdin) != NULL) {
+		cp = strchr(buf, '\n');
+		if (cp)
+			*cp = '\0';
+		else {
+			bb_error_msg("line too long.");
+			continue;
+		}
+
+		name = buf;
+		cp = strchr(name, ':');
+		if (cp)
+			*cp++ = '\0';
+		else {
+			bb_error_msg("missing new password.");
+			continue;
+		}
+
+		pw = getpwnam(name);
+		if (!pw)
+			bb_error_msg_and_die("unknown user %s", name);
+
+		logmode = LOGMODE_BOTH;
+
+		if (!(flag & OPT_ENC)) {
+			crypt_make_salt(salt, 1);
+
+			if (flag & OPT_MD5) {
+				strcpy(salt, "$1$");
+				crypt_make_salt(salt + 3, 4);
+			}
+
+			ret = xstrdup(pw_encrypt(cp, salt));
+		} else
+			ret = xstrdup(cp);
+
+		if (!update_passwd(pwfile, name, ret)) {
+			/* LOGMODE_BOTH */
+			bb_info_msg("Password for `%s' changed", name);
+		} else {
+			/* LOGMODE_BOTH */
+			bb_error_msg_and_die("An error occurred updating %s", pwfile);
+		}
+
+		free(ret);
+	}
+
+	return 0;
+}
+
diff -purN busybox.orig/loginutils/Config.in busybox-trybuild/loginutils/Config.in
--- busybox.orig/loginutils/Config.in	2007-07-19 02:03:40.000000000 +0400
+++ busybox-trybuild/loginutils/Config.in	2007-07-20 00:14:36.000000000 +0400
@@ -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 -purN busybox.orig/loginutils/Kbuild busybox-trybuild/loginutils/Kbuild
--- busybox.orig/loginutils/Kbuild	2007-07-19 02:03:40.000000000 +0400
+++ busybox-trybuild/loginutils/Kbuild	2007-07-20 00:14:36.000000000 +0400
@@ -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 -purN busybox.orig/loginutils/passwd.c busybox-trybuild/loginutils/passwd.c
--- busybox.orig/loginutils/passwd.c	2007-07-19 02:03:40.000000000 +0400
+++ busybox-trybuild/loginutils/passwd.c	2007-07-20 00:14:36.000000000 +0400
@@ -70,115 +70,6 @@ static char* new_password(const struct p
 	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)
 {
_______________________________________________
busybox mailing list
[email protected]
http://busybox.net/cgi-bin/mailman/listinfo/busybox

Reply via email to