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:
parent
480207ab3d
commit
2399cd14a7
@ -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 {
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -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
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
@ -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);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user