[PATCH]passwd: size reduction and clean up
Bernhard Fischer
rep.nop at aon.at
Thu Dec 29 12:48:35 UTC 2005
On Thu, Dec 29, 2005 at 01:49:52AM +0100, Tito wrote:
>Hi,
>I know that we are in feature freeze, but this patch is trivial...
>The patch changes:
>
>a) getopt -> bb_getopt_ulflags
>b) fprintf(stderr ... -> bb_error_msg/bb_perror_msg
>c) some minor hacks to save space.
>d) adds a GPL license text
>e) adds some CLEANUP stuff
>
>Size reduction is:
> text data bss dec hex filename
> 3243 0 160 3403 d4b passwd.o.orig
> 3025 0 160 3185 c71 passwd.o
>
>I tested the patch a few times on my box and it worked fine.
>
>Please take a look at it and apply or save for 1.2.
What do you think about the attached further size reduction?
text data bss dec hex filename
3159 0 160 3319 cf7 loginutils/passwd.o.oorig
2947 0 160 3107 c23 loginutils/passwd.o.tito
2871 0 160 3031 bd7 loginutils/passwd.o
I only compile-tested this with gcc-4.1, so please check with your
compiler if these help you or not. Perhaps also look if another applet
uses something like i64c(), we could move it onto a common place then.
Note how it saves space to reuse the same strings and how reusing the
block near rename() helps the size, too.
Also replaced bzero (which is deprecated in favour of memset, nowadays)
while at it.
cheers,
Bernhard
-------------- next part --------------
text data bss dec hex filename
3159 0 160 3319 cf7 loginutils/passwd.o.oorig
2947 0 160 3107 c23 loginutils/passwd.o.tito
2871 0 160 3031 bd7 loginutils/passwd.o
Index: busybox/loginutils/passwd.c
===================================================================
--- busybox/loginutils/passwd.c (revision 13010)
+++ busybox/loginutils/passwd.c (working copy)
@@ -1,4 +1,13 @@
/* vi: set sw=4 ts=4: */
+/*
+ * Mini passwd implementation for busybox
+ *
+ * Copyright (C) many different people.
+ * If you wrote this, please acknowledge your work.
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ */
+
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
@@ -18,19 +27,8 @@
static int create_backup(const char *backup, FILE * fp);
static int new_password(const struct passwd *pw, int amroot, int algo);
-static void set_filesize_limit(int blocks);
-static int get_algo(char *a)
-{
- int x = 1; /* standard: MD5 */
-
- if (strcasecmp(a, "des") == 0)
- x = 0;
- return x;
-}
-
-
static int update_passwd(const struct passwd *pw, char *crypt_pw)
{
char filename[1024];
@@ -39,7 +37,6 @@
char username[32];
char *pw_rest;
int mask;
- int continued;
FILE *fp;
FILE *out_fp;
struct stat sb;
@@ -65,7 +62,7 @@
lock.l_start = 0;
lock.l_len = 0;
if (fcntl(fileno(fp), F_SETLK, &lock) < 0) {
- fprintf(stderr, "%s: %s\n", filename, strerror(errno));
+ bb_perror_msg("%s", filename);
return 1;
}
lock.l_type = F_UNLCK;
@@ -88,13 +85,15 @@
return 1;
}
- continued = 0;
+ /* reuse mask to determine if the line is "continued" */
+ mask = 0;
snprintf(username, sizeof username, "%s:", pw->pw_name);
rewind(fp);
while (!feof(fp)) {
fgets(buffer, sizeof buffer, fp);
- if (!continued) { // Check to see if we're updating this line.
- if (strncmp(username, buffer, strlen(username)) == 0) { // we have a match.
+ if (!mask) { /* Check to see if we're updating this line. */
+ if (strncmp(username, buffer, strlen(username)) == 0) {
+ /* we have a match. */
pw_rest = strchr(buffer, ':');
*pw_rest++ = '\0';
pw_rest = strchr(pw_rest, ':');
@@ -106,11 +105,11 @@
fputs(buffer, out_fp);
}
if (buffer[strlen(buffer) - 1] == '\n') {
- continued = 0;
+ mask = 0;
} else {
- continued = 1;
+ mask = 1;
}
- bzero(buffer, sizeof buffer);
+ memset(buffer, 0, sizeof buffer);
}
if (fflush(out_fp) || fsync(fileno(out_fp)) || fclose(out_fp)) {
@@ -119,17 +118,18 @@
fclose(fp);
return 1;
}
+ fcntl(fileno(fp), F_SETLK, &lock);
+ fclose(fp);
if (rename(buf, filename) < 0) {
- fcntl(fileno(fp), F_SETLK, &lock);
- fclose(fp);
return 1;
- } else {
- fcntl(fileno(fp), F_SETLK, &lock);
- fclose(fp);
- return 0;
}
+ return 0;
}
+#define OPT_ALGO 1
+#define OPT_LOCK 2
+#define OPT_UNLOCK 4
+#define OPT_DELETE 8
extern int passwd_main(int argc, char **argv)
{
@@ -138,53 +138,38 @@
char *np;
char *name;
char *myname;
- int flag;
- int algo = 1; /* -a - password algorithm */
- int lflg = 0; /* -l - lock account */
- int uflg = 0; /* -u - unlock account */
- int dflg = 0; /* -d - delete password */
+ int algo = 1;
const struct passwd *pw;
+ unsigned long opt;
+ char *algo_arg;
#ifdef CONFIG_FEATURE_SHADOWPASSWDS
const struct spwd *sp;
#endif /* CONFIG_FEATURE_SHADOWPASSWDS */
amroot = (getuid() == 0);
- openlog("passwd", LOG_PID | LOG_CONS | LOG_NOWAIT, LOG_AUTH);
- while ((flag = getopt(argc, argv, "a:dlu")) != EOF) {
- switch (flag) {
- case 'a':
- algo = get_algo(optarg);
- break;
- case 'd':
- dflg++;
- break;
- case 'l':
- lflg++;
- break;
- case 'u':
- uflg++;
- break;
- default:
- bb_show_usage();
- }
- }
+ openlog(bb_applet_name, LOG_PID | LOG_CONS | LOG_NOWAIT, LOG_AUTH);
+ /* -a - password algorithm */
+ /* -d - delete password */
+ /* -l - lock account */
+ /* -u - unlock account */
+ opt = bb_getopt_ulflags (argc, argv, "a:dlu", &algo_arg);
+
+ if (opt & OPT_ALGO)
+ algo = (strcasecmp(algo_arg, "des") == 0) ? 0 : 1;
+
myname = (char *) bb_xstrdup(bb_getpwuid(NULL, getuid(), -1));
/* exits on error */
- if (optind < argc) {
- name = argv[optind];
- } else {
- name = myname;
- }
- if ((lflg || uflg || dflg) && (optind >= argc || !amroot)) {
+ name = (optind < argc) ? argv[optind] : myname;
+ if ((opt > 1) && (optind >= argc || !amroot)) {
+ /* OPT_LOCK || OPT_UNLOCK || OPT_DELETE are set */
bb_show_usage();
}
- pw = getpwnam(name);
- if (!pw) {
- bb_error_msg_and_die("Unknown user %s\n", name);
- }
+ /* exits on error and saves an error message "Unknown user XXXX" */
+ pw = getpwuid(bb_xgetpwnam(name));
if (!amroot && pw->pw_uid != getuid()) {
- syslog(LOG_WARNING, "can't change pwd for `%s'", name);
- bb_error_msg_and_die("Permission denied.\n");
+ syslog(LOG_WARNING, "The password for `%s' cannot be changed.", name);
+ errno = EACCES;
+ bb_perror_nomsg_and_die(); /* Permission denied */
}
#ifdef CONFIG_FEATURE_SHADOWPASSWDS
sp = getspnam(name);
@@ -199,40 +184,49 @@
#endif /* CONFIG_FEATURE_SHADOWPASSWDS */
safe_strncpy(crypt_passwd, cp, sizeof(crypt_passwd));
- if (!(dflg || lflg || uflg)) {
+ if (opt<= 1) {
+ /* OPT_LOCK || OPT_UNLOCK || OPT_DELETE are not set */
if (!amroot) {
if (cp[0] == '!') {
- syslog(LOG_WARNING, "password locked for `%s'", np);
- bb_error_msg_and_die( "The password for `%s' cannot be changed.\n", np);
+ syslog(LOG_WARNING, "The password for `%s' cannot be changed.",
+ np);
+ bb_error_msg_and_die("The password for `%s' cannot be changed.",
+ np);
}
}
printf("Changing password for %s\n", name);
if (new_password(pw, amroot, algo)) {
- bb_error_msg_and_die( "The password for %s is unchanged.\n", name);
+ bb_error_msg_and_die( "The password for %s is unchanged.", name);
}
- } else if (lflg) {
+ } else if (opt & OPT_LOCK) {
if (crypt_passwd[0] != '!') {
memmove(&crypt_passwd[1], crypt_passwd,
sizeof crypt_passwd - 1);
crypt_passwd[sizeof crypt_passwd - 1] = '\0';
crypt_passwd[0] = '!';
}
- } else if (uflg) {
+ } else if (opt & OPT_UNLOCK) {
if (crypt_passwd[0] == '!') {
memmove(crypt_passwd, &crypt_passwd[1],
sizeof crypt_passwd - 1);
}
- } else if (dflg) {
+ } else if (opt & OPT_DELETE) {
crypt_passwd[0] = '\0';
}
- set_filesize_limit(30000);
+ {
+ struct rlimit rlimit_fsize;
+
+ 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);
umask(077);
+ /* Maybe not needed as passwd sets _BB_SUID_ALWAYS ? */
if (setuid(0)) {
- syslog(LOG_ERR, "can't setuid(0)");
- bb_error_msg_and_die( "Cannot change ID to root.\n");
+ syslog(LOG_ERR, "Cannot change ID to root.");
+ bb_error_msg_and_die( "Cannot change ID to root.");
}
if (!update_passwd(pw, crypt_passwd)) {
syslog(LOG_INFO, "password for `%s' changed by user `%s'", name,
@@ -240,8 +234,9 @@
printf("Password changed.\n");
} else {
syslog(LOG_WARNING, "an error occurred updating the password file");
- bb_error_msg_and_die("An error occurred updating the password file.\n");
+ bb_error_msg_and_die("an error occurred updating the password file");
}
+ if (ENABLE_FEATURE_CLEAN_UP) free(myname);
return (0);
}
@@ -332,7 +327,7 @@
}
cipher = pw_encrypt(clear, crypt_passwd);
if (strcmp(cipher, crypt_passwd) != 0) {
- syslog(LOG_WARNING, "incorrect password for `%s'",
+ syslog(LOG_WARNING, "Incorrect password for `%s'",
pw->pw_name);
time(&start);
now = start;
@@ -340,13 +335,13 @@
sleep(FAIL_DELAY);
time(&now);
}
- fprintf(stderr, "Incorrect password.\n");
+ bb_error_msg("Incorrect password.");
/* return -1; */
return 1;
}
safe_strncpy(orig, clear, sizeof(orig));
- bzero(clear, strlen(clear));
- bzero(cipher, strlen(cipher));
+ memset(clear, 0, strlen(clear));
+ memset(cipher, 0, strlen(cipher));
} else {
orig[0] = '\0';
}
@@ -354,12 +349,12 @@
"Please use a combination of upper and lower case letters and numbers.\n"
"Enter new password: ")))
{
- bzero(orig, sizeof orig);
+ memset(orig, 0, sizeof orig);
/* return -1; */
return 1;
}
safe_strncpy(pass, cp, sizeof(pass));
- bzero(cp, strlen(cp));
+ memset(cp, 0, strlen(cp));
/* if (!obscure(orig, pass, pw)) { */
if (obscure(orig, pass, pw)) {
if (amroot) {
@@ -370,31 +365,24 @@
}
}
if (!(cp = bb_askpass(0, "Re-enter new password: "))) {
- bzero(orig, sizeof orig);
+ memset(orig, 0, sizeof orig);
/* return -1; */
return 1;
}
if (strcmp(cp, pass)) {
- fprintf(stderr, "Passwords do not match.\n");
+ bb_error_msg("Passwords do not match.");
/* return -1; */
return 1;
}
- bzero(cp, strlen(cp));
- bzero(orig, sizeof(orig));
+ memset(cp, 0, strlen(cp));
+ memset(orig, 0, sizeof(orig));
if (algo == 1) {
cp = pw_encrypt(pass, "$1$");
} else
cp = pw_encrypt(pass, crypt_make_salt());
- bzero(pass, sizeof pass);
+ memset(pass, 0, sizeof pass);
safe_strncpy(crypt_passwd, cp, sizeof(crypt_passwd));
return 0;
}
-static void set_filesize_limit(int blocks)
-{
- struct rlimit rlimit_fsize;
-
- rlimit_fsize.rlim_cur = rlimit_fsize.rlim_max = 512L * blocks;
- setrlimit(RLIMIT_FSIZE, &rlimit_fsize);
-}
More information about the busybox
mailing list