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.
This commit is contained in:
David Nugent 1999-10-26 08:34:09 +00:00
parent 480207ab3d
commit 2399cd14a7
4 changed files with 47 additions and 8 deletions

View File

@ -35,16 +35,20 @@ static const char rcsid[] =
#include <sys/wait.h> #include <sys/wait.h>
#include "pw.h" #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}; const char *Which[] = {"user", "group", NULL};
static const char *Combo1[] = { static const char *Combo1[] = {
"useradd", "userdel", "usermod", "usershow", "usernext", "useradd", "userdel", "usermod", "usershow", "usernext",
"lock", "unlock",
"groupadd", "groupdel", "groupmod", "groupshow", "groupnext", "groupadd", "groupdel", "groupmod", "groupshow", "groupnext",
NULL}; NULL};
static const char *Combo2[] = { static const char *Combo2[] = {
"adduser", "deluser", "moduser", "showuser", "nextuser", "adduser", "deluser", "moduser", "showuser", "nextuser",
"lock", "unlock",
"addgroup", "delgroup", "modgroup", "showgroup", "nextgroup", "addgroup", "delgroup", "modgroup", "showgroup", "nextgroup",
NULL}; NULL};
struct pwf PWF = struct pwf PWF =
{ {
@ -102,6 +106,8 @@ main(int argc, char *argv[])
"V:C:qn:u:rY", "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:c:d:e:p:g:G:ml:k:s:w:L:h:FNPY",
"V:C:qn:u:FPa7", "V:C:qn:u:FPa7",
"V:C:q",
"V:C:q",
"V:C:q" "V:C:q"
}, },
{ /* grp */ { /* grp */
@ -272,9 +278,9 @@ static void
cmdhelp(int mode, int which) cmdhelp(int mode, int which)
{ {
if (which == -1) 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) 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 { else {
/* /*

View File

@ -50,6 +50,8 @@ enum _mode
M_UPDATE, M_UPDATE,
M_PRINT, M_PRINT,
M_NEXT, M_NEXT,
M_LOCK,
M_UNLOCK,
M_NUM M_NUM
}; };

View File

@ -60,12 +60,14 @@ pw_group(struct userconf * cnf, int mode, struct cargs * args)
NULL 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 * With M_NEXT, we only need to return the
* next gid to stdout * next gid to stdout
*/ */
if (mode == M_NEXT) if (mode == M_NEXT) {
{
gid_t next = gr_gidpolicy(cnf, args); gid_t next = gr_gidpolicy(cnf, args);
if (getarg(args, 'q')) if (getarg(args, 'q'))
return next; return next;

View File

@ -55,6 +55,7 @@ static const char rcsid[] =
#endif #endif
static int randinit; static int randinit;
static char locked_str[] = "*LOCKED*";
static int print_user(struct passwd * pwd, int pretty, int v7); static int print_user(struct passwd * pwd, int pretty, int v7);
static uid_t pw_uidpolicy(struct userconf * cnf, struct cargs * args); 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; int rc;
char *p = NULL; char *p = NULL;
char *passtmp;
struct carg *a_name; struct carg *a_name;
struct carg *a_uid; struct carg *a_uid;
struct carg *arg; struct carg *arg;
@ -127,6 +129,7 @@ pw_user(struct userconf * cnf, int mode, struct cargs * args)
0 0
}; };
/* /*
* With M_NEXT, we only need to return the * With M_NEXT, we only need to return the
* next uid to stdout * 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 * 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 */ if (a_name == NULL && pwd == NULL) /* Try harder */
pwd = GETPWUID(atoi(a_uid->val)); 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 */ if (a_name == NULL) /* May be needed later */
a_name = addarg(args, 'n', newstr(pwd->pw_name)); 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 * Handle deletions now
*/ */
@ -563,7 +592,7 @@ pw_user(struct userconf * cnf, int mode, struct cargs * args)
warnc(rc, "NIS passwd update"); warnc(rc, "NIS passwd update");
/* NOTE: we treat NIS-only update errors as non-fatal */ /* 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); rc = chgpwent(a_name->val, pwd);
if (rc == -1) { if (rc == -1) {
warnx("user '%s' does not exist (NIS?)", pwd->pw_name); warnx("user '%s' does not exist (NIS?)", pwd->pw_name);