Teach pw(8) about how to use pw/gr API to reduce code duplication
MFC after: 2 months
This commit is contained in:
parent
9bdff6fffa
commit
fb2db03194
@ -3,10 +3,10 @@
|
||||
PROG= pw
|
||||
MAN= pw.conf.5 pw.8
|
||||
SRCS= pw.c pw_conf.c pw_user.c pw_group.c pw_log.c pw_nis.c pw_vpw.c \
|
||||
grupd.c pwupd.c fileupd.c edgroup.c psdate.c \
|
||||
grupd.c pwupd.c fileupd.c psdate.c \
|
||||
bitmap.c cpdir.c rm_r.c
|
||||
|
||||
WARNS?= 1
|
||||
WARNS?= 2
|
||||
|
||||
DPADD= ${LIBCRYPT} ${LIBUTIL}
|
||||
LDADD= -lcrypt -lutil
|
||||
|
@ -1,229 +0,0 @@
|
||||
/*-
|
||||
* Copyright (C) 1996
|
||||
* David L. Nugent. All rights reserved.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY DAVID L. NUGENT AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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.
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static const char rcsid[] =
|
||||
"$FreeBSD$";
|
||||
#endif /* not lint */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <stdarg.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <pwd.h>
|
||||
#include <grp.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/param.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include "pwupd.h"
|
||||
|
||||
static int
|
||||
isingroup(char const * name, char **mem)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; mem[i] != NULL; i++)
|
||||
if (strcmp(name, mem[i]) == 0)
|
||||
return i;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int
|
||||
editgroups(char *name, char **groups)
|
||||
{
|
||||
int rc = 0;
|
||||
int infd;
|
||||
char groupfile[MAXPATHLEN];
|
||||
char grouptmp[MAXPATHLEN];
|
||||
|
||||
strncpy(groupfile, getgrpath(_GROUP), MAXPATHLEN - 5);
|
||||
groupfile[MAXPATHLEN - 5] = '\0';
|
||||
strcpy(grouptmp, groupfile);
|
||||
strcat(grouptmp, ".new");
|
||||
|
||||
if ((infd = open(groupfile, O_RDWR | O_CREAT | O_EXLOCK, 0644)) != -1) {
|
||||
FILE *infp;
|
||||
|
||||
if ((infp = fdopen(infd, "r+")) == NULL)
|
||||
close(infd);
|
||||
else {
|
||||
int outfd;
|
||||
|
||||
if ((outfd = open(grouptmp, O_RDWR | O_CREAT | O_TRUNC, 0644)) != -1) {
|
||||
FILE *outfp;
|
||||
|
||||
if ((outfp = fdopen(outfd, "w+")) == NULL)
|
||||
close(outfd);
|
||||
else {
|
||||
int linelen = PWBUFSZ;
|
||||
int outlen = PWBUFSZ;
|
||||
int memlen = 200; /* Arbitrary */
|
||||
char *line = malloc(linelen);
|
||||
char *outl = malloc(outlen);
|
||||
char **mems = malloc(memlen * sizeof(char *));
|
||||
int namlen = strlen(name);
|
||||
|
||||
if (line == NULL || outl == NULL || mems == NULL) {
|
||||
mem_abort:
|
||||
rc = 0;
|
||||
} else {
|
||||
while (fgets(line, linelen, infp) != NULL) {
|
||||
char *p;
|
||||
int l;
|
||||
|
||||
while ((p = strchr(line, '\n')) == NULL)
|
||||
{
|
||||
if (extendline(&line, &linelen, linelen + PWBUFSZ) == -1) {
|
||||
goto mem_abort;
|
||||
}
|
||||
l = strlen(line);
|
||||
if (fgets(line + l, linelen - l, infp) == NULL)
|
||||
break; /* No newline terminator on last line */
|
||||
}
|
||||
l = strlen(line) + namlen + 1;
|
||||
if (extendline(&outl, &outlen, l) == -1) {
|
||||
goto mem_abort;
|
||||
}
|
||||
if (*line == '#')
|
||||
strcpy(outl, line);
|
||||
else if (*line == '\n')
|
||||
*outl = '\0';
|
||||
else {
|
||||
int i,
|
||||
mno = 0;
|
||||
char *cp = line;
|
||||
char const *sep = ":\n";
|
||||
struct group grp;
|
||||
|
||||
memset(&grp, 0, sizeof grp);
|
||||
for (i = 0; (p = strsep(&cp, sep)) != NULL; i++) {
|
||||
switch (i) {
|
||||
case 0: /* Group name */
|
||||
grp.gr_name = p;
|
||||
break;
|
||||
case 1: /* Group password */
|
||||
grp.gr_passwd = p;
|
||||
break;
|
||||
case 2: /* Group id */
|
||||
grp.gr_gid = atoi(p);
|
||||
break;
|
||||
case 3: /* Member list */
|
||||
cp = p;
|
||||
sep = ",\n";
|
||||
break;
|
||||
default: /* Individual members */
|
||||
if (*p) {
|
||||
if (extendarray(&mems, &memlen, mno + 2) == -1) {
|
||||
goto mem_abort;
|
||||
}
|
||||
mems[mno++] = p;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i < 2) /* Bail out - insufficient fields */
|
||||
continue;
|
||||
|
||||
grp.gr_mem = mems;
|
||||
for (i = mno; i < memlen; i++)
|
||||
mems[i] = NULL;
|
||||
|
||||
/*
|
||||
* Delete from group, or add to group?
|
||||
*/
|
||||
if (groups == NULL || isingroup(grp.gr_name, groups) == -1) { /* Delete */
|
||||
int idx;
|
||||
|
||||
while ((idx = isingroup(name, mems)) != -1) {
|
||||
for (i = idx; i < (memlen - 1); i++)
|
||||
mems[i] = mems[i + 1];
|
||||
mems[i] = NULL;
|
||||
--mno;
|
||||
}
|
||||
/*
|
||||
* Special case - deleting user and group may be user's own
|
||||
*/
|
||||
if (groups == NULL && mems[0] == NULL && strcmp(name, grp.gr_name) == 0) {
|
||||
/*
|
||||
* First, make _sure_ we don't have other members
|
||||
*/
|
||||
struct passwd *pwd;
|
||||
|
||||
SETPWENT();
|
||||
while ((pwd = GETPWENT()) != NULL && (gid_t)pwd->pw_gid != (gid_t)grp.gr_gid);
|
||||
ENDPWENT();
|
||||
if (pwd == NULL) /* No members at all */
|
||||
continue; /* Drop the group */
|
||||
}
|
||||
} else if (isingroup(name, mems) == -1) {
|
||||
if (extendarray(&mems, &memlen, mno + 2) == -1) {
|
||||
goto mem_abort;
|
||||
}
|
||||
grp.gr_mem = mems; /* May have realloced() */
|
||||
mems[mno++] = name;
|
||||
mems[mno ] = NULL;
|
||||
}
|
||||
fmtgrentry(&outl, &outlen, &grp, PWF_GROUP);
|
||||
}
|
||||
fputs(outl, outfp);
|
||||
}
|
||||
if (fflush(outfp) != EOF) {
|
||||
rc = 1;
|
||||
|
||||
/*
|
||||
* Copy data back into the original file and truncate
|
||||
*/
|
||||
rewind(infp);
|
||||
rewind(outfp);
|
||||
while (fgets(outl, outlen, outfp) != NULL)
|
||||
fputs(outl, infp);
|
||||
|
||||
/*
|
||||
* This is a gross hack, but we may have corrupted the
|
||||
* original file.
|
||||
*/
|
||||
if (fflush(infp) == EOF || ferror(infp))
|
||||
rc = rename(grouptmp, groupfile) == 0;
|
||||
else
|
||||
ftruncate(infd, ftell(infp));
|
||||
}
|
||||
}
|
||||
free(mems);
|
||||
free(outl);
|
||||
free(line);
|
||||
fclose(outfp);
|
||||
}
|
||||
remove(grouptmp);
|
||||
}
|
||||
fclose(infp);
|
||||
}
|
||||
}
|
||||
return rc;
|
||||
}
|
@ -66,138 +66,3 @@ extendarray(char ***buf, int * buflen, int needed)
|
||||
}
|
||||
return *buflen;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
fileupdate(char const * filename, mode_t fmode, char const * newline, char const * prefix, int pfxlen, int updmode)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
if (pfxlen <= 1)
|
||||
rc = EINVAL;
|
||||
else {
|
||||
int infd = open(filename, O_RDWR | O_CREAT | O_EXLOCK, fmode);
|
||||
|
||||
if (infd == -1)
|
||||
rc = errno;
|
||||
else {
|
||||
FILE *infp = fdopen(infd, "r+");
|
||||
|
||||
if (infp == NULL) {
|
||||
rc = errno; /* Assumes fopen(3) sets errno from open(2) */
|
||||
close(infd);
|
||||
} else {
|
||||
int outfd;
|
||||
char file[MAXPATHLEN];
|
||||
|
||||
strcpy(file, filename);
|
||||
strcat(file, ".new");
|
||||
outfd = open(file, O_RDWR | O_CREAT | O_TRUNC, fmode);
|
||||
if (outfd == -1)
|
||||
rc = errno;
|
||||
else {
|
||||
FILE *outfp = fdopen(outfd, "w+");
|
||||
|
||||
if (outfp == NULL) {
|
||||
rc = errno;
|
||||
close(outfd);
|
||||
} else {
|
||||
int updated = UPD_CREATE;
|
||||
int linesize = PWBUFSZ;
|
||||
char *line = malloc(linesize);
|
||||
|
||||
nextline:
|
||||
while (fgets(line, linesize, infp) != NULL) {
|
||||
char *p = strchr(line, '\n');
|
||||
|
||||
while ((p = strchr(line, '\n')) == NULL) {
|
||||
int l;
|
||||
if (extendline(&line, &linesize, linesize + PWBUFSZ) == -1) {
|
||||
int ch;
|
||||
fputs(line, outfp);
|
||||
while ((ch = fgetc(infp)) != EOF) {
|
||||
fputc(ch, outfp);
|
||||
if (ch == '\n')
|
||||
break;
|
||||
}
|
||||
goto nextline;
|
||||
}
|
||||
l = strlen(line);
|
||||
if (fgets(line + l, linesize - l, infp) == NULL)
|
||||
break;
|
||||
}
|
||||
if (*line != '#' && *line != '\n') {
|
||||
if (!updated && strncmp(line, prefix, pfxlen) == 0) {
|
||||
updated = updmode == UPD_REPLACE ? UPD_REPLACE : UPD_DELETE;
|
||||
|
||||
/*
|
||||
* Only actually write changes if updating
|
||||
*/
|
||||
if (updmode == UPD_REPLACE)
|
||||
strcpy(line, newline);
|
||||
else if (updmode == UPD_DELETE)
|
||||
continue;
|
||||
}
|
||||
}
|
||||
fputs(line, outfp);
|
||||
}
|
||||
|
||||
/*
|
||||
* Now, we need to decide what to do: If we are in
|
||||
* update mode, and no record was updated, then error If
|
||||
* we are in insert mode, and record already exists,
|
||||
* then error
|
||||
*/
|
||||
if (updmode != updated)
|
||||
/* -1 return means:
|
||||
* update,delete=no user entry
|
||||
* create=entry exists
|
||||
*/
|
||||
rc = -1;
|
||||
else {
|
||||
|
||||
/*
|
||||
* If adding a new record, append it to the end
|
||||
*/
|
||||
if (updmode == UPD_CREATE)
|
||||
fputs(newline, outfp);
|
||||
|
||||
/*
|
||||
* Flush the file and check for the result
|
||||
*/
|
||||
if (fflush(outfp) == EOF)
|
||||
rc = errno; /* Failed to update */
|
||||
else {
|
||||
/*
|
||||
* Copy data back into the
|
||||
* original file and truncate
|
||||
*/
|
||||
rewind(infp);
|
||||
rewind(outfp);
|
||||
while (fgets(line, linesize, outfp) != NULL)
|
||||
fputs(line, infp);
|
||||
|
||||
/*
|
||||
* If there was a problem with copying
|
||||
* we will just rename 'file.new'
|
||||
* to 'file'.
|
||||
* This is a gross hack, but we may have
|
||||
* corrupted the original file
|
||||
*/
|
||||
if (fflush(infp) == EOF || ferror(infp))
|
||||
rename(file, filename);
|
||||
else
|
||||
ftruncate(infd, ftell(infp));
|
||||
}
|
||||
}
|
||||
free(line);
|
||||
fclose(outfp);
|
||||
}
|
||||
remove(file);
|
||||
}
|
||||
fclose(infp);
|
||||
}
|
||||
}
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
@ -29,6 +29,9 @@ static const char rcsid[] =
|
||||
"$FreeBSD$";
|
||||
#endif /* not lint */
|
||||
|
||||
#include <grp.h>
|
||||
#include <libutil.h>
|
||||
#include <err.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
@ -65,107 +68,62 @@ getgrpath(const char * file)
|
||||
return pathbuf;
|
||||
}
|
||||
|
||||
int
|
||||
grdb(char *arg,...)
|
||||
{
|
||||
/*
|
||||
* This is a stub for now, but maybe eventually be functional
|
||||
* if ever an indexed version of /etc/groups is implemented.
|
||||
*/
|
||||
arg=arg;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
fmtgrentry(char **buf, int * buflen, struct group * grp, int type)
|
||||
{
|
||||
int i, l;
|
||||
|
||||
/*
|
||||
* Since a group line is of arbitrary length,
|
||||
* we need to calculate up-front just how long
|
||||
* it will need to be...
|
||||
*/
|
||||
/* groupname : password : gid : */
|
||||
l = strlen(grp->gr_name) + 1 + strlen(grp->gr_passwd) + 1 + 5 + 1;
|
||||
/* group members + comma separator */
|
||||
for (i = 0; grp->gr_mem[i] != NULL; i++) {
|
||||
l += strlen(grp->gr_mem[i]) + 1;
|
||||
}
|
||||
l += 2; /* For newline & NUL */
|
||||
if (extendline(buf, buflen, l) == -1)
|
||||
l = -1;
|
||||
else{
|
||||
/*
|
||||
* Now we can safely format
|
||||
*/
|
||||
if (type == PWF_STANDARD)
|
||||
l = sprintf(*buf, "%s:*:%ld:", grp->gr_name, (long) grp->gr_gid);
|
||||
else
|
||||
l = sprintf(*buf, "%s:%s:%ld:", grp->gr_name, grp->gr_passwd, (long) grp->gr_gid);
|
||||
|
||||
/*
|
||||
* List members
|
||||
*/
|
||||
for (i = 0; grp->gr_mem[i] != NULL; i++) {
|
||||
l += sprintf(*buf + l, "%s%s", i ? "," : "", grp->gr_mem[i]);
|
||||
}
|
||||
|
||||
(*buf)[l++] = '\n';
|
||||
(*buf)[l] = '\0';
|
||||
}
|
||||
return l;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
fmtgrent(char **buf, int * buflen, struct group * grp)
|
||||
{
|
||||
return fmtgrentry(buf, buflen, grp, PWF_STANDARD);
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
gr_update(struct group * grp, char const * group, int mode)
|
||||
gr_update(struct group * grp, char const * group)
|
||||
{
|
||||
int l;
|
||||
char pfx[64];
|
||||
int grbuflen = 0;
|
||||
char *grbuf = NULL;
|
||||
int pfd, tfd;
|
||||
struct group *gr = NULL;
|
||||
struct group *old_gr = NULL;
|
||||
|
||||
ENDGRENT();
|
||||
l = snprintf(pfx, sizeof pfx, "%s:", group);
|
||||
if (grp != NULL)
|
||||
gr = gr_dup(grp);
|
||||
|
||||
/*
|
||||
* Update the group file
|
||||
*/
|
||||
if (grp != NULL && fmtgrentry(&grbuf, &grbuflen, grp, PWF_PASSWD) == -1)
|
||||
l = -1;
|
||||
else {
|
||||
l = fileupdate(getgrpath(_GROUP), 0644, grbuf, pfx, l, mode);
|
||||
if (l == 0)
|
||||
l = grdb(NULL);
|
||||
if (group != NULL)
|
||||
old_gr = GETGRNAM(group);
|
||||
|
||||
if (gr_init(grpath, NULL))
|
||||
err(1, "gr_init()");
|
||||
|
||||
if ((pfd = gr_lock()) == -1) {
|
||||
gr_fini();
|
||||
err(1, "gr_lock()");
|
||||
}
|
||||
if (grbuf != NULL)
|
||||
free(grbuf);
|
||||
return l;
|
||||
if ((tfd = gr_tmp(-1)) == -1) {
|
||||
gr_fini();
|
||||
err(1, "gr_tmp()");
|
||||
}
|
||||
if (gr_copy(pfd, tfd, gr, old_gr) == -1) {
|
||||
gr_fini();
|
||||
err(1, "gr_copy()");
|
||||
}
|
||||
if (gr_mkdb() == -1) {
|
||||
gr_fini();
|
||||
err(1, "gr_mkdb()");
|
||||
}
|
||||
free(gr);
|
||||
gr_fini();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
addgrent(struct group * grp)
|
||||
{
|
||||
return gr_update(grp, grp->gr_name, UPD_CREATE);
|
||||
return gr_update(grp, NULL);
|
||||
}
|
||||
|
||||
int
|
||||
chggrent(char const * login, struct group * grp)
|
||||
{
|
||||
return gr_update(grp, login, UPD_REPLACE);
|
||||
return gr_update(grp, login);
|
||||
}
|
||||
|
||||
int
|
||||
delgrent(struct group * grp)
|
||||
{
|
||||
return gr_update(NULL, grp->gr_name, UPD_DELETE);
|
||||
char group[MAXLOGNAME];
|
||||
|
||||
strlcpy(group, grp->gr_name, MAXLOGNAME);
|
||||
|
||||
return gr_update(NULL, group);
|
||||
}
|
||||
|
@ -24,7 +24,7 @@
|
||||
.\"
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd December 21, 2011
|
||||
.Dd October 29, 2012
|
||||
.Dt PW 8
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -904,12 +904,6 @@ A Version 7 format password file
|
||||
The user capabilities database
|
||||
.It Pa /etc/group
|
||||
The group database
|
||||
.It Pa /etc/master.passwd.new
|
||||
Temporary copy of the master password file
|
||||
.It Pa /etc/passwd.new
|
||||
Temporary copy of the Version 7 password file
|
||||
.It Pa /etc/group.new
|
||||
Temporary copy of the group file
|
||||
.It Pa /etc/pw.conf
|
||||
Pw default options file
|
||||
.It Pa /var/log/userlog
|
||||
|
@ -62,13 +62,11 @@ struct pwf PWF =
|
||||
getpwent,
|
||||
getpwuid,
|
||||
getpwnam,
|
||||
pwdb,
|
||||
setgrent,
|
||||
endgrent,
|
||||
getgrent,
|
||||
getgrgid,
|
||||
getgrnam,
|
||||
grdb
|
||||
|
||||
};
|
||||
struct pwf VPWF =
|
||||
@ -79,13 +77,11 @@ struct pwf VPWF =
|
||||
vgetpwent,
|
||||
vgetpwuid,
|
||||
vgetpwnam,
|
||||
vpwdb,
|
||||
vsetgrent,
|
||||
vendgrent,
|
||||
vgetgrent,
|
||||
vgetgrgid,
|
||||
vgetgrnam,
|
||||
vgrdb
|
||||
};
|
||||
|
||||
static struct cargs arglist;
|
||||
|
@ -109,19 +109,10 @@ int pw_user(struct userconf * cnf, int mode, struct cargs * _args);
|
||||
int pw_group(struct userconf * cnf, int mode, struct cargs * _args);
|
||||
char *pw_checkname(u_char *name, int gecos);
|
||||
|
||||
int addpwent(struct passwd * pwd);
|
||||
int delpwent(struct passwd * pwd);
|
||||
int chgpwent(char const * login, struct passwd * pwd);
|
||||
int fmtpwent(char *buf, struct passwd * pwd);
|
||||
|
||||
int addnispwent(const char *path, struct passwd *pwd);
|
||||
int delnispwent(const char *path, const char *login);
|
||||
int chgnispwent(const char *path, const char *login, struct passwd *pwd);
|
||||
|
||||
int addgrent(struct group * grp);
|
||||
int delgrent(struct group * grp);
|
||||
int chggrent(char const * login, struct group * grp);
|
||||
|
||||
int boolean_val(char const * str, int dflt);
|
||||
char const *boolean_str(int val);
|
||||
char *newstr(char const * p);
|
||||
|
@ -34,6 +34,8 @@ static const char rcsid[] =
|
||||
#include <termios.h>
|
||||
#include <stdbool.h>
|
||||
#include <unistd.h>
|
||||
#include <grp.h>
|
||||
#include <libutil.h>
|
||||
|
||||
#include "pw.h"
|
||||
#include "bitmap.h"
|
||||
@ -403,10 +405,9 @@ static int
|
||||
print_group(struct group * grp, int pretty)
|
||||
{
|
||||
if (!pretty) {
|
||||
int buflen = 0;
|
||||
char *buf = NULL;
|
||||
|
||||
fmtgrent(&buf, &buflen, grp);
|
||||
buf = gr_make(grp);
|
||||
fputs(buf, stdout);
|
||||
free(buf);
|
||||
} else {
|
||||
|
@ -51,7 +51,7 @@ pw_log(struct userconf * cnf, int mode, int which, char const * fmt,...)
|
||||
time_t now = time(NULL);
|
||||
struct tm *t = localtime(&now);
|
||||
char nfmt[256];
|
||||
char *name;
|
||||
const char *name;
|
||||
|
||||
if ((name = getenv("LOGNAME")) == NULL && (name = getenv("USER")) == NULL)
|
||||
name = "unknown";
|
||||
|
@ -33,40 +33,62 @@ static const char rcsid[] =
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <err.h>
|
||||
#include <pwd.h>
|
||||
#include <libutil.h>
|
||||
|
||||
#include "pw.h"
|
||||
|
||||
static int
|
||||
pw_nisupdate(const char * path, struct passwd * pwd, char const * user, int mode)
|
||||
pw_nisupdate(const char * path, struct passwd * pwd, char const * user)
|
||||
{
|
||||
char pfx[32];
|
||||
char pwbuf[PWBUFSZ];
|
||||
int l = sprintf(pfx, "%s:", user);
|
||||
int pfd, tfd;
|
||||
struct passwd *pw = NULL;
|
||||
struct passwd *old_pw = NULL;
|
||||
|
||||
/*
|
||||
* Update the passwd file first
|
||||
*/
|
||||
if (pwd == NULL)
|
||||
*pwbuf = '\0';
|
||||
else
|
||||
fmtpwentry(pwbuf, pwd, PWF_MASTER);
|
||||
return fileupdate(path, 0600, pwbuf, pfx, l, mode) != 0;
|
||||
if (pwd != NULL)
|
||||
pw = pw_dup(pwd);
|
||||
|
||||
if (user != NULL)
|
||||
old_pw = GETPWNAM(user);
|
||||
|
||||
if (pw_init(NULL, path))
|
||||
err(1,"pw_init()");
|
||||
if ((pfd = pw_lock()) == -1) {
|
||||
pw_fini();
|
||||
err(1, "pw_lock()");
|
||||
}
|
||||
if ((tfd = pw_tmp(-1)) == -1) {
|
||||
pw_fini();
|
||||
err(1, "pw_tmp()");
|
||||
}
|
||||
if (pw_copy(pfd, tfd, pw, old_pw) == -1) {
|
||||
pw_fini();
|
||||
err(1, "pw_copy()");
|
||||
}
|
||||
if (rename(pw_tempname(), path) == -1)
|
||||
err(1, "rename()");
|
||||
|
||||
free(pw);
|
||||
pw_fini();
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
addnispwent(const char *path, struct passwd * pwd)
|
||||
{
|
||||
return pw_nisupdate(path, pwd, pwd->pw_name, UPD_CREATE);
|
||||
return pw_nisupdate(path, pwd, NULL);
|
||||
}
|
||||
|
||||
int
|
||||
chgnispwent(const char *path, char const * login, struct passwd * pwd)
|
||||
{
|
||||
return pw_nisupdate(path, pwd, login, UPD_REPLACE);
|
||||
return pw_nisupdate(path, pwd, login);
|
||||
}
|
||||
|
||||
int
|
||||
delnispwent(const char *path, const char *login)
|
||||
{
|
||||
return pw_nisupdate(path, NULL, login, UPD_DELETE);
|
||||
return pw_nisupdate(path, NULL, login);
|
||||
}
|
||||
|
@ -42,6 +42,9 @@ static const char rcsid[] =
|
||||
#include <sys/resource.h>
|
||||
#include <unistd.h>
|
||||
#include <login_cap.h>
|
||||
#include <pwd.h>
|
||||
#include <grp.h>
|
||||
#include <libutil.h>
|
||||
#include "pw.h"
|
||||
#include "bitmap.h"
|
||||
|
||||
@ -292,7 +295,6 @@ pw_user(struct userconf * cnf, int mode, struct cargs * args)
|
||||
if (mode == M_PRINT && getarg(args, 'a')) {
|
||||
int pretty = getarg(args, 'P') != NULL;
|
||||
int v7 = getarg(args, '7') != NULL;
|
||||
|
||||
SETPWENT();
|
||||
while ((pwd = GETPWENT()) != NULL)
|
||||
print_user(pwd, pretty, v7);
|
||||
@ -422,7 +424,24 @@ pw_user(struct userconf * cnf, int mode, struct cargs * args)
|
||||
/* non-fatal */
|
||||
}
|
||||
|
||||
editgroups(a_name->val, NULL);
|
||||
grp = GETGRNAM(a_name->val);
|
||||
if (*grp->gr_mem == NULL)
|
||||
delgrent(GETGRNAM(a_name->val));
|
||||
SETGRENT();
|
||||
while ((grp = GETGRENT()) != NULL) {
|
||||
int i;
|
||||
char group[MAXLOGNAME];
|
||||
for (i = 0; grp->gr_mem[i] != NULL; i++) {
|
||||
if (!strcmp(grp->gr_mem[i], a_name->val)) {
|
||||
while (grp->gr_mem[i] != NULL) {
|
||||
grp->gr_mem[i] = grp->gr_mem[i+1];
|
||||
}
|
||||
strlcpy(group, grp->gr_name, MAXLOGNAME);
|
||||
chggrent(group, grp);
|
||||
}
|
||||
}
|
||||
}
|
||||
ENDGRENT();
|
||||
|
||||
pw_log(cnf, mode, W_USER, "%s(%ld) account removed", a_name->val, (long) uid);
|
||||
|
||||
@ -725,8 +744,29 @@ pw_user(struct userconf * cnf, int mode, struct cargs * args)
|
||||
* Ok, user is created or changed - now edit group file
|
||||
*/
|
||||
|
||||
if (mode == M_ADD || getarg(args, 'G') != NULL)
|
||||
editgroups(pwd->pw_name, cnf->groups);
|
||||
if (mode == M_ADD || getarg(args, 'G') != NULL) {
|
||||
int i, j;
|
||||
for (i = 0; cnf->groups[i] != NULL; i++) {
|
||||
grp = GETGRNAM(cnf->groups[i]);
|
||||
for (j = 0; grp->gr_mem[j] != NULL; j++) {
|
||||
if (!strcmp(grp->gr_mem[j], pwd->pw_name))
|
||||
break;
|
||||
}
|
||||
if (grp->gr_mem[j] != NULL) /* user already member of group */
|
||||
continue;
|
||||
|
||||
if (j == 0)
|
||||
grp->gr_mem = NULL;
|
||||
|
||||
grp->gr_mem = reallocf(grp->gr_mem, sizeof(*grp->gr_mem) *
|
||||
(j + 2));
|
||||
|
||||
grp->gr_mem[j] = pwd->pw_name;
|
||||
grp->gr_mem[j+1] = NULL;
|
||||
chggrent(cnf->groups[i], grp);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* go get a current version of pwd */
|
||||
pwd = GETPWNAM(a_name->val);
|
||||
@ -1090,10 +1130,14 @@ static int
|
||||
print_user(struct passwd * pwd, int pretty, int v7)
|
||||
{
|
||||
if (!pretty) {
|
||||
char buf[_UC_MAXLINE];
|
||||
char *buf;
|
||||
|
||||
fmtpwentry(buf, pwd, v7 ? PWF_PASSWD : PWF_STANDARD);
|
||||
fputs(buf, stdout);
|
||||
if (!v7)
|
||||
pwd->pw_passwd = (pwd->pw_passwd == NULL) ? "" : "*";
|
||||
|
||||
buf = v7 ? pw_make_v7(pwd) : pw_make(pwd);
|
||||
printf("%s\n", buf);
|
||||
free(buf);
|
||||
} else {
|
||||
int j;
|
||||
char *p;
|
||||
|
@ -170,13 +170,6 @@ vgetpwnam(const char * nam)
|
||||
return vnextpwent(nam, -1, 1);
|
||||
}
|
||||
|
||||
int vpwdb(char *arg, ...)
|
||||
{
|
||||
arg=arg;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static FILE * grp_fp = NULL;
|
||||
|
||||
@ -221,7 +214,7 @@ vnextgrent(char const * nam, gid_t gid, int doclose)
|
||||
int i, quickout = 0;
|
||||
int mno = 0;
|
||||
char * q, * p;
|
||||
char * sep = ":\n";
|
||||
const char * sep = ":\n";
|
||||
|
||||
if ((p = strchr(grtmp, '\n')) == NULL) {
|
||||
int l;
|
||||
@ -307,10 +300,3 @@ vgetgrnam(const char * nam)
|
||||
return vnextgrent(nam, -1, 1);
|
||||
}
|
||||
|
||||
int
|
||||
vgrdb(char *arg, ...)
|
||||
{
|
||||
arg=arg;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -34,7 +34,10 @@ static const char rcsid[] =
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <stdarg.h>
|
||||
#include <pwd.h>
|
||||
#include <libutil.h>
|
||||
#include <errno.h>
|
||||
#include <err.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/param.h>
|
||||
@ -71,7 +74,7 @@ getpwpath(char const * file)
|
||||
return pathbuf;
|
||||
}
|
||||
|
||||
int
|
||||
static int
|
||||
pwdb(char *arg,...)
|
||||
{
|
||||
int i = 0;
|
||||
@ -106,44 +109,11 @@ pwdb(char *arg,...)
|
||||
return i;
|
||||
}
|
||||
|
||||
int
|
||||
fmtpwentry(char *buf, struct passwd * pwd, int type)
|
||||
{
|
||||
int l;
|
||||
char *pw;
|
||||
|
||||
pw = (type == PWF_MASTER) ?
|
||||
((pwd->pw_passwd == NULL) ? "" : pwd->pw_passwd) : "*";
|
||||
|
||||
if (type == PWF_PASSWD)
|
||||
l = sprintf(buf, "%s:*:%ld:%ld:%s:%s:%s\n",
|
||||
pwd->pw_name, (long) pwd->pw_uid, (long) pwd->pw_gid,
|
||||
pwd->pw_gecos ? pwd->pw_gecos : "User &",
|
||||
pwd->pw_dir, pwd->pw_shell);
|
||||
else
|
||||
l = sprintf(buf, "%s:%s:%ld:%ld:%s:%lu:%lu:%s:%s:%s\n",
|
||||
pwd->pw_name, pw, (long) pwd->pw_uid, (long) pwd->pw_gid,
|
||||
pwd->pw_class ? pwd->pw_class : "",
|
||||
(unsigned long) pwd->pw_change,
|
||||
(unsigned long) pwd->pw_expire,
|
||||
pwd->pw_gecos, pwd->pw_dir, pwd->pw_shell);
|
||||
return l;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
fmtpwent(char *buf, struct passwd * pwd)
|
||||
{
|
||||
return fmtpwentry(buf, pwd, PWF_STANDARD);
|
||||
}
|
||||
|
||||
static int
|
||||
pw_update(struct passwd * pwd, char const * user, int mode)
|
||||
pw_update(struct passwd * pwd, char const * user)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
ENDPWENT();
|
||||
|
||||
/*
|
||||
* First, let's check the see if the database is alright
|
||||
* Note: -C is only available in FreeBSD 2.2 and above
|
||||
@ -154,61 +124,57 @@ pw_update(struct passwd * pwd, char const * user, int mode)
|
||||
#else
|
||||
{ /* No -C */
|
||||
#endif
|
||||
char pfx[PWBUFSZ];
|
||||
char pwbuf[PWBUFSZ];
|
||||
int l = snprintf(pfx, PWBUFSZ, "%s:", user);
|
||||
#ifdef HAVE_PWDB_U
|
||||
int isrename = pwd!=NULL && strcmp(user, pwd->pw_name);
|
||||
#endif
|
||||
int pfd, tfd;
|
||||
struct passwd *pw = NULL;
|
||||
struct passwd *old_pw = NULL;
|
||||
|
||||
/*
|
||||
* Update the passwd file first
|
||||
*/
|
||||
if (pwd == NULL)
|
||||
*pwbuf = '\0';
|
||||
else
|
||||
fmtpwentry(pwbuf, pwd, PWF_PASSWD);
|
||||
if (pwd != NULL)
|
||||
pw = pw_dup(pwd);
|
||||
|
||||
if (l < 0)
|
||||
l = 0;
|
||||
rc = fileupdate(getpwpath(_PASSWD), 0644, pwbuf, pfx, l, mode);
|
||||
if (rc == 0) {
|
||||
if (user != NULL)
|
||||
old_pw = GETPWNAM(user);
|
||||
|
||||
/*
|
||||
* Then the master.passwd file
|
||||
*/
|
||||
if (pwd != NULL)
|
||||
fmtpwentry(pwbuf, pwd, PWF_MASTER);
|
||||
rc = fileupdate(getpwpath(_MASTERPASSWD), 0600, pwbuf, pfx, l, mode);
|
||||
if (rc == 0) {
|
||||
#ifdef HAVE_PWDB_U
|
||||
if (mode == UPD_DELETE || isrename)
|
||||
#endif
|
||||
rc = pwdb(NULL);
|
||||
#ifdef HAVE_PWDB_U
|
||||
else
|
||||
rc = pwdb("-u", user, (char *)NULL);
|
||||
#endif
|
||||
}
|
||||
if (pw_init(pwpath, NULL))
|
||||
err(1, "pw_init()");
|
||||
if ((pfd = pw_lock()) == -1) {
|
||||
pw_fini();
|
||||
err(1, "pw_lock()");
|
||||
}
|
||||
if ((tfd = pw_tmp(-1)) == -1) {
|
||||
pw_fini();
|
||||
err(1, "pw_tmp()");
|
||||
}
|
||||
if (pw_copy(pfd, tfd, pw, old_pw) == -1) {
|
||||
pw_fini();
|
||||
err(1, "pw_copy()");
|
||||
}
|
||||
if (pw_mkdb(user) == -1) {
|
||||
pw_fini();
|
||||
err(1, "pw_mkdb()");
|
||||
}
|
||||
free(pw);
|
||||
pw_fini();
|
||||
}
|
||||
return rc;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
addpwent(struct passwd * pwd)
|
||||
{
|
||||
return pw_update(pwd, pwd->pw_name, UPD_CREATE);
|
||||
return pw_update(pwd, NULL);
|
||||
}
|
||||
|
||||
int
|
||||
chgpwent(char const * login, struct passwd * pwd)
|
||||
{
|
||||
return pw_update(pwd, login, UPD_REPLACE);
|
||||
return pw_update(pwd, login);
|
||||
}
|
||||
|
||||
int
|
||||
delpwent(struct passwd * pwd)
|
||||
{
|
||||
return pw_update(NULL, pwd->pw_name, UPD_DELETE);
|
||||
char login[MAXLOGNAME];
|
||||
|
||||
strlcpy(login, pwd->pw_name, MAXLOGNAME);
|
||||
return pw_update(NULL, login);
|
||||
}
|
||||
|
@ -41,25 +41,6 @@
|
||||
#define RET_SETGRENT void
|
||||
#endif
|
||||
|
||||
enum updtype
|
||||
{
|
||||
UPD_DELETE = -1,
|
||||
UPD_CREATE = 0,
|
||||
UPD_REPLACE = 1
|
||||
};
|
||||
|
||||
__BEGIN_DECLS
|
||||
int fileupdate(char const * fname, mode_t fm, char const * nline, char const * pfx, int pfxlen, int updmode);
|
||||
__END_DECLS
|
||||
|
||||
enum pwdfmttype
|
||||
{
|
||||
PWF_STANDARD, /* MASTER format but with '*' as password */
|
||||
PWF_PASSWD, /* V7 format */
|
||||
PWF_GROUP = PWF_PASSWD,
|
||||
PWF_MASTER /* MASTER format with password */
|
||||
};
|
||||
|
||||
struct pwf
|
||||
{
|
||||
int _altdir;
|
||||
@ -68,13 +49,11 @@ struct pwf
|
||||
struct passwd * (*_getpwent)(void);
|
||||
struct passwd * (*_getpwuid)(uid_t uid);
|
||||
struct passwd * (*_getpwnam)(const char * nam);
|
||||
int (*_pwdb)(char *arg, ...);
|
||||
RET_SETGRENT (*_setgrent)(void);
|
||||
void (*_endgrent)(void);
|
||||
struct group * (*_getgrent)(void);
|
||||
struct group * (*_getgrgid)(gid_t gid);
|
||||
struct group * (*_getgrnam)(const char * nam);
|
||||
int (*_grdb)(char *arg, ...);
|
||||
};
|
||||
|
||||
extern struct pwf PWF;
|
||||
@ -85,14 +64,12 @@ extern struct pwf VPWF;
|
||||
#define GETPWENT() PWF._getpwent()
|
||||
#define GETPWUID(uid) PWF._getpwuid(uid)
|
||||
#define GETPWNAM(nam) PWF._getpwnam(nam)
|
||||
#define PWDB(args) PWF._pwdb(args)
|
||||
|
||||
#define SETGRENT() PWF._setgrent()
|
||||
#define ENDGRENT() PWF._endgrent()
|
||||
#define GETGRENT() PWF._getgrent()
|
||||
#define GETGRGID(gid) PWF._getgrgid(gid)
|
||||
#define GETGRNAM(nam) PWF._getgrnam(nam)
|
||||
#define GRDB(args) PWF._grdb(args)
|
||||
|
||||
#define PWALTDIR() PWF._altdir
|
||||
#ifndef _PATH_PWD
|
||||
@ -101,51 +78,35 @@ extern struct pwf VPWF;
|
||||
#ifndef _GROUP
|
||||
#define _GROUP "group"
|
||||
#endif
|
||||
#ifndef _PASSWD
|
||||
#define _PASSWD "passwd"
|
||||
#endif
|
||||
#ifndef _MASTERPASSWD
|
||||
#define _MASTERPASSWD "master.passwd"
|
||||
#endif
|
||||
#ifndef _GROUP
|
||||
#define _GROUP "group"
|
||||
#endif
|
||||
|
||||
__BEGIN_DECLS
|
||||
int addpwent(struct passwd * pwd);
|
||||
int delpwent(struct passwd * pwd);
|
||||
int chgpwent(char const * login, struct passwd * pwd);
|
||||
int fmtpwent(char *buf, struct passwd * pwd);
|
||||
int fmtpwentry(char *buf, struct passwd * pwd, int type);
|
||||
|
||||
int setpwdir(const char * dir);
|
||||
char * getpwpath(char const * file);
|
||||
int pwdb(char *arg, ...);
|
||||
|
||||
int addgrent(struct group * grp);
|
||||
int delgrent(struct group * grp);
|
||||
int chggrent(char const * name, struct group * grp);
|
||||
int fmtgrent(char **buf, int * buflen, struct group * grp);
|
||||
int fmtgrentry(char **buf, int * buflen, struct group * grp, int type);
|
||||
int editgroups(char *name, char **groups);
|
||||
|
||||
int setgrdir(const char * dir);
|
||||
char * getgrpath(const char *file);
|
||||
int grdb(char *arg, ...);
|
||||
|
||||
void vsetpwent(void);
|
||||
void vendpwent(void);
|
||||
struct passwd * vgetpwent(void);
|
||||
struct passwd * vgetpwuid(uid_t uid);
|
||||
struct passwd * vgetpwnam(const char * nam);
|
||||
struct passwd * vgetpwent(void);
|
||||
int vpwdb(char *arg, ...);
|
||||
|
||||
struct group * vgetgrent(void);
|
||||
struct group * vgetgrgid(gid_t gid);
|
||||
struct group * vgetgrnam(const char * nam);
|
||||
struct group * vgetgrent(void);
|
||||
int vgrdb(char *arg, ...);
|
||||
RET_SETGRENT vsetgrent(void);
|
||||
void vendgrent(void);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user