Author: bapt
Date: Sat Jul  4 15:27:04 2015
New Revision: 285133
URL: https://svnweb.freebsd.org/changeset/base/285133

Log:
  Validate input of pw usermod -h and pwusermod -H
  
  Push the code that set the password into a separate function to improve
  readability
  
  Add regression tests about pw usermod -h and pw usermod -H

Modified:
  head/usr.sbin/pw/pw.c
  head/usr.sbin/pw/pw_user.c
  head/usr.sbin/pw/pwupd.h
  head/usr.sbin/pw/tests/pw_usermod.sh

Modified: head/usr.sbin/pw/pw.c
==============================================================================
--- head/usr.sbin/pw/pw.c       Sat Jul  4 14:50:32 2015        (r285132)
+++ head/usr.sbin/pw/pw.c       Sat Jul  4 15:27:04 2015        (r285133)
@@ -137,6 +137,7 @@ main(int argc, char *argv[])
        relocated = nis = false;
        memset(&conf, 0, sizeof(conf));
        strlcpy(conf.etcpath, _PATH_PWD, sizeof(conf.etcpath));
+       conf.fd = -1;
 
        LIST_INIT(&arglist);
 
@@ -280,6 +281,35 @@ main(int argc, char *argv[])
                                errx(EX_USAGE, "Bad id '%s': %s", optarg,
                                    errstr);
                        break;
+               case 'H':
+                       if (conf.fd != -1)
+                               errx(EX_USAGE, "'-h' and '-H' are mutually "
+                                   "exclusive options");
+                       conf.precrypted = true;
+                       if (strspn(optarg, "0123456789") != strlen(optarg))
+                               errx(EX_USAGE, "'-H' expects a file 
descriptor");
+
+                       conf.fd = strtonum(optarg, 0, INT_MAX, &errstr);
+                       if (errstr != NULL)
+                               errx(EX_USAGE, "Bad file descriptor '%s': %s",
+                                   optarg, errstr);
+                       break;
+               case 'h':
+                       if (conf.fd != -1)
+                               errx(EX_USAGE, "'-h' and '-H' are mutually "
+                                   "exclusive options");
+
+                       if (strcmp(optarg, "-") == 0)
+                               conf.fd = '-';
+                       else if (strspn(optarg, "0123456789") == 
strlen(optarg)) {
+                               conf.fd = strtonum(optarg, 0, INT_MAX, &errstr);
+                               if (errstr != NULL)
+                                       errx(EX_USAGE, "'-h' expects a "
+                                           "file descriptor or '-'");
+                       } else
+                               errx(EX_USAGE, "'-h' expects a file "
+                                   "descriptor or '-'");
+                       break;
                case 'o':
                        conf.checkduplicate = true;
                        break;

Modified: head/usr.sbin/pw/pw_user.c
==============================================================================
--- head/usr.sbin/pw/pw_user.c  Sat Jul  4 14:50:32 2015        (r285132)
+++ head/usr.sbin/pw/pw_user.c  Sat Jul  4 15:27:04 2015        (r285133)
@@ -86,6 +86,67 @@ create_and_populate_homedir(int mode, st
            pwd->pw_uid, pwd->pw_dir);
 }
 
