summaryrefslogtreecommitdiffstats
path: root/pw/pw_user.c
diff options
context:
space:
mode:
authorBaptiste Daroussin <bapt@FreeBSD.org>2015-07-11 20:10:12 +0000
committerBaptiste Daroussin <bapt@FreeBSD.org>2015-07-11 20:10:12 +0000
commit4aab0b552a1d04d6f70d3ab16b6878477969cedd (patch)
treee31ade9a2bbec4855768b90481e936e94be2f3b2 /pw/pw_user.c
parenta7e5163d9fe3e0c757e5ff06a6471406d69312f0 (diff)
downloadpw-darwin-4aab0b552a1d04d6f70d3ab16b6878477969cedd.tar.gz
pw-darwin-4aab0b552a1d04d6f70d3ab16b6878477969cedd.tar.zst
pw-darwin-4aab0b552a1d04d6f70d3ab16b6878477969cedd.zip
Isolate pw lock/unlock into a separate function
Diffstat (limited to 'pw/pw_user.c')
-rw-r--r--pw/pw_user.c122
1 files changed, 78 insertions, 44 deletions
diff --git a/pw/pw_user.c b/pw/pw_user.c
index a375b31..b9d01a8 100644
--- a/pw/pw_user.c
+++ b/pw/pw_user.c
@@ -191,6 +191,78 @@ pw_usershow(char *name, long id, struct passwd *fakeuser)
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, struct cargs * args)
{
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, struct cargs * args)
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, struct cargs * args)
/*
* 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, struct cargs * args)
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, struct cargs * args)
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