Upgrade from the author, reflecting all my wishes resulting out of the
sysinstall use of this tool (plus some bug fixes). 2.2 candidate... Submitted by: David Nugent <davidn@nserver.usn.blaze.net.au>
This commit is contained in:
parent
222ca58f9a
commit
48aee7f33a
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/cvs2svn/branches/DAVIDN/; revision=20267
@ -8,7 +8,7 @@ SRCS= pw.c pw_conf.c pw_user.c pw_group.c pw_log.c \
|
||||
MAN5= pw.conf.5
|
||||
MAN8= pw.8
|
||||
|
||||
CFLAGS+= -Wall
|
||||
CFLAGS+= -Wall $(CDB)
|
||||
LDADD= -lcrypt
|
||||
DPADD= ${LIBCRYPT}
|
||||
|
||||
|
@ -116,3 +116,4 @@ copymkdir(char const * dir, char const * skel, mode_t mode, uid_t uid, gid_t gid
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -36,13 +36,15 @@
|
||||
|
||||
static char *progname = "pw";
|
||||
|
||||
const char *Modes[] = {"add", "del", "mod", "show", NULL};
|
||||
const char *Modes[] = {"add", "del", "mod", "show", "next", NULL};
|
||||
const char *Which[] = {"user", "group", NULL};
|
||||
static const char *Combo1[] = {"useradd", "userdel", "usermod", "usershow",
|
||||
"groupadd", "groupdel", "groupmod", "groupshow",
|
||||
NULL};
|
||||
static const char *Combo2[] = {"adduser", "deluser", "moduser", "showuser",
|
||||
"addgroup", "delgroup", "modgroup", "showgroup",
|
||||
static const char *Combo1[] = {
|
||||
"useradd", "userdel", "usermod", "usershow", "usernext",
|
||||
"groupadd", "groupdel", "groupmod", "groupshow", "groupnext",
|
||||
NULL};
|
||||
static const char *Combo2[] = {
|
||||
"adduser", "deluser", "moduser", "showuser", "nextuser",
|
||||
"addgroup", "delgroup", "modgroup", "showgroup", "nextgroup",
|
||||
NULL};
|
||||
|
||||
static struct cargs arglist;
|
||||
@ -61,8 +63,20 @@ main(int argc, char *argv[])
|
||||
|
||||
static const char *opts[W_NUM][M_NUM] =
|
||||
{
|
||||
/* user */ {"C:qn:u:c:d:e:p:g:G:mk:s:oL:i:w:h:Db", "C:qn:u:r", "C:qn:u:c:d:e:p:g:G:mk:s:L:h:F", "C:qn:u:Fpa"},
|
||||
/* grp */ {"C:qn:g:h:p", "C:qn:g:", "C:qn:g:l:h:F", "C:qn:g:Fpa"}
|
||||
{ /* user */
|
||||
"C:qn:u:c:d:e:p:g:G:mk:s:oL:i:w:h:Db:NP",
|
||||
"C:qn:u:r",
|
||||
"C:qn:u:c:d:e:p:g:G:mk:s:w:L:h:FNP",
|
||||
"C:qn:u:FPa",
|
||||
"C:q"
|
||||
},
|
||||
{ /* grp */
|
||||
"C:qn:g:h:M:pNP",
|
||||
"C:qn:g:",
|
||||
"C:qn:g:l:h:FM:m:NP",
|
||||
"C:qn:g:FPa",
|
||||
"C:q"
|
||||
}
|
||||
};
|
||||
|
||||
static int (*funcs[W_NUM]) (struct userconf * _cnf, int _mode, struct cargs * _args) =
|
||||
@ -99,7 +113,7 @@ main(int argc, char *argv[])
|
||||
else if (which != -1 && mode != -1 && arglist.lh_first == NULL)
|
||||
addarg(&arglist, 'n', argv[1]);
|
||||
else
|
||||
cmderr(X_CMDERR, "Unknown keyword `%s'\n", argv[1]);
|
||||
cmderr(EX_USAGE, "Unknown keyword `%s'\n", argv[1]);
|
||||
++argv;
|
||||
--argc;
|
||||
}
|
||||
@ -110,12 +124,6 @@ main(int argc, char *argv[])
|
||||
if (mode == -1 || which == -1)
|
||||
cmdhelp(mode, which);
|
||||
|
||||
/*
|
||||
* Must be root to attempt an update
|
||||
*/
|
||||
if (getuid() != 0 && mode != M_PRINT)
|
||||
cmderr(X_PERMERR, "you must be root to run this program\n");
|
||||
|
||||
/*
|
||||
* We know which mode we're in and what we're about to do, so now
|
||||
* let's dispatch the remaining command line args in a genric way.
|
||||
@ -125,12 +133,18 @@ main(int argc, char *argv[])
|
||||
|
||||
while ((ch = getopt(argc, argv, opts[which][mode])) != -1) {
|
||||
if (ch == '?')
|
||||
cmderr(X_CMDERR, NULL);
|
||||
cmderr(EX_USAGE, NULL);
|
||||
else
|
||||
addarg(&arglist, ch, optarg);
|
||||
optarg = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Must be root to attempt an update
|
||||
*/
|
||||
if (getuid() != 0 && mode != M_PRINT && mode != M_NEXT && getarg(&arglist, 'N')==NULL)
|
||||
cmderr(EX_NOPERM, "you must be root to run this program\n");
|
||||
|
||||
/*
|
||||
* We should immediately look for the -q 'quiet' switch so that we
|
||||
* don't bother with extraneous errors
|
||||
@ -138,19 +152,11 @@ main(int argc, char *argv[])
|
||||
if (getarg(&arglist, 'q') != NULL)
|
||||
freopen("/dev/null", "w", stderr);
|
||||
|
||||
ch = X_CMDERR;
|
||||
|
||||
/*
|
||||
* Now, let's do the common initialisation
|
||||
*/
|
||||
cnf = read_userconfig(getarg(&arglist, 'C') ? getarg(&arglist, 'C')->val : NULL);
|
||||
|
||||
if (funcs[which])
|
||||
ch = funcs[which] (cnf, mode, &arglist);
|
||||
else
|
||||
fprintf(stderr, "%s: %s[%s] not yet implemented.\n", progname, Which[which], Modes[mode]);
|
||||
|
||||
return ch;
|
||||
return funcs[which] (cnf, mode, &arglist);
|
||||
}
|
||||
|
||||
static int
|
||||
@ -197,9 +203,9 @@ cmdhelp(int mode, int which)
|
||||
{
|
||||
banner();
|
||||
if (which == -1)
|
||||
fprintf(stderr, "usage: %s [user|group] [add|del|mod|show] [ help | switches/values ]\n", progname);
|
||||
fprintf(stderr, "usage: %s [user|group] [add|del|mod|show|next] [ help | switches/values ]\n", progname);
|
||||
else if (mode == -1)
|
||||
fprintf(stderr, "usage: %s %s [add|del|mod] [ help | switches/values ]\n", progname, Which[which]);
|
||||
fprintf(stderr, "usage: %s %s [add|del|mod|show|next] [ help | switches/values ]\n", progname, Which[which]);
|
||||
else {
|
||||
|
||||
/*
|
||||
@ -225,6 +231,7 @@ cmdhelp(int mode, int which)
|
||||
"\t-o duplicate uid ok\n"
|
||||
"\t-L class user class\n"
|
||||
"\t-h fd read password on fd\n"
|
||||
"\t-N no update\n"
|
||||
" Setting defaults:\n"
|
||||
"\t-D set user defaults\n"
|
||||
"\t-b dir default home root dir\n"
|
||||
@ -258,13 +265,17 @@ cmdhelp(int mode, int which)
|
||||
"\t-L class user class\n"
|
||||
"\t-m [ -k dir ] create and set up home\n"
|
||||
"\t-s shell name of login shell\n"
|
||||
"\t-h fd read password on fd\n",
|
||||
"\t-w method set new password using method\n"
|
||||
"\t-h fd read password on fd\n"
|
||||
"\t-N no update\n",
|
||||
"usage: %s usershow [uid|name] [switches]\n"
|
||||
"\t-n name login name\n"
|
||||
"\t-u uid user id\n"
|
||||
"\t-F force print\n"
|
||||
"\t-p prettier format\n"
|
||||
"\t-a print all users\n"
|
||||
"\t-P prettier format\n"
|
||||
"\t-a print all users\n",
|
||||
"usage: %s usernext [switches]\n"
|
||||
"\t-C config configuration file\n"
|
||||
},
|
||||
{
|
||||
"usage: %s groupadd [group|gid] [switches]\n"
|
||||
@ -272,7 +283,9 @@ cmdhelp(int mode, int which)
|
||||
"\t-q quiet operation\n"
|
||||
"\t-n group group name\n"
|
||||
"\t-g gid group id\n"
|
||||
"\t-o duplicate gid ok\n",
|
||||
"\t-M usr1,usr2 add users as group members\n"
|
||||
"\t-o duplicate gid ok\n"
|
||||
"\t-N no update\n",
|
||||
"usage: %s groupdel [group|gid] [switches]\n"
|
||||
"\t-n name group name\n"
|
||||
"\t-g gid group id\n",
|
||||
@ -282,19 +295,24 @@ cmdhelp(int mode, int which)
|
||||
"\t-F force add if not exists\n"
|
||||
"\t-n name group name\n"
|
||||
"\t-g gid group id\n"
|
||||
"\t-l name new group name\n",
|
||||
"\t-M usr1,usr2 replaces users as group members\n"
|
||||
"\t-m usr1,usr2 add users as group members\n"
|
||||
"\t-l name new group name\n"
|
||||
"\t-N no update\n",
|
||||
"usage: %s groupshow [group|gid] [switches]\n"
|
||||
"\t-n name group name\n"
|
||||
"\t-g gid group id\n"
|
||||
"\t-F force print\n"
|
||||
"\t-p prettier format\n"
|
||||
"\t-a print all accounting groups\n"
|
||||
"\t-P prettier format\n"
|
||||
"\t-a print all accounting groups\n",
|
||||
"usage: %s groupnext [switches]\n"
|
||||
"\t-C config configuration file\n"
|
||||
}
|
||||
};
|
||||
|
||||
fprintf(stderr, help[which][mode], progname);
|
||||
}
|
||||
exit(X_CMDERR);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
struct carg *
|
||||
@ -313,7 +331,7 @@ addarg(struct cargs * _args, int ch, char *argstr)
|
||||
struct carg *ca = malloc(sizeof(struct carg));
|
||||
|
||||
if (ca == NULL)
|
||||
cmderr(X_MEMERR, "Abort - out of memory\n");
|
||||
cmderr(EX_OSERR, "Abort - out of memory\n");
|
||||
ca->ch = ch;
|
||||
ca->val = argstr;
|
||||
LIST_INSERT_HEAD(_args, ca, list);
|
||||
|
@ -1,10 +1,36 @@
|
||||
.\" Copyright (c) 1996
|
||||
.\" David L. Nugent.
|
||||
.\" Password/Group file maintenance suite
|
||||
.\" Password Maintenance
|
||||
.\"
|
||||
.\" $Id: pw.conf.5,v 1.2 1996/11/18 03:09:02 davidn Exp $
|
||||
.\" Redistribution and use in source and binary forms, with or without
|
||||
.\" modification, are permitted provided that the following conditions
|
||||
.\" are met:
|
||||
.\" 1. Redistributions of source code must retain the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer.
|
||||
.\" 2. Redistributions in binary form must reproduce the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer in the
|
||||
.\" documentation and/or other materials provided with the distribution.
|
||||
.\" 3. All advertising materials mentioning features or use of this software
|
||||
.\" must display the following acknowledgement:
|
||||
.\" This product includes software developed by David L. Nugent.
|
||||
.\" 4. The name of the author may not be used to endorse or promote products
|
||||
.\" derived from this software without specific prior written permission.
|
||||
.\"
|
||||
.Dd November 13, 1996
|
||||
.\" THIS SOFTWARE IS PROVIDED BY THE DAVID L. NUGENT ``AS IS'' AND
|
||||
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
.\" ARE DISCLAIMED. IN NO EVENT SHALL DAVID L. NUGENT BE LIABLE
|
||||
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
.\" SUCH DAMAGE.
|
||||
.\"
|
||||
.\" $Id$
|
||||
.\"
|
||||
.Dd December 9, 1996
|
||||
.Dt PW.CONF 5
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -64,7 +90,7 @@ default shell (without path)
|
||||
default group
|
||||
.It extragroups
|
||||
add new users to this groups
|
||||
.It loginclass
|
||||
.It defaultclass
|
||||
place new users in this login class
|
||||
.It minuid
|
||||
.It maxuid
|
||||
@ -200,7 +226,7 @@ their own created automatically.
|
||||
This is the recommended procedure for new users as it best secures each
|
||||
user's files against interference by other users of the system
|
||||
irrespective of the
|
||||
.Em umask .
|
||||
.Em umask
|
||||
normally used by the user.
|
||||
.Pp
|
||||
.Ar extragroups
|
||||
@ -212,11 +238,18 @@ This is useful where all users share some resources, and is preferable
|
||||
to placing users into the same primary group.
|
||||
The effect of this keyword can be overridden using the
|
||||
.Ql \&-G
|
||||
option on
|
||||
.Xr pw 8 's
|
||||
option on the
|
||||
.Xr pw 8
|
||||
command line.
|
||||
.Pp
|
||||
The
|
||||
.Ar defaultclass
|
||||
field determines the login class (See
|
||||
.Xr login.conf 5 )
|
||||
that new users will be allocated unless overwritten by
|
||||
.Xr pw 8 .
|
||||
.Pp
|
||||
The
|
||||
.Ar minuid ,
|
||||
.Ar maxuid ,
|
||||
.Ar mingid ,
|
||||
@ -259,6 +292,7 @@ as comments.
|
||||
.El
|
||||
.Sh SEE ALSO
|
||||
.Xr pw 8 ,
|
||||
.Xr login.conf 5 ,
|
||||
.Xr passwd 1 ,
|
||||
.Xr passwd 5 ,
|
||||
.Xr group 5
|
||||
|
@ -43,6 +43,7 @@
|
||||
#include <pwd.h>
|
||||
#include <grp.h>
|
||||
#include <sys/queue.h>
|
||||
#include <sysexits.h>
|
||||
|
||||
#include "psdate.h"
|
||||
|
||||
@ -52,6 +53,7 @@ enum _mode
|
||||
M_DELETE,
|
||||
M_UPDATE,
|
||||
M_PRINT,
|
||||
M_NEXT,
|
||||
M_NUM
|
||||
};
|
||||
|
||||
@ -62,21 +64,6 @@ enum _which
|
||||
W_NUM
|
||||
};
|
||||
|
||||
enum _excode
|
||||
{
|
||||
X_ALLOK,
|
||||
X_CMDERR,
|
||||
X_PERMERR,
|
||||
X_MEMERR,
|
||||
X_NOUPDATE,
|
||||
X_NOTFOUND,
|
||||
X_UPDERROR,
|
||||
X_TOOMANY,
|
||||
X_EXISTS,
|
||||
X_DBERROR,
|
||||
X_CONFIG
|
||||
};
|
||||
|
||||
struct carg
|
||||
{
|
||||
int ch;
|
||||
|
@ -60,18 +60,31 @@ pw_group(struct userconf * cnf, int mode, struct cargs * args)
|
||||
NULL
|
||||
};
|
||||
|
||||
/*
|
||||
* With M_NEXT, we only need to return the
|
||||
* next gid to stdout
|
||||
*/
|
||||
if (mode == M_NEXT)
|
||||
{
|
||||
gid_t next = gr_gidpolicy(cnf, args);
|
||||
if (getarg(args, 'q'))
|
||||
return next;
|
||||
printf("%ld\n", (long)next);
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
if (mode == M_PRINT && getarg(args, 'a')) {
|
||||
int pretty = getarg(args, 'p') != NULL;
|
||||
int pretty = getarg(args, 'P') != NULL;
|
||||
|
||||
setgrent();
|
||||
while ((grp = getgrent()) != NULL)
|
||||
print_group(grp, pretty);
|
||||
endgrent();
|
||||
return X_ALLOK;
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
if (a_gid == NULL) {
|
||||
if (a_name == NULL)
|
||||
cmderr(X_CMDERR, "group name or id required\n");
|
||||
cmderr(EX_DATAERR, "group name or id required\n");
|
||||
|
||||
if (mode != M_ADD && grp == NULL && isdigit(*a_name->val)) {
|
||||
(a_gid = a_name)->ch = 'g';
|
||||
@ -88,9 +101,9 @@ pw_group(struct userconf * cnf, int mode, struct cargs * args)
|
||||
if (mode == M_PRINT && getarg(args, 'F')) {
|
||||
fakegroup.gr_name = a_name ? a_name->val : "nogroup";
|
||||
fakegroup.gr_gid = a_gid ? (gid_t) atol(a_gid->val) : -1;
|
||||
return print_group(&fakegroup, getarg(args, 'p') != NULL);
|
||||
return print_group(&fakegroup, getarg(args, 'P') != NULL);
|
||||
}
|
||||
cmderr(X_CMDERR, "unknown group `%s'\n", a_name ? a_name->val : a_gid->val);
|
||||
cmderr(EX_DATAERR, "unknown group `%s'\n", a_name ? a_name->val : a_gid->val);
|
||||
}
|
||||
if (a_name == NULL) /* Needed later */
|
||||
a_name = addarg(args, 'n', grp->gr_name);
|
||||
@ -102,11 +115,11 @@ pw_group(struct userconf * cnf, int mode, struct cargs * args)
|
||||
gid_t gid = grp->gr_gid;
|
||||
|
||||
if (delgrent(grp) == -1)
|
||||
cmderr(X_NOUPDATE, "Error updating group file: %s\n", strerror(errno));
|
||||
cmderr(EX_IOERR, "Error updating group file: %s\n", strerror(errno));
|
||||
pw_log(cnf, mode, W_GROUP, "%s(%ld) removed", a_name->val, (long) gid);
|
||||
return X_ALLOK;
|
||||
return EXIT_SUCCESS;
|
||||
} else if (mode == M_PRINT)
|
||||
return print_group(grp, getarg(args, 'p') != NULL);
|
||||
return print_group(grp, getarg(args, 'P') != NULL);
|
||||
|
||||
if (a_gid)
|
||||
grp->gr_gid = (gid_t) atoi(a_gid->val);
|
||||
@ -115,9 +128,9 @@ pw_group(struct userconf * cnf, int mode, struct cargs * args)
|
||||
grp->gr_name = arg->val;
|
||||
} else {
|
||||
if (a_name == NULL) /* Required */
|
||||
cmderr(X_CMDERR, "group name required\n");
|
||||
cmderr(EX_DATAERR, "group name required\n");
|
||||
else if (grp != NULL) /* Exists */
|
||||
cmderr(X_EXISTS, "group name `%s' already exists\n", a_name->val);
|
||||
cmderr(EX_DATAERR, "group name `%s' already exists\n", a_name->val);
|
||||
|
||||
memset(members, 0, sizeof members);
|
||||
grp = &fakegroup;
|
||||
@ -165,27 +178,61 @@ pw_group(struct userconf * cnf, int mode, struct cargs * args)
|
||||
}
|
||||
if (b < 0) {
|
||||
perror("-h file descriptor");
|
||||
return X_CMDERR;
|
||||
return EX_OSERR;
|
||||
}
|
||||
line[b] = '\0';
|
||||
if ((p = strpbrk(line, " \t\r\n")) != NULL)
|
||||
*p = '\0';
|
||||
if (!*line)
|
||||
cmderr(X_CMDERR, "empty password read on file descriptor %d\n", fd);
|
||||
cmderr(EX_DATAERR, "empty password read on file descriptor %d\n", fd);
|
||||
grp->gr_passwd = pw_pwcrypt(line);
|
||||
}
|
||||
}
|
||||
|
||||
if (((arg = getarg(args, 'M')) != NULL || (arg = getarg(args, 'm')) != NULL) && arg->val) {
|
||||
int i = 0;
|
||||
char *p;
|
||||
struct passwd *pwd;
|
||||
|
||||
if (arg->ch == 'm') {
|
||||
while (i < _UC_MAXGROUPS && grp->gr_mem[i] != NULL) {
|
||||
members[i] = grp->gr_mem[i];
|
||||
i++;
|
||||
}
|
||||
}
|
||||
for (p = strtok(arg->val, ", \t"); i < _UC_MAXGROUPS && p != NULL; p = strtok(NULL, ", \t")) {
|
||||
int j;
|
||||
if ((pwd = getpwnam(p)) == NULL) {
|
||||
if (!isdigit(*p) || (pwd = getpwuid((uid_t) atoi(p))) == NULL)
|
||||
cmderr(EX_NOUSER, "user `%s' does not exist\n", p);
|
||||
}
|
||||
/*
|
||||
* Check for duplicates
|
||||
*/
|
||||
for (j = 0; j < i && strcmp(members[j], pwd->pw_name)!=0; j++)
|
||||
;
|
||||
if (j == i)
|
||||
members[i++] = newstr(pwd->pw_name);
|
||||
}
|
||||
while (i < _UC_MAXGROUPS)
|
||||
members[i++] = NULL;
|
||||
grp->gr_mem = members;
|
||||
}
|
||||
|
||||
if (getarg(args, 'N') != NULL)
|
||||
return print_group(grp, getarg(args, 'P') != NULL);
|
||||
|
||||
if ((mode == M_ADD && !addgrent(grp)) || (mode == M_UPDATE && !chggrent(a_name->val, grp))) {
|
||||
perror("group update");
|
||||
return X_NOUPDATE;
|
||||
return EX_IOERR;
|
||||
}
|
||||
/* grp may have been invalidated */
|
||||
if ((grp = getgrnam(a_name->val)) == NULL)
|
||||
cmderr(X_NOTFOUND, "group disappeared during update\n");
|
||||
cmderr(EX_SOFTWARE, "group disappeared during update\n");
|
||||
|
||||
pw_log(cnf, mode, W_GROUP, "%s(%ld)", grp->gr_name, (long) grp->gr_gid);
|
||||
|
||||
return X_ALLOK;
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
@ -203,7 +250,7 @@ gr_gidpolicy(struct userconf * cnf, struct cargs * args)
|
||||
gid = (gid_t) atol(a_gid->val);
|
||||
|
||||
if ((grp = getgrgid(gid)) != NULL && getarg(args, 'o') == NULL)
|
||||
cmderr(X_EXISTS, "gid `%ld' has already been allocated\n", (long) grp->gr_gid);
|
||||
cmderr(EX_DATAERR, "gid `%ld' has already been allocated\n", (long) grp->gr_gid);
|
||||
} else {
|
||||
struct bitmap bm;
|
||||
|
||||
@ -244,7 +291,7 @@ gr_gidpolicy(struct userconf * cnf, struct cargs * args)
|
||||
* Another sanity check
|
||||
*/
|
||||
if (gid < cnf->min_gid || gid > cnf->max_gid)
|
||||
cmderr(X_EXISTS, "unable to allocate a new gid - range fully used\n");
|
||||
cmderr(EX_SOFTWARE, "unable to allocate a new gid - range fully used\n");
|
||||
bm_dealloc(&bm);
|
||||
}
|
||||
return gid;
|
||||
@ -269,5 +316,5 @@ print_group(struct group * grp, int pretty)
|
||||
printf("%s%s", i ? "," : "", grp->gr_mem[i]);
|
||||
fputs("\n\n", stdout);
|
||||
}
|
||||
return X_ALLOK;
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
@ -112,13 +112,28 @@ pw_user(struct userconf * cnf, int mode, struct cargs * args)
|
||||
0
|
||||
};
|
||||
|
||||
/*
|
||||
* With M_NEXT, we only need to return the
|
||||
* next uid to stdout
|
||||
*/
|
||||
if (mode == M_NEXT)
|
||||
{
|
||||
uid_t next = pw_uidpolicy(cnf, args);
|
||||
if (getarg(args, 'q'))
|
||||
return next;
|
||||
printf("%ld:", (long)next);
|
||||
pw_group(cnf, mode, args);
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
* We can do all of the common legwork here
|
||||
*/
|
||||
|
||||
if ((arg = getarg(args, 'b')) != NULL) {
|
||||
if (stat(cnf->home = arg->val, &st) == -1 || S_ISDIR(st.st_mode))
|
||||
cmderr(X_CMDERR, "root home `%s' is not a directory or does not exist\n", cnf->home);
|
||||
cnf->home = arg->val;
|
||||
if (stat(cnf->home, &st) == -1 || !S_ISDIR(st.st_mode))
|
||||
cmderr(EX_OSFILE, "root home `%s' is not a directory or does not exist\n", cnf->home);
|
||||
}
|
||||
if ((arg = getarg(args, 'e')) != NULL)
|
||||
cnf->expire_days = atoi(arg->val);
|
||||
@ -130,7 +145,7 @@ pw_user(struct userconf * cnf, int mode, struct cargs * args)
|
||||
p = arg->val;
|
||||
if ((grp = getgrnam(p)) == NULL) {
|
||||
if (!isdigit(*p) || (grp = getgrgid((gid_t) atoi(p))) == NULL)
|
||||
cmderr(X_NOTFOUND, "group `%s' does not exist\n", p);
|
||||
cmderr(EX_NOUSER, "group `%s' does not exist\n", p);
|
||||
}
|
||||
cnf->default_group = newstr(grp->gr_name);
|
||||
}
|
||||
@ -143,7 +158,7 @@ pw_user(struct userconf * cnf, int mode, struct cargs * args)
|
||||
for (p = strtok(arg->val, ", \t"); i < _UC_MAXGROUPS && p != NULL; p = strtok(NULL, ", \t")) {
|
||||
if ((grp = getgrnam(p)) == NULL) {
|
||||
if (!isdigit(*p) || (grp = getgrgid((gid_t) atoi(p))) == NULL)
|
||||
cmderr(X_NOTFOUND, "group `%s' does not exist\n", p);
|
||||
cmderr(EX_NOUSER, "group `%s' does not exist\n", p);
|
||||
}
|
||||
cnf->groups[i++] = newstr(grp->gr_name);
|
||||
}
|
||||
@ -152,14 +167,14 @@ pw_user(struct userconf * cnf, int mode, struct cargs * args)
|
||||
}
|
||||
if ((arg = getarg(args, 'k')) != NULL) {
|
||||
if (stat(cnf->dotdir = arg->val, &st) == -1 || S_ISDIR(st.st_mode))
|
||||
cmderr(X_CMDERR, "skeleton `%s' is not a directory or does not exist\n", cnf->dotdir);
|
||||
cmderr(EX_OSFILE, "skeleton `%s' is not a directory or does not exist\n", cnf->dotdir);
|
||||
}
|
||||
if ((arg = getarg(args, 's')) != NULL)
|
||||
cnf->shell_default = arg->val;
|
||||
|
||||
if (mode == M_ADD && getarg(args, 'D')) {
|
||||
if (getarg(args, 'n') != NULL)
|
||||
cmderr(X_CMDERR, "can't combine `-D' with `-n name'\n");
|
||||
cmderr(EX_DATAERR, "can't combine `-D' with `-n name'\n");
|
||||
if ((arg = getarg(args, 'u')) != NULL && (p = strtok(arg->val, ", \t")) != NULL) {
|
||||
if ((cnf->min_uid = (uid_t) atoi(p)) == 0)
|
||||
cnf->min_uid = 1000;
|
||||
@ -177,18 +192,18 @@ pw_user(struct userconf * cnf, int mode, struct cargs * args)
|
||||
|
||||
arg = getarg(args, 'C');
|
||||
if (write_userconfig(arg ? arg->val : NULL))
|
||||
return X_ALLOK;
|
||||
return EXIT_SUCCESS;
|
||||
perror("config update");
|
||||
return X_UPDERROR;
|
||||
return EX_IOERR;
|
||||
}
|
||||
if (mode == M_PRINT && getarg(args, 'a')) {
|
||||
int pretty = getarg(args, 'p') != NULL;
|
||||
int pretty = getarg(args, 'P') != NULL;
|
||||
|
||||
setpwent();
|
||||
while ((pwd = getpwent()) != NULL)
|
||||
print_user(pwd, pretty);
|
||||
endpwent();
|
||||
return X_ALLOK;
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
if ((a_name = getarg(args, 'n')) != NULL)
|
||||
pwd = getpwnam(pw_checkname(a_name->val, 0));
|
||||
@ -196,7 +211,7 @@ pw_user(struct userconf * cnf, int mode, struct cargs * args)
|
||||
|
||||
if (a_uid == NULL) {
|
||||
if (a_name == NULL)
|
||||
cmderr(X_CMDERR, "user name or id required\n");
|
||||
cmderr(EX_DATAERR, "user name or id required\n");
|
||||
|
||||
/*
|
||||
* Determine whether 'n' switch is name or uid - we don't
|
||||
@ -219,11 +234,11 @@ pw_user(struct userconf * cnf, int mode, struct cargs * args)
|
||||
if (mode == M_PRINT && getarg(args, 'F')) {
|
||||
fakeuser.pw_name = a_name ? a_name->val : "nouser";
|
||||
fakeuser.pw_uid = a_uid ? (uid_t) atol(a_uid->val) : -1;
|
||||
return print_user(&fakeuser, getarg(args, 'p') != NULL);
|
||||
return print_user(&fakeuser, getarg(args, 'P') != NULL);
|
||||
}
|
||||
if (a_name == NULL)
|
||||
cmderr(X_NOTFOUND, "no such uid `%s'\n", a_uid->val);
|
||||
cmderr(X_NOTFOUND, "no such user `%s'\n", a_name->val);
|
||||
cmderr(EX_NOUSER, "no such uid `%s'\n", a_uid->val);
|
||||
cmderr(EX_NOUSER, "no such user `%s'\n", a_name->val);
|
||||
}
|
||||
if (a_name == NULL) /* May be needed later */
|
||||
a_name = addarg(args, 'n', newstr(pwd->pw_name));
|
||||
@ -237,7 +252,7 @@ pw_user(struct userconf * cnf, int mode, struct cargs * args)
|
||||
uid_t uid = pwd->pw_uid;
|
||||
|
||||
if (strcmp(pwd->pw_name, "root") == 0)
|
||||
cmderr(X_CMDERR, "cannot remove user 'root'\n");
|
||||
cmderr(EX_DATAERR, "cannot remove user 'root'\n");
|
||||
|
||||
/*
|
||||
* Remove crontabs
|
||||
@ -256,7 +271,7 @@ pw_user(struct userconf * cnf, int mode, struct cargs * args)
|
||||
home[sizeof home - 1] = '\0';
|
||||
|
||||
if (!delpwent(pwd))
|
||||
cmderr(X_NOUPDATE, "Error updating passwd file: %s\n", strerror(errno));
|
||||
cmderr(EX_IOERR, "Error updating passwd file: %s\n", strerror(errno));
|
||||
editgroups(a_name->val, NULL);
|
||||
|
||||
pw_log(cnf, mode, W_USER, "%s(%ld) account removed", a_name->val, (long) uid);
|
||||
@ -283,22 +298,22 @@ pw_user(struct userconf * cnf, int mode, struct cargs * args)
|
||||
stat(home, &st) == -1 ? "" : "not completely ");
|
||||
}
|
||||
}
|
||||
return X_ALLOK;
|
||||
return EXIT_SUCCESS;
|
||||
} else if (mode == M_PRINT)
|
||||
return print_user(pwd, getarg(args, 'p') != NULL);
|
||||
return print_user(pwd, getarg(args, 'P') != NULL);
|
||||
|
||||
/*
|
||||
* The rest is edit code
|
||||
*/
|
||||
if ((arg = getarg(args, 'l')) != NULL) {
|
||||
if (strcmp(pwd->pw_name, "root") == 0)
|
||||
cmderr(X_CMDERR, "can't rename `root' account\n");
|
||||
cmderr(EX_DATAERR, "can't rename `root' account\n");
|
||||
pwd->pw_name = pw_checkname(arg->val, 0);
|
||||
}
|
||||
if ((arg = getarg(args, 'u')) != NULL && isdigit(*arg->val)) {
|
||||
pwd->pw_uid = (uid_t) atol(arg->val);
|
||||
if (pwd->pw_uid != 0 && strcmp(pwd->pw_name, "root") == 0)
|
||||
cmderr(X_CMDERR, "can't change uid of `root' account\n");
|
||||
cmderr(EX_DATAERR, "can't change uid of `root' account\n");
|
||||
if (pwd->pw_uid == 0 && strcmp(pwd->pw_name, "root") != 0)
|
||||
fprintf(stderr, "WARNING: account `%s' will have a uid of 0 (superuser access!)\n", pwd->pw_name);
|
||||
}
|
||||
@ -313,11 +328,11 @@ pw_user(struct userconf * cnf, int mode, struct cargs * args)
|
||||
time_t expire = parse_date(now, arg->val);
|
||||
|
||||
if (now == expire)
|
||||
cmderr(X_CMDERR, "Invalid password change date `%s'\n", arg->val);
|
||||
cmderr(EX_DATAERR, "Invalid password change date `%s'\n", arg->val);
|
||||
pwd->pw_change = expire;
|
||||
}
|
||||
}
|
||||
if ((arg = getarg(args, 'p')) != NULL) {
|
||||
if ((arg = getarg(args, 'e')) != NULL) {
|
||||
if (*arg->val == '\0' || strcmp(arg->val, "0") == 0)
|
||||
pwd->pw_expire = 0;
|
||||
else {
|
||||
@ -325,7 +340,7 @@ pw_user(struct userconf * cnf, int mode, struct cargs * args)
|
||||
time_t expire = parse_date(now, arg->val);
|
||||
|
||||
if (now == expire)
|
||||
cmderr(X_CMDERR, "Invalid password change date `%s'\n", arg->val);
|
||||
cmderr(EX_DATAERR, "Invalid account expiry date `%s'\n", arg->val);
|
||||
pwd->pw_expire = expire;
|
||||
}
|
||||
}
|
||||
@ -335,11 +350,14 @@ pw_user(struct userconf * cnf, int mode, struct cargs * args)
|
||||
if (getarg(args, 'L'))
|
||||
pwd->pw_class = cnf->default_class;
|
||||
|
||||
if ((arg = getarg(args, 'w')) != NULL && getarg(args, 'h') == NULL)
|
||||
pwd->pw_passwd = pw_password(cnf, args, pwd->pw_name);
|
||||
|
||||
} else {
|
||||
if (a_name == NULL) /* Required */
|
||||
cmderr(X_CMDERR, "login name required\n");
|
||||
cmderr(EX_DATAERR, "login name required\n");
|
||||
else if ((pwd = getpwnam(a_name->val)) != NULL) /* Exists */
|
||||
cmderr(X_EXISTS, "login name `%s' already exists\n", a_name->val);
|
||||
cmderr(EX_DATAERR, "login name `%s' already exists\n", a_name->val);
|
||||
|
||||
/*
|
||||
* Now, set up defaults for a new user
|
||||
@ -395,20 +413,27 @@ pw_user(struct userconf * cnf, int mode, struct cargs * args)
|
||||
}
|
||||
if (b < 0) {
|
||||
perror("-h file descriptor");
|
||||
return X_CMDERR;
|
||||
return EX_IOERR;
|
||||
}
|
||||
line[b] = '\0';
|
||||
if ((p = strpbrk(line, " \t\r\n")) != NULL)
|
||||
*p = '\0';
|
||||
if (!*line)
|
||||
cmderr(X_CMDERR, "empty password read on file descriptor %d\n", fd);
|
||||
cmderr(EX_DATAERR, "empty password read on file descriptor %d\n", fd);
|
||||
pwd->pw_passwd = pw_pwcrypt(line);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Special case: -N only displays & exits
|
||||
*/
|
||||
if (getarg(args, 'N') != NULL)
|
||||
return print_user(pwd, getarg(args, 'P') != NULL);
|
||||
|
||||
if ((mode == M_ADD && !addpwent(pwd)) ||
|
||||
(mode == M_UPDATE && !chgpwent(a_name->val, pwd))) {
|
||||
perror("password update");
|
||||
return X_NOUPDATE;
|
||||
return EX_IOERR;
|
||||
}
|
||||
/*
|
||||
* Ok, user is created or changed - now edit group file
|
||||
@ -419,7 +444,7 @@ pw_user(struct userconf * cnf, int mode, struct cargs * args)
|
||||
|
||||
/* pwd may have been invalidated */
|
||||
if ((pwd = getpwnam(a_name->val)) == NULL)
|
||||
cmderr(X_NOTFOUND, "user '%s' disappeared during update\n", a_name->val);
|
||||
cmderr(EX_NOUSER, "user '%s' disappeared during update\n", a_name->val);
|
||||
|
||||
grp = getgrgid(pwd->pw_gid);
|
||||
pw_log(cnf, mode, W_USER, "%s(%ld):%s(%d):%s:%s:%s",
|
||||
@ -471,7 +496,7 @@ pw_user(struct userconf * cnf, int mode, struct cargs * args)
|
||||
pw_log(cnf, mode, W_USER, "%s(%ld) home %s made",
|
||||
pwd->pw_name, (long) pwd->pw_uid, pwd->pw_dir);
|
||||
}
|
||||
return X_ALLOK;
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
@ -489,7 +514,7 @@ pw_uidpolicy(struct userconf * cnf, struct cargs * args)
|
||||
uid = (uid_t) atol(a_uid->val);
|
||||
|
||||
if ((pwd = getpwuid(uid)) != NULL && getarg(args, 'o') == NULL)
|
||||
cmderr(X_EXISTS, "uid `%ld' has already been allocated\n", (long) pwd->pw_uid);
|
||||
cmderr(EX_DATAERR, "uid `%ld' has already been allocated\n", (long) pwd->pw_uid);
|
||||
} else {
|
||||
struct bitmap bm;
|
||||
|
||||
@ -524,7 +549,7 @@ pw_uidpolicy(struct userconf * cnf, struct cargs * args)
|
||||
* Another sanity check
|
||||
*/
|
||||
if (uid < cnf->min_uid || uid > cnf->max_uid)
|
||||
cmderr(X_EXISTS, "unable to allocate a new uid - range fully used\n");
|
||||
cmderr(EX_SOFTWARE, "unable to allocate a new uid - range fully used\n");
|
||||
bm_dealloc(&bm);
|
||||
}
|
||||
return uid;
|
||||
@ -547,15 +572,16 @@ pw_gidpolicy(struct userconf * cnf, struct cargs * args, char *nam, gid_t prefer
|
||||
/*
|
||||
* Check the given gid, if any
|
||||
*/
|
||||
setgrent();
|
||||
if (a_gid != NULL) {
|
||||
setgrent();
|
||||
if ((grp = getgrnam(a_gid->val)) == NULL) {
|
||||
gid = (gid_t) atol(a_gid->val);
|
||||
if ((gid == 0 && !isdigit(*a_gid->val)) || (grp = getgrgid(gid)) == NULL)
|
||||
cmderr(X_NOTFOUND, "group `%s' is not defined\n", a_gid->val);
|
||||
cmderr(EX_NOUSER, "group `%s' is not defined\n", a_gid->val);
|
||||
}
|
||||
endgrent();
|
||||
gid = grp->gr_gid;
|
||||
} else if ((grp = getgrnam(nam)) != NULL && grp->gr_mem[0] == NULL) {
|
||||
gid = grp->gr_gid; /* Already created? Use it anyway... */
|
||||
} else {
|
||||
struct cargs grpargs;
|
||||
char tmp[32];
|
||||
@ -576,18 +602,26 @@ pw_gidpolicy(struct userconf * cnf, struct cargs * args, char *nam, gid_t prefer
|
||||
sprintf(tmp, "%lu", (unsigned long) prefer);
|
||||
addarg(&grpargs, 'g', tmp);
|
||||
}
|
||||
endgrent();
|
||||
pw_group(cnf, M_ADD, &grpargs);
|
||||
if (getarg(args, 'N'))
|
||||
{
|
||||
addarg(&grpargs, 'N', NULL);
|
||||
addarg(&grpargs, 'q', NULL);
|
||||
gid = pw_group(cnf, M_NEXT, &grpargs);
|
||||
}
|
||||
else
|
||||
{
|
||||
pw_group(cnf, M_ADD, &grpargs);
|
||||
if ((grp = getgrnam(nam)) != NULL)
|
||||
gid = grp->gr_gid;
|
||||
}
|
||||
a_gid = grpargs.lh_first;
|
||||
while (a_gid != NULL) {
|
||||
struct carg *t = a_gid->list.le_next;
|
||||
|
||||
LIST_REMOVE(a_gid, list);
|
||||
a_gid = t;
|
||||
}
|
||||
if ((grp = getgrnam(nam)) != NULL)
|
||||
gid = grp->gr_gid;
|
||||
}
|
||||
endgrent();
|
||||
return gid;
|
||||
}
|
||||
|
||||
@ -601,7 +635,7 @@ pw_pwdpolicy(struct userconf * cnf, struct cargs * args)
|
||||
|
||||
if (arg != NULL) {
|
||||
if ((result = parse_date(now, arg->val)) == now)
|
||||
cmderr(X_NOTFOUND, "invalid date/time `%s'\n", arg->val);
|
||||
cmderr(EX_DATAERR, "invalid date/time `%s'\n", arg->val);
|
||||
} else if (cnf->password_days > 0)
|
||||
result = now + ((long) cnf->password_days * 86400L);
|
||||
return result;
|
||||
@ -617,7 +651,7 @@ pw_exppolicy(struct userconf * cnf, struct cargs * args)
|
||||
|
||||
if (arg != NULL) {
|
||||
if ((result = parse_date(now, arg->val)) == now)
|
||||
cmderr(X_NOTFOUND, "invalid date/time `%s'\n", arg->val);
|
||||
cmderr(EX_DATAERR, "invalid date/time `%s'\n", arg->val);
|
||||
} else if (cnf->expire_days > 0)
|
||||
result = now + ((long) cnf->expire_days * 86400L);
|
||||
return result;
|
||||
@ -635,7 +669,7 @@ pw_homepolicy(struct userconf * cnf, struct cargs * args, char const * user)
|
||||
static char home[128];
|
||||
|
||||
if (cnf->home == NULL || *cnf->home == '\0')
|
||||
cmderr(X_NOTFOUND, "no base home directory set\n");
|
||||
cmderr(EX_CONFIG, "no base home directory set\n");
|
||||
sprintf(home, "%s/%s", cnf->home, user);
|
||||
return home;
|
||||
}
|
||||
@ -671,8 +705,8 @@ shell_path(char const * path, char *shells[], char *sh)
|
||||
}
|
||||
}
|
||||
if (sh == NULL)
|
||||
cmderr(X_CMDERR, "can't find shell `%s' in shell paths\n", sh);
|
||||
cmderr(X_CMDERR, "no default shell available or defined\n");
|
||||
cmderr(EX_OSFILE, "can't find shell `%s' in shell paths\n", sh);
|
||||
cmderr(EX_CONFIG, "no default shell available or defined\n");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
@ -728,7 +762,7 @@ pw_password(struct userconf * cnf, struct cargs * args, char const * user)
|
||||
/*
|
||||
* We give this information back to the user
|
||||
*/
|
||||
if (getarg(args, 'h') == NULL) {
|
||||
if (getarg(args, 'h') == NULL && getarg(args, 'N') == NULL) {
|
||||
if (isatty(0))
|
||||
printf("Password is: ");
|
||||
printf("%s\n", pwbuf);
|
||||
@ -761,6 +795,7 @@ print_user(struct passwd * pwd, int pretty)
|
||||
fmtpwent(buf, pwd);
|
||||
fputs(buf, stdout);
|
||||
} else {
|
||||
int j;
|
||||
char *p;
|
||||
struct group *grp = getgrgid(pwd->pw_gid);
|
||||
char uname[60] = "User &", office[60] = "[None]",
|
||||
@ -797,13 +832,31 @@ print_user(struct passwd * pwd, int pretty)
|
||||
" Full Name : %s\n"
|
||||
" Home : %-32.32s Class : %s\n"
|
||||
" Shell : %-32.32s Office : %s\n"
|
||||
"Work Phone : %-32.32s Home Phone : %s\n\n",
|
||||
"Work Phone : %-32.32s Home Phone : %s\n",
|
||||
|
||||
pwd->pw_name, (long) pwd->pw_uid,
|
||||
grp ? grp->gr_name : "(invalid)", (long) pwd->pw_gid,
|
||||
uname, pwd->pw_dir, pwd->pw_class,
|
||||
pwd->pw_shell, office, wphone, hphone);
|
||||
setgrent();
|
||||
j = 0;
|
||||
while ((grp=getgrent()) != NULL)
|
||||
{
|
||||
int i = 0;
|
||||
while (i < _UC_MAXGROUPS && grp->gr_mem[i] != NULL)
|
||||
{
|
||||
if (strcmp(grp->gr_mem[i], pwd->pw_name)==0)
|
||||
{
|
||||
printf(j++ == 0 ? " Groups : %s" : ",%s", grp->gr_name);
|
||||
break;
|
||||
}
|
||||
++i;
|
||||
}
|
||||
}
|
||||
endgrent();
|
||||
printf("%s\n", j ? "\n" : "");
|
||||
}
|
||||
return X_ALLOK;
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
static char *
|
||||
@ -814,11 +867,11 @@ pw_checkname(char *name, int gecos)
|
||||
|
||||
while (name[l]) {
|
||||
if (strchr(notch, name[l]) != NULL || name[l] < ' ')
|
||||
cmderr(X_CMDERR, "invalid character `%c' in field\n", name[l]);
|
||||
cmderr(EX_DATAERR, "invalid character `%c' in field\n", name[l]);
|
||||
++l;
|
||||
}
|
||||
if (!gecos && l > 8)
|
||||
cmderr(X_CMDERR, "name too long `%s'\n", name);
|
||||
cmderr(EX_DATAERR, "name too long `%s'\n", name);
|
||||
return name;
|
||||
}
|
||||
|
||||
|
@ -45,6 +45,8 @@
|
||||
|
||||
#include "pwupd.h"
|
||||
|
||||
#define HAVE_PWDB_C 1
|
||||
|
||||
static int
|
||||
pwdb(char *arg,...)
|
||||
{
|
||||
@ -114,8 +116,13 @@ pw_update(struct passwd * pwd, char const * user, int mode)
|
||||
|
||||
/*
|
||||
* First, let's check the see if the database is alright
|
||||
* Note: -c is only available in FreeBSD 2.2 and above
|
||||
*/
|
||||
#ifdef HAVE_PWDB_C
|
||||
if (pwdb("-c", NULL) == 0) { /* Check only */
|
||||
#else
|
||||
{ /* No -c */
|
||||
#endif
|
||||
char pfx[32];
|
||||
char pwbuf[MAXPWLINE];
|
||||
int l = sprintf(pfx, "%s:", user);
|
||||
|
Loading…
Reference in New Issue
Block a user