From 6d9a1b6caae301dc8c6b0d18e8c5d3ef931d1ea5 Mon Sep 17 00:00:00 2001 From: David Nugent Date: Tue, 26 Oct 1999 08:34:09 +0000 Subject: Add new functionality "lock" and "unlock" to provide a simple password locking mechanism for users. This works by prepending the string "*LOCKED*" to the password field in master.passwd to prevent successful decoding. --- pw/pw.c | 14 ++++++++++---- pw/pw.h | 2 ++ pw/pw_group.c | 6 ++++-- pw/pw_user.c | 33 +++++++++++++++++++++++++++++++-- 4 files changed, 47 insertions(+), 8 deletions(-) diff --git a/pw/pw.c b/pw/pw.c index 1da063c..2118854 100644 --- a/pw/pw.c +++ b/pw/pw.c @@ -35,16 +35,20 @@ static const char rcsid[] = #include #include "pw.h" -const char *Modes[] = {"add", "del", "mod", "show", "next", NULL}; +const char *Modes[] = { + "add", "del", "mod", "show", "next", + NULL}; const char *Which[] = {"user", "group", NULL}; static const char *Combo1[] = { "useradd", "userdel", "usermod", "usershow", "usernext", + "lock", "unlock", "groupadd", "groupdel", "groupmod", "groupshow", "groupnext", NULL}; static const char *Combo2[] = { "adduser", "deluser", "moduser", "showuser", "nextuser", + "lock", "unlock", "addgroup", "delgroup", "modgroup", "showgroup", "nextgroup", -NULL}; + NULL}; struct pwf PWF = { @@ -102,6 +106,8 @@ main(int argc, char *argv[]) "V:C:qn:u:rY", "V:C:qn:u:c:d:e:p:g:G:ml:k:s:w:L:h:FNPY", "V:C:qn:u:FPa7", + "V:C:q", + "V:C:q", "V:C:q" }, { /* grp */ @@ -272,9 +278,9 @@ static void cmdhelp(int mode, int which) { if (which == -1) - fprintf(stderr, "usage: pw [user|group] [add|del|mod|show|next] [ help | switches/values ]\n"); + fprintf(stderr, "usage:\n pw [user|group|lock|unlock] [add|del|mod|show|next] [help|switches/values]\n"); else if (mode == -1) - fprintf(stderr, "usage: pw %s [add|del|mod|show|next] [ help | switches/values ]\n", Which[which]); + fprintf(stderr, "usage:\n pw %s [add|del|mod|show|next] [help|switches/values]\n", Which[which]); else { /* diff --git a/pw/pw.h b/pw/pw.h index f85eac7..aa437ec 100644 --- a/pw/pw.h +++ b/pw/pw.h @@ -50,6 +50,8 @@ enum _mode M_UPDATE, M_PRINT, M_NEXT, + M_LOCK, + M_UNLOCK, M_NUM }; diff --git a/pw/pw_group.c b/pw/pw_group.c index 54125d8..d489a6b 100644 --- a/pw/pw_group.c +++ b/pw/pw_group.c @@ -60,12 +60,14 @@ pw_group(struct userconf * cnf, int mode, struct cargs * args) NULL }; + if (mode == M_LOCK || mode == M_UNLOCK) + errx(EX_USAGE, "'lock' command is not available for groups"); + /* * With M_NEXT, we only need to return the * next gid to stdout */ - if (mode == M_NEXT) - { + if (mode == M_NEXT) { gid_t next = gr_gidpolicy(cnf, args); if (getarg(args, 'q')) return next; diff --git a/pw/pw_user.c b/pw/pw_user.c index da6c83b..c9d2b40 100644 --- a/pw/pw_user.c +++ b/pw/pw_user.c @@ -55,6 +55,7 @@ static const char rcsid[] = #endif static int randinit; +static char locked_str[] = "*LOCKED*"; static int print_user(struct passwd * pwd, int pretty, int v7); static uid_t pw_uidpolicy(struct userconf * cnf, struct cargs * args); @@ -104,6 +105,7 @@ pw_user(struct userconf * cnf, int mode, struct cargs * args) { int rc; char *p = NULL; + char *passtmp; struct carg *a_name; struct carg *a_uid; struct carg *arg; @@ -127,6 +129,7 @@ pw_user(struct userconf * cnf, int mode, struct cargs * args) 0 }; + /* * With M_NEXT, we only need to return the * next uid to stdout @@ -303,7 +306,8 @@ pw_user(struct userconf * cnf, int mode, struct cargs * args) /* * Update, delete & print require that the user exists */ - if (mode == M_UPDATE || mode == M_DELETE || mode == M_PRINT) { + if (mode == M_UPDATE || mode == M_DELETE || + mode == M_PRINT || mode == M_LOCK || mode == M_UNLOCK) { if (a_name == NULL && pwd == NULL) /* Try harder */ pwd = GETPWUID(atoi(a_uid->val)); @@ -322,6 +326,31 @@ pw_user(struct userconf * cnf, int mode, struct cargs * args) if (a_name == NULL) /* May be needed later */ a_name = addarg(args, 'n', newstr(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); + passtmp = malloc(strlen(pwd->pw_passwd) + sizeof(locked_str)); + if (passtmp == NULL) /* disaster */ + errx(EX_UNAVAILABLE, "out of memory"); + strcpy(passtmp, locked_str); + strcat(passtmp, pwd->pw_passwd); + pwd->pw_passwd = passtmp; + } 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; + } + /* * Handle deletions now */ @@ -563,7 +592,7 @@ pw_user(struct userconf * cnf, int mode, struct cargs * args) warnc(rc, "NIS passwd update"); /* NOTE: we treat NIS-only update errors as non-fatal */ } - } else if (mode == M_UPDATE) { + } else if (mode == M_UPDATE || mode == M_LOCK || mode == M_UNLOCK) { rc = chgpwent(a_name->val, pwd); if (rc == -1) { warnx("user '%s' does not exist (NIS?)", pwd->pw_name); -- cgit v1.2.3-56-ge451