Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 11 Jul 2015 20:10:13 +0000 (UTC)
From:      Baptiste Daroussin <bapt@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r285405 - head/usr.sbin/pw
Message-ID:  <201507112010.t6BKADlU084556@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: bapt
Date: Sat Jul 11 20:10:12 2015
New Revision: 285405
URL: https://svnweb.freebsd.org/changeset/base/285405

Log:
  Isolate pw lock/unlock into a separate function

Modified:
  head/usr.sbin/pw/pw_user.c

Modified: head/usr.sbin/pw/pw_user.c
==============================================================================
--- head/usr.sbin/pw/pw_user.c	Sat Jul 11 19:41:31 2015	(r285404)
+++ head/usr.sbin/pw/pw_user.c	Sat Jul 11 20:10:12 2015	(r285405)
@@ -191,6 +191,78 @@ pw_usershow(char *name, long id, struct 
 	return (print_user(pwd));
 }
 
+static void
+perform_chgpwent(const char *name, struct passwd *pwd)
+{
+	int rc;
+
+	rc = chgpwent(name, pwd);
+	if (rc == -1)
+		errx(EX_IOERR, "user '%s' does not exist (NIS?)", pwd->pw_name);
+	else if (rc != 0)
+		err(EX_IOERR, "passwd file update");
+
+	if (conf.userconf->nispasswd && *conf.userconf->nispasswd == '/') {
+		rc = chgnispwent(conf.userconf->nispasswd, name, pwd);
+		if (rc == -1)
+			warn("User '%s' not found in NIS passwd", pwd->pw_name);
+		else
+			warn("NIS passwd update");
+		/* NOTE: NIS-only update errors are not fatal */
+	}
+}
+
+/*
+ * The M_LOCK and M_UNLOCK functions simply add or remove
+ * a "*LOCKED*" prefix from in front of the password to
+ * prevent it decoding correctly, and therefore prevents
+ * access. Of course, this only prevents access via
+ * password authentication (not ssh, kerberos or any
+ * other method that does not use the UNIX password) but
+ * that is a known limitation.
+ */
+static int
+pw_userlock(char *name, long id, int mode)
+{
+	struct passwd *pwd = NULL;
+	char *passtmp = NULL;
+	bool locked = false;
+
+	if (id < 0 && name == NULL)
+		errx(EX_DATAERR, "username or id required");
+
+	pwd = (name != NULL) ? GETPWNAM(pw_checkname(name, 0)) : GETPWUID(id);
+	if (pwd == NULL) {
+		if (name == NULL)
+			errx(EX_NOUSER, "no such uid `%ld'", id);
+		errx(EX_NOUSER, "no such user `%s'", name);
+	}
+
+	if (name == NULL)
+		name = pwd->pw_name;
+
+	if (strncmp(pwd->pw_passwd, locked_str, sizeof(locked_str) -1) == 0)
+		locked = true;
+	if (mode == M_LOCK && locked)
+		errx(EX_DATAERR, "user '%s' is already locked", pwd->pw_name);
+	if (mode == M_UNLOCK && !locked)
+		errx(EX_DATAERR, "user '%s' is not locked", pwd->pw_name);
+
+	if (mode == M_LOCK) {
+		asprintf(&passtmp, "%s%s", locked_str, pwd->pw_passwd);
+		if (passtmp == NULL)	/* disaster */
+			errx(EX_UNAVAILABLE, "out of memory");
+		pwd->pw_passwd = passtmp;
+	} else {
+		pwd->pw_passwd += sizeof(locked_str)-1;
+	}
+
+	perform_chgpwent(name, pwd);
+	free(passtmp);
+
+	return (EXIT_SUCCESS);
+}
+
 /*-
  * -C config      configuration file
  * -q             quiet operation
@@ -228,7 +300,6 @@ pw_user(int mode, char *name, long id, s
 {
 	int	        rc, edited = 0;
 	char           *p = NULL;
-	char					 *passtmp;
 	struct carg    *arg;
 	struct passwd  *pwd = NULL;
 	struct group   *grp;
@@ -268,6 +339,9 @@ pw_user(int mode, char *name, long id, s
 	if (mode == M_DELETE)
 		return (pw_userdel(name, id));
 
+	if (mode == M_LOCK || mode == M_UNLOCK)
+		return (pw_userlock(name, id, mode));
+
 	/*
 	 * We can do all of the common legwork here
 	 */
@@ -421,7 +495,7 @@ pw_user(int mode, char *name, long id, s
 	/*
 	 * Update require that the user exists
 	 */
-	if (mode == M_UPDATE || mode == M_LOCK   || mode == M_UNLOCK) {
+	if (mode == M_UPDATE) {
 
 		if (name == NULL && pwd == NULL)	/* Try harder */
 			pwd = GETPWUID(id);
@@ -436,31 +510,6 @@ pw_user(int mode, char *name, long id, s
 			name = pwd->pw_name;
 
 		/*
-		 * The M_LOCK and M_UNLOCK functions simply add or remove
-		 * a "*LOCKED*" prefix from in front of the password to
-		 * prevent it decoding correctly, and therefore prevents
-		 * access. Of course, this only prevents access via
-		 * password authentication (not ssh, kerberos or any
-		 * other method that does not use the UNIX password) but
-		 * that is a known limitation.
-		 */
-
-		if (mode == M_LOCK) {
-			if (strncmp(pwd->pw_passwd, locked_str, sizeof(locked_str)-1) == 0)
-				errx(EX_DATAERR, "user '%s' is already locked", pwd->pw_name);
-			asprintf(&passtmp, "%s%s", locked_str, pwd->pw_passwd);
-			if (passtmp == NULL)	/* disaster */
-				errx(EX_UNAVAILABLE, "out of memory");
-			pwd->pw_passwd = passtmp;
-			edited = 1;
-		} else if (mode == M_UNLOCK) {
-			if (strncmp(pwd->pw_passwd, locked_str, sizeof(locked_str)-1) != 0)
-				errx(EX_DATAERR, "user '%s' is not locked", pwd->pw_name);
-			pwd->pw_passwd += sizeof(locked_str)-1;
-			edited = 1;
-		}
-
-		/*
 		 * The rest is edit code
 		 */
 		if (conf.newname != NULL) {
@@ -635,23 +684,8 @@ pw_user(int mode, char *name, long id, s
 				warn("NIS passwd update");
 			/* NOTE: we treat NIS-only update errors as non-fatal */
 		}
-	} else if (mode == M_UPDATE || mode == M_LOCK || mode == M_UNLOCK) {
-		if (edited) {	/* Only updated this if required */
-			rc = chgpwent(name, pwd);
-			if (rc == -1)
-				errx(EX_IOERR, "user '%s' does not exist (NIS?)", pwd->pw_name);
-			else if (rc != 0)
-				err(EX_IOERR, "passwd file update");
-			if ( cnf->nispasswd && *cnf->nispasswd=='/') {
-				rc = chgnispwent(cnf->nispasswd, name, pwd);
-				if (rc == -1)
-					warn("User '%s' not found in NIS passwd", pwd->pw_name);
-				else
-					warn("NIS passwd update");
-				/* NOTE: NIS-only update errors are not fatal */
-			}
-		}
-	}
+	} else if (mode == M_UPDATE && edited) /* Only updated this if required */
+		perform_chgpwent(name, pwd);
 
 	/*
 	 * Ok, user is created or changed - now edit group file



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201507112010.t6BKADlU084556>