+static int
+set_passwd(struct passwd *pwd, struct carg *arg, bool update)
+{
+       int              b, istty;
+       struct termios   t, n;
+       login_cap_t     *lc;
+       char            line[_PASSWORD_LEN+1];
+       char            *p;
+
+       if (conf.fd == '-') {
+               if (!pwd->pw_passwd || *pwd->pw_passwd != '*') {
+                       pwd->pw_passwd = "*";   /* No access */
+                       return (1);
+               }
+               return (0);
+       }
+
+       if ((istty = isatty(conf.fd))) {
+               if (tcgetattr(conf.fd, &t) == -1)
+                       istty = 0;
+               else {
+                       n.c_lflag &= ~(ECHO);
+                       tcsetattr(conf.fd, TCSANOW, &n);
+                       printf("%s%spassword for user %s:",
+                           update ? "new " : "",
+                           conf.precrypted ? "encrypted " : "",
+                           pwd->pw_name);
+                       fflush(stdout);
+               }
+       }
+       b = read(conf.fd, line, sizeof(line) - 1);
+       if (istty) {    /* Restore state */
+               tcsetattr(conf.fd, TCSANOW, &t);
+               fputc('\n', stdout);
+               fflush(stdout);
+       }
+
+       if (b < 0)
+               err(EX_IOERR, "-%c file descriptor",
+                   conf.precrypted ? 'H' : 'h');
+       line[b] = '\0';
+       if ((p = strpbrk(line, "\r\n")) != NULL)
+               *p = '\0';
+       if (!*line)
+               errx(EX_DATAERR, "empty password read on file descriptor %d",
+                   conf.fd);
+       if (conf.precrypted) {
+               if (strchr(line, ':') != NULL)
+                       return EX_DATAERR;
+               pwd->pw_passwd = line;
+       } else {
+               lc = login_getpwclass(pwd);
+               if (lc == NULL ||
+                               login_setcryptfmt(lc, "sha512", NULL) == NULL)
+                       warn("setting crypt(3) format");
+               login_close(lc);
+               pwd->pw_passwd = pw_pwcrypt(line);
+       }
+       return (1);
+}
+
 /*-
  * -C config      configuration file
  * -q             quiet operation
@@ -529,66 +590,8 @@ pw_user(int mode, char *name, long id, s
                }
        }
 
-       if ((arg = getarg(args, 'h')) != NULL ||
-           (arg = getarg(args, 'H')) != NULL) {
-               if (strcmp(arg->val, "-") == 0) {
-                       if (!pwd->pw_passwd || *pwd->pw_passwd != '*') {
-                               pwd->pw_passwd = "*";   /* No access */
-                               edited = 1;
-                       }
-               } else {
-                       int             fd = atoi(arg->val);
-                       int             precrypt = (arg->ch == 'H');
-                       int             b;
-                       int             istty = isatty(fd);
-                       struct termios  t;
-                       login_cap_t     *lc;
-
-                       if (istty) {
-                               if (tcgetattr(fd, &t) == -1)
-                                       istty = 0;
-                               else {
-                                       struct termios  n = t;
-
-                                       /* Disable echo */
-                                       n.c_lflag &= ~(ECHO);
-                                       tcsetattr(fd, TCSANOW, &n);
-                                       printf("%s%spassword for user %s:",
-                                            (mode == M_UPDATE) ? "new " : "",
-                                            precrypt ? "encrypted " : "",
-                                            pwd->pw_name);
-                                       fflush(stdout);
-                               }
-                       }
-                       b = read(fd, line, sizeof(line) - 1);
-                       if (istty) {    /* Restore state */
-                               tcsetattr(fd, TCSANOW, &t);
-                               fputc('\n', stdout);
-                               fflush(stdout);
-                       }
-                       if (b < 0)
-                               err(EX_IOERR, "-%c file descriptor",
-                                   precrypt ? 'H' : 'h');
-                       line[b] = '\0';
-                       if ((p = strpbrk(line, "\r\n")) != NULL)
-                               *p = '\0';
-                       if (!*line)
-                               errx(EX_DATAERR, "empty password read on file 
descriptor %d", fd);
-                       if (precrypt) {
-                               if (strchr(line, ':') != NULL)
-                                       return EX_DATAERR;
-                               pwd->pw_passwd = line;
-                       } else {
-                               lc = login_getpwclass(pwd);
-                               if (lc == NULL ||
-                                   login_setcryptfmt(lc, "sha512", NULL) == 
NULL)
-                                       warn("setting crypt(3) format");
-                               login_close(lc);
-                               pwd->pw_passwd = pw_pwcrypt(line);
-                       }
-                       edited = 1;
-               }
-       }
+       if (conf.fd != -1)
+               edited = set_passwd(pwd, arg, mode == M_UPDATE);
 
        /*
         * Special case: -N only displays & exits

Modified: head/usr.sbin/pw/pwupd.h
==============================================================================
--- head/usr.sbin/pw/pwupd.h    Sat Jul  4 14:50:32 2015        (r285132)
+++ head/usr.sbin/pw/pwupd.h    Sat Jul  4 15:27:04 2015        (r285133)
@@ -85,10 +85,12 @@ struct pwconf {
        char             etcpath[MAXPATHLEN];
        char            *newname;
        char            *config;
+       int              fd;
        bool             dryrun;
        bool             pretty;
        bool             v7;
        bool             checkduplicate;
+       bool             precrypted;
        struct userconf *userconf;
 };
 

Modified: head/usr.sbin/pw/tests/pw_usermod.sh
==============================================================================
--- head/usr.sbin/pw/tests/pw_usermod.sh        Sat Jul  4 14:50:32 2015        
(r285132)
+++ head/usr.sbin/pw/tests/pw_usermod.sh        Sat Jul  4 15:27:04 2015        
(r285133)
@@ -119,6 +119,41 @@ user_mod_rename_too_long_body() {
                -l name_very_very_very_very_very_long
 }
 
+atf_test_case user_mod_h
+user_mod_h_body() {
+       populate_etc_skel
+
+       atf_check -s exit:0 ${PW} useradd foo
+       atf_check -s exit:0 ${PW} usermod foo -h 0 <<- EOF
+       $(echo a)
+       EOF
+       atf_check -s exit:0 -o not-match:"^foo:\*:.*" \
+               grep "^foo" ${HOME}/master.passwd
+       atf_check -s exit:0 ${PW} usermod foo -h - <<- EOF
+       $(echo b)
+       EOF
+       atf_check -s exit:0 -o match:"^foo:\*:.*" \
+               grep "^foo" ${HOME}/master.passwd
+       atf_check -e inline:"pw: '-h' expects a file descriptor or '-'\n" \
+               -s exit:64 ${PW} usermod foo -h a <<- EOF
+       $(echo a)
+       EOF
+}
+
+atf_test_case user_mod_H
+user_mod_H_body() {
+       populate_etc_skel
+
+       atf_check -s exit:0 ${PW} useradd foo
+       atf_check -s exit:0 ${PW} usermod foo -H 0 <<- EOF
+       $(echo a)
+       EOF
+       atf_check -s exit:0 -o match:"^foo:a:.*" \
+               grep "^foo" ${HOME}/master.passwd
+       atf_check -s exit:64 -e inline:"pw: '-H' expects a file descriptor\n" \
+               ${PW} usermod foo -H -
+}
+
 atf_init_test_cases() {
        atf_add_test_case user_mod
        atf_add_test_case user_mod_noupdate
@@ -130,4 +165,6 @@ atf_init_test_cases() {
        atf_add_test_case user_mod_name_noupdate
        atf_add_test_case user_mod_rename
        atf_add_test_case user_mod_rename_too_long
+       atf_add_test_case user_mod_h
+       atf_add_test_case user_mod_H
 }
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to