Switch to NetBSD passwd format

Based on work by Vivek Prakash and Gianluca Guida.

See UPDATING about caveats on currently existing accounts.

	. restores netbsd libc pwcache functions
This commit is contained in:
Ben Gras 2011-09-30 10:18:10 +00:00
parent cedeabb357
commit 5c00743626
96 changed files with 10891 additions and 1220 deletions

View file

@ -62,6 +62,7 @@ commands: includes libraries
$(MAKE) -C bin all
$(MAKE) -C usr.bin all
$(MAKE) -C libexec all
$(MAKE) -C usr.sbin all
dep-all:
$(MAKE) CC=cc -C boot dependall
@ -69,6 +70,7 @@ dep-all:
$(MAKE) -C bin dependall
$(MAKE) -C usr.bin dependall
$(MAKE) -C libexec dependall
$(MAKE) -C usr.sbin dependall
$(MAKE) -C kernel dependall
$(MAKE) -C servers dependall
$(MAKE) -C drivers dependall
@ -85,6 +87,7 @@ all:
$(MAKE) -C bin all
$(MAKE) -C usr.bin all
$(MAKE) -C libexec all
$(MAKE) -C usr.sbin all
$(MAKE) -C tools all
install:
@ -94,6 +97,7 @@ install:
$(MAKE) -C commands install
$(MAKE) -C bin install
$(MAKE) -C usr.bin install
$(MAKE) -C usr.sbin install
$(MAKE) -C servers install
$(MAKE) -C share install
$(MAKE) -C tools install
@ -104,6 +108,7 @@ clean: mkfiles
$(MAKE) -C bin clean
$(MAKE) -C usr.bin clean
$(MAKE) -C libexec clean
$(MAKE) -C usr.sbin clean
$(MAKE) -C tools clean
$(MAKE) -C lib clean_all
$(MAKE) -C test clean
@ -115,4 +120,5 @@ cleandepend: mkfiles
$(MAKE) -C bin cleandepend
$(MAKE) -C usr.bin cleandepend
$(MAKE) -C libexec cleandepend
$(MAKE) -C usr.sbin cleandepend
$(MAKE) -C tools cleandepend

View file

@ -2,7 +2,7 @@
.include <bsd.own.mk>
SUBDIR= aal add_route adduser arp ash at autil awk \
SUBDIR= aal add_route arp ash at autil awk \
backup badblocks banner basename binpackage \
binpackages bzip2 bzip2recover cal calendar \
cat cawf cd cdprobe checkhier chmem \
@ -19,7 +19,7 @@ SUBDIR= aal add_route adduser arp ash at autil awk \
lpd ls lspci M mail make MAKEDEV \
mdb mesg mined ackmkdep mkfifo mkfs.mfs mknod \
mkproto modem mount mt netconf newroot nice acknm nohup \
nonamed od passwd paste patch pax \
nonamed od paste patch pax \
ping postinstall poweroff pr prep printf printroot \
profile progressbar proto pr_routes ps pwd pwdauth \
ramdisk rarpd rawspeed rcp rdate readall readclock \

View file

@ -1,4 +0,0 @@
SCRIPTS= adduser.sh
MAN=
.include <bsd.prog.mk>

View file

@ -1,121 +0,0 @@
#!/bin/sh
#
# adduser 1.0 - add a new user to the system Author: Kees J. Bot
# 16 Jan 1996
# Check arguments.
case "$#" in
3) user="$1"; group="$2"; home="$3"
;;
*) echo "Usage: adduser user group home-dir" >&2; exit 1
esac
# We need to be root.
case "`id`" in
'uid=0('*)
;;
*) echo "adduser: you must be root to add users" >&2; exit 1
esac
# User and group names must be alphanumeric and no longer than 8 characters.
len=`expr "$user" : '[a-z][a-z0-9]*$'`
if [ "$len" -eq 0 -o "$len" -gt 8 ]
then
echo >&2 \
"adduser: the user name must be alphanumeric and no longer than 8 characters"
exit 1
fi
len=`expr "$group" : '[a-z][a-z0-9]*$'`
if [ "$len" -eq 0 -o "$len" -gt 8 ]
then
echo >&2 \
"adduser: the group name must be alphanumeric and no longer than 8 characters"
exit 1
fi
# The new user name must not exist, but the group must exist.
if grep "^$user:" /etc/passwd >/dev/null
then
echo "adduser: user $user already exists" >&2
exit 1
fi
gid=`sed -e "/^$group:/!d" -e 's/^[^:]*:[^:]*:\\([^:]*\\):.*/\\1/' /etc/group`
if [ `expr "$gid" : '[0-9]*$'` -eq 0 ]
then
echo "adduser: group $group does not exist" >&2
exit 1
fi
# Find the first free user-id of 10 or higher.
uid=10
while grep "^[^:]*:[^:]*:$uid:.*" /etc/passwd >/dev/null
do
uid=`expr $uid + 1`
done
# No interruptions.
trap '' 1 2 3 15
# Lock the password file.
ln /etc/passwd /etc/ptmp || {
echo "adduser: password file busy, try again later"
exit 1
}
# Make the new home directory, it should not exist already.
mkdir "$home" || {
rm -rf /etc/ptmp
exit 1
}
# Make the new home directory by copying the honorary home directory of our
# fearless leader.
echo cpdir /usr/ast "$home"
cpdir /usr/ast "$home" || {
rm -rf /etc/ptmp "$home"
exit 1
}
# Change the ownership to the new user.
echo chown -R $uid:$gid "$home"
chown -R $uid:$group "$home" || {
rm -rf /etc/ptmp "$home"
exit 1
}
# Is there a shadow password file? If so add an entry.
if [ -f /etc/shadow ]
then
echo "echo $user::0:0::: >>/etc/shadow"
echo "$user::0:0:::" >>/etc/shadow || {
rm -rf /etc/ptmp "$home"
exit 1
}
pwd="##$user"
else
pwd=
fi
# Finish up by adding a password file entry.
echo "echo $user:$pwd:$uid:$gid:$user:$home: >>/etc/passwd"
echo "$user:$pwd:$uid:$gid:$user:$home:" >>/etc/passwd || {
rm -rf /etc/ptmp "$home"
exit 1
}
# Remove the lock.
rm /etc/ptmp || exit
echo "
The new user $user has been added to the system. Note that the password,
full name, and shell may be changed with the commands passwd(1), chfn(1),
and chsh(1). The password is now empty, so only console logins are possible."
if [ $gid = 0 ]
then
echo "\
Also note that a new operator needs an executable search path (\$PATH) that
does not contain the current directory (an empty field or "." in \$PATH)."
fi
exit 0

View file

@ -31,7 +31,7 @@
#define S_IUGID (S_ISUID|S_ISGID)
/* Global variables, such as flags and path names */
int gflag, oflag, rflag, error;
int gflag, oflag, rflag, error, hflag = 0;
char *pgmname, path[PATH_MAX + 1];
uid_t nuid;
gid_t ngid;
@ -44,9 +44,6 @@ _PROTOTYPE(void usage, (void));
* identical, except that the default when a single name is given as an
* argument is to take a group id rather than an user id. This allow the
* non-Posix "chgrp user:group file".
* The single option switch used by chown/chgrp (-R) does not warrant a
* call to the getopt stuff. The two others flags (-g, -u) are set from
* the program name and arguments.
*/
int main(argc, argv)
int argc;
@ -55,20 +52,30 @@ char *argv[];
char *id, *id2;
struct group *grp;
struct passwd *pwp;
int ch;
if (pgmname = strrchr(*argv, '/'))
pgmname++;
else
pgmname = *argv;
argc--;
argv++;
gflag = strcmp(pgmname, "chgrp");
if (argc && **argv == '-' && argv[0][1] == 'R') {
argc--;
argv++;
rflag = 1;
while((ch = getopt(argc, argv, "Rh")) != -1) {
switch(ch) {
case 'R':
rflag = 1;
break;
case 'h':
hflag = 1;
break;
default:
usage();
}
}
argc -= optind;
argv += optind;
if (argc < 2) usage();
id = *argv++;
@ -131,6 +138,11 @@ char *file;
if (S_ISLNK(st.st_mode) && rflag) return; /* Note: violates POSIX. */
if (S_ISLNK(st.st_mode) && hflag) {
fprintf(stderr, "chown: cannot lchown %s\n", file);
error = 1;
}
if (chown(file, oflag ? nuid : st.st_uid, gflag ? ngid : st.st_gid)) {
perror(file);
error = 1;

View file

@ -8,8 +8,7 @@ SRCS= ftpd.c access.c file.c net.c
MAN= ftpd.8
SCRIPTS= ftpdsh
FILES= setup.anonftp
.if defined(NBSD_LIBC) && (${NBSD_LIBC} != "no")
NEED_NBSDLIBC=y
LDADD+= -lcrypt
.endif
.include <bsd.prog.mk>

View file

@ -1,3 +1,5 @@
.include <minix.newlibc.mk>
PROG= login
MAN=
.if defined(NBSD_LIBC) && (${NBSD_LIBC} != "no")

View file

@ -339,9 +339,8 @@ char *argv[];
* pre-authorized users.
*/
} else
if (pwd && secure && strcmp(crypt("", pwd->pw_passwd),
pwd->pw_passwd) == 0) {
check_pw= 0; /* empty password */
if (pwd && secure && (pwd->pw_passwd[0] == '\0')) {
check_pw= 0; /* empty password, pretend password okay */
}
if (check_pw) {

View file

@ -1,5 +1,6 @@
PROG= ls
BINDIR= /bin
MAN=
NEED_NBSDLIBC=yes
.include <bsd.prog.mk>

View file

@ -1,11 +0,0 @@
PROG= passwd
BINMODE= 4755
MAN=
.if defined(NBSD_LIBC) && (${NBSD_LIBC} != "no")
LDADD+= -lcrypt
.endif
LINKS+= ${BINDIR}/passwd ${BINDIR}/chsh
LINKS+= ${BINDIR}/passwd ${BINDIR}/chfn
.include <bsd.prog.mk>

View file

@ -1,260 +0,0 @@
/* passwd - change a passwd Author: Adri Koppes */
/* chfn, chsh - change full name, shell Added by: Kees J. Bot */
#include <sys/types.h>
#include <fcntl.h>
#include <string.h>
#include <signal.h>
#include <pwd.h>
#include <errno.h>
#include <stdlib.h>
#include <unistd.h>
#include <time.h>
#include <sys/stat.h>
#include <minix/minlib.h>
#include <stdio.h>
_PROTOTYPE(void report, (char *label));
_PROTOTYPE(void quit, (int ex_stat));
_PROTOTYPE(void fatal, (char *label));
_PROTOTYPE(void usage, (void));
_PROTOTYPE(int goodchars, (char *s));
_PROTOTYPE(int main, (int argc, char **argv));
char pw_file[] = "/etc/passwd";
char sh_file[] = "/etc/shadow";
char pw_tmp[] = "/etc/ptmp";
char bad[] = "Permission denied\n";
char buf[1024];
enum action {
PASSWD, CHFN, CHSH
} action = PASSWD;
char *arg0;
void report(label)
char *label;
{
int e = errno;
fprintf(stderr, "%s: ", arg0);
fflush(stderr);
errno = e;
perror(label);
}
void quit(ex_stat)
int ex_stat;
{
if (unlink(pw_tmp) < 0 && errno != ENOENT) {
report(pw_tmp);
ex_stat = 1;
}
exit(ex_stat);
}
void fatal(label)
char *label;
{
report(label);
quit(1);
}
void usage()
{
static char *usages[] = {
"passwd [user]\n",
"chfn [user] fullname\n",
"chsh [user] shell\n"
};
std_err(usages[(int) action]);
exit(1);
}
int goodchars(s)
char *s;
{
int c;
while ((c = *s++) != 0) {
if (c == ':' || c < ' ' || c >= 127) return(0);
}
return(1);
}
int main(argc, argv)
int argc;
char *argv[];
{
int uid, cn, n;
int fd_pwd, fd_tmp;
FILE *fp_tmp;
time_t salt;
struct passwd *pwd;
char *name, pwname[9], oldpwd[9], newpwd[9], newcrypted[14], sl[2];
char *argn;
int shadow = 0;
if ((arg0 = strrchr(argv[0], '/')) != 0)
arg0++;
else
arg0 = argv[0];
if (strcmp(arg0, "chfn") == 0)
action = CHFN;
else if (strcmp(arg0, "chsh") == 0)
action = CHSH;
uid = getuid();
n = action == PASSWD ? 1 : 2;
if (argc != n && argc != n + 1) usage();
if (argc == n) {
pwd = getpwuid(uid);
strcpy(pwname, pwd->pw_name);
name = pwname;
} else {
name = argv[1];
pwd = getpwnam(name);
}
if (pwd == NULL || ((uid != pwd->pw_uid) && uid != 0)) {
std_err(bad);
exit(1);
}
switch (action) {
case PASSWD:
if (pwd->pw_passwd[0] == '#' && pwd->pw_passwd[1] == '#') {
/* The password is found in the shadow password file. */
shadow = 1;
strncpy(pwname, pwd->pw_passwd + 2, 8);
pwname[8] = 0;
name = pwname;
setpwfile(sh_file);
if ((pwd= getpwnam(name)) == NULL) {
std_err(bad);
exit(1);
}
printf("Changing the shadow password of %s\n", name);
} else {
printf("Changing the password of %s\n", name);
}
oldpwd[0] = 0;
if (pwd->pw_passwd[0] != '\0' && uid != 0) {
strcpy(oldpwd, getpass("Old password:"));
if (strcmp(pwd->pw_passwd, crypt(oldpwd, pwd->pw_passwd)) != 0)
{
std_err(bad);
exit(1);
}
}
for (;;) {
strcpy(newpwd, getpass("New password:"));
if (newpwd[0] == '\0')
std_err("Password cannot be null");
else if (strcmp(newpwd, getpass("Retype password:")) != 0)
std_err("Passwords don't match");
else
break;
std_err(", try again\n");
}
time(&salt);
sl[0] = (salt & 077) + '.';
sl[1] = ((salt >> 6) & 077) + '.';
for (cn = 0; cn < 2; cn++) {
if (sl[cn] > '9') sl[cn] += 7;
if (sl[cn] > 'Z') sl[cn] += 6;
}
strcpy(newcrypted, crypt(newpwd, sl));
break;
case CHFN:
case CHSH:
argn = argv[argc - 1];
if (strlen(argn) > (action == CHFN ? 80 : 60) || !goodchars(argn)) {
std_err(bad);
exit(1);
}
}
signal(SIGHUP, SIG_IGN);
signal(SIGINT, SIG_IGN);
signal(SIGQUIT, SIG_IGN);
signal(SIGTERM, SIG_IGN);
umask(0);
n = 10;
while ((fd_tmp = open(pw_tmp, O_RDWR | O_CREAT | O_EXCL, 0400)) < 0) {
if (errno != EEXIST) fatal("Can't create temporary file");
if (n-- > 0) {
sleep(2);
} else {
fprintf(stderr, "Password file busy, try again later.\n");
exit(1);
}
}
if ((fp_tmp = fdopen(fd_tmp, "w+")) == NULL) fatal(pw_tmp);
setpwent();
while ((pwd = getpwent()) != 0) {
if (strcmp(name, pwd->pw_name) == 0) {
switch (action) {
case PASSWD:
pwd->pw_passwd = newcrypted;
break;
case CHFN:
pwd->pw_gecos = argn;
break;
case CHSH:
pwd->pw_shell = argn;
break;
}
}
if (strcmp(pwd->pw_shell, "/bin/sh") == 0
|| strcmp(pwd->pw_shell, "/usr/bin/sh") == 0
)
pwd->pw_shell = "";
fprintf(fp_tmp, "%s:%s:%s:",
pwd->pw_name,
pwd->pw_passwd,
itoa(pwd->pw_uid)
);
if (ferror(fp_tmp)) fatal(pw_tmp);
fprintf(fp_tmp, "%s:%s:%s:%s\n",
itoa(pwd->pw_gid),
pwd->pw_gecos,
pwd->pw_dir,
pwd->pw_shell
);
if (ferror(fp_tmp)) fatal(pw_tmp);
}
endpwent();
if (fflush(fp_tmp) == EOF) fatal(pw_tmp);
if (lseek(fd_tmp, (off_t) 0, SEEK_SET) != 0)
fatal("Can't reread temp file");
if ((fd_pwd = open(shadow ? sh_file : pw_file, O_WRONLY | O_TRUNC)) < 0)
fatal("Can't recreate password file");
while ((n = read(fd_tmp, buf, sizeof(buf))) != 0) {
if (n < 0 || write(fd_pwd, buf, n) != n) {
report("Error rewriting password file, tell root!");
exit(1);
}
}
close(fd_tmp);
close(fd_pwd);
quit(0);
}

View file

@ -2,5 +2,8 @@ PROG= pwdauth
BINDIR= /usr/lib
BINMODE= 4755
MAN=
NEED_NBSDLIBC=y
LDADD+=-lcrypt
.include <bsd.prog.mk>

View file

@ -16,7 +16,6 @@
* a no-password login.
*/
#define nil 0
#define crypt CRYPT /* The true crypt is included here. */
#include <sys/types.h>
#include <pwd.h>
#include <stdlib.h>
@ -30,7 +29,6 @@
#endif
#define LEN 1024
char SHADOW[] = "/etc/shadow";
int main(int argc, char **argv)
{
@ -51,11 +49,6 @@ int main(int argc, char **argv)
salt = key + strlen(key) + 1;
if (salt[0] == '#' && salt[1] == '#') {
/* Get the encrypted password from the shadow password file,
* encrypt key and compare.
*/
setpwfile(SHADOW);
if ((pw= getpwnam(salt + 2)) == nil) return 2;
/* A null encrypted password matches a null key, otherwise
@ -80,283 +73,3 @@ int main(int argc, char **argv)
if (write(1, salt, strlen(salt) + 1) < 0) return 1;
return 0;
}
/* The one and only crypt(3) function. */
/* From Andy Tanenbaum's book "Computer Networks",
rewritten in C
*/
struct block {
unsigned char b_data[64];
};
struct ordering {
unsigned char o_data[64];
};
static struct block key;
static struct ordering InitialTr = {
58,50,42,34,26,18,10, 2,60,52,44,36,28,20,12, 4,
62,54,46,38,30,22,14, 6,64,56,48,40,32,24,16, 8,
57,49,41,33,25,17, 9, 1,59,51,43,35,27,19,11, 3,
61,53,45,37,29,21,13, 5,63,55,47,39,31,23,15, 7,
};
static struct ordering FinalTr = {
40, 8,48,16,56,24,64,32,39, 7,47,15,55,23,63,31,
38, 6,46,14,54,22,62,30,37, 5,45,13,53,21,61,29,
36, 4,44,12,52,20,60,28,35, 3,43,11,51,19,59,27,
34, 2,42,10,50,18,58,26,33, 1,41, 9,49,17,57,25,
};
static struct ordering swap = {
33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,
49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,
1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15,16,
17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,
};
static struct ordering KeyTr1 = {
57,49,41,33,25,17, 9, 1,58,50,42,34,26,18,
10, 2,59,51,43,35,27,19,11, 3,60,52,44,36,
63,55,47,39,31,23,15, 7,62,54,46,38,30,22,
14, 6,61,53,45,37,29,21,13, 5,28,20,12, 4,
};
static struct ordering KeyTr2 = {
14,17,11,24, 1, 5, 3,28,15, 6,21,10,
23,19,12, 4,26, 8,16, 7,27,20,13, 2,
41,52,31,37,47,55,30,40,51,45,33,48,
44,49,39,56,34,53,46,42,50,36,29,32,
};
static struct ordering etr = {
32, 1, 2, 3, 4, 5, 4, 5, 6, 7, 8, 9,
8, 9,10,11,12,13,12,13,14,15,16,17,
16,17,18,19,20,21,20,21,22,23,24,25,
24,25,26,27,28,29,28,29,30,31,32, 1,
};
static struct ordering ptr = {
16, 7,20,21,29,12,28,17, 1,15,23,26, 5,18,31,10,
2, 8,24,14,32,27, 3, 9,19,13,30, 6,22,11, 4,25,
};
static unsigned char s_boxes[8][64] = {
{ 14, 4,13, 1, 2,15,11, 8, 3,10, 6,12, 5, 9, 0, 7,
0,15, 7, 4,14, 2,13, 1,10, 6,12,11, 9, 5, 3, 8,
4, 1,14, 8,13, 6, 2,11,15,12, 9, 7, 3,10, 5, 0,
15,12, 8, 2, 4, 9, 1, 7, 5,11, 3,14,10, 0, 6,13,
},
{ 15, 1, 8,14, 6,11, 3, 4, 9, 7, 2,13,12, 0, 5,10,
3,13, 4, 7,15, 2, 8,14,12, 0, 1,10, 6, 9,11, 5,
0,14, 7,11,10, 4,13, 1, 5, 8,12, 6, 9, 3, 2,15,
13, 8,10, 1, 3,15, 4, 2,11, 6, 7,12, 0, 5,14, 9,
},
{ 10, 0, 9,14, 6, 3,15, 5, 1,13,12, 7,11, 4, 2, 8,
13, 7, 0, 9, 3, 4, 6,10, 2, 8, 5,14,12,11,15, 1,
13, 6, 4, 9, 8,15, 3, 0,11, 1, 2,12, 5,10,14, 7,
1,10,13, 0, 6, 9, 8, 7, 4,15,14, 3,11, 5, 2,12,
},
{ 7,13,14, 3, 0, 6, 9,10, 1, 2, 8, 5,11,12, 4,15,
13, 8,11, 5, 6,15, 0, 3, 4, 7, 2,12, 1,10,14, 9,
10, 6, 9, 0,12,11, 7,13,15, 1, 3,14, 5, 2, 8, 4,
3,15, 0, 6,10, 1,13, 8, 9, 4, 5,11,12, 7, 2,14,
},
{ 2,12, 4, 1, 7,10,11, 6, 8, 5, 3,15,13, 0,14, 9,
14,11, 2,12, 4, 7,13, 1, 5, 0,15,10, 3, 9, 8, 6,
4, 2, 1,11,10,13, 7, 8,15, 9,12, 5, 6, 3, 0,14,
11, 8,12, 7, 1,14, 2,13, 6,15, 0, 9,10, 4, 5, 3,
},
{ 12, 1,10,15, 9, 2, 6, 8, 0,13, 3, 4,14, 7, 5,11,
10,15, 4, 2, 7,12, 9, 5, 6, 1,13,14, 0,11, 3, 8,
9,14,15, 5, 2, 8,12, 3, 7, 0, 4,10, 1,13,11, 6,
4, 3, 2,12, 9, 5,15,10,11,14, 1, 7, 6, 0, 8,13,
},
{ 4,11, 2,14,15, 0, 8,13, 3,12, 9, 7, 5,10, 6, 1,
13, 0,11, 7, 4, 9, 1,10,14, 3, 5,12, 2,15, 8, 6,
1, 4,11,13,12, 3, 7,14,10,15, 6, 8, 0, 5, 9, 2,
6,11,13, 8, 1, 4,10, 7, 9, 5, 0,15,14, 2, 3,12,
},
{ 13, 2, 8, 4, 6,15,11, 1,10, 9, 3,14, 5, 0,12, 7,
1,15,13, 8,10, 3, 7, 4,12, 5, 6,11, 0,14, 9, 2,
7,11, 4, 1, 9,12,14, 2, 0, 6,10,13,15, 3, 5, 8,
2, 1,14, 7, 4,10, 8,13,15,12, 9, 0, 3, 5, 6,11,
},
};
static int rots[] = {
1,1,2,2,2,2,2,2,1,2,2,2,2,2,2,1,
};
static void transpose(struct block *data, struct ordering *t, int n)
{
struct block x;
x = *data;
while (n-- > 0) {
data->b_data[n] = x.b_data[t->o_data[n] - 1];
}
}
static void rotate(struct block *key)
{
unsigned char *p = key->b_data;
unsigned char *ep = &(key->b_data[55]);
int data0 = key->b_data[0], data28 = key->b_data[28];
while (p++ < ep) *(p-1) = *p;
key->b_data[27] = data0;
key->b_data[55] = data28;
}
static struct ordering *EP = &etr;
static void f(int i, struct block *key, struct block *a, struct block *x)
{
struct block e, ikey, y;
int k;
unsigned char *p, *q, *r;
e = *a;
transpose(&e, EP, 48);
for (k = rots[i]; k; k--) rotate(key);
ikey = *key;
transpose(&ikey, &KeyTr2, 48);
p = &(y.b_data[48]);
q = &(e.b_data[48]);
r = &(ikey.b_data[48]);
while (p > y.b_data) {
*--p = *--q ^ *--r;
}
q = x->b_data;
for (k = 0; k < 8; k++) {
int xb, r;
r = *p++ << 5;
r += *p++ << 3;
r += *p++ << 2;
r += *p++ << 1;
r += *p++;
r += *p++ << 4;
xb = s_boxes[k][r];
*q++ = (xb >> 3) & 1;
*q++ = (xb>>2) & 1;
*q++ = (xb>>1) & 1;
*q++ = (xb & 1);
}
transpose(x, &ptr, 32);
}
static void setkey(char *k)
{
key = *((struct block *) k);
transpose(&key, &KeyTr1, 56);
}
static void encrypt(char *blck, int edflag)
{
struct block *p = (struct block *) blck;
int i;
transpose(p, &InitialTr, 64);
for (i = 15; i>= 0; i--) {
int j = edflag ? i : 15 - i;
int k;
struct block b, x;
b = *p;
for (k = 31; k >= 0; k--) {
p->b_data[k] = b.b_data[k + 32];
}
f(j, &key, p, &x);
for (k = 31; k >= 0; k--) {
p->b_data[k+32] = b.b_data[k] ^ x.b_data[k];
}
}
transpose(p, &swap, 64);
transpose(p, &FinalTr, 64);
}
char *crypt(const char *pw, const char *salt)
{
char pwb[66];
char *cp;
static char result[16];
char *p = pwb;
struct ordering new_etr;
int i;
while (*pw && p < &pwb[64]) {
int j = 7;
while (j--) {
*p++ = (*pw >> j) & 01;
}
pw++;
*p++ = 0;
}
while (p < &pwb[64]) *p++ = 0;
setkey(p = pwb);
while (p < &pwb[66]) *p++ = 0;
new_etr = etr;
EP = &new_etr;
if (salt[0] == 0 || salt[1] == 0) salt = "**";
for (i = 0; i < 2; i++) {
char c = *salt++;
int j;
result[i] = c;
if ( c > 'Z') c -= 6 + 7 + '.'; /* c was a lower case letter */
else if ( c > '9') c -= 7 + '.';/* c was upper case letter */
else c -= '.'; /* c was digit, '.' or '/'. */
/* now, 0 <= c <= 63 */
for (j = 0; j < 6; j++) {
if ((c >> j) & 01) {
int t = 6*i + j;
int temp = new_etr.o_data[t];
new_etr.o_data[t] = new_etr.o_data[t+24];
new_etr.o_data[t+24] = temp;
}
}
}
if (result[1] == 0) result[1] = result[0];
for (i = 0; i < 25; i++) encrypt(pwb,0);
EP = &etr;
p = pwb;
cp = result+2;
while (p < &pwb[66]) {
int c = 0;
int j = 6;
while (j--) {
c <<= 1;
c |= *p++;
}
c += '.'; /* becomes >= '.' */
if (c > '9') c += 7; /* not in [./0-9], becomes upper */
if (c > 'Z') c += 6; /* not in [A-Z], becomes lower */
*cp++ = c;
}
*cp = 0;
return result;
}

View file

@ -1,9 +1,8 @@
PROG= su
BINMODE= 4755
MAN=
.if defined(NBSD_LIBC) && (${NBSD_LIBC} != "no")
NEED_NBSDLIBC=y
LDADD+= -lcrypt
.endif
.include <bsd.prog.mk>

View file

@ -1,3 +1,37 @@
20111109:
Switch to NetBSD passwd system.
You have to bootstrap pwd_mkdb:
# make clean includes elf-libraries
# make -C usr.sbin/pwd_mkdb install
Now build world. WARNING: this will blind your system to
/etc/shadow, making current user accounts vanish. Updating the
group file is necessary to add a 'users' group so the new stock
useradd will work.
# make clean world
# cp etc/group /etc/group
The new shadow file is /etc/master.passwd. Add your old user
accounts back with useradd(8), groups with groupadd(8), and
set a root pw with passwd(1) if you want. Use vipw(8) to edit
/etc/master.passwd if you want. See useradd(8) to get started
with the new pw format. Test your new system now by logging in.
Once you're satisfied your new system works, remove the old
adduser, and rely exclusively on the new useradd and
master.passwd.
# rm /usr/bin/adduser
# mv /etc/shadow /etc/shadow.orig
pwdauth is updated so that current binaries (e.g. sshd) will
work with the new pw db.
By default your new users are in the 'users' group. Add yourself
to the 'operator' group if you want to be able to su without
typing in the password.
20111109:
fstab format change. /etc/rc reads both formats for a while.
Please convert your /etc/fstab to the new format though as

View file

@ -25,7 +25,7 @@ PROTO= proto.small
STRIPFLAG+= -s
.endif
EXTRA=system.conf passwd rs.single
EXTRA=system.conf master.passwd passwd pwd.db rs.single
CPPFLAGS+= -I${MINIXSRCDIR}/servers -I${MINIXSRCDIR}
CLEANFILES += $(PROGRAMS) $(SCRIPTS) $(EXTRA) bintoc image image.c t proto.gen
@ -150,7 +150,16 @@ ext2: ../../servers/ext2/ext2
system.conf: ../../etc/system.conf
install ${STRIPFLAG} ../../etc/$@ $@
passwd: ../../etc/passwd
passwd: ../../etc/master.passwd
rm -f ../../etc/master.passwd.orig ../../etc/passwd.orig
rm -f ../../etc/pwd.db.tmp ../../etc/spwd.db.tmp
../../usr.sbin/pwd_mkdb/pwd_mkdb -V 0 -p -d ../../ ../../etc/master.passwd
install ${STRIPFLAG} ../../etc/$@ $@
master.passwd: ../../etc/master.passwd
install ${STRIPFLAG} ../../etc/$@ $@
pwd.db: passwd
install ${STRIPFLAG} ../../etc/$@ $@
rs.single: ../../etc/rs.single

View file

@ -1,23 +1,24 @@
ETC=/etc/
USR=/usr/
USRETC=/usr/etc/
FILES1=group hostname.file inet.conf motd.install mtab passwd profile \
FILES1=group hostname.file inet.conf motd.install mtab profile \
protocols rc services termcap ttytab utmp rc.cd binary_sizes \
binary_sizes.big binary_sizes.xxl syslog.conf rc.daemons.dist \
rs.inet rs.single make.conf system.conf ttys resolv.conf rc.conf \
rc.subr rc.subr.minix man.conf
FILES2=shadow
PWFILES=master.passwd
FILES3=daily dhcptags.conf rc
USRFILES=Makefile
TOOL_PWD_MKDB= pwd_mkdb
clean::
install::
install:: installpw # installpw needed to bootstrap pw db
@echo "Installing /etc, /usr/etc and /usr/lib.."
mkdir -p $(ETC) $(USRLIB)
@for f in $(FILES1); do if [ -f $(ETC)/$$f ]; then :; else cp $$f $(ETC)/$$f; chmod 755 $(ETC)/$$f; fi; done
@for f in $(FILES2); do if [ -f $(ETC)/$$f ]; then :; else cp $$f $(ETC)/$$f; chmod 600 $(ETC)/$$f; fi; done
@for f in $(USRFILES); do cp usr/$$f $(USR)/$$f; chmod 644 $(USR)/$$f; done
@echo "Making hierarchy.."
sh mtree.sh mtree/minix.tree
@ -33,7 +34,13 @@ install::
@echo "Installing /usr/lib/descr.."
install -m 644 -o root -g operator descr /usr/lib/
installforce:: $(ETC)/rc $(ETC)/rs.inet $(ETC)/rs.single $(ETC)/system.conf $(USRETC)/rc $(USR)/Makefile
installforce:: $(ETC)/rc $(ETC)/rs.inet $(ETC)/rs.single $(ETC)/system.conf $(USRETC)/rc $(USR)/Makefile installpw
installpw::
if [ ! -d $(ETC) ]; then mkdir $(ETC); chmod 755 $(ETC); fi
@for f in $(PWFILES); do if [ -f $(ETC)/$$f ]; then :; else cp $$f $(ETC)/$$f; chmod 600 $(ETC)/$$f; fi; done
touch /etc/pwd.db; touch /etc/spwd.db; ${TOOL_PWD_MKDB} -p -V 0 /etc/master.passwd
$(ETC)/rc: rc
install -m 755 -o root -g operator $> $@

View file

@ -11,9 +11,19 @@ www:*:9:
driver:*:10:
server:*:11:
games:*:13:
sshd:*:23:
smtpd:*:26:
postfix:*:27:
maildrop:*:28:
mail:*:29:
_pflogd:*:18:
_rwhod:*:19:
_proxy:*:21:
_timedc:*:22:
_sdpd:*:23:
_httpd:*:24:
_mdnsd:*:25:
_tests:*:26:
_tcpdump:*:27:
smtpd:*:40:
postfix:*:41:
maildrop:*:42:
mail:*:43:
sshd:*:44:
nogroup:*:99:
users:*:100:

17
etc/master.passwd Normal file
View file

@ -0,0 +1,17 @@
root::0:0::0:0:Big Brother:/root:/bin/sh
daemon:*:1:1::0:0:The Deuce:/etc:/bin/sh
bin:*:2:0::0:0:Binaries:/home/bin:/bin/sh
uucp:*:5:5::0:0:UNIX to UNIX copy:/usr/spool/uucp:/usr/bin/uucico
news:*:6:6::0:0:Usenet news:/usr/spool/news:/bin/sh
ftp:*:7:7::0:0:Anonymous FTP:/usr/ftp:/bin/sh
ast:*:8:3::0:0:Andrew S. Tanenbaum:/home/ast:/bin/sh
www:*:9:9::0:0:World Wide Web:/usr/www:/bin/sh
driver:*:10:10::0:0:Device Drivers:/:/bin/sh
server:*:11:11::0:0:OS Servers:/:/bin/sh
service:*:12:12::0:0:System Services:/:/bin/sh
sshd:*:22:22::0:0:sshd:/:/bin/sh
smtpd:*:25:25::0:0:smtpd:/:/bin/sh
postfix:*:27:27::0:0:postfix:/usr/var/spool/postfix:/bin/false
postgres:*:30:30::0:0:postgresql:/:/bin/false
games:*:9998:13::0:0:games:/:/bin/sh
nobody:*:9999:39::0:0:Unprivileged user:/tmp:/bin/sh

View file

@ -1,17 +0,0 @@
root:##root:0:0:Big Brother:/root:
daemon:*:1:1:The Deuce:/etc:
bin:##root:2:0:Binaries:/home/bin:
uucp:*:5:5:UNIX to UNIX copy:/usr/spool/uucp:/usr/bin/uucico
news:*:6:6:Usenet news:/usr/spool/news:
ftp:*:7:7:Anonymous FTP:/usr/ftp:
ast:*:8:3:Andrew S. Tanenbaum:/home/ast:
www:*:9:9:World Wide Web:/usr/www:
driver:*:10:10:Device Drivers:/:
server:*:11:11:OS Servers:/:
service:*:12:12:System Services:/:
sshd:*:22:22:sshd:/:
smtpd:*:25:25:smtpd:/:
postfix:*:27:27:postfix:/usr/var/spool/postfix:/bin/false
postgres:*:30:30:postgresql:/:/bin/false
games:*:9998:98::/:
nobody:*:9999:99::/tmp:

View file

@ -1 +0,0 @@
root::0:0:::

View file

@ -3,6 +3,7 @@
.if defined(NBSD_LIBC) && (${NBSD_LIBC} != "no")
LIBC_DIR= nbsd_libc
LIBM_DIR= nbsd_libm
LIBUTIL_DIR= libutil
LIBCOMPAT_DIR= nbsd_libcompat_minix
LIBMINLIB_DIR= nbsd_libminlib
LIBASYN_DIR= nbsd_libasyn
@ -10,12 +11,13 @@ LIBASYN_DIR= nbsd_libasyn
LIBC_DIR?= libc
LIBM_DIR?= libm
LIBUTIL_DIR?= libminixutil
LIBCOMPAT_DIR?=
LIBMINLIB_DIR?=
LIBASYN_DIR?=
SUBDIR= csu ${LIBCOMPAT_DIR} ${LIBC_DIR} libdriver libnetdriver \
libedit ${LIBM_DIR} libsys libtimers libminixutil libbz2 libl libhgfs \
libedit ${LIBM_DIR} libsys libtimers ${LIBUTIL_DIR} libbz2 libl libhgfs \
libz libfetch libarchive libvtreefs libaudiodriver libmthread \
libexec libdevman libusb ${LIBMINLIB_DIR} ${LIBASYN_DIR} \
libddekit libminixfs libbdev

View file

@ -41,7 +41,6 @@ SRCS+= \
bcopy.c \
bzero.c \
configfile.c \
crypt.c \
ctermid.c \
cuserid.c \
dirname.c \
@ -64,7 +63,6 @@ SRCS+= \
getpagesize.c \
getpass.c \
getprogname.c \
getpwent.c \
getsubopt.c \
getttyent.c \
getw.c \
@ -85,7 +83,6 @@ SRCS+= \
popen.c \
putenv.c \
putw.c \
pwcache.c \
random.c \
read_tsc.S \
read_tsc_64.c \
@ -125,3 +122,9 @@ SRCS+= \
vwarnx.c \
warn.c \
warnx.c
# XXX To be removed after full
# XXX switch to NetBSD passwd.
SRCS+= \
getpwent.c \
pwcache.c

View file

@ -1,115 +0,0 @@
/* crypt() - one-way password encryption function Author: Kees J. Bot
* 7 Feb 1994
* This routine does not encrypt anything, it uses the pwdauth
* program to do the hard work.
*/
#define nil ((void*)0)
#define pipe _pipe
#define fork _fork
#define close _close
#define dup2 _dup2
#define execl _execl
#define read _read
#define _exit __exit
#define write _write
#define waitpid _waitpid
#include <sys/types.h>
#include <unistd.h>
#include <string.h>
#include <stdio.h>
#include <errno.h>
#include <stdarg.h>
#include <sys/wait.h>
/* Set-uid root program to read /etc/shadow or encrypt passwords. */
static char PWDAUTH[] = "/usr/lib/pwdauth";
#define LEN 1024
static void tell(const char *s0, ...)
{
va_list ap;
const char *s;
va_start(ap, s0);
s= s0;
while (s != nil) {
(void) write(2, s, strlen(s));
s= va_arg(ap, const char *);
}
va_end(ap);
}
char *crypt(const char *key, const char *salt)
{
pid_t pid;
int status;
int pfd[2];
static char pwdata[LEN];
char *p= pwdata;
const char *k= key;
const char *s= salt;
int n;
/* Fill pwdata[] with the key and salt. */
while ((*p++ = *k++) != 0) if (p == pwdata+LEN-1) goto fail;
while ((*p++ = *s++) != 0) if (p == pwdata+LEN-0) goto fail;
if (pipe(pfd) < 0) goto fail;
/* Prefill the pipe. */
(void) write(pfd[1], pwdata, p - pwdata);
switch ((pid= fork())) {
case -1:
close(pfd[0]);
close(pfd[1]);
goto fail;
case 0:
/* Connect both input and output to the pipe. */
if (pfd[0] != 0) {
dup2(pfd[0], 0);
close(pfd[0]);
}
if (pfd[1] != 1) {
dup2(pfd[1], 1);
close(pfd[1]);
}
execl(PWDAUTH, PWDAUTH, (char *) nil);
tell("crypt(): ", PWDAUTH, ": ", strerror(errno), "\r\n",
(char *) nil);
/* No pwdauth? Fail! */
(void) read(0, pwdata, LEN);
_exit(1);
}
close(pfd[1]);
status= -1;
while (waitpid(pid, &status, 0) == -1 && errno == EINTR) {}
if (status != 0) {
close(pfd[0]);
goto fail;
}
/* Read and return the result. Check if it contains exactly one
* string.
*/
n= read(pfd[0], pwdata, LEN);
close(pfd[0]);
if (n < 0) goto fail;
p = pwdata + n;
n = 0;
while (p > pwdata) if (*--p == 0) n++;
if (n != 1) goto fail;
return pwdata;
fail:
pwdata[0] = salt[0] ^ 1; /* make result != salt */
pwdata[1] = 0;
return pwdata;
}
/*
* $PchId: crypt.c,v 1.5 1996/04/11 07:46:11 philip Exp $
*/

View file

@ -17,7 +17,7 @@ SRCS= efun.c getbootfile.c \
passwd.c pw_scan.c pidfile.c pidlock.c pty.c \
raise_default_signal.c \
secure_path.c snprintb.c \
ttyaction.c
ttyaction.c login_cap.c
#disklabel_dkcksum.c disklabel_scan.c \
#if_media.c \
#sockaddr_snprintf.c
@ -25,7 +25,6 @@ SRCS= efun.c getbootfile.c \
#getmaxpartitions.c
#stat_flags.c
#getrawpartition.c
#login_cap.c
#ttymsg.c
#parsedate.y

View file

@ -3,5 +3,6 @@
.PATH: ${.CURDIR}/compat
CPPFLAGS+=-I${.CURDIR}/../libc -I${.CURDIR}/../../sys
SRCS+=compat_passwd.c compat_loginx.c compat_login.c compat_parsedate.c \
SRCS+=compat_passwd.c compat_loginx.c compat_parsedate.c \
compat_login_cap.c
# compat_login.c

View file

@ -417,12 +417,16 @@ static struct {
{ RLIMIT_FSIZE, R_CSIZE, "filesize", },
{ RLIMIT_DATA, R_CSIZE, "datasize", },
{ RLIMIT_STACK, R_CSIZE, "stacksize", },
#ifndef __minix
{ RLIMIT_RSS, R_CSIZE, "memoryuse", },
{ RLIMIT_MEMLOCK, R_CSIZE, "memorylocked", },
{ RLIMIT_NPROC, R_CNUMB, "maxproc", },
#endif
{ RLIMIT_NOFILE, R_CNUMB, "openfiles", },
{ RLIMIT_CORE, R_CSIZE, "coredumpsize", },
#ifdef RLIMIT_SBSIZE
{ RLIMIT_SBSIZE, R_CSIZE, "sbsize", },
#endif
{ -1, 0, 0 }
};
@ -472,11 +476,13 @@ gsetrl(login_cap_t *lc, int what, const char *name, int type)
return (-1);
}
#ifndef __minix
if (setrlimit(what, &rl)) {
syslog(LOG_ERR, "%s: setting resource limit %s: %m",
lc->lc_class, name);
return (-1);
}
#endif
#undef RCUR
#undef RMAX
return (0);
@ -570,6 +576,7 @@ setusercontext(login_cap_t *lc, struct passwd *pwd, uid_t uid, u_int flags)
if (!lc)
flc = lc = login_getclass(pwd ? pwd->pw_class : NULL);
#define LOGIN_SETLOGIN 0
/*
* Without the pwd entry being passed we cannot set either
* the group or the login. We could complain about it.

View file

@ -59,6 +59,16 @@
* POSSIBILITY OF SUCH DAMAGE.
*/
#if HAVE_NBTOOL_CONFIG_H
#include "nbtool_config.h"
/*
* XXX Undefine the renames of these functions so that we don't
* XXX rename the versions found in the host's <pwd.h> by mistake!
*/
#undef group_from_gid
#undef user_from_uid
#endif
#include <sys/cdefs.h>
#if defined(LIBC_SCCS) && !defined(lint)
#if 0
@ -81,6 +91,18 @@ __RCSID("$NetBSD: pwcache.c,v 1.31 2010/03/23 20:28:59 drochner Exp $");
#include <string.h>
#include <unistd.h>
#if HAVE_NBTOOL_CONFIG_H
/* XXX Now, re-apply the renaming that we undid above. */
#define group_from_gid __nbcompat_group_from_gid
#define user_from_uid __nbcompat_user_from_uid
#endif
#ifdef __weak_alias
__weak_alias(user_from_uid,_user_from_uid)
__weak_alias(group_from_gid,_group_from_gid)
__weak_alias(pwcache_groupdb,_pwcache_groupdb)
#endif
#if !HAVE_PWCACHE_USERDB || HAVE_NBTOOL_CONFIG_H
#include "pwcache.h"
@ -226,6 +248,273 @@ grptb_start(void)
return (0);
}
/*
* user_from_uid()
* caches the name (if any) for the uid. If noname clear, we always
* return the stored name (if valid or invalid match).
* We use a simple hash table.
* Return
* Pointer to stored name (or a empty string)
*/
const char *
user_from_uid(uid_t uid, int noname)
{
struct passwd *pw;
UIDC *ptr, **pptr;
if ((uidtb == NULL) && (uidtb_start() < 0))
return (NULL);
/*
* see if we have this uid cached
*/
pptr = uidtb + (uid % UID_SZ);
ptr = *pptr;
if ((ptr != NULL) && (ptr->valid > 0) && (ptr->uid == uid)) {
/*
* have an entry for this uid
*/
if (!noname || (ptr->valid == VALID))
return (ptr->name);
return (NULL);
}
/*
* No entry for this uid, we will add it
*/
if (!pwopn) {
if (_pwcache_setpassent != NULL)
(*_pwcache_setpassent)(1);
++pwopn;
}
if (ptr == NULL)
*pptr = ptr = (UIDC *)malloc(sizeof(UIDC));
if ((pw = (*_pwcache_getpwuid)(uid)) == NULL) {
/*
* no match for this uid in the local password file
* a string that is the uid in numeric format
*/
if (ptr == NULL)
return (NULL);
ptr->uid = uid;
(void)snprintf(ptr->name, UNMLEN, "%lu", (long) uid);
ptr->valid = INVALID;
if (noname)
return (NULL);
} else {
/*
* there is an entry for this uid in the password file
*/
if (ptr == NULL)
return (pw->pw_name);
ptr->uid = uid;
(void)strlcpy(ptr->name, pw->pw_name, UNMLEN);
ptr->valid = VALID;
}
return (ptr->name);
}
/*
* group_from_gid()
* caches the name (if any) for the gid. If noname clear, we always
* return the stored name (if valid or invalid match).
* We use a simple hash table.
* Return
* Pointer to stored name (or a empty string)
*/
const char *
group_from_gid(gid_t gid, int noname)
{
struct group *gr;
GIDC *ptr, **pptr;
if ((gidtb == NULL) && (gidtb_start() < 0))
return (NULL);
/*
* see if we have this gid cached
*/
pptr = gidtb + (gid % GID_SZ);
ptr = *pptr;
if ((ptr != NULL) && (ptr->valid > 0) && (ptr->gid == gid)) {
/*
* have an entry for this gid
*/
if (!noname || (ptr->valid == VALID))
return (ptr->name);
return (NULL);
}
/*
* No entry for this gid, we will add it
*/
if (!gropn) {
if (_pwcache_setgroupent != NULL)
(*_pwcache_setgroupent)(1);
++gropn;
}
if (ptr == NULL)
*pptr = ptr = (GIDC *)malloc(sizeof(GIDC));
if ((gr = (*_pwcache_getgrgid)(gid)) == NULL) {
/*
* no match for this gid in the local group file, put in
* a string that is the gid in numberic format
*/
if (ptr == NULL)
return (NULL);
ptr->gid = gid;
(void)snprintf(ptr->name, GNMLEN, "%lu", (long) gid);
ptr->valid = INVALID;
if (noname)
return (NULL);
} else {
/*
* there is an entry for this group in the group file
*/
if (ptr == NULL)
return (gr->gr_name);
ptr->gid = gid;
(void)strlcpy(ptr->name, gr->gr_name, GNMLEN);
ptr->valid = VALID;
}
return (ptr->name);
}
/*
* uid_from_user()
* caches the uid for a given user name. We use a simple hash table.
* Return
* the uid (if any) for a user name, or a -1 if no match can be found
*/
int
uid_from_user(const char *name, uid_t *uid)
{
struct passwd *pw;
UIDC *ptr, **pptr;
size_t namelen;
/*
* return -1 for mangled names
*/
if (name == NULL || ((namelen = strlen(name)) == 0))
return (-1);
if ((usrtb == NULL) && (usrtb_start() < 0))
return (-1);
/*
* look up in hash table, if found and valid return the uid,
* if found and invalid, return a -1
*/
pptr = usrtb + st_hash(name, namelen, UNM_SZ);
ptr = *pptr;
if ((ptr != NULL) && (ptr->valid > 0) && !strcmp(name, ptr->name)) {
if (ptr->valid == INVALID)
return (-1);
*uid = ptr->uid;
return (0);
}
if (!pwopn) {
if (_pwcache_setpassent != NULL)
(*_pwcache_setpassent)(1);
++pwopn;
}
if (ptr == NULL)
*pptr = ptr = (UIDC *)malloc(sizeof(UIDC));
/*
* no match, look it up, if no match store it as an invalid entry,
* or store the matching uid
*/
if (ptr == NULL) {
if ((pw = (*_pwcache_getpwnam)(name)) == NULL)
return (-1);
*uid = pw->pw_uid;
return (0);
}
(void)strlcpy(ptr->name, name, UNMLEN);
if ((pw = (*_pwcache_getpwnam)(name)) == NULL) {
ptr->valid = INVALID;
return (-1);
}
ptr->valid = VALID;
*uid = ptr->uid = pw->pw_uid;
return (0);
}
/*
* gid_from_group()
* caches the gid for a given group name. We use a simple hash table.
* Return
* the gid (if any) for a group name, or a -1 if no match can be found
*/
int
gid_from_group(const char *name, gid_t *gid)
{
struct group *gr;
GIDC *ptr, **pptr;
size_t namelen;
/*
* return -1 for mangled names
*/
if (name == NULL || ((namelen = strlen(name)) == 0))
return (-1);
if ((grptb == NULL) && (grptb_start() < 0))
return (-1);
/*
* look up in hash table, if found and valid return the uid,
* if found and invalid, return a -1
*/
pptr = grptb + st_hash(name, namelen, GID_SZ);
ptr = *pptr;
if ((ptr != NULL) && (ptr->valid > 0) && !strcmp(name, ptr->name)) {
if (ptr->valid == INVALID)
return (-1);
*gid = ptr->gid;
return (0);
}
if (!gropn) {
if (_pwcache_setgroupent != NULL)
(*_pwcache_setgroupent)(1);
++gropn;
}
if (ptr == NULL)
*pptr = ptr = (GIDC *)malloc(sizeof(GIDC));
/*
* no match, look it up, if no match store it as an invalid entry,
* or store the matching gid
*/
if (ptr == NULL) {
if ((gr = (*_pwcache_getgrnam)(name)) == NULL)
return (-1);
*gid = gr->gr_gid;
return (0);
}
(void)strlcpy(ptr->name, name, GNMLEN);
if ((gr = (*_pwcache_getgrnam)(name)) == NULL) {
ptr->valid = INVALID;
return (-1);
}
ptr->valid = VALID;
*gid = ptr->gid = gr->gr_gid;
return (0);
}
#define FLUSHTB(arr, len, fail) \
do { \
if (arr != NULL) { \

View file

@ -24,11 +24,6 @@ SRCS+= nlist.c
# NetBSD's 'mtab' format.
SRCS+= mtab.c
# Minix legacy passwd format
# These should be removed when we switch to
# NetBSD's 'passwd' db-based format.
SRCS+= getpwent.c
# fttyslot(fd), a Minix-specific extension
SRCS+= fttyslot.c
@ -36,11 +31,6 @@ SRCS+= fttyslot.c
# Now considered "compat" feature in NetBSD.
SRCS+= cuserid.c
# XXX: hack
# user_from_uid(), uid_from_user()
# group_from_gid(), gid_from_group()
SRCS+= passwd.c
.include "include/Makefile.inc"
.include <bsd.own.mk>

View file

@ -1,156 +0,0 @@
/* getpwent(), getpwuid(), getpwnam() - password file routines
*
* Author: Kees J. Bot
* 31 Jan 1994
*/
#include <sys/types.h>
#include <compat/pwd.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#define arraysize(a) (sizeof(a) / sizeof((a)[0]))
#define arraylimit(a) ((a) + arraysize(a))
static char PASSWD[]= "/etc/passwd"; /* The password file. */
static const char *pwfile; /* Current password file. */
static char buf[1024]; /* Read buffer. */
static char pwline[256]; /* One line from the password file. */
static struct passwd entry; /* Entry to fill and return. */
static int pwfd= -1; /* Filedescriptor to the file. */
static char *bufptr; /* Place in buf. */
static ssize_t buflen= 0; /* Remaining characters in buf. */
static char *lineptr; /* Place in the line. */
void endpwent(void)
/* Close the password file. */
{
if (pwfd >= 0) {
(void) close(pwfd);
pwfd= -1;
buflen= 0;
}
}
int setpwent(void)
/* Open the password file. */
{
if (pwfd >= 0) endpwent();
if (pwfile == NULL) pwfile= PASSWD;
if ((pwfd= open(pwfile, O_RDONLY)) < 0) return -1;
(void) fcntl(pwfd, F_SETFD, fcntl(pwfd, F_GETFD) | FD_CLOEXEC);
return 0;
}
void setpwfile(const char *file)
/* Prepare for reading an alternate password file. */
{
endpwent();
pwfile= file;
}
static int getline(void)
/* Get one line from the password file, return 0 if bad or EOF. */
{
lineptr= pwline;
do {
if (buflen == 0) {
if ((buflen= read(pwfd, buf, sizeof(buf))) <= 0)
return 0;
bufptr= buf;
}
if (lineptr == arraylimit(pwline)) return 0;
buflen--;
} while ((*lineptr++ = *bufptr++) != '\n');
lineptr= pwline;
return 1;
}
static char *scan_colon(void)
/* Scan for a field separator in a line, return the start of the field. */
{
char *field= lineptr;
char *last;
for (;;) {
last= lineptr;
if (*lineptr == 0) return NULL;
if (*lineptr == '\n') break;
if (*lineptr++ == ':') break;
}
*last= 0;
return field;
}
struct passwd *getpwent(void)
/* Read one entry from the password file. */
{
char *p;
/* Open the file if not yet open. */
if (pwfd < 0 && setpwent() < 0) return NULL;
/* Until a good line is read. */
for (;;) {
if (!getline()) return NULL; /* EOF or corrupt. */
if ((entry.pw_name= scan_colon()) == NULL) continue;
if ((entry.pw_passwd= scan_colon()) == NULL) continue;
if ((p= scan_colon()) == NULL) continue;
entry.pw_uid= strtol(p, NULL, 0);
if ((p= scan_colon()) == NULL) continue;
entry.pw_gid= strtol(p, NULL, 0);
if ((entry.pw_gecos= scan_colon()) == NULL) continue;
if ((entry.pw_dir= scan_colon()) == NULL) continue;
if ((entry.pw_shell= scan_colon()) == NULL) continue;
if (*lineptr == 0) return &entry;
}
}
struct passwd *getpwuid(uid_t uid)
/* Return the password file entry belonging to the user-id. */
{
struct passwd *pw;
endpwent();
while ((pw= getpwent()) != NULL && pw->pw_uid != uid) {}
endpwent();
return pw;
}
struct passwd *getpwnam(const char *name)
/* Return the password file entry belonging to the user name. */
{
struct passwd *pw;
endpwent();
while ((pw= getpwent()) != NULL && strcmp(pw->pw_name, name) != 0) {}
endpwent();
return pw;
}
#ifndef L_cuserid
#define L_cuserid 9
#endif
char *getlogin()
{
static char userid[L_cuserid];
struct passwd *pw_entry;
pw_entry = getpwuid(getuid());
if (pw_entry == (struct passwd *)NULL) return((char *)NULL);
strcpy(userid, pw_entry->pw_name);
return(userid);
}

View file

@ -1,95 +0,0 @@
/*
* grotesque hack to get these functions working.
*/
#include <sys/types.h>
#include <compat/pwd.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <pwd.h>
#include <grp.h>
#include <stdio.h>
/*
* group_from_gid()
* caches the name (if any) for the gid. If noname clear, we always
* return the stored name (if valid or invalid match).
* We use a simple hash table.
* Return
* Pointer to stored name (or a empty string)
*/
const char *
group_from_gid(gid_t gid, int noname)
{
static char buf[16];
struct group *g = getgrgid(gid);
if (g == NULL) {
if (noname) {
return NULL;
} else {
sprintf(buf, "%d", gid);
return buf;
}
}
return g->gr_name;
}
/*
* user_from_uid()
* caches the name (if any) for the uid. If noname clear, we always
* return the stored name (if valid or invalid match).
* We use a simple hash table.
* Return
* Pointer to stored name (or a empty string)
*/
const char *
user_from_uid(uid_t uid, int noname)
{
static char buf[16];
struct passwd *p = getpwuid(uid);
if (p == NULL) {
if (noname) {
return NULL;
} else {
sprintf(buf, "%d", uid);
return buf;
}
}
return p->pw_name;
}
/*
* uid_from_user()
* caches the uid for a given user name. We use a simple hash table.
* Return
* the uid (if any) for a user name, or a -1 if no match can be found
*/
int
uid_from_user(const char *name, uid_t *uid)
{
struct passwd *p = getpwnam(name);
if (p == NULL) {
return -1;
}
*uid = p->pw_uid;
return *uid;
}
/*
* gid_from_group()
* caches the gid for a given group name. We use a simple hash table.
* Return
* the gid (if any) for a group name, or a -1 if no match can be found
*/
int
gid_from_group(const char *name, gid_t *gid)
{
struct group *g = getgrnam(name);
if (g == NULL) {
return -1;
}
*gid = g->gr_gid;
return *gid;
}

View file

@ -13,7 +13,6 @@ MAN= acd.1 anm.1 ar.1 ash.1 asize.1 at.1 banner.1 basename.1 \
look.1 lp.1 ls.1 lspci.1 M.1 mail.1 \
mesg.1 mixer.1 ackmkdep.1 mkfs.1 \
mkproto.1 modem.1 mount.1 mt.1 nice.1 nm.1 nohup.1 od.1 \
passwd.1 \
paste.1 ping.1 playwave.1 postmort.1 pr.1 prep.1 \
profile.1 ps.1 pwd.1 rcp.1 readall.1 recwave.1 \
ref.1 remsync.1 rget.1 rlogin.1 rmdir.1 rsh.1 rz.1 \
@ -61,7 +60,6 @@ MLINKS += cp.1 cpdir.1
MLINKS += elvis.1 ex.1
MLINKS += expr.1 test.1
MLINKS += expr.1 [.1
MLINKS += passwd.1 chfn.1
MLINKS += svc.1 ci.1
MLINKS += svc.1 co.1

View file

@ -1,44 +0,0 @@
.TH PASSWD 1
.SH NAME
passwd, chfn, chsh \- change a login password, full name or shell
.SH SYNOPSIS
\fBpasswd\fR [\fIuser\fR]\fR
.br
\fBchfn\fR [\fIuser\fR] \fIfullname\fR\fR
.br
\fBchsh\fR [\fIuser\fR] \fIshell\fR\fR
.br
.de FL
.TP
\\fB\\$1\\fR
\\$2
..
.de EX
.TP 20
\\fB\\$1\\fR
# \\$2
..
.SH EXAMPLES
.EX "passwd" "Change current user's password"
.EX "passwd ast" "Change ast's password (super\-user only)"
.EX "chsh /usr/bin/mail" "For those who only read mail"
.EX "chfn 'Jane Doe'" "Current user is Jane Doe"
.SH DESCRIPTION
.PP
.I Passwd
is used to change your password.
It prompts for the old and new passwords.
It asks for the new password twice, to reduce the effect of a typing error.
.I Chfn
changes the full name (GECOS field) in the password file.
.I Chsh
changes your login shell.
Do not forget to copy the modified password file back to the root file system,
or the changes will be lost when the system is rebooted.
.SH "SEE ALSO"
.BR login (1),
.BR su (1),
.BR crypt (3),
.BR getpwent (3),
.BR passwd (5),
.BR adduser (8).

View file

@ -1,4 +1,4 @@
MAN= add_route.8 adduser.8 backup.8 badblocks.8 boot.8 \
MAN= add_route.8 backup.8 badblocks.8 boot.8 \
cdprobe.8 checkhier.8 chown.8 cleantmp.8 config.8 cron.8 \
dhcpd.8 diskctl.8 dosminix.8 elvprsv.8 fdisk.8 fingerd.8 ftpd.8 \
getty.8 halt.8 hgfs.8 httpd.8 ifconfig.8 inet.8 init.8 \

View file

@ -1,43 +0,0 @@
.TH ADDUSER 8
.SH NAME
adduser \- add a new user to the system
.SH SYNOPSIS
\fBadduser \fIuser group home-dir\fR\fR
.br
.de FL
.TP
\\fB\\$1\\fR
\\$2
..
.de EX
.TP 20
\\fB\\$1\\fR
# \\$2
..
.SH EXAMPLES
.EX "adduser ast other /usr/ast" "How user ast could be added"
.EX "adduser bin operator /usr/src" "How user bin could be added"
.SH DESCRIPTION
.PP
.I Adduser
adds a new user to the system by making new entries in
.B /etc/passwd
and
.B /etc/shadow
for the new user, creating a new home directory, and copying the contents
of the template home directory
.B /usr/ast
into it. The user-id of this new user will be the first free number not less
than 10. The password is initially empty, the full name must be set, and
the shell is the Bourne Shell,
.B /bin/sh .
Use
.I passwd ,
.I chfn ,
and
.I chsh
to change.
.SH "SEE ALSO"
.BR login (1),
.BR passwd (1),
.BR passwd (5).

View file

@ -1,4 +1,3 @@
.TH PWDAUTH
.SH NAME
pwdauth \- password authentication program
.SH SYNOPSIS

View file

@ -62,6 +62,10 @@
#define PGOFSET (NBPG-1) /* byte offset into page */
#define NPTEPG (NBPG/(sizeof (pt_entry_t)))
#ifndef MAXPHYS
#define MAXPHYS (64 * 1024) /* max raw I/O transfer size */
#endif
/*
* Mach derived conversion macros
*/

View file

@ -43,7 +43,9 @@
#define _PATH_LOGIN_CONF "/etc/login.conf"
#define LOGIN_OSETGROUP 0x0001 /* Obsolete setgroup */
#ifndef __minix
#define LOGIN_SETLOGIN 0x0002 /* Set login */
#endif
#define LOGIN_SETPATH 0x0004 /* Set path */
#define LOGIN_SETPRIORITY 0x0008 /* Set priority */
#define LOGIN_SETRESOURCES 0x0010 /* Set resource limits */

View file

@ -61,14 +61,6 @@
* SUCH DAMAGE.
*/
#if defined(__minix) && defined(_MINIX_COMPAT)
#include <compat/pwd.h>
/* Avoid inclusion of the rest of the header. */
#ifndef _PWD_H_
#define _PWD_H_
#endif
#endif /* __minix && _MINIX_COMPAT */
#ifndef _PWD_H_
#define _PWD_H_

View file

@ -18,6 +18,7 @@ struct dirent { /* Largest entry (8 slots) */
};
#if defined(_NETBSD_SOURCE)
#define MAXNAMLEN 511
#define d_fileno d_ino
#endif

View file

@ -8,15 +8,20 @@ lib/libutil src/lib/libutil
common/lib/libutil src/common/lib/libutil
nbsd_include src/include
bin/mkdir src/bin/mkdir
usr.bin/chpass src/usr.bin/chpass
usr.bin/m4 src/usr.bin/m4
usr.bin/indent src/usr.bin/indent
usr.bin/sed src/usr.bin/sed
usr.bin/stat src/usr.bin/stat
usr.bin/tic src/usr.bin/tic
usr.bin/mkdep src/usr.bin/mkdep
usr.bin/newgrp src/usr.bin/newgrp
usr.bin/uniq src/usr.bin/uniq
usr.bin/seq src/usr.bin/seq
usr.bin/man src/usr.bin/man
usr.bin/apropos src/usr.bin/apropos
usr.bin/mdocml src/external/bsd/mdocml
usr.sbin/pwd_mkdb src/usr.sbin/pwd_mkdb
usr.sbin/user src/usr.sbin/user
usr.sbin/vipw src/usr.sbin/vipw
libexec/makewhatis src/libexec/makewhatis

View file

@ -179,7 +179,7 @@ mkdir -p $RELEASEDIR/bin
mkdir -p $RELEASEPACKAGE
echo " * Transfering bootstrap dirs to $RELEASEDIR"
cp -p /bin/* /usr/bin/* /sbin/* $RELEASEDIR/$XBIN
cp -p /bin/* /usr/bin/* /usr/sbin/* /sbin/* $RELEASEDIR/$XBIN
cp -rp /usr/lib $RELEASEDIR/usr
cp -rp /bin/sh /bin/echo /bin/install /bin/rm \
/bin/date /bin/ls $RELEASEDIR/bin

View file

@ -4,7 +4,7 @@
# NetBSD imports
SUBDIR= indent m4 stat tic sed mkdep uniq seq man mdocml \
apropos
apropos chpass newgrp passwd
# Non-NetBSD imports
SUBDIR+= ministat

View file

@ -1,6 +1,4 @@
.include <minix.newlibc.mk>
CPPFLAGS+= -D_NETBSD_SOURCE -D__NBSD_LIBC=1
BINDIR?=/usr/bin

42
usr.bin/chpass/Makefile Normal file
View file

@ -0,0 +1,42 @@
# $NetBSD: Makefile,v 1.15 2007/05/28 12:06:25 tls Exp $
# @(#)Makefile 8.2 (Berkeley) 4/2/94
.include <bsd.own.mk>
USE_FORT?= yes # setuid
PROG= chpass
SRCS= chpass.c edit.c field.c table.c util.c
BINOWN= root
BINMODE=4555
.ifdef __MINIX
.PATH: ${NETBSDSRCDIR}/lib/nbsd_libc/gen
.else
.PATH: ${NETBSDSRCDIR}/lib/libc/gen
.endif
LINKS= ${BINDIR}/chpass ${BINDIR}/chfn ${BINDIR}/chpass ${BINDIR}/chsh
MLINKS= chpass.1 chfn.1 chpass.1 chsh.1
.ifdef __MINIX
CPPFLAGS+=-I${NETBSDSRCDIR}/lib/nbsd_libc/include
.else
CPPFLAGS+=-I${NETBSDSRCDIR}/lib/libc/include
.endif
.if defined(__MINIX)
USE_YP= no
.endif
.if (${USE_YP} != "no")
SRCS+= pw_yp.c
CPPFLAGS+=-DYP
DPADD+= ${LIBRPCSVC}
LDADD+= -lrpcsvc
.else
SRCS+= getpwent.c
CPPFLAGS.getpwent.c=-UYP
.endif
DPADD+= ${LIBUTIL}
LDADD+= -lutil
.include <bsd.prog.mk>

268
usr.bin/chpass/chpass.1 Normal file
View file

@ -0,0 +1,268 @@
.\" $NetBSD: chpass.1,v 1.23 2006/10/07 20:09:09 elad Exp $
.\"
.\" Copyright (c) 1988, 1990, 1993
.\" The Regents of the University of California. 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.
.\" 3. Neither the name of the University nor the names of its contributors
.\" may be used to endorse or promote products derived from this software
.\" without specific prior written permission.
.\"
.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 THE REGENTS 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.
.\"
.\" @(#)chpass.1 8.2 (Berkeley) 12/30/93
.\"
.Dd October 7, 2006
.Dt CHPASS 1
.Os
.Sh NAME
.Nm chpass ,
.Nm chfn ,
.Nm chsh
.Nd add or change user database information
.Sh SYNOPSIS
.Nm
.Op Fl a Ar list
.Op Fl s Ar newshell
.Op Fl l
.Op user
.Nm chpass
.Op Fl a Ar list
.Op Fl s Ar newshell
.Op Fl y
.Op user
.Sh DESCRIPTION
.Nm
allows editing of the user database information associated
with
.Ar user
or, by default, the current user.
The information is formatted and supplied to an editor for changes.
.Pp
Only the information that the user is allowed to change is displayed.
.Pp
The options are as follows:
.Bl -tag -width Ds
.It Fl a
The super-user is allowed to directly supply a user database
entry, in the format specified by
.Xr passwd 5 ,
as an argument.
This argument must be a colon
.Pq Dq \&:
separated list of all the
user database fields, although they may be empty.
.It Fl s
The
.Fl s
option attempts to change the user's shell to
.Ar newshell .
.It Fl l
This option causes the password to be updated only in the local
password file.
When changing only the local password,
.Xr pwd_mkdb 8
is used to update the password databases.
.It Fl y
This forces the YP password database entry to be changed, even if
the user has an entry in the local database.
The
.Xr rpc.yppasswdd 8
daemon should be running on the YP master server.
.El
.Pp
Possible display items are as follows:
.Pp
.Bl -tag -width "Home Directory:" -compact -offset indent
.It Login :
user's login name
.It Password :
user's encrypted password
.It Uid :
user's login
.It Gid :
user's login group
.It Change :
password change time
.It Expire :
account expiration time
.It Class :
user's general classification
.It Home Directory :
user's home directory
.It Shell :
user's login shell
.It Full Name :
user's real name
.It Location :
user's normal location
.It Home Phone :
user's home phone
.It Office Phone :
user's office phone
.El
.Pp
The
.Ar login
field is the user name used to access the computer account.
.Pp
The
.Ar password
field contains the encrypted form of the user's password.
.Pp
The
.Ar uid
field is the number associated with the
.Ar login
field.
Both of these fields should be unique across the system (and often
across a group of systems) as they control file access.
.Pp
While it is possible to have multiple entries with identical login names
and/or identical user id's, it is usually a mistake to do so.
Routines
that manipulate these files will often return only one of the multiple
entries, and that one by random selection.
.Pp
The
.Ar group
field is the group that the user will be placed in at login.
Since
.Bx
supports multiple groups (see
.Xr groups 1 )
this field currently has little special meaning.
This field may be filled in with either a number or a group name (see
.Xr group 5 ) .
.Pp
The
.Ar change
field is the date by which the password must be changed.
.Pp
The
.Ar expire
field is the date on which the account expires.
.Pp
Both the
.Ar change
and
.Ar expire
fields should be entered in the form
.Dq month day year
where
.Ar month
is the month name (the first three characters are sufficient),
.Ar day
is the day of the month, and
.Ar year
is the year.
.Pp
The
.Ar class
field is a key for a user's login class.
Login classes are defined in
.Xr login.conf 5 ,
which is a
.Xr termcap 5
style database of user attributes, accounting, resource and
environment settings.
.Pp
The user's
.Ar home directory
is the full
.Ux
path name where the user will be placed at login.
.Pp
The
.Ar shell
field is the command interpreter the user prefers.
If the
.Ar shell
field is empty, the Bourne shell,
.Pa /bin/sh ,
is assumed.
When altering a login shell, and not the super-user, the user
may not change from a non-standard shell or to a non-standard
shell.
Non-standard is defined as a shell not found in
.Pa /etc/shells .
.Pp
The last four fields are for storing the user's
.Ar full name , office location ,
and
.Ar home
and
.Ar work telephone
numbers.
.Pp
Once the information has been verified,
.Nm
uses
.Xr pwd_mkdb 8
to update the user database.
.Sh ENVIRONMENT
The
.Xr vi 1
editor will be used unless the environment variable
.Ev EDITOR
is set to an alternative editor.
When the editor terminates, the information is re-read and used to
update the user database itself.
Only the user, or the super-user, may edit the information associated
with the user.
.Sh FILES
.Bl -tag -width /etc/master.passwd -compact
.It Pa /etc/master.passwd
The user database
.It Pa /etc/passwd
A Version 7 format password file
.It Pa /etc/ptmp
Lock file for the passwd database
.It Pa /tmp/pw.XXXXXX
Temporary copy of the user passwd information
.It Pa /etc/shells
The list of approved shells
.El
.Sh SEE ALSO
.Xr finger 1 ,
.Xr login 1 ,
.Xr passwd 1 ,
.Xr pwhash 1 ,
.Xr getusershell 3 ,
.Xr passwd 5 ,
.Xr passwd.conf 5 ,
.Xr pwd_mkdb 8 ,
.Xr vipw 8
.Rs
.%A Robert Morris
.%A Ken Thompson
.%T "UNIX Password Security"
.Re
.Sh HISTORY
The
.Nm
command appeared in
.Bx 4.3 Reno .
.Sh BUGS
This program's interface is poorly suited to cryptographic systems such as
Kerberos, and consequently Kerberos password changing is not a feature of
this program.
.Pp
User information should (and eventually will) be stored elsewhere.

316
usr.bin/chpass/chpass.c Normal file
View file

@ -0,0 +1,316 @@
/* $NetBSD: chpass.c,v 1.33 2008/07/21 14:19:21 lukem Exp $ */
/*-
* Copyright (c) 1988, 1993, 1994
* The Regents of the University of California. 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.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 THE REGENTS 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.
*/
#include <sys/cdefs.h>
#ifndef lint
__COPYRIGHT("@(#) Copyright (c) 1988, 1993, 1994\
The Regents of the University of California. All rights reserved.");
#endif /* not lint */
#ifndef lint
#if 0
static char sccsid[] = "@(#)chpass.c 8.4 (Berkeley) 4/2/94";
#else
__RCSID("$NetBSD: chpass.c,v 1.33 2008/07/21 14:19:21 lukem Exp $");
#endif
#endif /* not lint */
#include <sys/param.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <ctype.h>
#include <err.h>
#include <errno.h>
#include <fcntl.h>
#include <pwd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <util.h>
#include <libgen.h>
#include "chpass.h"
#include "pathnames.h"
static char tempname[] = "/tmp/pw.XXXXXX";
uid_t uid;
int use_yp;
void (*Pw_error)(const char *, int, int);
#ifdef YP
extern int _yp_check(char **); /* buried deep inside libc */
#endif
void baduser(void);
void cleanup(void);
void usage(void);
int
main(int argc, char **argv)
{
enum { NEWSH, LOADENTRY, EDITENTRY } op;
struct passwd *pw, lpw, old_pw;
int ch, dfd, pfd, tfd;
#ifdef YP
int yflag = 0;
#endif
char *arg, *username = NULL;
#ifdef __GNUC__
pw = NULL; /* XXX gcc -Wuninitialized */
arg = NULL;
#endif
#ifdef YP
use_yp = _yp_check(NULL);
#endif
op = EDITENTRY;
while ((ch = getopt(argc, argv, "a:s:ly")) != -1)
switch (ch) {
case 'a':
op = LOADENTRY;
arg = optarg;
break;
case 's':
op = NEWSH;
arg = optarg;
break;
case 'l':
use_yp = 0;
break;
case 'y':
#ifdef YP
if (!use_yp)
errx(1, "YP not in use.");
yflag = 1;
#else
errx(1, "YP support not compiled in.");
#endif
break;
default:
usage();
}
argc -= optind;
argv += optind;
uid = getuid();
switch (argc) {
case 0:
/* nothing */
break;
case 1:
username = argv[0];
break;
default:
usage();
}
#ifdef YP
/*
* We need to determine if we _really_ want to use YP.
* If we defaulted to YP (i.e. were not given the -y flag),
* and the master is not running rpc.yppasswdd, we check
* to see if the user exists in the local passwd database.
* If so, we use it, otherwise we error out.
*/
if (use_yp && yflag == 0) {
if (check_yppasswdd()) {
/*
* We weren't able to contact rpc.yppasswdd.
* Check to see if we're in the local
* password database. If we are, use it.
*/
if (username != NULL)
pw = getpwnam(username);
else
pw = getpwuid(uid);
if (pw != NULL)
use_yp = 0;
else {
warnx("master YP server not running yppasswd"
" daemon.");
errx(1, "Can't change password.");
}
}
}
#endif
#ifdef YP
if (use_yp)
Pw_error = yppw_error;
else
#endif
Pw_error = pw_error;
#ifdef YP
if (op == LOADENTRY && use_yp)
errx(1, "cannot load entry using YP.\n"
"\tUse the -l flag to load local.");
#endif
if (op == EDITENTRY || op == NEWSH) {
if (username != NULL) {
pw = getpwnam(username);
if (pw == NULL)
errx(1, "unknown user: %s", username);
if (uid && uid != pw->pw_uid)
baduser();
} else {
pw = getpwuid(uid);
if (pw == NULL)
errx(1, "unknown user: uid %u", uid);
}
/* Make a copy for later verification */
old_pw = *pw;
old_pw.pw_gecos = strdup(old_pw.pw_gecos);
if (!old_pw.pw_gecos) {
err(1, "strdup");
/*NOTREACHED*/
}
}
if (op == NEWSH) {
/* protect p_shell -- it thinks NULL is /bin/sh */
if (!arg[0])
usage();
if (p_shell(arg, pw, NULL))
(*Pw_error)(NULL, 0, 1);
}
if (op == LOADENTRY) {
if (uid)
baduser();
pw = &lpw;
if (!pw_scan(arg, pw, NULL))
exit(1);
}
/* Edit the user passwd information if requested. */
if (op == EDITENTRY) {
struct stat sb;
dfd = mkstemp(tempname);
if (dfd < 0 || fcntl(dfd, F_SETFD, 1) < 0)
(*Pw_error)(tempname, 1, 1);
if (atexit(cleanup)) {
cleanup();
errx(1, "couldn't register cleanup");
}
if (stat(dirname(tempname), &sb) == -1)
err(1, "couldn't stat `%s'", dirname(tempname));
if (!(sb.st_mode & S_ISTXT))
errx(1, "temporary directory `%s' is not sticky",
dirname(tempname));
display(tempname, dfd, pw);
edit(tempname, pw);
}
#ifdef YP
if (use_yp) {
if (pw_yp(pw, uid))
yppw_error((char *)NULL, 0, 1);
else
exit(0);
/* Will not exit from this if. */
}
#endif /* YP */
/*
* Get the passwd lock file and open the passwd file for
* reading.
*/
pw_init();
tfd = pw_lock(0);
if (tfd < 0) {
if (errno != EEXIST)
err(1, "%s", _PATH_MASTERPASSWD_LOCK);
warnx("The passwd file is busy, waiting...");
tfd = pw_lock(10);
if (tfd < 0) {
if (errno != EEXIST)
err(1, "%s", _PATH_MASTERPASSWD_LOCK);
errx(1, "The passwd file is still busy, "
"try again later.");
}
}
if (fcntl(tfd, F_SETFD, 1) < 0)
pw_error(_PATH_MASTERPASSWD_LOCK, 1, 1);
pfd = open(_PATH_MASTERPASSWD, O_RDONLY, 0);
if (pfd < 0 || fcntl(pfd, F_SETFD, 1) < 0)
pw_error(_PATH_MASTERPASSWD, 1, 1);
/* Copy the passwd file to the lock file, updating pw. */
pw_copy(pfd, tfd, pw, (op == LOADENTRY) ? NULL : &old_pw);
close(pfd);
close(tfd);
/* Now finish the passwd file update. */
if (pw_mkdb(username, 0) < 0)
pw_error(NULL, 0, 1);
exit(0);
}
void
baduser(void)
{
errx(1, "%s", strerror(EACCES));
}
void
usage(void)
{
(void)fprintf(stderr,
"usage: %s [-a list] [-s shell] [-l] [user]\n"
" %s [-a list] [-s shell] [-y] [user]\n",
getprogname(), getprogname());
exit(1);
}
void
cleanup(void)
{
(void)unlink(tempname);
}

81
usr.bin/chpass/chpass.h Normal file
View file

@ -0,0 +1,81 @@
/* $NetBSD: chpass.h,v 1.12 2005/02/17 17:09:48 xtraeme Exp $ */
/*
* Copyright (c) 1988, 1993, 1994
* The Regents of the University of California. 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.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 THE REGENTS 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.
*
* @(#)chpass.h 8.4 (Berkeley) 4/2/94
*/
struct passwd;
typedef struct _entry {
const char *prompt;
int (*func)(const char *, struct passwd *, struct _entry *), restricted, len;
const char *except, *save;
} ENTRY;
extern int use_yp;
/* Field numbers. */
#define E_BPHONE 8
#define E_HPHONE 9
#define E_LOCATE 10
#define E_NAME 7
#define E_SHELL 12
extern ENTRY list[];
extern uid_t uid;
int atot(const char *, time_t *);
void display(char *, int, struct passwd *);
void edit(char *, struct passwd *);
const char *
ok_shell(const char *);
int p_change(const char *, struct passwd *, ENTRY *);
int p_class(const char *, struct passwd *, ENTRY *);
int p_expire(const char *, struct passwd *, ENTRY *);
int p_gecos(const char *, struct passwd *, ENTRY *);
int p_gid(const char *, struct passwd *, ENTRY *);
int p_hdir(const char *, struct passwd *, ENTRY *);
int p_login(const char *, struct passwd *, ENTRY *);
int p_passwd(const char *, struct passwd *, ENTRY *);
int p_shell(const char *, struct passwd *, ENTRY *);
int p_uid(const char *, struct passwd *, ENTRY *);
char *ttoa(char *, size_t, time_t);
int verify(char *, struct passwd *);
#ifdef YP
int check_yppasswdd(void);
int pw_yp(struct passwd *, uid_t);
void yppw_error(const char *name, int, int);
void yppw_prompt(void);
struct passwd *ypgetpwnam(const char *);
struct passwd *ypgetpwuid(uid_t);
#endif
extern void (*Pw_error)(const char *name, int, int);

227
usr.bin/chpass/edit.c Normal file
View file

@ -0,0 +1,227 @@
/* $NetBSD: edit.c,v 1.20 2009/04/11 12:10:02 lukem Exp $ */
/*-
* Copyright (c) 1990, 1993, 1994
* The Regents of the University of California. 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.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 THE REGENTS 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.
*/
#include <sys/cdefs.h>
#ifndef lint
#if 0
static char sccsid[] = "@(#)edit.c 8.3 (Berkeley) 4/2/94";
#else
__RCSID("$NetBSD: edit.c,v 1.20 2009/04/11 12:10:02 lukem Exp $");
#endif
#endif /* not lint */
#include <sys/param.h>
#include <sys/stat.h>
#include <ctype.h>
#include <err.h>
#include <errno.h>
#include <paths.h>
#include <pwd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <util.h>
#include "chpass.h"
void
edit(char *tempname, struct passwd *pw)
{
struct stat begin, end;
for (;;) {
if (stat(tempname, &begin))
(*Pw_error)(tempname, 1, 1);
pw_edit(1, tempname);
if (stat(tempname, &end))
(*Pw_error)(tempname, 1, 1);
if (begin.st_mtime == end.st_mtime) {
warnx("no changes made");
(*Pw_error)(NULL, 0, 0);
}
if (verify(tempname, pw))
break;
#ifdef YP
if (use_yp)
yppw_prompt();
else
#endif
pw_prompt();
}
}
/*
* display --
* print out the file for the user to edit; strange side-effect:
* set conditional flag if the user gets to edit the shell.
*/
void
display(char *tempname, int fd, struct passwd *pw)
{
FILE *fp;
char *bp, *p;
char chgstr[256], expstr[256];
if (!(fp = fdopen(fd, "w")))
(*Pw_error)(tempname, 1, 1);
(void)fprintf(fp,
"#Changing user %sdatabase information for %s.\n",
use_yp ? "YP " : "", pw->pw_name);
if (!uid) {
(void)fprintf(fp, "Login: %s\n", pw->pw_name);
(void)fprintf(fp, "Password: %s\n", pw->pw_passwd);
(void)fprintf(fp, "Uid [#]: %d\n", pw->pw_uid);
(void)fprintf(fp, "Gid [# or name]: %d\n", pw->pw_gid);
(void)fprintf(fp, "Change [month day year]: %s\n",
ttoa(chgstr, sizeof chgstr, pw->pw_change));
(void)fprintf(fp, "Expire [month day year]: %s\n",
ttoa(expstr, sizeof expstr, pw->pw_expire));
(void)fprintf(fp, "Class: %s\n", pw->pw_class);
(void)fprintf(fp, "Home directory: %s\n", pw->pw_dir);
(void)fprintf(fp, "Shell: %s\n",
*pw->pw_shell ? pw->pw_shell : _PATH_BSHELL);
}
/* Only admin can change "restricted" shells. */
else if (ok_shell(pw->pw_shell))
/*
* Make shell a restricted field. Ugly with a
* necklace, but there's not much else to do.
*/
(void)fprintf(fp, "Shell: %s\n",
*pw->pw_shell ? pw->pw_shell : _PATH_BSHELL);
else
list[E_SHELL].restricted = 1;
bp = strdup(pw->pw_gecos);
if (!bp) {
err(1, "strdup");
/*NOTREACHED*/
}
p = strsep(&bp, ",");
(void)fprintf(fp, "Full Name: %s\n", p ? p : "");
p = strsep(&bp, ",");
(void)fprintf(fp, "Location: %s\n", p ? p : "");
p = strsep(&bp, ",");
(void)fprintf(fp, "Office Phone: %s\n", p ? p : "");
p = strsep(&bp, ",");
(void)fprintf(fp, "Home Phone: %s\n", p ? p : "");
(void)fchown(fd, getuid(), getgid());
(void)fclose(fp);
}
int
verify(char *tempname, struct passwd *pw)
{
ENTRY *ep;
char *p;
struct stat sb;
FILE *fp = NULL;
int len, fd;
static char buf[LINE_MAX];
#ifdef __minix
if ((fd = open(tempname, O_RDONLY)) == -1 ||
(fp = fdopen(fd, "r")) == NULL)
#else
if ((fd = open(tempname, O_RDONLY|O_NOFOLLOW)) == -1 ||
(fp = fdopen(fd, "r")) == NULL)
#endif
(*Pw_error)(tempname, 1, 1);
if (fstat(fd, &sb))
(*Pw_error)(tempname, 1, 1);
if (sb.st_size == 0 || sb.st_nlink != 1) {
warnx("corrupted temporary file");
goto bad;
}
while (fgets(buf, sizeof(buf), fp)) {
if (!buf[0] || buf[0] == '#')
continue;
if (!(p = strchr(buf, '\n'))) {
warnx("line too long");
goto bad;
}
*p = '\0';
for (ep = list;; ++ep) {
if (!ep->prompt) {
warnx("unrecognized field");
goto bad;
}
if (!strncasecmp(buf, ep->prompt, ep->len)) {
if (ep->restricted && uid) {
warnx(
"you may not change the %s field",
ep->prompt);
goto bad;
}
if (!(p = strchr(buf, ':'))) {
warnx("line corrupted");
goto bad;
}
while (isspace((unsigned char)*++p));
if (ep->except && strpbrk(p, ep->except)) {
warnx(
"illegal character in the \"%s\" field",
ep->prompt);
goto bad;
}
if ((ep->func)(p, pw, ep)) {
bad: (void)fclose(fp);
return (0);
}
break;
}
}
}
(void)fclose(fp);
/* Build the gecos field. */
len = strlen(list[E_NAME].save) + strlen(list[E_BPHONE].save) +
strlen(list[E_HPHONE].save) + strlen(list[E_LOCATE].save) + 4;
if (!(p = malloc(len)))
err(1, "malloc");
(void)snprintf(p, len, "%s,%s,%s,%s", list[E_NAME].save,
list[E_LOCATE].save, list[E_BPHONE].save, list[E_HPHONE].save);
pw->pw_gecos = p;
if (snprintf(buf, sizeof(buf),
"%s:%s:%d:%d:%s:%lu:%lu:%s:%s:%s",
pw->pw_name, pw->pw_passwd, pw->pw_uid, pw->pw_gid, pw->pw_class,
(u_long)pw->pw_change, (u_long)pw->pw_expire, pw->pw_gecos,
pw->pw_dir, pw->pw_shell) >= (int)sizeof(buf)) {
warnx("entries too long");
return (0);
}
return (pw_scan(buf, pw, (int *)NULL));
}

253
usr.bin/chpass/field.c Normal file
View file

@ -0,0 +1,253 @@
/* $NetBSD: field.c,v 1.12 2009/04/11 12:10:02 lukem Exp $ */
/*
* Copyright (c) 1988, 1993, 1994
* The Regents of the University of California. 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.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 THE REGENTS 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.
*/
#include <sys/cdefs.h>
#ifndef lint
#if 0
static char sccsid[] = "@(#)field.c 8.4 (Berkeley) 4/2/94";
#else
__RCSID("$NetBSD: field.c,v 1.12 2009/04/11 12:10:02 lukem Exp $");
#endif
#endif /* not lint */
#include <sys/param.h>
#include <ctype.h>
#include <err.h>
#include <errno.h>
#include <grp.h>
#include <pwd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "chpass.h"
#include "pathnames.h"
/* ARGSUSED */
int
p_login(const char *p, struct passwd *pw, ENTRY *ep)
{
if (!*p) {
warnx("empty login field");
return (1);
}
if (*p == '-') {
warnx("login names may not begin with a hyphen");
return (1);
}
if (!(pw->pw_name = strdup(p))) {
warnx("can't save entry");
return (1);
}
if (strchr(p, '.'))
warnx("\'.\' is dangerous in a login name");
for (; *p; ++p)
if (isupper((unsigned char)*p)) {
warnx("upper-case letters are dangerous in a login name");
break;
}
return (0);
}
/* ARGSUSED */
int
p_passwd(const char *p, struct passwd *pw, ENTRY *ep)
{
if (!(pw->pw_passwd = strdup(p))) {
warnx("can't save password entry");
return (1);
}
return (0);
}
/* ARGSUSED */
int
p_uid(const char *p, struct passwd *pw, ENTRY *ep)
{
unsigned long id;
char *np;
if (!*p) {
warnx("empty uid field");
return (1);
}
if (!isdigit((unsigned char)*p)) {
warnx("illegal uid");
return (1);
}
errno = 0;
id = strtoul(p, &np, 10);
/*
* We don't need to check the return value of strtoul()
* since ULONG_MAX is greater than UID_MAX.
*/
if (*np || id > UID_MAX) {
warnx("illegal uid");
return (1);
}
pw->pw_uid = (uid_t)id;
return (0);
}
/* ARGSUSED */
int
p_gid(const char *p, struct passwd *pw, ENTRY *ep)
{
struct group *gr;
unsigned long id;
char *np;
if (!*p) {
warnx("empty gid field");
return (1);
}
if (!isdigit((unsigned char)*p)) {
if (!(gr = getgrnam(p))) {
warnx("unknown group %s", p);
return (1);
}
pw->pw_gid = gr->gr_gid;
return (0);
}
errno = 0;
id = strtoul(p, &np, 10);
/*
* We don't need to check the return value of strtoul()
* since ULONG_MAX is greater than GID_MAX.
*/
if (*np || id > GID_MAX) {
warnx("illegal gid");
return (1);
}
pw->pw_gid = (gid_t)id;
return (0);
}
/* ARGSUSED */
int
p_class(const char *p, struct passwd *pw, ENTRY *ep)
{
if (!(pw->pw_class = strdup(p))) {
warnx("can't save entry");
return (1);
}
return (0);
}
/* ARGSUSED */
int
p_change(const char *p, struct passwd *pw, ENTRY *ep)
{
if (!atot(p, &pw->pw_change))
return (0);
warnx("illegal date for change field");
return (1);
}
/* ARGSUSED */
int
p_expire(const char *p, struct passwd *pw, ENTRY *ep)
{
if (!atot(p, &pw->pw_expire))
return (0);
warnx("illegal date for expire field");
return (1);
}
/* ARGSUSED */
int
p_gecos(const char *p, struct passwd *pw, ENTRY *ep)
{
if (!(ep->save = strdup(p))) {
warnx("can't save entry");
return (1);
}
return (0);
}
/* ARGSUSED */
int
p_hdir(const char *p, struct passwd *pw, ENTRY *ep)
{
if (!*p) {
warnx("empty home directory field");
return (1);
}
if (!(pw->pw_dir = strdup(p))) {
warnx("can't save entry");
return (1);
}
return (0);
}
/* ARGSUSED */
int
p_shell(const char *p, struct passwd *pw, ENTRY *ep)
{
const char *t;
if (!*p) {
if (!(pw->pw_shell = strdup(_PATH_BSHELL))) {
warnx("can't save entry");
return (1);
}
return (0);
}
/* only admin can change from or to "restricted" shells */
if (uid && pw->pw_shell && !ok_shell(pw->pw_shell)) {
warnx("%s: current shell non-standard", pw->pw_shell);
return (1);
}
if (!(t = ok_shell(p))) {
if (uid) {
warnx("%s: non-standard shell", p);
return (1);
}
}
else
p = t;
if (!(pw->pw_shell = strdup(p))) {
warnx("can't save entry");
return (1);
}
return (0);
}

View file

@ -0,0 +1,37 @@
/* $NetBSD: pathnames.h,v 1.4 2003/08/07 11:13:19 agc Exp $ */
/*
* Copyright (c) 1989, 1993
* The Regents of the University of California. 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.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 THE REGENTS 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.
*
* @(#)pathnames.h 8.1 (Berkeley) 6/6/93
*/
#include <paths.h>
#undef _PATH_TMP
#define _PATH_TMP "/tmp/chpass.XXXXXX"

239
usr.bin/chpass/pw_yp.c Normal file
View file

@ -0,0 +1,239 @@
/* $NetBSD: pw_yp.c,v 1.22 2009/04/11 12:10:02 lukem Exp $ */
/*
* Copyright (c) 1988 The Regents of the University of California.
* 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.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 THE REGENTS 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.
*/
#include <sys/cdefs.h>
#ifndef lint
#if 0
static char sccsid[] = "@(#)pw_yp.c 1.0 2/2/93";
#else
__RCSID("$NetBSD: pw_yp.c,v 1.22 2009/04/11 12:10:02 lukem Exp $");
#endif
#endif /* not lint */
#ifdef YP
#include <err.h>
#include <errno.h>
#include <netdb.h>
#include <pwd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#include <rpc/rpc.h>
#include <rpcsvc/yp_prot.h>
#include <rpcsvc/ypclnt.h>
#define passwd yp_passwd_rec
#include <rpcsvc/yppasswd.h>
#undef passwd
#include "chpass.h"
static char *domain;
/*
* Check if rpc.yppasswdd is running on the master YP server.
* XXX this duplicates some code, but is much less complex
* than the alternative.
*/
int
check_yppasswdd(void)
{
char *master;
int rpcport;
/*
* Get local domain
*/
if (!domain && yp_get_default_domain(&domain) != 0)
return (1);
/*
* Find the host for the passwd map; it should be running
* the daemon.
*/
master = NULL;
if (yp_master(domain, "passwd.byname", &master) != 0) {
if (master != NULL)
free (master);
return (1);
}
/*
* Ask the portmapper for the port of the daemon.
*/
if ((rpcport = getrpcport(master, YPPASSWDPROG, YPPASSWDPROC_UPDATE,
IPPROTO_UDP)) == 0)
return (1);
/*
* Successful contact with rpc.yppasswdd.
*/
return (0);
}
int
pw_yp(struct passwd *pw, uid_t ypuid)
{
char *master;
int r, rpcport, status;
struct yppasswd yppw;
struct timeval tv;
CLIENT *client;
/*
* Get local domain
*/
if (!domain && (r = yp_get_default_domain(&domain)))
errx(1, "can't get local YP domain. Reason: %s",
yperr_string(r));
/*
* Find the host for the passwd map; it should be running
* the daemon.
*/
master = NULL;
if ((r = yp_master(domain, "passwd.byname", &master)) != 0) {
if (master)
free (master);
warnx("can't find the master YP server. Reason: %s",
yperr_string(r));
return (1);
}
/*
* Ask the portmapper for the port of the daemon.
*/
if ((rpcport = getrpcport(master, YPPASSWDPROG, YPPASSWDPROC_UPDATE,
IPPROTO_UDP)) == 0) {
warnx("master YP server not running yppasswd daemon.\n\t%s\n",
"Can't change password.");
return (1);
}
/*
* Be sure the port is privileged
*/
if (rpcport >= IPPORT_RESERVED) {
warnx("yppasswd daemon is on an invalid port.");
return (1);
}
/* prompt for old password */
memset(&yppw, 0, sizeof yppw);
yppw.oldpass = getpass("Old password:");
if (!yppw.oldpass) {
warnx("Cancelled.");
return (1);
}
/* tell rpc.yppasswdd */
yppw.newpw.pw_name = strdup(pw->pw_name);
if (!yppw.newpw.pw_name) {
err(1, "strdup");
/*NOTREACHED*/
}
yppw.newpw.pw_passwd = strdup(pw->pw_passwd);
if (!yppw.newpw.pw_passwd) {
err(1, "strdup");
/*NOTREACHED*/
}
yppw.newpw.pw_uid = pw->pw_uid;
yppw.newpw.pw_gid = pw->pw_gid;
yppw.newpw.pw_gecos = strdup(pw->pw_gecos);
if (!yppw.newpw.pw_gecos) {
err(1, "strdup");
/*NOTREACHED*/
}
yppw.newpw.pw_dir = strdup(pw->pw_dir);
if (!yppw.newpw.pw_dir) {
err(1, "strdup");
/*NOTREACHED*/
}
yppw.newpw.pw_shell = strdup(pw->pw_shell);
if (!yppw.newpw.pw_shell) {
err(1, "strdup");
/*NOTREACHED*/
}
client = clnt_create(master, YPPASSWDPROG, YPPASSWDVERS, "udp");
if (client == NULL) {
warnx("cannot contact yppasswdd on %s: Reason: %s",
master, yperr_string(YPERR_YPBIND));
return (1);
}
client->cl_auth = authunix_create_default();
tv.tv_sec = 5;
tv.tv_usec = 0;
r = clnt_call(client, YPPASSWDPROC_UPDATE,
xdr_yppasswd, &yppw, xdr_int, &status, tv);
if (r) {
warnx("rpc to yppasswdd failed.");
return (1);
} else if (status)
printf("Couldn't change YP password.\n");
else
printf("%s %s, %s\n",
"The YP password information has been changed on",
master, "the master YP passwd server.");
return (0);
}
void
yppw_error(const char *name, int yperr, int eval)
{
if (yperr) {
if (name)
warn("%s", name);
else
warn(NULL);
}
errx(eval, "YP passwd information unchanged");
}
void
yppw_prompt(void)
{
int c;
(void)printf("re-edit the password file? [y]: ");
(void)fflush(stdout);
c = getchar();
if (c != EOF && c != '\n')
while (getchar() != '\n');
if (c == 'n')
yppw_error(NULL, 0, 0);
}
#endif /* YP */

63
usr.bin/chpass/table.c Normal file
View file

@ -0,0 +1,63 @@
/* $NetBSD: table.c,v 1.7 2009/04/11 12:10:02 lukem Exp $ */
/*-
* Copyright (c) 1990, 1993, 1994
* The Regents of the University of California. 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.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 THE REGENTS 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.
*/
#include <sys/cdefs.h>
#ifndef lint
#if 0
static char sccsid[] = "@(#)table.c 8.3 (Berkeley) 4/2/94";
#else
__RCSID("$NetBSD: table.c,v 1.7 2009/04/11 12:10:02 lukem Exp $");
#endif
#endif /* not lint */
#include <sys/types.h>
#include <stddef.h>
#include "chpass.h"
char e1[] = ": ";
char e2[] = ":,";
ENTRY list[] = {
{ "login", p_login, 1, 5, e1, NULL },
{ "password", p_passwd, 1, 8, e1, NULL },
{ "uid", p_uid, 1, 3, e1, NULL },
{ "gid", p_gid, 1, 3, e1, NULL },
{ "class", p_class, 1, 5, e1, NULL },
{ "change", p_change, 1, 6, NULL, NULL },
{ "expire", p_expire, 1, 6, NULL, NULL },
{ "full name", p_gecos, 0, 9, e2, ""},
{ "office phone", p_gecos, 0, 12, e2, ""},
{ "home phone", p_gecos, 0, 10, e2, ""},
{ "location", p_gecos, 0, 8, e2, ""},
{ "home directory", p_hdir, 1, 14, e1, NULL },
{ "shell", p_shell, 0, 5, e1, NULL },
{ NULL, NULL, 0, 0, NULL, NULL },
};

113
usr.bin/chpass/util.c Normal file
View file

@ -0,0 +1,113 @@
/* $NetBSD: util.c,v 1.12 2005/02/17 17:09:48 xtraeme Exp $ */
/*-
* Copyright (c) 1988, 1993, 1994
* The Regents of the University of California. 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.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 THE REGENTS 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.
*/
#include <sys/cdefs.h>
#ifndef lint
#if 0
static char sccsid[] = "@(#)util.c 8.4 (Berkeley) 4/2/94";
#else
__RCSID("$NetBSD: util.c,v 1.12 2005/02/17 17:09:48 xtraeme Exp $");
#endif
#endif /* not lint */
#include <sys/types.h>
#include <ctype.h>
#include <pwd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <tzfile.h>
#include <unistd.h>
#include "chpass.h"
#include "pathnames.h"
char *
ttoa(char *buf, size_t len, time_t tval)
{
if (tval) {
struct tm *tp = localtime(&tval);
(void) strftime(buf, len, "%B %d, %Y", tp);
buf[len - 1] = '\0';
}
else if (len > 0)
*buf = '\0';
return (buf);
}
int
atot(const char *p, time_t *store)
{
static struct tm *lt;
struct tm tm;
char *t;
time_t tval;
if (!*p) {
*store = 0;
return (0);
}
if (!lt) {
unsetenv("TZ");
(void)time(&tval);
lt = localtime(&tval);
}
(void) memset(&tm, 0, sizeof(tm));
while ((t = strchr(p, ',')) != NULL)
*t = ' ';
t = strptime(p, "%B %d %Y", &tm);
if (t == NULL || (*t != '\0' && *t != '\n'))
return 1;
if ((*store = mktime(&tm)) == (time_t) -1)
return 1;
return (0);
}
const char *
ok_shell(const char *name)
{
char *p;
const char *sh;
setusershell();
while ((sh = getusershell()) != NULL) {
if (!strcmp(name, sh))
return (name);
/* allow just shell name, but use "real" path */
if ((p = strrchr(sh, '/')) && strcmp(name, p + 1) == 0)
return (sh);
}
return (NULL);
}

View file

@ -16,8 +16,8 @@ SRCS+= ohash_create_entry.c ohash_delete.c ohash_do.c ohash_entries.c \
ohash_qlookupi.c strtonum.c
YHEADER=1
.if (${HOSTPROG:U} == "")
DPADD+= ${LIBMINIXUTIL} ${LIBL}
LDADD+= -lminixutil -ll
DPADD+= ${LIBUTIL} ${LIBL}
LDADD+= -lutil -ll
.endif
tokenizer.o: parser.h

26
usr.bin/newgrp/Makefile Normal file
View file

@ -0,0 +1,26 @@
# $NetBSD: Makefile,v 1.4 2009/04/14 22:15:24 lukem Exp $
#
.include <bsd.own.mk>
.if defined(__MINIX)
USE_KERBEROS= no
.endif
PROG= newgrp
SRCS= newgrp.c grutil.c
BINOWN= root
BINMODE=4555
CPPFLAGS+=-DGRUTIL_ACCEPT_GROUP_NUMBERS
CPPFLAGS+=-DGRUTIL_ALLOW_GROUP_ERRORS # for POSIX.1 compliance
CPPFLAGS+= #-DLOGIN_CAP
DPADD+= ${LIBCRYPT} ${LIBUTIL}
LDADD+= -lcrypt -lutil
.if (${USE_KERBEROS} != "no")
CPPFLAGS+=-DKERBEROS
.endif
.include <bsd.prog.mk>

337
usr.bin/newgrp/grutil.c Normal file
View file

@ -0,0 +1,337 @@
/* $NetBSD: grutil.c,v 1.2 2008/04/28 20:24:14 martin Exp $ */
/*-
* Copyright (c) 2007 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Brian Ginsbach.
*
* 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 THE NETBSD FOUNDATION, INC. 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 THE FOUNDATION 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.
*/
#include <sys/cdefs.h>
__RCSID("$NetBSD: grutil.c,v 1.2 2008/04/28 20:24:14 martin Exp $");
#include <sys/param.h>
#include <err.h>
#include <errno.h>
#include <grp.h>
#include <pwd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <util.h>
#ifdef LOGIN_CAP
#include <login_cap.h>
#endif
#include "grutil.h"
typedef enum {
ADDGRP_NOERROR = 0, /* must be zero */
ADDGRP_EMALLOC = 1,
ADDGRP_EGETGROUPS = 2,
ADDGRP_ESETGROUPS = 3
} addgrp_ret_t;
static void
free_groups(void *groups)
{
int oerrno;
oerrno = errno;
free(groups);
errno = oerrno;
}
static addgrp_ret_t
alloc_groups(int *ngroups, gid_t **groups, int *ngroupsmax)
{
*ngroupsmax = (int)sysconf(_SC_NGROUPS_MAX);
if (*ngroupsmax < 0)
*ngroupsmax = NGROUPS_MAX;
*groups = malloc(*ngroupsmax * sizeof(**groups));
if (*groups == NULL)
return ADDGRP_EMALLOC;
*ngroups = getgroups(*ngroupsmax, *groups);
if (*ngroups == -1) {
free_groups(*groups);
return ADDGRP_ESETGROUPS;
}
return ADDGRP_NOERROR;
}
static addgrp_ret_t
addgid(gid_t *groups, int ngroups, int ngroupsmax, gid_t gid, int makespace)
{
int i;
/* search for gid in supplemental group list */
for (i = 0; i < ngroups && groups[i] != gid; i++)
continue;
/* add the gid to the supplemental group list */
if (i == ngroups) {
if (ngroups < ngroupsmax)
groups[ngroups++] = gid;
else { /*
* setgroups(2) will fail with errno = EINVAL
* if ngroups > nmaxgroups. If makespace is
* set, replace the last group with the new
* one. Otherwise, fail the way setgroups(2)
* would if we passed the larger groups array.
*/
if (makespace) {
/*
* Find a slot that doesn't contain
* the primary group.
*/
struct passwd *pwd;
gid_t pgid;
pwd = getpwuid(getuid());
if (pwd == NULL)
goto error;
pgid = pwd->pw_gid;
for (i = ngroupsmax - 1; i >= 0; i--)
if (groups[i] != pgid)
break;
if (i < 0)
goto error;
groups[i] = gid;
}
else {
error:
errno = EINVAL;
return ADDGRP_ESETGROUPS;
}
}
if (setgroups(ngroups, groups) < 0)
return ADDGRP_ESETGROUPS;
}
return ADDGRP_NOERROR;
}
static addgrp_ret_t
addgrp(gid_t newgid, int makespace)
{
int ngroups, ngroupsmax, rval;
gid_t *groups;
gid_t oldgid;
oldgid = getgid();
if (oldgid == newgid) /* nothing to do */
return ADDGRP_NOERROR;
rval = alloc_groups(&ngroups, &groups, &ngroupsmax);
if (rval != 0)
return rval;
/*
* BSD based systems normally have the egid in the supplemental
* group list.
*/
#if (defined(BSD) && BSD >= 199306)
/*
* According to POSIX/XPG6:
* On system where the egid is normally in the supplemental group list
* (or whenever the old egid actually is in the supplemental group
* list):
* o If the new egid is in the supplemental group list,
* just change the egid.
* o If the new egid is not in the supplemental group list,
* add the new egid to the list if there is room.
*/
rval = addgid(groups, ngroups, ngroupsmax, newgid, makespace);
#else
/*
* According to POSIX/XPG6:
* On systems where the egid is not normally in the supplemental group
* list (or whenever the old egid is not in the supplemental group
* list):
* o If the new egid is in the supplemental group list, delete
* it from the list.
* o If the old egid is not in the supplemental group list,
* add the old egid to the list if there is room.
*/
{
int i;
/* search for new egid in supplemental group list */
for (i = 0; i < ngroups && groups[i] != newgid; i++)
continue;
/* remove new egid from supplemental group list */
if (i != ngroups)
for (--ngroups; i < ngroups; i++)
groups[i] = groups[i + 1];
rval = addgid(groups, ngroups, ngroupsmax, oldgid, makespace);
}
#endif
free_groups(groups);
return rval;
}
/*
* If newgrp fails, it returns (gid_t)-1 and the errno variable is
* set to:
* [EINVAL] Unknown group.
* [EPERM] Bad password.
*/
static gid_t
newgrp(const char *gname, struct passwd *pwd, uid_t ruid, const char *prompt)
{
struct group *grp;
char **ap;
char *p;
gid_t *groups;
int ngroups, ngroupsmax;
if (gname == NULL)
return pwd->pw_gid;
grp = getgrnam(gname);
#ifdef GRUTIL_ACCEPT_GROUP_NUMBERS
if (grp == NULL) {
gid_t gid;
if (*gname != '-') {
gid = (gid_t)strtol(gname, &p, 10);
if (*p == '\0')
grp = getgrgid(gid);
}
}
#endif
if (grp == NULL) {
errno = EINVAL;
return (gid_t)-1;
}
if (ruid == 0 || pwd->pw_gid == grp->gr_gid)
return grp->gr_gid;
if (alloc_groups(&ngroups, &groups, &ngroupsmax) == 0) {
int i;
for (i = 0; i < ngroups; i++)
if (groups[i] == grp->gr_gid) {
free_groups(groups);
return grp->gr_gid;
}
free_groups(groups);
}
/*
* Check the group membership list in case the groups[] array
* was maxed out or the user has been added to it since login.
*/
for (ap = grp->gr_mem; *ap != NULL; ap++)
if (strcmp(*ap, pwd->pw_name) == 0)
return grp->gr_gid;
if (*grp->gr_passwd != '\0') {
p = getpass(prompt);
if (strcmp(grp->gr_passwd, crypt(p, grp->gr_passwd)) == 0) {
(void)memset(p, '\0', _PASSWORD_LEN);
return grp->gr_gid;
}
(void)memset(p, '\0', _PASSWORD_LEN);
}
errno = EPERM;
return (gid_t)-1;
}
#ifdef GRUTIL_SETGROUPS_MAKESPACE
# define ADDGRP_MAKESPACE 1
#else
# define ADDGRP_MAKESPACE 0
#endif
#ifdef GRUTIL_ALLOW_GROUP_ERRORS
# define maybe_exit(e)
#else
# define maybe_exit(e) exit(e);
#endif
void
addgroup(
#ifdef LOGIN_CAP
login_cap_t *lc,
#endif
const char *gname, struct passwd *pwd, uid_t ruid, const char *prompt)
{
pwd->pw_gid = newgrp(gname, pwd, ruid, prompt);
if (pwd->pw_gid == (gid_t)-1) {
switch (errno) {
case EINVAL:
warnx("Unknown group `%s'", gname);
maybe_exit(EXIT_FAILURE);
break;
case EPERM: /* password failure */
warnx("Sorry");
maybe_exit(EXIT_FAILURE);
break;
default: /* XXX - should never happen */
err(EXIT_FAILURE, "unknown error");
break;
}
pwd->pw_gid = getgid();
}
switch (addgrp(pwd->pw_gid, ADDGRP_MAKESPACE)) {
case ADDGRP_NOERROR:
break;
case ADDGRP_EMALLOC:
err(EXIT_FAILURE, "malloc");
break;
case ADDGRP_EGETGROUPS:
err(EXIT_FAILURE, "getgroups");
break;
case ADDGRP_ESETGROUPS:
switch(errno) {
case EINVAL:
warnx("setgroups: ngroups > ngroupsmax");
maybe_exit(EXIT_FAILURE);
break;
case EPERM:
case EFAULT:
default:
warn("setgroups");
maybe_exit(EXIT_FAILURE);
break;
}
break;
}
#ifdef LOGIN_CAP
if (setusercontext(lc, pwd, pwd->pw_uid, LOGIN_SETGID) == -1)
err(EXIT_FAILURE, "setting user context");
#else
if (setgid(pwd->pw_gid) == -1)
err(EXIT_FAILURE, "setgid");
#endif
}

40
usr.bin/newgrp/grutil.h Normal file
View file

@ -0,0 +1,40 @@
/* $NetBSD: grutil.h,v 1.2 2008/04/28 20:24:14 martin Exp $ */
/*-
* Copyright (c) 2007 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Brian Ginsbach.
*
* 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 THE NETBSD FOUNDATION, INC. 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 THE FOUNDATION 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 _GRUTIL_H_
#define _GRUTIL_H_
void addgroup(
#ifdef LOGIN_CAP
login_cap_t *,
#endif
const char *, struct passwd *, uid_t, const char *);
#endif /* _GRUTIL_H_ */

121
usr.bin/newgrp/newgrp.1 Normal file
View file

@ -0,0 +1,121 @@
.\" $NetBSD: newgrp.1,v 1.4 2010/05/14 17:28:23 joerg Exp $
.\"
.\" Copyright (c) 2007, The NetBSD Foundation.
.\" All Rights Reserved.
.\"
.\" This code is derived from software contributed to The NetBSD Foundation
.\" by Brian Ginsbach.
.\"
.\" 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 THE NETBSD FOUNDATION, INC. 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 THE FOUNDATION 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.
.\"
.Dd June 6, 2007
.Dt NEWGRP 1
.Os
.Sh NAME
.Nm newgrp
.Nd change to a new primary group
.Sh SYNOPSIS
.Nm
.Op Fl l
.Op Ar group
.Sh DESCRIPTION
The
.Nm
command changes a user to a new primary group
.Pq real and effective group ID
by starting a new shell.
The user remains logged in and the current directory
and file creation mask remain unchanged.
The user is always given a new shell even if
the primary group change fails.
.Pp
The
.Nm
command accepts the following options:
.Bl -tag -width indent
.It Fl l
The environment is changed to what would be expected if the user
actually logged in again.
This simulates a full login.
.El
.Pp
The
.Ar group
is a group name or non-negative numeric group ID from the group database.
The real and effective group IDs are set to
.Ar group
or the group ID associated with the group name.
.Pp
If
.Ar group
is not specified,
.Nm
restores the user's real and effective group IDs to the user's
primary group specified in the password database.
The user's supplementary group IDs are restored to the set specified
for the user in the group database.
.Pp
If the user is not a member of the specified group, and the group
requires a password, the user will be prompted for the group password.
.Sh FILES
.Bl -tag -width /etc/master.passwd -compact
.It Pa /etc/group
The group database
.It Pa /etc/master.passwd
The user database
.It Pa /etc/passwd
A Version 7 format password file
.El
.Sh EXIT STATUS
If a new shell is started the exit status is the exit status of the shell.
Otherwise the exit status will be \*[Gt]0.
.Sh SEE ALSO
.Xr csh 1 ,
.Xr groups 1 ,
.Xr login 1 ,
.Xr sh 1 ,
.Xr su 1 ,
.Xr umask 2 ,
.Xr group 5 ,
.Xr passwd 5 ,
.Xr environ 7
.Sh STANDARDS
The
.Nm
command conforms to
.St -p1003.1-2001 .
.Sh HISTORY
A
.Nm
command appeared in
.At v6 .
A
.Nm
command appeared in
.Nx 5.0 .
.Sh BUGS
There is no convenient way to enter a password into
.Pa /etc/group .
The use of group passwords is strongly discouraged
since they are inherently insecure.
It is not possible to stop users from obtaining the encrypted
password from the group database.

195
usr.bin/newgrp/newgrp.c Normal file
View file

@ -0,0 +1,195 @@
/*-
* Copyright (c) 2007 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Brian Ginsbach.
*
* 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 THE NETBSD FOUNDATION, INC. 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 THE FOUNDATION 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.
*/
#include <sys/cdefs.h>
#ifndef lint
__RCSID("$NetBSD: newgrp.c,v 1.6 2008/04/28 20:24:14 martin Exp $");
#endif /* not lint */
#include <sys/param.h>
#include <sys/types.h>
#include <err.h>
#include <grp.h>
#include <libgen.h>
#include <paths.h>
#include <pwd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#ifdef LOGIN_CAP
#include <login_cap.h>
#endif
#include "grutil.h"
static void
usage(void)
{
(void)fprintf(stderr, "usage: %s [-l] [group]\n", getprogname());
exit(EXIT_FAILURE);
}
int
main(int argc, char *argv[])
{
extern char **environ;
struct passwd *pwd;
int c, lflag;
char *shell, sbuf[MAXPATHLEN + 2];
uid_t uid;
#ifdef LOGIN_CAP
login_cap_t *lc;
u_int flags = LOGIN_SETUSER;
#endif
uid = getuid();
pwd = getpwuid(uid);
if (pwd == NULL)
errx(EXIT_FAILURE, "who are you?");
#ifdef LOGIN_CAP
if ((lc = login_getclass(pwd->pw_class)) == NULL)
errx(EXIT_FAILURE, "%s: unknown login class", pwd->pw_class);
#endif
(void)setprogname(argv[0]);
lflag = 0;
while ((c = getopt(argc, argv, "-l")) != -1) {
switch (c) {
case '-':
case 'l':
if (lflag)
usage();
lflag = 1;
break;
default:
usage();
break;
}
}
argc -= optind;
argv += optind;
if (argc > 0) {
#if 0
pwd->pw_gid = newgrp(*argv, pwd);
addgrp(pwd->pw_gid);
if (setgid(pwd->pw_gid) < 0)
err(1, "setgid");
#endif
#ifdef LOGIN_CAP
addgroup(lc, *argv, pwd, getuid(), "Password:");
#else
addgroup(*argv, pwd, getuid(), "Password:");
#endif
} else {
#ifdef LOGIN_CAP
flags |= LOGIN_SETGROUP;
#else
if (initgroups(pwd->pw_name, pwd->pw_gid) == -1)
err(EXIT_FAILURE, "initgroups");
if (setgid(pwd->pw_gid) == -1)
err(EXIT_FAILURE, "setgid");
#endif
}
#ifdef LOGIN_CAP
if (setusercontext(lc, pwd, uid, flags) == -1)
err(EXIT_FAILURE, "setusercontext");
if (!lflag)
login_close(lc);
#else
if (setuid(pwd->pw_uid) == -1)
err(EXIT_FAILURE, "setuid");
#endif
if (*pwd->pw_shell == '\0') {
#ifdef TRUST_ENV_SHELL
shell = getenv("SHELL");
if (shell != NULL)
pwd->pw_shell = shell;
else
#endif
pwd->pw_shell = __UNCONST(_PATH_BSHELL);
}
shell = pwd->pw_shell;
if (lflag) {
char *term;
#ifdef KERBEROS
char *krbtkfile;
#endif
if (chdir(pwd->pw_dir) == -1)
warn("%s", pwd->pw_dir);
term = getenv("TERM");
#ifdef KERBEROS
krbtkfile = getenv("KRBTKFILE");
#endif
/* create an empty environment */
if ((environ = malloc(sizeof(char *))) == NULL)
err(EXIT_FAILURE, NULL);
environ[0] = NULL;
#ifdef LOGIN_CAP
if (setusercontext(lc, pwd, uid, LOGIN_SETENV | LOGIN_SETPATH) == -1)
err(EXIT_FAILURE, "setusercontext");
login_close(lc);
#else
(void)setenv("PATH", _PATH_DEFPATH, 1);
#endif
if (term != NULL)
(void)setenv("TERM", term, 1);
#ifdef KERBEROS
if (krbtkfile != NULL)
(void)setenv("KRBTKFILE", krbtkfile, 1);
#endif
(void)setenv("LOGNAME", pwd->pw_name, 1);
(void)setenv("USER", pwd->pw_name, 1);
(void)setenv("HOME", pwd->pw_dir, 1);
(void)setenv("SHELL", pwd->pw_shell, 1);
sbuf[0] = '-';
(void)strlcpy(sbuf + 1, basename(pwd->pw_shell),
sizeof(sbuf) - 1);
shell = sbuf;
}
(void)execl(pwd->pw_shell, shell, NULL);
err(EXIT_FAILURE, "%s", pwd->pw_shell);
/* NOTREACHED */
}

51
usr.bin/passwd/Makefile Normal file
View file

@ -0,0 +1,51 @@
# $NetBSD: Makefile,v 1.41 2007/05/28 12:06:29 tls Exp $
# from: @(#)Makefile 8.3 (Berkeley) 4/2/94
.include <bsd.own.mk>
.if defined(__MINIX)
USE_YP= no
USE_KERBEROS= no
USE_PAM= no
.endif
USE_FORT?= yes # setuid
PROG= passwd
SRCS= local_passwd.c passwd.c
MAN= passwd.1
CPPFLAGS+=-I${.CURDIR} #-DLOGIN_CAP
.if (${USE_YP} != "no")
SRCS+= yp_passwd.c
CPPFLAGS+=-DYP
DPADD+= ${LIBRPCSVC}
LDADD+= -lrpcsvc
LINKS+= ${BINDIR}/passwd ${BINDIR}/yppasswd
MAN+= yppasswd.1
.endif
DPADD+= ${LIBCRYPT} ${LIBUTIL}
LDADD+= -lcrypt -lutil
BINOWN= root
BINMODE=4555
.if (${USE_KERBEROS} != "no")
CPPFLAGS+= -DKERBEROS5 -I${DESTDIR}/usr/include/krb5
SRCS+= krb5_passwd.c
DPADD+= ${LIBKRB5} ${LIBCRYPTO} ${LIBASN1} ${LIBCOM_ERR} ${LIBROKEN} ${LIBCRYPT}
LDADD+= -lkrb5 -lcrypto -lasn1 -lcom_err -lroken -lcrypt
LINKS+= ${BINDIR}/passwd ${BINDIR}/kpasswd
MAN+= kpasswd.1
.endif
.if (${USE_PAM} != "no")
CPPFLAGS+=-DUSE_PAM
SRCS+= pam_passwd.c
LDADD+=-lpam ${PAM_STATIC_LDADD}
DPADD+=${LIBPAM} ${PAM_STATIC_DPADD}
.endif
.include <bsd.prog.mk>

85
usr.bin/passwd/extern.h Normal file
View file

@ -0,0 +1,85 @@
/* $NetBSD: extern.h,v 1.13 2006/03/23 23:37:07 wiz Exp $ */
/*
* Copyright (c) 1994
* The Regents of the University of California. 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.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 THE REGENTS 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.
*
* @(#)extern.h 8.1 (Berkeley) 4/2/94
*/
#ifdef USE_PAM
void usage(void);
#ifdef KERBEROS5
void pwkrb5_usage(const char *);
void pwkrb5_argv0_usage(const char *);
void pwkrb5_process(const char *, int, char **);
#endif
#ifdef YP
void pwyp_usage(const char *);
void pwyp_argv0_usage(const char *);
void pwyp_process(const char *, int, char **);
#endif
void pwlocal_usage(const char *);
void pwlocal_process(const char *, int, char **);
void pwpam_process(const char *, int, char **);
#else /* ! USE_PAM */
/* return values from pw_init() and pw_arg_end() */
enum {
PW_USE_FORCE,
PW_USE,
PW_DONT_USE
};
#ifdef KERBEROS5
int krb5_init __P((const char *));
int krb5_arg __P((char, const char *));
int krb5_arg_end __P((void));
void krb5_end __P((void));
int krb5_chpw __P((const char *));
#endif
#ifdef YP
int yp_init __P((const char *));
int yp_arg __P((char, const char *));
int yp_arg_end __P((void));
void yp_end __P((void));
int yp_chpw __P((const char *));
#endif
/* local */
int local_init __P((const char *));
int local_arg __P((char, const char *));
int local_arg_end __P((void));
void local_end __P((void));
int local_chpw __P((const char *));
#endif /* USE_PAM */

48
usr.bin/passwd/kpasswd.1 Normal file
View file

@ -0,0 +1,48 @@
.\" $NetBSD: kpasswd.1,v 1.3 2008/04/30 13:11:01 martin Exp $
.\"
.\" Copyright (c) 2005 The NetBSD Foundation, Inc.
.\" All rights reserved.
.\"
.\" This code is derived from software contributed to The NetBSD Foundation
.\" by Jason R. Thorpe.
.\"
.\" 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 THE NETBSD FOUNDATION, INC. 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 THE FOUNDATION 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.
.\"
.Dd February 25, 2005
.Dt KPASSWD 1
.Os
.Sh NAME
.Nm kpasswd
.Nd modify a user's Kerberos 5 password
.Sh SYNOPSIS
.Nm
.Op Ar principal
.Sh DESCRIPTION
.Nm
changes the user's Kerberos 5 password.
.Pp
The
.Nm
command is deprecated.
See
.Xr passwd 1
for more information.

View file

@ -0,0 +1,351 @@
/* $NetBSD: krb5_passwd.c,v 1.18 2009/04/18 09:04:34 mlelstv Exp $ */
/*
* Copyright (c) 2000, 2005 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Johan Danielsson; and by Jason R. Thorpe.
*
* 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 THE NETBSD FOUNDATION, INC. 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 THE FOUNDATION 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.
*/
/* uses the `Kerberos Change Password Protocol' */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <err.h>
#include <errno.h>
#include <pwd.h>
#include <unistd.h>
#include <openssl/ui.h>
#include <krb5.h>
#include "extern.h"
#ifdef USE_PAM
void
pwkrb5_usage(const char *prefix)
{
(void) fprintf(stderr, "%s %s [-d krb5 | -k] [principal]\n",
prefix, getprogname());
}
void
pwkrb5_argv0_usage(const char *prefix)
{
(void) fprintf(stderr, "%s %s [principal]\n",
prefix, getprogname());
}
void
pwkrb5_process(const char *username, int argc, char **argv)
{
krb5_context context;
krb5_error_code ret;
krb5_get_init_creds_opt opt;
krb5_principal principal;
krb5_creds cred;
int result_code;
krb5_data result_code_string, result_string;
char pwbuf[BUFSIZ];
int ch;
while ((ch = getopt(argc, argv, "5ku:")) != -1) {
switch (ch) {
case '5':
/*
* Compatibility option that historically
* specified to use Kerberos 5. Silently
* ignore it.
*/
break;
case 'k':
/*
* Absorb the -k that may have gotten us here.
*/
break;
case 'u':
/*
* Historical option to specify principal.
*/
username = optarg;
break;
default:
usage();
/* NOTREACHED */
}
}
argc -= optind;
argv += optind;
switch (argc) {
case 0:
/* username already provided */
break;
case 1:
/* overrides -u <principal> */
username = argv[0];
break;
default:
usage();
/* NOTREACHED */
}
ret = krb5_init_context(&context);
if (ret != 0) {
if (ret == ENXIO)
errx(1, "Kerberos 5 not in use.");
warnx("Unable to initialize Kerberos 5: %s",
krb5_get_err_text(context, ret));
goto bad;
}
krb5_get_init_creds_opt_init(&opt);
krb5_get_init_creds_opt_set_tkt_life(&opt, 300L);
krb5_get_init_creds_opt_set_forwardable(&opt, FALSE);
krb5_get_init_creds_opt_set_proxiable(&opt, FALSE);
ret = krb5_parse_name(context, username, &principal);
if (ret) {
warnx("failed to parse principal: %s",
krb5_get_err_text(context, ret));
goto bad;
}
ret = krb5_get_init_creds_password(context,
&cred,
principal,
NULL,
krb5_prompter_posix,
NULL,
0L,
"kadmin/changepw",
&opt);
switch (ret) {
case 0:
break;
case KRB5_LIBOS_PWDINTR :
/* XXX */
goto bad;
case KRB5KRB_AP_ERR_BAD_INTEGRITY :
case KRB5KRB_AP_ERR_MODIFIED :
fprintf(stderr, "Password incorrect\n");
goto bad;
default:
warnx("failed to get credentials: %s",
krb5_get_err_text(context, ret));
goto bad;
}
krb5_data_zero(&result_code_string);
krb5_data_zero(&result_string);
/* XXX use getpass? It has a broken interface. */
if (UI_UTIL_read_pw_string(pwbuf, sizeof(pwbuf),
"New password: ", 1) != 0)
goto bad;
ret = krb5_set_password(context, &cred, pwbuf, NULL,
&result_code,
&result_code_string,
&result_string);
if (ret) {
warnx("unable to set password: %s",
krb5_get_err_text(context, ret));
goto bad;
}
printf("%s%s%.*s\n",
krb5_passwd_result_to_string(context, result_code),
result_string.length > 0 ? " : " : "",
(int)result_string.length,
result_string.length > 0 ? (char *)result_string.data : "");
krb5_data_free(&result_code_string);
krb5_data_free(&result_string);
krb5_free_cred_contents(context, &cred);
krb5_free_context(context);
if (result_code)
exit(1);
return;
bad:
krb5_free_context(context);
exit(1);
}
#else /* ! USE_PAM */
static krb5_context defcontext;
static krb5_principal defprinc;
static int kusage = PW_USE;
int
krb5_init(const char *progname)
{
return krb5_init_context(&defcontext);
}
int
krb5_arg (char ch, const char *opt)
{
krb5_error_code ret;
switch(ch) {
case '5':
case 'k':
kusage = PW_USE_FORCE;
return 1;
case 'u':
ret = krb5_parse_name(defcontext, opt, &defprinc);
if(ret) {
krb5_warn(defcontext, ret, "%s", opt);
return 0;
}
return 1;
}
return 0;
}
int
krb5_arg_end(void)
{
return kusage;
}
void
krb5_end(void)
{
if (defcontext == NULL)
return;
if(defprinc)
krb5_free_principal(defcontext, defprinc);
krb5_free_context(defcontext);
}
int
krb5_chpw(const char *username)
{
krb5_error_code ret;
krb5_context context;
krb5_principal principal;
krb5_get_init_creds_opt opt;
krb5_creds cred;
int result_code;
krb5_data result_code_string, result_string;
char pwbuf[BUFSIZ];
ret = krb5_init_context (&context);
if (ret) {
warnx("failed kerberos initialisation: %s",
krb5_get_err_text(context, ret));
return 1;
}
krb5_get_init_creds_opt_init (&opt);
krb5_get_init_creds_opt_set_tkt_life (&opt, 300);
krb5_get_init_creds_opt_set_forwardable (&opt, FALSE);
krb5_get_init_creds_opt_set_proxiable (&opt, FALSE);
if(username != NULL) {
ret = krb5_parse_name (context, username, &principal);
if (ret) {
warnx("failed to parse principal: %s",
krb5_get_err_text(context, ret));
return 1;
}
} else
principal = defprinc;
ret = krb5_get_init_creds_password (context,
&cred,
principal,
NULL,
krb5_prompter_posix,
NULL,
0,
"kadmin/changepw",
&opt);
switch (ret) {
case 0:
break;
case KRB5_LIBOS_PWDINTR :
/* XXX */
return 1;
case KRB5KRB_AP_ERR_BAD_INTEGRITY :
case KRB5KRB_AP_ERR_MODIFIED :
fprintf(stderr, "Password incorrect\n");
return 1;
break;
default:
warnx("failed to get credentials: %s",
krb5_get_err_text(context, ret));
return 1;
}
krb5_data_zero (&result_code_string);
krb5_data_zero (&result_string);
/* XXX use getpass? It has a broken interface. */
if(UI_UTIL_read_pw_string(pwbuf, sizeof(pwbuf), "New password: ", 1) != 0)
return 1;
ret = krb5_set_password (context, &cred, pwbuf, NULL,
&result_code,
&result_code_string,
&result_string);
if (ret)
krb5_err (context, 1, ret, "krb5_set_password");
printf ("%s%s%.*s\n", krb5_passwd_result_to_string(context, result_code),
result_string.length > 0 ? " : " : "",
(int)result_string.length,
result_string.length > 0 ? (char *)result_string.data : "");
krb5_data_free (&result_code_string);
krb5_data_free (&result_string);
krb5_free_cred_contents (context, &cred);
krb5_free_context (context);
return result_code;
}
#endif /* USE_PAM */

View file

@ -0,0 +1,345 @@
/* $NetBSD: local_passwd.c,v 1.34 2010/03/02 16:19:13 gdt Exp $ */
/*-
* Copyright (c) 1990, 1993, 1994
* The Regents of the University of California. 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.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 THE REGENTS 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.
*/
#include <sys/cdefs.h>
#ifndef lint
#if 0
static char sccsid[] = "from: @(#)local_passwd.c 8.3 (Berkeley) 4/2/94";
#else
__RCSID("$NetBSD: local_passwd.c,v 1.34 2010/03/02 16:19:13 gdt Exp $");
#endif
#endif /* not lint */
#include <sys/types.h>
#include <sys/stat.h>
#include <ctype.h>
#include <err.h>
#include <errno.h>
#include <fcntl.h>
#include <pwd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#include <time.h>
#include <unistd.h>
#include <util.h>
#include <login_cap.h>
#include <syslog.h>
#include "extern.h"
static uid_t uid;
static char *
getnewpasswd(struct passwd *pw, int min_pw_len)
{
int tries;
char *p, *t;
char buf[_PASSWORD_LEN+1], salt[_PASSWORD_LEN+1];
char option[LINE_MAX], *key, *opt;
(void)printf("Changing local password for %s.\n", pw->pw_name);
if (uid && pw->pw_passwd[0] &&
strcmp(crypt(getpass("Old password:"), pw->pw_passwd),
pw->pw_passwd)) {
errno = EACCES;
syslog(LOG_AUTH | LOG_NOTICE,
"user %s (UID %lu) failed to change the "
"local password of user %s: %m",
pw->pw_name, (unsigned long)uid, pw->pw_name);
pw_error(NULL, 1, 1);
}
for (buf[0] = '\0', tries = 0;;) {
p = getpass("New password:");
if (!*p) {
(void)printf("Password unchanged.\n");
pw_error(NULL, 0, 0);
}
if (min_pw_len > 0 && (int)strlen(p) < min_pw_len) {
(void) printf("Password is too short.\n");
continue;
}
if (strlen(p) <= 5 && ++tries < 2) {
(void)printf("Please enter a longer password.\n");
continue;
}
for (t = p; *t && islower((unsigned char)*t); ++t);
if (!*t && ++tries < 2) {
(void)printf("Please don't use an all-lower case "
"password.\nUnusual capitalization, "
"control characters or digits are "
"suggested.\n");
continue;
}
(void)strlcpy(buf, p, sizeof(buf));
if (!strcmp(buf, getpass("Retype new password:")))
break;
(void)printf("Mismatch; try again, EOF to quit.\n");
}
pw_getpwconf(option, sizeof(option), pw, "localcipher");
opt = option;
key = strsep(&opt, ",");
if(pw_gensalt(salt, _PASSWORD_LEN, key, opt) == -1) {
warn("Couldn't generate salt");
pw_error(NULL, 0, 0);
}
return(crypt(buf, salt));
}
#ifdef USE_PAM
void
pwlocal_usage(const char *prefix)
{
(void) fprintf(stderr, "%s %s [-d files | -l] [user]\n",
prefix, getprogname());
}
void
pwlocal_process(const char *username, int argc, char **argv)
{
struct passwd *pw;
struct passwd old_pw;
time_t old_change;
int pfd, tfd;
int min_pw_len = 0;
int pw_expiry = 0;
int ch;
#ifdef LOGIN_CAP
login_cap_t *lc;
#endif
while ((ch = getopt(argc, argv, "l")) != -1) {
switch (ch) {
case 'l':
/*
* Aborb the -l that may have gotten us here.
*/
break;
default:
usage();
/* NOTREACHED */
}
}
argc -= optind;
argv += optind;
switch (argc) {
case 0:
/* username already provided */
break;
case 1:
username = argv[0];
break;
default:
usage();
/* NOTREACHED */
}
if (!(pw = getpwnam(username)))
errx(1, "unknown user %s", username);
uid = getuid();
if (uid && uid != pw->pw_uid)
errx(1, "%s", strerror(EACCES));
/* Save the old pw information for comparing on pw_copy(). */
old_pw = *pw;
/*
* Get class restrictions for this user, then get the new password.
*/
#ifdef LOGIN_CAP
if((lc = login_getclass(pw->pw_class)) != NULL) {
min_pw_len = (int) login_getcapnum(lc, "minpasswordlen", 0, 0);
pw_expiry = (int) login_getcaptime(lc, "passwordtime", 0, 0);
login_close(lc);
}
#endif
#if 0
printf("AAA: pw_expiry = %x\n", pw_expiry);
#endif
pw->pw_passwd = getnewpasswd(pw, min_pw_len);
old_change = pw->pw_change;
pw->pw_change = pw_expiry ? pw_expiry + time(NULL) : 0;
/*
* Now that the user has given us a new password, let us
* change the database.
*/
pw_init();
tfd = pw_lock(0);
if (tfd < 0) {
warnx ("The passwd file is busy, waiting...");
tfd = pw_lock(10);
if (tfd < 0)
errx(1, "The passwd file is still busy, "
"try again later.");
}
pfd = open(_PATH_MASTERPASSWD, O_RDONLY, 0);
if (pfd < 0)
pw_error(_PATH_MASTERPASSWD, 1, 1);
pw_copy(pfd, tfd, pw, &old_pw);
if (pw_mkdb(username, old_change == pw->pw_change) < 0)
pw_error((char *)NULL, 0, 1);
syslog(LOG_AUTH | LOG_INFO,
"user %s (UID %lu) successfully changed "
"the local password of user %s",
uid ? username : "root", (unsigned long)uid, username);
}
#else /* ! USE_PAM */
static int force_local;
int
local_init(progname)
const char *progname;
{
force_local = 0;
return (0);
}
int
local_arg(char ch, const char *arg)
{
switch (ch) {
case 'l':
force_local = 1;
break;
default:
return(0);
}
return(1);
}
int
local_arg_end()
{
if (force_local)
return(PW_USE_FORCE);
return(PW_USE);
}
void
local_end()
{
/* NOOP */
}
int
local_chpw(uname)
const char *uname;
{
struct passwd *pw;
struct passwd old_pw;
time_t old_change;
int pfd, tfd;
int min_pw_len = 0;
int pw_expiry = 0;
#ifdef LOGIN_CAP
login_cap_t *lc;
#endif
if (!(pw = getpwnam(uname))) {
warnx("unknown user %s", uname);
return (1);
}
uid = getuid();
if (uid && uid != pw->pw_uid) {
warnx("%s", strerror(EACCES));
return (1);
}
/* Save the old pw information for comparing on pw_copy(). */
old_pw = *pw;
/*
* Get class restrictions for this user, then get the new password.
*/
#ifdef LOGIN_CAP
if((lc = login_getclass(pw->pw_class))) {
min_pw_len = (int) login_getcapnum(lc, "minpasswordlen", 0, 0);
pw_expiry = (int) login_getcaptime(lc, "passwordtime", 0, 0);
login_close(lc);
}
#endif
#if 0
printf("pw_expiry = %x, pw->pw_expire = %x\n", pw_expiry, pw->pw_expire);
#endif
pw->pw_passwd = getnewpasswd(pw, min_pw_len);
old_change = pw->pw_change;
pw->pw_change = pw_expiry ? pw_expiry + time(NULL) : 0;
/*
* Now that the user has given us a new password, let us
* change the database.
*/
pw_init();
tfd = pw_lock(0);
if (tfd < 0) {
warnx ("The passwd file is busy, waiting...");
tfd = pw_lock(10);
if (tfd < 0)
errx(1, "The passwd file is still busy, "
"try again later.");
}
pfd = open(_PATH_MASTERPASSWD, O_RDONLY, 0);
if (pfd < 0)
pw_error(_PATH_MASTERPASSWD, 1, 1);
pw_copy(pfd, tfd, pw, &old_pw);
if (pw_mkdb(uname, old_change == pw->pw_change) < 0)
pw_error((char *)NULL, 0, 1);
syslog(LOG_AUTH | LOG_INFO,
"user %s (UID %lu) successfully changed "
"the local password of user %s",
uid ? uname : "root", (unsigned long)uid, uname);
return (0);
}
#endif /* USE_PAM */

149
usr.bin/passwd/pam_passwd.c Normal file
View file

@ -0,0 +1,149 @@
/* $NetBSD: pam_passwd.c,v 1.6 2010/03/09 16:14:08 joerg Exp $ */
/*-
* Copyright (c) 2002 Networks Associates Technologies, Inc.
* All rights reserved.
*
* This software was developed for the FreeBSD Project by ThinkSec AS and
* NAI Labs, the Security Research Division of Network Associates, Inc.
* under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"), as part of the
* DARPA CHATS research program.
*
* 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. The name of the author may not be used to endorse or promote
* products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 THE AUTHOR 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.
*/
#include <sys/cdefs.h>
#ifdef __FreeBSD__
__FBSDID("$FreeBSD: src/usr.bin/passwd/passwd.c,v 1.23 2003/04/18 21:27:09 nectar Exp $");
#else
__RCSID("$NetBSD: pam_passwd.c,v 1.6 2010/03/09 16:14:08 joerg Exp $");
#endif
#include <sys/param.h>
#include <err.h>
#include <pwd.h>
#include <stdio.h>
#include <stdlib.h>
#include <syslog.h>
#include <unistd.h>
#include "extern.h"
#include <security/pam_appl.h>
#include <security/openpam.h>
static pam_handle_t *pamh;
static struct pam_conv pamc = {
openpam_ttyconv,
NULL
};
#define pam_check(msg) \
do { \
if (pam_err != PAM_SUCCESS) { \
warnx("%s: %s", (msg), pam_strerror(pamh, pam_err)); \
goto end; \
} \
} while (/*CONSTCOND*/0)
void
pwpam_process(const char *username, int argc, char **argv)
{
int ch, pam_err;
char hostname[MAXHOSTNAMELEN + 1];
/* details about the invoking user for logging */
const uid_t i_uid = getuid();
const struct passwd *const i_pwd = getpwuid(i_uid);
const char *const i_username = (i_pwd && i_pwd->pw_name)
? i_pwd->pw_name : "(null)";
while ((ch = getopt(argc, argv, "")) != -1) {
switch (ch) {
default:
usage();
/* NOTREACHED */
}
}
argc -= optind;
argv += optind;
switch (argc) {
case 0:
/* username already provided */
break;
case 1:
username = argv[0];
break;
default:
usage();
/* NOTREACHED */
}
(void)printf("Changing password for %s.\n", username);
/* initialize PAM -- always use the program name "passwd" */
pam_err = pam_start("passwd", username, &pamc, &pamh);
if (pam_err != PAM_SUCCESS)
errx(1, "unable to start PAM session: %s",
pam_strerror(NULL, pam_err));
pam_err = pam_set_item(pamh, PAM_TTY, ttyname(STDERR_FILENO));
pam_check("unable to set TTY");
(void)gethostname(hostname, sizeof hostname);
pam_err = pam_set_item(pamh, PAM_RHOST, hostname);
pam_check("unable to set RHOST");
pam_err = pam_set_item(pamh, PAM_RUSER, getlogin());
pam_check("unable to set RUSER");
/* set new password */
pam_err = pam_chauthtok(pamh, 0);
if (pam_err != PAM_SUCCESS) {
if (pam_err == PAM_PERM_DENIED) {
syslog(LOG_AUTH | LOG_NOTICE,
"user %s (UID %lu) failed to change the "
"PAM authentication token of user %s: %s",
i_username, (unsigned long)i_uid, username,
pam_strerror(pamh, pam_err));
}
printf("Unable to change auth token: %s\n",
pam_strerror(pamh, pam_err));
} else {
syslog(LOG_AUTH | LOG_INFO,
"user %s (UID %lu) successfully changed the "
"PAM authentication token of user %s",
i_username, (unsigned long)i_uid, username);
}
end:
pam_end(pamh, pam_err);
if (pam_err == PAM_SUCCESS)
return;
exit(1);
}

142
usr.bin/passwd/passwd.1 Normal file
View file

@ -0,0 +1,142 @@
.\" $NetBSD: passwd.1,v 1.28 2006/03/07 01:52:09 hubertf Exp $
.\"
.\" Copyright (c) 1990, 1993
.\" The Regents of the University of California. 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.
.\" 3. Neither the name of the University nor the names of its contributors
.\" may be used to endorse or promote products derived from this software
.\" without specific prior written permission.
.\"
.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 THE REGENTS 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.
.\"
.\" from: @(#)passwd.1 8.1 (Berkeley) 6/6/93
.\"
.Dd February 25, 2005
.Dt PASSWD 1
.Os
.Sh NAME
.Nm passwd
.Nd modify a user's password
.Sh SYNOPSIS
.Nm
.Op Ar user
.Nm
.Oo Fl d Ar files | Fl l Oc
.Op Ar user
.Nm
.Oo Fl d Ar nis | Fl y Oc
.Op Ar user
.Nm
.Oo Fl d Ar krb5 | Fl k Oc
.Op Ar principal
.Sh DESCRIPTION
.Nm
changes the user's password.
First, the user is
prompted for their current password.
If the current password is correctly typed, a new password is
requested.
The new password must be entered twice to avoid typing errors.
.Pp
The new password should be at least six characters long and not
purely alphabetic.
Its total length must be less than
.Dv _PASSWORD_LEN
(currently 128 characters).
Numbers, upper case letters and meta characters
are encouraged.
.Pp
All options may not be available on all systems.
.Bl -tag -width flag
.It Fl d Ar database
This option specifies the password database that should be updated. The
following databases are supported:
.Bl -tag -width files
.It files
This specifies that the password change should be applied to the local
password file.
When changing only the local password,
.Nm
uses
.Xr pwd_mkdb 8
to update the password databases.
.It nis
This specifies that the password change should be applied to the NIS
password database.
The
.Xr rpc.yppasswdd 8
daemon should be running on the master NIS server.
.It krb5
This specifies that the user's Kerberos 5 password should be changed.
The host must be configured to use Kerberos.
See
.Xr krb5.conf 5 .
.El
.It Fl l
This is the equivalent of
.Fl d Ar files .
.It Fl y
This is the equivalent of
.Fl d Ar nis .
.It Fl k
This is the equivalent of
.Fl d Ar krb5 .
.El
.Pp
If a password database is not specified,
.Nm
will change the password database as determined by the
Pluggable Authentication Module
.Pq PAM
library.
.Pp
The type of cipher used to encrypt the password depends on the configuration
in
.Xr passwd.conf 5 .
It can be different for local and NIS passwords.
.Sh FILES
.Bl -tag -width /etc/master.passwd -compact
.It Pa /etc/master.passwd
The user database
.It Pa /etc/passwd
A Version 7 format password file
.It Pa /etc/passwd.XXXXXX
Temporary copy of the password file
.El
.Sh SEE ALSO
.Xr chpass 1 ,
.Xr login 1 ,
.Xr pwhash 1 ,
.Xr passwd 5 ,
.Xr passwd.conf 5 ,
.Xr pam 8 ,
.Xr pwd_mkdb 8 ,
.Xr vipw 8
.Rs
.%A Robert Morris
.%A Ken Thompson
.%T "UNIX password security"
.Re
.Sh HISTORY
A
.Nm
command appeared in
.At v6 .

405
usr.bin/passwd/passwd.c Normal file
View file

@ -0,0 +1,405 @@
/* $NetBSD: passwd.c,v 1.30 2009/04/17 20:25:08 dyoung Exp $ */
/*
* Copyright (c) 1988, 1993, 1994
* The Regents of the University of California. 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.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 THE REGENTS 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.
*/
#include <sys/cdefs.h>
#ifndef lint
__COPYRIGHT("@(#) Copyright (c) 1988, 1993, 1994\
The Regents of the University of California. All rights reserved.");
#endif /* not lint */
#ifndef lint
#if 0
static char sccsid[] = "from: @(#)passwd.c 8.3 (Berkeley) 4/2/94";
#else
__RCSID("$NetBSD: passwd.c,v 1.30 2009/04/17 20:25:08 dyoung Exp $");
#endif
#endif /* not lint */
#include <assert.h>
#include <err.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <pwd.h>
#include "extern.h"
#ifdef USE_PAM
static void global_usage(const char *);
static const struct pw_module_s {
const char *argv0;
const char *dbname;
char compat_opt;
void (*pw_usage)(const char *);
void (*pw_process)(const char *, int, char **);
} pw_modules[] = {
/* "files" -- local password database */
{ NULL, "files", 'l', pwlocal_usage, pwlocal_process },
#ifdef YP
/* "nis" -- YP/NIS password database */
{ NULL, "nis", 'y', pwyp_usage, pwyp_process },
{ "yppasswd", NULL, 0, pwyp_argv0_usage, pwyp_process },
#endif
#ifdef KERBEROS5
/* "krb5" -- Kerberos 5 password database */
{ NULL, "krb5", 'k', pwkrb5_usage, pwkrb5_process },
{ "kpasswd", NULL, 0, pwkrb5_argv0_usage, pwkrb5_process },
#endif
/* default -- use whatever PAM decides */
{ NULL, NULL, 0, NULL, pwpam_process },
{ NULL, NULL, 0, NULL, NULL }
};
static const struct pw_module_s *personality;
static void
global_usage(const char *prefix)
{
const struct pw_module_s *pwm;
(void) fprintf(stderr, "%s %s [user]\n", prefix, getprogname());
for (pwm = pw_modules; pwm->pw_process != NULL; pwm++) {
if (pwm->argv0 == NULL && pwm->pw_usage != NULL)
(*pwm->pw_usage)(" ");
}
}
void
usage(void)
{
if (personality != NULL && personality->pw_usage != NULL)
(*personality->pw_usage)("usage:");
else
global_usage("usage:");
exit(1);
}
int
main(int argc, char **argv)
{
const struct pw_module_s *pwm;
const char *username;
int ch, i;
char opts[16];
/* Build opts string from module compat_opts */
i = 0;
opts[i++] = 'd';
opts[i++] = ':';
for (pwm = pw_modules; pwm->pw_process != NULL; pwm++) {
if (pwm->compat_opt != 0)
opts[i++] = pwm->compat_opt;
}
opts[i++] = '\0';
/* First, look for personality based on argv[0]. */
for (pwm = pw_modules; pwm->pw_process != NULL; pwm++) {
if (pwm->argv0 != NULL &&
strcmp(pwm->argv0, getprogname()) == 0)
goto got_personality;
}
/* Try based on compat_opt or -d. */
for (ch = 0, pwm = pw_modules; pwm->pw_process != NULL; pwm++) {
if (pwm->argv0 == NULL && pwm->dbname == NULL &&
pwm->compat_opt == 0) {
/*
* We have reached the default personality case.
* Make sure the user didn't provide a bogus
* personality name.
*/
if (ch == 'd')
usage();
break;
}
ch = getopt(argc, argv, opts);
if (ch == '?')
usage();
if (ch == 'd' && pwm->dbname != NULL &&
strcmp(pwm->dbname, optarg) == 0) {
/*
* "passwd -d dbname" matches; this is our
* chosen personality.
*/
break;
}
if (pwm->compat_opt != 0 && ch == pwm->compat_opt) {
/*
* Legacy "passwd -l" or similar matches; this
* is our chosen personality.
*/
break;
}
/* Reset getopt() and go around again. */
optind = 1;
optreset = 1;
}
got_personality:
personality = pwm;
/*
* At this point, optind should be either 1 ("passwd"),
* 2 ("passwd -l"), or 3 ("passwd -d files"). Consume
* these arguments and reset getopt() for the modules to use.
*/
assert(optind >= 1 && optind <= 3);
argc -= optind;
argv += optind;
optind = 0;
optreset = 1;
username = getlogin();
if (username == NULL)
errx(1, "who are you ??");
(*personality->pw_process)(username, argc, argv);
return 0;
}
#else /* ! USE_PAM */
static struct pw_module_s {
const char *argv0;
const char *args;
const char *usage;
int (*pw_init) __P((const char *));
int (*pw_arg) __P((char, const char *));
int (*pw_arg_end) __P((void));
void (*pw_end) __P((void));
int (*pw_chpw) __P((const char*));
int invalid;
#define INIT_INVALID 1
#define ARG_INVALID 2
int use_class;
} pw_modules[] = {
#ifdef KERBEROS5
{ NULL, "5ku:", "[-5] [-k] [-u principal]",
krb5_init, krb5_arg, krb5_arg_end, krb5_end, krb5_chpw, 0, 0 },
{ "kpasswd", "5ku:", "[-5] [-k] [-u principal]",
krb5_init, krb5_arg, krb5_arg_end, krb5_end, krb5_chpw, 0, 0 },
#endif
#ifdef YP
{ NULL, "y", "[-y]",
yp_init, yp_arg, yp_arg_end, yp_end, yp_chpw, 0, 0 },
{ "yppasswd", "", "[-y]",
yp_init, yp_arg, yp_arg_end, yp_end, yp_chpw, 0, 0 },
#endif
/* local */
{ NULL, "l", "[-l]",
local_init, local_arg, local_arg_end, local_end, local_chpw, 0, 0 },
/* terminator */
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
};
static void
usage(void)
{
int i;
fprintf(stderr, "usage:\n");
for (i = 0; pw_modules[i].pw_init != NULL; i++)
if (! (pw_modules[i].invalid & INIT_INVALID))
fprintf(stderr, "\t%s %s [user]\n", getprogname(),
pw_modules[i].usage);
exit(1);
}
int
main(int argc, char **argv)
{
int ch;
char *username;
char optstring[64]; /* if we ever get more than 64 args, shoot me. */
const char *curopt, *oopt;
int i, j;
int valid;
int use_always;
/* allow passwd modules to do argv[0] specific processing */
use_always = 0;
valid = 0;
for (i = 0; pw_modules[i].pw_init != NULL; i++) {
pw_modules[i].invalid = 0;
if (pw_modules[i].argv0) {
/*
* If we have a module that matches this progname, be
* sure that no modules but those that match this
* progname can be used. If we have a module that
* matches against a particular progname, but does NOT
* match this one, don't use that module.
*/
if ((strcmp(getprogname(), pw_modules[i].argv0) == 0) &&
use_always == 0) {
for (j = 0; j < i; j++) {
pw_modules[j].invalid |= INIT_INVALID;
(*pw_modules[j].pw_end)();
}
use_always = 1;
} else if (use_always == 0)
pw_modules[i].invalid |= INIT_INVALID;
} else if (use_always)
pw_modules[i].invalid |= INIT_INVALID;
if (pw_modules[i].invalid)
continue;
pw_modules[i].invalid |=
(*pw_modules[i].pw_init)(getprogname()) ?
/* zero on success, non-zero on error */
INIT_INVALID : 0;
if (! pw_modules[i].invalid)
valid = 1;
}
if (valid == 0)
errx(1, "Can't change password.");
/* Build the option string from the individual modules' option
* strings. Note that two modules can share a single option
* letter. */
optstring[0] = '\0';
j = 0;
for (i = 0; pw_modules[i].pw_init != NULL; i++) {
if (pw_modules[i].invalid)
continue;
curopt = pw_modules[i].args;
while (*curopt != '\0') {
if ((oopt = strchr(optstring, *curopt)) == NULL) {
optstring[j++] = *curopt;
if (curopt[1] == ':') {
curopt++;
optstring[j++] = *curopt;
}
optstring[j] = '\0';
} else if ((oopt[1] == ':' && curopt[1] != ':') ||
(oopt[1] != ':' && curopt[1] == ':')) {
errx(1, "NetBSD ERROR! Different password "
"modules have two different ideas about "
"%c argument format.", curopt[0]);
}
curopt++;
}
}
while ((ch = getopt(argc, argv, optstring)) != -1)
{
valid = 0;
for (i = 0; pw_modules[i].pw_init != NULL; i++) {
if (pw_modules[i].invalid)
continue;
if ((oopt = strchr(pw_modules[i].args, ch)) != NULL) {
j = (oopt[1] == ':') ?
! (*pw_modules[i].pw_arg)(ch, optarg) :
! (*pw_modules[i].pw_arg)(ch, NULL);
if (j != 0)
pw_modules[i].invalid |= ARG_INVALID;
if (pw_modules[i].invalid)
(*pw_modules[i].pw_end)();
} else {
/* arg doesn't match this module */
pw_modules[i].invalid |= ARG_INVALID;
(*pw_modules[i].pw_end)();
}
if (! pw_modules[i].invalid)
valid = 1;
}
if (! valid) {
usage();
exit(1);
}
}
/* select which module to use to actually change the password. */
use_always = 0;
valid = 0;
for (i = 0; pw_modules[i].pw_init != NULL; i++)
if (! pw_modules[i].invalid) {
pw_modules[i].use_class = (*pw_modules[i].pw_arg_end)();
if (pw_modules[i].use_class != PW_DONT_USE)
valid = 1;
if (pw_modules[i].use_class == PW_USE_FORCE)
use_always = 1;
}
if (! valid)
/* hang the DJ */
errx(1, "No valid password module specified.");
argc -= optind;
argv += optind;
username = getlogin();
if (username == NULL)
errx(1, "who are you ??");
switch(argc) {
case 0:
break;
case 1:
username = argv[0];
break;
default:
usage();
exit(1);
}
/* allow for fallback to other chpw() methods. */
for (i = 0; pw_modules[i].pw_init != NULL; i++) {
if (pw_modules[i].invalid)
continue;
if ((use_always && pw_modules[i].use_class == PW_USE_FORCE) ||
(!use_always && pw_modules[i].use_class == PW_USE)) {
valid = (*pw_modules[i].pw_chpw)(username);
(*pw_modules[i].pw_end)();
if (valid >= 0)
exit(valid);
/* return value < 0 indicates continuation. */
}
}
exit(1);
}
#endif /* USE_PAM */

468
usr.bin/passwd/yp_passwd.c Normal file
View file

@ -0,0 +1,468 @@
/* $NetBSD: yp_passwd.c,v 1.35 2010/09/08 13:58:46 christos Exp $ */
/*
* Copyright (c) 1988, 1990, 1993, 1994
* The Regents of the University of California. 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.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 THE REGENTS 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.
*/
#include <sys/cdefs.h>
#ifndef lint
#if 0
static char sccsid[] = "from: @(#)local_passwd.c 8.3 (Berkeley) 4/2/94";
#else
__RCSID("$NetBSD: yp_passwd.c,v 1.35 2010/09/08 13:58:46 christos Exp $");
#endif
#endif /* not lint */
#ifdef YP
#include <ctype.h>
#include <err.h>
#include <errno.h>
#include <netdb.h>
#include <pwd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#include <limits.h>
#include <util.h>
#include <rpc/rpc.h>
#include <rpcsvc/yp_prot.h>
#include <rpcsvc/ypclnt.h>
#include "extern.h"
#define passwd yp_passwd_rec
#include <rpcsvc/yppasswd.h>
#undef passwd
#ifndef _PASSWORD_LEN
#define _PASSWORD_LEN PASS_MAX
#endif
static uid_t uid;
static char *domain;
static void
pwerror(const char *name, int show_err, int eval)
{
if (show_err)
warn("%s", name);
errx(eval, "NIS passwd database unchanged");
}
static char *
getnewpasswd(struct passwd *pw, char **old_pass)
{
int tries;
const char *p, *t;
char *result;
static char buf[_PASSWORD_LEN + 1];
char salt[_PASSWORD_LEN + 1];
char option[LINE_MAX], *key, *opt;
(void)printf("Changing NIS password for %s.\n", pw->pw_name);
if (old_pass) {
*old_pass = NULL;
if (pw->pw_passwd[0]) {
if (strcmp(crypt(p = getpass("Old password:"),
pw->pw_passwd), pw->pw_passwd)) {
(void)printf("Sorry.\n");
pwerror(NULL, 0, 1);
}
} else {
p = "";
}
*old_pass = strdup(p);
if (!*old_pass) {
(void)printf("not enough core.\n");
pwerror(NULL, 0, 1);
}
}
for (buf[0] = '\0', tries = 0;;) {
p = getpass("New password:");
if (!*p) {
(void)printf("Password unchanged.\n");
pwerror(NULL, 0, 0);
}
if (strlen(p) <= 5 && ++tries < 2) {
(void)printf("Please enter a longer password.\n");
continue;
}
for (t = p; *t && islower((unsigned char)*t); ++t);
if (!*t && ++tries < 2) {
(void)printf("Please don't use an all-lower case "
"password.\nUnusual capitalization, "
"control characters or digits are "
"suggested.\n");
continue;
}
(void)strlcpy(buf, p, sizeof(buf));
if (!strcmp(buf, getpass("Retype new password:")))
break;
(void)printf("Mismatch; try again, EOF to quit.\n");
}
pw_getpwconf(option, sizeof(option), pw, "ypcipher");
opt = option;
key = strsep(&opt, ",");
if (pw_gensalt(salt, _PASSWORD_LEN, key, opt) == -1) {
warn("Couldn't generate salt");
pwerror(NULL, 0, 0);
}
result = strdup(crypt(buf, salt));
if (!result) {
(void)printf("not enough core.\n");
pwerror(NULL, 0, 0);
}
return result;
}
static void
makeypp(struct yppasswd *ypp, struct passwd *pw)
{
/* prompt for new password */
ypp->newpw.pw_passwd = getnewpasswd(pw, &ypp->oldpass);
/* tell rpc.yppasswdd */
ypp->newpw.pw_name = estrdup(pw->pw_name);
ypp->newpw.pw_uid = pw->pw_uid;
ypp->newpw.pw_gid = pw->pw_gid;
ypp->newpw.pw_gecos = estrdup(pw->pw_gecos);
ypp->newpw.pw_dir = estrdup(pw->pw_dir);
ypp->newpw.pw_shell = estrdup(pw->pw_shell);
}
static int
ypgetpwnam(const char *nam, struct passwd *pwd)
{
char *val;
int reason, vallen, namlen = (int)strlen(nam);
int flags;
int ok;
flags = ok = 0;
val = NULL;
reason = yp_match(domain, "master.passwd.byname", nam, namlen,
&val, &vallen);
if (reason == YPERR_MAP) {
reason = yp_match(domain, "passwd.byname", nam, namlen,
&val, &vallen);
flags = _PASSWORD_OLDFMT;
}
if (reason != 0)
goto out;
if (pw_scan(val, pwd, &flags) == 0)
goto out;
ok = 1;
val = NULL; /* Don't free the memory, it is still in use */
out:
if (val)
free(val);
return ok;
}
#ifdef USE_PAM
void
pwyp_usage(const char *prefix)
{
(void)fprintf(stderr, "%s %s [-d nis | -y] [user]\n",
prefix, getprogname());
}
void
pwyp_argv0_usage(const char *prefix)
{
(void)fprintf(stderr, "%s %s [user]\n",
prefix, getprogname());
}
void
pwyp_process(const char *username, int argc, char **argv)
{
char *master;
int ch, r, rpcport, status;
enum clnt_stat yr;
struct yppasswd ypp;
struct passwd pwb, pwb2, *pw;
char pwbuf[1024];
struct timeval tv;
CLIENT *client;
while ((ch = getopt(argc, argv, "y")) != -1) {
switch (ch) {
case 'y':
/*
* Abosrb the -y that may have gotten us here.
*/
break;
default:
usage();
/* NOTREACHED */
}
}
argc -= optind;
argv += optind;
switch (argc) {
case 0:
/* username already provided */
break;
case 1:
username = argv[0];
break;
default:
usage();
/*NOTREACHED*/
}
if (_yp_check(NULL) == 0) {
/* can't use YP. */
errx(EXIT_FAILURE, "NIS not in use.");
}
uid = getuid();
/*
* Get local domain
*/
if ((r = yp_get_default_domain(&domain)) != 0)
errx(EXIT_FAILURE, "Can't get local NIS domain (%s)",
yperr_string(r));
/*
* Find the host for the passwd map; it should be running
* the daemon.
*/
if ((r = yp_master(domain, "passwd.byname", &master)) != 0)
errx(EXIT_FAILURE, "Can't find the master NIS server (%s)",
yperr_string(r));
/*
* Ask the portmapper for the port of the daemon.
*/
if ((rpcport = getrpcport(master, YPPASSWDPROG,
YPPASSWDPROC_UPDATE, IPPROTO_UDP)) == 0)
errx(EXIT_FAILURE, "Master NIS server not running yppasswd "
"daemon");
/*
* Be sure the port is privileged
*/
if (rpcport >= IPPORT_RESERVED)
errx(EXIT_FAILURE, "Yppasswd daemon is on an invalid port");
/* Bail out if this is a local (non-yp) user, */
/* then get user's login identity */
if (!ypgetpwnam(username, &pwb) ||
getpwnam_r(username, &pwb2, pwbuf, sizeof(pwbuf), &pw) ||
pw == NULL)
errx(EXIT_FAILURE, "NIS unknown user %s", username);
if (uid && uid != pwb.pw_uid) {
errno = EACCES;
err(EXIT_FAILURE, "You may only change your own password");
}
makeypp(&ypp, &pwb);
client = clnt_create(master, YPPASSWDPROG, YPPASSWDVERS, "udp");
if (client == NULL)
errx(EXIT_FAILURE, "Cannot contact yppasswdd on %s (%s)",
master, yperr_string(YPERR_YPBIND));
client->cl_auth = authunix_create_default();
tv.tv_sec = 2;
tv.tv_usec = 0;
yr = clnt_call(client, YPPASSWDPROC_UPDATE,
xdr_yppasswd, &ypp, xdr_int, &status, tv);
if (yr != RPC_SUCCESS)
errx(EXIT_FAILURE, "RPC to yppasswdd failed (%s)",
clnt_sperrno(yr));
else if (status)
printf("Couldn't change NIS password.\n");
else
printf("The NIS password has been changed on %s, %s\n",
master, "the master NIS passwd server.");
}
#else /* ! USE_PAM */
static int yflag;
int
yp_init(progname)
const char *progname;
{
int yppwd;
if (strcmp(progname, "yppasswd") == 0) {
yppwd = 1;
} else
yppwd = 0;
yflag = 0;
if (_yp_check(NULL) == 0) {
/* can't use YP. */
if (yppwd)
errx(EXIT_FAILURE, "NIS not in use");
return -1;
}
return 0;
}
int
yp_arg(char ch, const char *arg)
{
switch (ch) {
case 'y':
yflag = 1;
break;
default:
return 0;
}
return 1;
}
int
yp_arg_end(void)
{
if (yflag)
return PW_USE_FORCE;
return PW_USE;
}
void
yp_end(void)
{
/* NOOP */
}
int
yp_chpw(const char *username)
{
char *master;
int r, rpcport, status;
enum clnt_stat yr;
struct yppasswd ypp;
struct passwd *pw, pwb;
char pwbuf[1024];
struct timeval tv;
CLIENT *client;
uid = getuid();
/*
* Get local domain
*/
if ((r = yp_get_default_domain(&domain)) != 0)
errx(EXIT_FAILURE, "can't get local NIS domain. Reason: %s",
yperr_string(r));
/*
* Find the host for the passwd map; it should be running
* the daemon.
*/
if ((r = yp_master(domain, "passwd.byname", &master)) != 0) {
warnx("can't find the master NIS server. Reason: %s",
yperr_string(r));
/* continuation */
return -1;
}
/*
* Ask the portmapper for the port of the daemon.
*/
if ((rpcport = getrpcport(master, YPPASSWDPROG,
YPPASSWDPROC_UPDATE, IPPROTO_UDP)) == 0) {
warnx("Master NIS server not running yppasswd daemon");
/* continuation */
return -1;
}
/*
* Be sure the port is privileged
*/
if (rpcport >= IPPORT_RESERVED)
errx(EXIT_FAILURE, "Yppasswd daemon is on an invalid port");
/* Bail out if this is a local (non-yp) user, */
/* then get user's login identity */
if (!ypgetpwnam(username, pw = &pwb) ||
getpwnam_r(username, &pwb, pwbuf, sizeof(pwbuf), &pw) ||
pw == NULL) {
warnx("NIS unknown user %s", username);
/* continuation */
return -1;
}
if (uid && uid != pw->pw_uid) {
errno = EACCES;
err(EXIT_FAILURE, "You may only change your own password");
}
makeypp(&ypp, pw);
client = clnt_create(master, YPPASSWDPROG, YPPASSWDVERS, "udp");
if (client == NULL) {
warnx("Cannot contact yppasswdd on %s (%s)",
master, yperr_string(YPERR_YPBIND));
return YPERR_YPBIND;
}
client->cl_auth = authunix_create_default();
tv.tv_sec = 2;
tv.tv_usec = 0;
yr = clnt_call(client, YPPASSWDPROC_UPDATE,
xdr_yppasswd, &ypp, xdr_int, &status, tv);
if (yr != RPC_SUCCESS)
errx(EXIT_FAILURE, "RPC to yppasswdd failed (%s)",
clnt_sperrno(yr));
else if (status)
printf("Couldn't change NIS password.\n");
else
printf("The NIS password has been changed on %s, %s\n",
master, "the master NIS passwd server.");
return 0;
}
#endif /* USE_PAM */
#endif /* YP */

48
usr.bin/passwd/yppasswd.1 Normal file
View file

@ -0,0 +1,48 @@
.\" $NetBSD: yppasswd.1,v 1.3 2008/04/30 13:11:01 martin Exp $
.\"
.\" Copyright (c) 2005 The NetBSD Foundation, Inc.
.\" All rights reserved.
.\"
.\" This code is derived from software contributed to The NetBSD Foundation
.\" by Jason R. Thorpe.
.\"
.\" 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 THE NETBSD FOUNDATION, INC. 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 THE FOUNDATION 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.
.\"
.Dd February 25, 2005
.Dt YPPASSWD 1
.Os
.Sh NAME
.Nm yppasswd
.Nd modify a user's NIS password
.Sh SYNOPSIS
.Nm
.Op Ar user
.Sh DESCRIPTION
.Nm
changes the user's NIS password.
.Pp
The
.Nm
command is deprecated.
See
.Xr passwd 1
for more information.

View file

@ -3,7 +3,9 @@
/* Modified for ProcFS by Alen Stojanov and David van Moolenbroek */
#define _MINIX 1
#ifndef __NBSD_LIBC
#define _POSIX_SOURCE 1
#endif
#include <stdio.h>
#include <unistd.h>

8
usr.sbin/Makefile Normal file
View file

@ -0,0 +1,8 @@
# Makefile for usr.bin
.include <bsd.own.mk>
# NetBSD imports
SUBDIR= pwd_mkdb user vipw
.include <bsd.subdir.mk>

3
usr.sbin/Makefile.inc Normal file
View file

@ -0,0 +1,3 @@
.include <minix.newlibc.mk>
BINDIR?= /usr/sbin

View file

@ -0,0 +1,19 @@
# from: @(#)Makefile 8.1 (Berkeley) 6/6/93
# $NetBSD: Makefile,v 1.19 2009/01/14 23:18:57 christos Exp $
.include <bsd.own.mk>
PROG= pwd_mkdb
MAN= pwd_mkdb.8
.if defined(__MINIX)
CPPFLAGS+= -I${NETBSDSRCDIR}/lib/nbsd_libc/include
.else
CPPFLAGS+= -I${NETBSDSRCDIR}/lib/libc/include
.endif
.ifndef HOSTPROG
LDADD+= -lutil
DPADD+= ${LIBUTIL}
.endif
.include <bsd.prog.mk>

View file

@ -0,0 +1,219 @@
.\" $NetBSD: pwd_mkdb.8,v 1.28 2010/08/18 10:00:49 wiz Exp $
.\"
.\" Copyright (c) 1991, 1993
.\" The Regents of the University of California. 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.
.\" 3. Neither the name of the University nor the names of its contributors
.\" may be used to endorse or promote products derived from this software
.\" without specific prior written permission.
.\"
.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 THE REGENTS 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.
.\"
.\" from: @(#)pwd_mkdb.8 8.2 (Berkeley) 4/27/95
.\"
.Dd August 18, 2010
.Dt PWD_MKDB 8
.Os
.Sh NAME
.Nm pwd_mkdb
.Nd generate the password databases
.Sh SYNOPSIS
.Nm
.Op Fl BLlpsvw
.Op Fl c Ar cachesize
.Op Fl d Ar directory
.Op Fl u Ar username
.Op Fl V Ar version
.Ar file
.Sh DESCRIPTION
.Nm
creates
.Xr db 3
style secure and insecure databases for the specified file.
These databases are then installed into
.Dq Pa /etc/spwd.db
and
.Dq Pa /etc/pwd.db
respectively.
The file is installed into
.Dq Pa /etc/master.passwd .
The file must be in the correct format (see
.Xr passwd 5 ) .
It is important to note that the format used in this system is
different from the historic Version 7 style format.
.Pp
The options are as follows:
.Bl -tag -width flag
.It Fl B
Store data in big-endian format (see also
.Fl L ) .
.It Fl c Ar cachesize
Specify the size of the memory cache in megabytes used by the
hashing library.
On systems with a large user base, a small cache size can lead to
prohibitively long database file rebuild times.
As a rough guide, the memory usage of
.Nm
in megabytes will be a little bit more than twice the figure
specified here.
If unspecified, this value will be calculated based on the size of
the input file up to a maximum of 8 megabytes.
.It Fl d Ar directory
Change the root directory of the generated files from
.Dq Pa /
to
.Ar directory .
.It Fl L
Store data in little-endian format (see also
.Fl B ) .
.It Fl l
Use
.Xr syslog 3
to report errors.
.It Fl p
Create a Version 7 style password file and install it into
.Dq Pa /etc/passwd .
.It Fl s
Update the secure database only.
This is useful when only encrypted passwords have changed.
This option negates the effect of any
.Fl p
option.
.It Fl u Ar name
Don't re-build the database files, but instead modify or add entries
for the specified user only.
This option may only be used when the line number and user name in
the password file have not changed, or when adding a new user from
the last line in the password file.
.It Fl V Ar version
Upgrade or downgrade databases to the numbered version.
Version
.Dv 0
is the old format (up to and including
.Nx 5.0 )
with the 4 byte time fields and version
.Dv 1
is the new format with the 8 byte time fields (greater than
.Nx 5.0 ) .
.Nx 5.0
cannot read version
.Dv 1
databases.
All versions above
.Nx 5.0
can read and write both version
.Dv 0
and version
.Dv 1
databases.
By default the databases stay in the version they were before the command
was run.
.It Fl v
Mention when a version change occurs.
.It Fl w
Print a warning if the system is using old style databases.
.El
.Pp
The two databases differ in that the secure version contains the user's
encrypted password and the insecure version has an asterisk
.Pq Dq * .
.Pp
The databases are used by the C library password routines (see
.Xr getpwent 3 ) .
.Sh FILES
.Bl -tag -width Pa -compact
.It Pa /etc/master.passwd
The current password file.
.It Pa /etc/passwd
A Version 7 format password file.
.It Pa /etc/pwd.db
The insecure password database file.
.It Pa /etc/pwd.db.tmp
A temporary file.
.It Pa /etc/spwd.db
The secure password database file.
.It Pa /etc/spwd.db.tmp
A temporary file.
.El
.Sh EXIT STATUS
.Nm
exits zero on success, non-zero on failure.
.Sh COMPATIBILITY
Previous versions of the system had a program similar to
.Nm
which built
.Em dbm
style databases for the password file but depended on the calling programs
to install them.
The program was renamed in order that previous users of the program
not be surprised by the changes in functionality.
.Sh SEE ALSO
.Xr chpass 1 ,
.Xr passwd 1 ,
.Xr pwhash 1 ,
.Xr db 3 ,
.Xr getpwent 3 ,
.Xr pw_mkdb 3 ,
.Xr syslog 3 ,
.Xr passwd 5 ,
.Xr useradd 8 ,
.Xr userdel 8 ,
.Xr usermod 8 ,
.Xr vipw 8
.Sh BUGS
Because of the necessity for atomic update of the password files,
.Nm
uses
.Xr rename 2
to install them.
This, however, requires that the file specified on the command line live
on the same file system as the
.Dq Pa /etc
directory.
.Pp
There are the obvious races with multiple people running
.Nm
on different password files at the same time.
The front-ends to
.Xr chpass 1 ,
.Xr passwd 1 ,
.Xr useradd 8 ,
.Xr userdel 8 ,
.Xr usermod 8 ,
and
.Xr vipw 8
handle the locking necessary to avoid this problem.
.Pp
The database files are copied when the
.Fl u
option is used.
Real locking would make this unnecessary.
.Pp
Although the DB format is endian-transparent, the data stored in
the DB is not.
Also, the format doesn't lend itself to insertion or removal of
records from arbitrary locations in the password file.
This is difficult to fix without breaking compatibility.
.Pp
Using the
.Fl u
option on a system where multiple users share the same UID can have
unexpected results.

1065
usr.sbin/pwd_mkdb/pwd_mkdb.c Normal file

File diff suppressed because it is too large Load diff

81
usr.sbin/user/Makefile Normal file
View file

@ -0,0 +1,81 @@
# $NetBSD: Makefile,v 1.12 2009/04/22 15:23:09 lukem Exp $
#
WARNS?= 1 # XXX: -Wsign-compare -Wcast-qual
.include <bsd.own.mk>
CPPFLAGS+= -DEXTENSIONS -DPW_MKDB_ARGC=2
PROG= user
SRCS+= user.c main.c
LINKS+= ${BINDIR}/user ${BINDIR}/useradd
LINKS+= ${BINDIR}/user ${BINDIR}/userdel
LINKS+= ${BINDIR}/user ${BINDIR}/usermod
LINKS+= ${BINDIR}/user ${BINDIR}/group
LINKS+= ${BINDIR}/user ${BINDIR}/groupadd
LINKS+= ${BINDIR}/user ${BINDIR}/groupdel
LINKS+= ${BINDIR}/user ${BINDIR}/groupmod
LINKS+= ${BINDIR}/user ${BINDIR}/userinfo
LINKS+= ${BINDIR}/user ${BINDIR}/groupinfo
LDADD+= -lutil
DPADD+= ${LIBUTIL}
MAN= user.8 useradd.8 userdel.8 usermod.8 userinfo.8 usermgmt.conf.5
MAN+= group.8 groupadd.8 groupdel.8 groupmod.8 groupinfo.8
MLINKS= useradd.8 adduser.8
# this target checks the built-in default group, and, if it doesn't exist,
# creates it
default-group:
@ln -fs ${.OBJDIR}/user ${.OBJDIR}/group; \
defgrp=`${.OBJDIR}/user add -D | \
${TOOL_AWK} '/^group/ { print $$2 }'`; \
if ${.OBJDIR}/group info -e $$defgrp; then \
defgid=`${.OBJDIR}/group info $$defgrp | \
${TOOL_AWK} '/^gid/ { print $$2 }'`; \
else \
defgid=99; \
while [ $$defgid -gt 0 ]; do \
${.OBJDIR}/group info -e $$defgid || break; \
defgid=`expr $$defgid - 1`; \
done; \
if [ $$defgid -eq 0 ]; then \
defgid=100; \
while [ $$defgid -lt 60000 ]; do \
${.OBJDIR}/group info -e $$defgid || break; \
defgid=`expr $$defgid + 1`; \
done; \
if [ $$defgid -eq 60000 ]; then \
echo "No gids left"; \
exit 1; \
fi; \
fi; \
${.OBJDIR}/group add -g $$defgid $$defgrp; \
fi; \
echo "Default group is $$defgrp ($$defgid):"; \
${.OBJDIR}/group info $$defgrp
.include <bsd.prog.mk>
test: ${PROG}
@echo "No news is good news"
@echo "1. Adding new user"
@rm -f useradd
@ln -s user useradd
-./useradd -m -g=uid test1.1
@echo "2. Modifying new user"
-./${PROG} mod -l test1.2 test1.1
@echo "3. Deleting new user"
-./${PROG} del -r test1.2
@echo "4. Attempting to add an invalid user name - IGNORE ANY ERROR"
-./${PROG} add -m test1%1
@echo "5. Bad usage - IGNORE ANY ERROR"
-./${PROG} add -m
@echo "6. Set range defaults"
-./${PROG} add -D -r4000..6000
-./${PROG} add -D
@echo "7. Get user information"
-./${PROG} info root
@echo "8. Bad user name - IGNORE ANY ERROR"
-./${PROG} info test1%1 || echo "User not found"
@echo "All tests completed"

59
usr.sbin/user/defs.h Normal file
View file

@ -0,0 +1,59 @@
/* $NetBSD: defs.h,v 1.6 2005/11/25 08:00:18 agc Exp $ */
/*
* Copyright (c) 1999 Alistair G. Crooks. 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.
* 3. The name of the author may not be used to endorse or promote
* products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 THE AUTHOR 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 DEFS_H_
#define DEFS_H_
#define NEWARRAY(type,ptr,size,action) do { \
if ((ptr = (type *) calloc(sizeof(type), size)) == (type *) NULL) { \
warn("can't allocate %ld bytes", (long)(size * sizeof(type))); \
action; \
} \
} while( /* CONSTCOND */ 0)
#define RENEW(type,ptr,size,action) do { \
if ((ptr = (type *) realloc(ptr, sizeof(type) * size)) == (type *) NULL) { \
warn("can't realloc %ld bytes", (long)(size * sizeof(type))); \
action; \
} \
} while( /* CONSTCOND */ 0)
#define NEW(type, ptr, action) NEWARRAY(type, ptr, 1, action)
#define FREE(ptr) (void) free(ptr)
#ifndef MIN
#define MIN(a,b) (((a) < (b)) ? (a) : (b))
#endif
#ifndef MAX
#define MAX(a,b) (((a) > (b)) ? (a) : (b))
#endif
#endif /* !DEFS_H_ */

89
usr.sbin/user/group.8 Normal file
View file

@ -0,0 +1,89 @@
.\" $NetBSD: group.8,v 1.17 2005/11/25 08:00:18 agc Exp $ */
.\"
.\" Copyright (c) 1999 Alistair G. Crooks. 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.
.\" 3. The name of the author may not be used to endorse or promote
.\" products derived from this software without specific prior written
.\" permission.
.\"
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 THE AUTHOR 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.
.\"
.\"
.Dd November 7, 2005
.Dt GROUP 8
.Os
.Sh NAME
.Nm group
.Nd manage group information on the system
.Sh SYNOPSIS
.Nm
.Cm add
.Op options
.Ar group
.Nm
.Cm del
.Op options
.Ar group
.Nm
.Cm info
.Op options
.Ar group
.Nm
.Cm mod
.Op options
.Ar group
.Sh DESCRIPTION
The
.Nm
utility acts as a frontend to the
.Xr groupadd 8 ,
.Xr groupmod 8 ,
.Xr groupinfo 8 ,
and
.Xr groupdel 8
commands.
The utilities by default are built with
.Dv EXTENSIONS .
This allows for further functionality.
.Pp
For a full explanation of the options available, please see the relevant manual page.
.Sh EXIT STATUS
.Ex -std group
.Sh SEE ALSO
.Xr group 5 ,
.Xr groupadd 8 ,
.Xr groupdel 8 ,
.Xr groupinfo 8 ,
.Xr groupmod 8
.Sh HISTORY
The
.Nm
utility first appeared in
.Nx 1.5 .
It is based on the
.Ar addnerd
package by the same author.
.Sh AUTHORS
The
.Nm
utility was written by
.An Alistair G. Crooks
.Aq agc@NetBSD.org .

87
usr.sbin/user/groupadd.8 Normal file
View file

@ -0,0 +1,87 @@
.\" $NetBSD: groupadd.8,v 1.17 2006/05/29 01:38:33 hubertf Exp $ */
.\"
.\" Copyright (c) 1999 Alistair G. Crooks. 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.
.\" 3. The name of the author may not be used to endorse or promote
.\" products derived from this software without specific prior written
.\" permission.
.\"
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 THE AUTHOR 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.
.\"
.\"
.Dd November 7, 2005
.Dt GROUPADD 8
.Os
.Sh NAME
.Nm groupadd
.Nd add a group to the system
.Sh SYNOPSIS
.Nm
.Op Fl ov
.Op Fl g Ar gid
.Op Fl r Ar lowgid Ns Li .. Ns Ar highgid
.Ar group
.Sh DESCRIPTION
The
.Nm
utility adds a group to the system.
See
.Xr group 8
for more information about
.Dv EXTENSIONS .
The options are as follows:
.Bl -tag -width Ds
.It Fl g Ar gid
Give the numeric group identifier to be used for the new group.
.It Fl o
Allow the new group to have a gid which is already in use for
another group.
.It Fl r Ar lowgid Ns Li .. Ns Ar highgid
Set the low and high bounds of a gid range for new groups.
A new group can only be created if there are gids which can be
assigned inside the range.
This option is included if built with
.Dv EXTENSIONS .
.It Fl v
Enable verbose mode - explain the commands as they are executed.
This option is included if built with
.Dv EXTENSIONS .
.El
.Sh EXIT STATUS
.Ex -std groupadd
.Sh SEE ALSO
.Xr group 5 ,
.Xr group 8 ,
.Xr user 8
.Sh HISTORY
The
.Nm
utility first appeared in
.Nx 1.5 .
It is based on the
.Ar addnerd
package by the same author.
.Sh AUTHORS
The
.Nm
utility was written by
.An Alistair G. Crooks
.Aq agc@NetBSD.org .

74
usr.sbin/user/groupdel.8 Normal file
View file

@ -0,0 +1,74 @@
.\" $NetBSD: groupdel.8,v 1.14 2006/05/29 01:38:33 hubertf Exp $ */
.\"
.\" Copyright (c) 1999 Alistair G. Crooks. 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.
.\" 3. The name of the author may not be used to endorse or promote
.\" products derived from this software without specific prior written
.\" permission.
.\"
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 THE AUTHOR 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.
.\"
.\"
.Dd November 7, 2005
.Dt GROUPDEL 8
.Os
.Sh NAME
.Nm groupdel
.Nd remove a group from the system
.Sh SYNOPSIS
.Nm
.Op Fl v
.Ar group
.Sh DESCRIPTION
The
.Nm
utility removes a group from the system.
See
.Xr group 8
for more information about
.Dv EXTENSIONS .
The options are as follows:
.Bl -tag -width Ds
.It Fl v
Enable verbose mode - explain the commands as they are executed.
This option is included if built with
.Dv EXTENSIONS .
.El
.Sh EXIT STATUS
.Ex -std groupdel
.Sh SEE ALSO
.Xr group 5 ,
.Xr group 8 ,
.Xr user 8
.Sh HISTORY
The
.Nm
utility first appeared in
.Nx 1.5 .
It is based on the
.Ar addnerd
package by the same author.
.Sh AUTHORS
The
.Nm
utility was written by
.An Alistair G. Crooks
.Aq agc@NetBSD.org .

90
usr.sbin/user/groupinfo.8 Normal file
View file

@ -0,0 +1,90 @@
.\" $NetBSD: groupinfo.8,v 1.12 2006/05/29 01:38:33 hubertf Exp $ */
.\"
.\" Copyright (c) 1999 Alistair G. Crooks. 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.
.\" 3. The name of the author may not be used to endorse or promote
.\" products derived from this software without specific prior written
.\" permission.
.\"
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 THE AUTHOR 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.
.\"
.\"
.Dd November 7, 2005
.Dt GROUPINFO 8
.Os
.Sh NAME
.Nm groupinfo
.Nd displays group information
.Sh SYNOPSIS
.Nm
.Op Fl ev
.Ar group
.Sh DESCRIPTION
The
.Nm
utility retrieves the group information from the system.
The
.Nm
utility is only available if built with
.Dv EXTENSIONS .
See
.Xr group 8
for more information.
.Pp
The following command line options are recognised:
.Bl -tag -width Ds
.It Fl e
Return 0 if the group exists, and non-zero if the
group does not exist, on the system.
No information is displayed.
This form of the command is useful for
scripts which need to check whether a particular group
name or gid is already in use on the system.
.It Fl v
Perform any actions in a verbose manner.
.El
.Pp
The
.Ar group
argument may either be a group's name, or a gid.
.Sh EXIT STATUS
.Ex -std groupinfo
.Sh FILES
.Bl -tag -width /etc/usermgmt.conf -compact
.It Pa /etc/usermgmt.conf
.El
.Sh SEE ALSO
.Xr passwd 5 ,
.Xr group 8
.Sh HISTORY
The
.Nm
utility first appeared in
.Nx 1.5 .
It is based on the
.Ar addnerd
package by the same author.
.Sh AUTHORS
The
.Nm
utility was written by
.An Alistair G. Crooks
.Aq agc@NetBSD.org .

83
usr.sbin/user/groupmod.8 Normal file
View file

@ -0,0 +1,83 @@
.\" $NetBSD: groupmod.8,v 1.14 2005/11/25 08:00:18 agc Exp $ */
.\"
.\" Copyright (c) 1999 Alistair G. Crooks. 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.
.\" 3. The name of the author may not be used to endorse or promote
.\" products derived from this software without specific prior written
.\" permission.
.\"
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 THE AUTHOR 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.
.\"
.\"
.Dd November 7, 2005
.Dt GROUPMOD 8
.Os
.Sh NAME
.Nm groupmod
.Nd modify an existing group on the system
.Sh SYNOPSIS
.Nm
.Op Fl ov
.Op Fl g Ar gid
.Op Fl n Ar newname
.Ar group
.Sh DESCRIPTION
The
.Nm
utility modifies an existing group on the system.
See
.Xr group 8
for more information about
.Dv EXTENSIONS .
The options are as follows:
.Bl -tag -width Ds
.It Fl g Ar gid
Give the numeric group identifier to be used for the new group.
.It Fl n Ar new-group-name
Give the new name which the group shall have.
.It Fl o
Allow the new group to have a gid which is already in use for
another group.
.It Fl v
Enable verbose mode - explain the commands as they are executed.
This option is included if built with
.Dv EXTENSIONS .
.El
.Sh EXIT STATUS
.Ex -std groupmod
.Sh SEE ALSO
.Xr group 5 ,
.Xr group 8 ,
.Xr user 8
.Sh HISTORY
The
.Nm
utility first appeared in
.Nx 1.5 .
It is based on the
.Ar addnerd
package by the same author.
.Sh AUTHORS
The
.Nm
utility was written by
.An Alistair G. Crooks
.Aq agc@NetBSD.org .

99
usr.sbin/user/main.c Normal file
View file

@ -0,0 +1,99 @@
/* $NetBSD: main.c,v 1.5 2006/10/22 21:16:58 christos Exp $ */
/*
* Copyright (c) 1999 Alistair G. Crooks. 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.
* 3. The name of the author may not be used to endorse or promote
* products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 THE AUTHOR 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.
*/
#include <err.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "usermgmt.h"
enum {
MaxCmdWords = 2
};
/* this struct describes a command */
typedef struct cmd_t {
int c_wc; /* word count */
const char *c_word[MaxCmdWords]; /* command words */
int (*c_func)(int, char **); /* called function */
} cmd_t;
/* despatch table for commands */
static cmd_t cmds[] = {
{ 1, { "useradd", NULL }, useradd },
{ 2, { "user", "add" }, useradd },
{ 1, { "usermod", NULL }, usermod },
{ 2, { "user", "mod" }, usermod },
{ 1, { "userdel", NULL }, userdel },
{ 2, { "user", "del" }, userdel },
#ifdef EXTENSIONS
{ 1, { "userinfo", NULL }, userinfo },
{ 2, { "user", "info" }, userinfo },
#endif
{ 1, { "groupadd", NULL }, groupadd },
{ 2, { "group", "add" }, groupadd },
{ 1, { "groupmod", NULL }, groupmod },
{ 2, { "group", "mod" }, groupmod },
{ 1, { "groupdel", NULL }, groupdel },
{ 2, { "group", "del" }, groupdel },
#ifdef EXTENSIONS
{ 1, { "groupinfo", NULL }, groupinfo },
{ 2, { "group", "info" }, groupinfo },
#endif
{ .c_wc = 0 }
};
int
main(int argc, char **argv)
{
cmd_t *cmdp;
int matched;
int i;
for (cmdp = cmds ; cmdp->c_wc > 0 ; cmdp++) {
for (matched = i = 0 ; i < cmdp->c_wc && i < MaxCmdWords ; i++) {
if (argc > i) {
if (strcmp((i == 0) ? getprogname() : argv[i],
cmdp->c_word[i]) == 0) {
matched += 1;
} else {
break;
}
}
}
if (matched == cmdp->c_wc) {
return (*cmdp->c_func)(argc - (matched - 1), argv + (matched - 1));
}
}
usermgmt_usage(getprogname());
errx(EXIT_FAILURE, "Program `%s' not recognised", getprogname());
/* NOTREACHED */
}

17
usr.sbin/user/out Normal file
View file

@ -0,0 +1,17 @@
chown: /home/test1.1/.ashrc: invalid argument
chown: /home/test1.1/.ellepro.b1: invalid argument
chown: /home/test1.1/.ellepro.e: invalid argument
chown: /home/test1.1/.exrc: invalid argument
chown: /home/test1.1/.profile: invalid argument
chown: /home/test1.1: invalid argument
useradd: Error running `/usr/sbin/chown -R -h 4000:4000 /home/test1.1': no such file or directory
user: User `test1.2' doesn't own directory `/home/test1.1', not removed
user: Can't add user `test1%1': invalid login name
usage: useradd -D [-F] [-b base-dir] [-e expiry-time] [-f inactive-time]
[-g gid | name | =uid] [-k skel-dir] [-L login-class]
[-M homeperm] [-r lowuid..highuid] [-s shell]
usage: useradd [-moSv] [-b base-dir] [-c comment] [-d home-dir] [-e expiry-time]
[-f inactive-time] [-G secondary-group] [-g gid | name | =uid]
[-k skeletondir] [-L login-class] [-M homeperm] [-p password]
[-r lowuid..highuid] [-s shell] [-u uid] user
user: Can't find user `test1%1'

115
usr.sbin/user/user.8 Normal file
View file

@ -0,0 +1,115 @@
.\" $NetBSD: user.8,v 1.23 2005/11/25 08:00:18 agc Exp $ */
.\"
.\" Copyright (c) 1999 Alistair G. Crooks. 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.
.\" 3. The name of the author may not be used to endorse or promote
.\" products derived from this software without specific prior written
.\" permission.
.\"
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 THE AUTHOR 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.
.\"
.\"
.Dd November 16, 2005
.Dt USER 8
.Os
.Sh NAME
.Nm user
.Nd manage user login information on the system
.Sh SYNOPSIS
.Nm
.Cm add
.Fl D
.Op options
.Nm
.Cm add
.Op options
.Ar user
.Nm
.Cm del
.Fl D
.Op options
.Nm
.Cm del
.Op options
.Ar user
.Nm
.Cm info
.Op options
.Ar user
.Nm
.Cm mod
.Op options
.Ar user
.Sh DESCRIPTION
The
.Nm
utility acts as a frontend to the
.Xr useradd 8 ,
.Xr usermod 8 ,
.Xr userinfo 8 ,
and
.Xr userdel 8
commands.
The utilities by default are built with
.Dv EXTENSIONS .
This allows for further functionality.
.Pp
For a full explanation of the options available, please see the relevant manual page.
.Sh EXIT STATUS
.Ex -std user
.Sh FILES
.Bl -tag -width /usr/share/examples/usermgmt -compact
.It Pa /etc/skel/.[A-z]*
Skeleton files for new user
.It Pa /etc/usermgmt.conf
Configuration file for
.Nm ,
.Xr group 8
and the backend commands mentioned above.
.\" .It Pa /usr/share/examples/usermgmt
.\" A directory containing examples for
.\" .Nm
.\" and
.\" .Xr group 8 .
.El
.Sh SEE ALSO
.Xr chpass 1 ,
.Xr group 5 ,
.Xr passwd 5 ,
.Xr usermgmt.conf 5 ,
.Xr useradd 8 ,
.Xr userdel 8 ,
.Xr userinfo 8 ,
.Xr usermod 8
.Sh HISTORY
The
.Nm
utility first appeared in
.Nx 1.5 .
It is based on the
.Ar addnerd
package by the same author.
.Sh AUTHORS
The
.Nm
utility was written by
.An Alistair G. Crooks
.Aq agc@NetBSD.org .

2561
usr.sbin/user/user.c Normal file

File diff suppressed because it is too large Load diff

318
usr.sbin/user/useradd.8 Normal file
View file

@ -0,0 +1,318 @@
.\" $NetBSD: useradd.8,v 1.42 2009/01/14 02:18:28 reed Exp $ */
.\"
.\"
.\" Copyright (c) 1999 Alistair G. Crooks. 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.
.\" 3. The name of the author may not be used to endorse or promote
.\" products derived from this software without specific prior written
.\" permission.
.\"
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 THE AUTHOR 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.
.\"
.\"
.Dd January 13, 2009
.Dt USERADD 8
.Os
.Sh NAME
.Nm useradd
.Nd add a user to the system
.Sh SYNOPSIS
.Nm
.Fl D
.Op Fl F
.Op Fl b Ar base-dir
.Op Fl e Ar expiry-time
.Op Fl f Ar inactive-time
.Op Fl g Ar gid | name | Li =uid
.Op Fl k Ar skel-dir
.Op Fl L Ar login-class
.Op Fl M Ar home-perm
.Op Fl r Ar lowuid Ns Li .. Ns Ar highuid
.Op Fl s Ar shell
.Nm
.Op Fl moSv
.Op Fl b Ar base-dir
.Op Fl c Ar comment
.Op Fl d Ar home-dir
.Op Fl e Ar expiry-time
.Op Fl f Ar inactive-time
.Op Fl G Ar secondary-group
.Op Fl g Ar gid | name | Li =uid
.Op Fl k Ar skel-dir
.Op Fl L Ar login-class
.Op Fl M Ar home-perm
.Op Fl p Ar password
.Op Fl r Ar lowuid Ns Li .. Ns Ar highuid
.Op Fl s Ar shell
.Op Fl u Ar uid
.Ar user
.Sh DESCRIPTION
The
.Nm useradd
utility adds a user to the system, creating and
populating a home directory if necessary.
Any skeleton files will be provided
for the new user if they exist in the
.Ar skel-dir
directory (see the
.Fl k
option).
Default values for
the base directory,
the time of password expiry,
the time of account expiry,
primary group,
the skeleton directory,
the range from which the uid will be allocated,
and default login shell
can be provided in the
.Pa /etc/usermgmt.conf
file, which, if running as root, is created using the built-in defaults if
it does not exist.
.Pp
The first form of the command shown above (using the
.Fl D
option)
sets and displays the defaults for the
.Nm
utility.
.Pp
See
.Xr user 8
for more information about
.Dv EXTENSIONS .
.Bl -tag -width Ds
.It Fl b Ar base-dir
Set the default base directory.
This is the directory to which the
user directory is added, which will be created if the
.Fl m
option is specified and no
.Fl d
option is specified.
.It Fl D
without any further options,
.Fl D
will show the current defaults which
will be used by the
.Nm
utility.
Together with one of the options shown for the first version
of the command,
.Fl D
will set the default to be the new value.
See
.Xr usermgmt.conf 5
for more information.
.It Fl e Ar expiry-time
Set the time at which the new user accounts will expire.
It should be entered in the form
.Dq month day year ,
where month is the month name (the first three characters are
sufficient), day is the day of the month, and year is the year.
Time in seconds since the epoch (UTC) is also valid.
A value of 0 can be used to disable this feature.
.It Fl F
Force the user to change their password upon next login.
.It Fl f Ar inactive-time
Set the time at which passwords for the new user accounts will
expire.
Also see the
.Fl e
option above.
.It Fl g Ar gid | groupname | Li =uid
Set the default group for new users.
.It Fl k Ar skel-dir
Set the skeleton directory in which to find files with
which to populate new users' home directories.
.It Fl L Ar login-class
Set the default login class for new users.
See
.Xr login.conf 5
for more information on user login classes.
This option is included if built with
.Dv EXTENSIONS .
.It Fl M Ar home-perm
sets the default permissions of the newly created home directory if
.Fl m
is given.
The permission is specified as an octal number, with or without a leading zero.
.It Fl r Ar lowuid Ns Li .. Ns Ar highuid
Set the low and high bounds of uid ranges for new users.
A new user can only be created if there are uids which can be
assigned from one of the free ranges.
This option is included if built with
.Dv EXTENSIONS .
.It Fl s Ar shell
Set the default login shell for new users.
.El
.Pp
In the second form of the command,
after setting any defaults, and then reading values from
.Pa /etc/usermgmt.conf ,
the following command line options are processed:
.Bl -tag -width Ds
.It Fl b Ar base-directory
Set the base directory name, in which the user's new home
directory will be created, should the
.Fl m
option be specified.
.It Fl c Ar comment
Set the comment field (also, for historical reasons known as the
GECOS field) which will be added for the user, and typically will include
the user's full name, and, perhaps, contact information for the user.
.It Fl d Ar home-directory
Set the home directory which will be created and populated for the user,
should the
.Fl m
option be specified.
.It Fl e Ar expiry-time
Set the time at which the current password will expire for new
users.
It should be entered in the form
.Dq month day year ,
where month is the month name (the first three characters are
sufficient), day is the day of the month, and year is the year.
Time in seconds since the epoch (UTC) is also valid.
A value of 0 can be used to disable this feature.
See
.Xr passwd 5
for more details.
.It Fl f Ar inactive-time
Set the time at which new user accounts will expire.
Also see the
.Fl e
option above.
.It Fl G Ar secondary-group
Add the user to the secondary group
.Ar secondary-group
in the
.Pa /etc/group
file.
The
.Ar secondary-group
may be a comma-delimited list for multiple groups.
Or the option may be repeated for multiple groups.
(16 groups maximum.)
.It Fl g Ar gid | name | Li =uid
Give the group name or identifier to be used for the new user's primary group.
If this is
.Ql =uid ,
then a uid and gid will be picked which are both unique
and the same, and a line added to
.Pa /etc/group
to describe the new group.
.It Fl k Ar skeleton directory
Give the skeleton directory in which to find files
with which to populate the new user's home directory.
.It Fl L Ar login-class
Set the login class for the user being created.
See
.Xr login.conf 5
for more information on user login classes.
This option is included if built with
.Dv EXTENSIONS .
.It Fl M Ar home-perm
sets the permissions of the newly created home directory if
.Fl m
is given.
The permission is specified as an octal number, with or without a leading zero.
.It Fl m
Create a new home directory for the new user.
.It Fl o
Allow the new user to have a uid which is already in use for another user.
.It Fl p Ar password
Specify an already-encrypted password for the new user.
Encrypted passwords can be generated with
.Xr pwhash 1 .
The password can be changed later by using
.Xr chpass 1
or
.Xr passwd 1 .
This option is included if built with
.Dv EXTENSIONS .
.It Fl S
Allow samba user names with a trailing dollar sign to be
added to the system.
This option is included if built with
.Dv EXTENSIONS .
.It Fl s Ar shell
Specify the login shell for the new user.
.It Fl u Ar uid
Specify a uid for the new user.
Boundaries for this value can be preset for all users
by using the
.Ar range
field in the
.Pa /etc/usermgmt.conf
file.
.It Fl v
Enable verbose mode - explain the commands as they are executed.
This option is included if built with
.Dv EXTENSIONS .
.El
.Pp
Once the information has been verified,
.Nm
uses
.Xr pwd_mkdb 8
to update the user database.
This is run in the background, and,
at very large sites could take several minutes.
Until this update
is completed, the password file is unavailable for other updates
and the new information is not available to programs.
.Sh EXIT STATUS
.Ex -std useradd
.Sh FILES
.Bl -tag -width /etc/usermgmt.conf -compact
.It Pa /etc/usermgmt.conf
.It Pa /etc/skel/*
.It Pa /etc/login.conf
.El
.Sh SEE ALSO
.Xr chpass 1 ,
.Xr passwd 1 ,
.Xr pwhash 1 ,
.Xr group 5 ,
.Xr login.conf 5 ,
.Xr passwd 5 ,
.Xr usermgmt.conf 5 ,
.Xr pwd_mkdb 8 ,
.Xr user 8 ,
.Xr userdel 8 ,
.Xr usermod 8
.Sh HISTORY
The
.Nm
utility first appeared in
.Nx 1.5 .
It is based on the
.Ar addnerd
package by the same author.
.Sh AUTHORS
The
.Nm
utility was written by
.An Alistair G. Crooks
.Aq agc@NetBSD.org .
.Pp
Support for setting permissions of home directories was added by Hubert Feyrer.

168
usr.sbin/user/userdel.8 Normal file
View file

@ -0,0 +1,168 @@
.\" $NetBSD: userdel.8,v 1.32 2006/05/29 01:38:33 hubertf Exp $ */
.\"
.\" Copyright (c) 1999 Alistair G. Crooks. 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.
.\" 3. The name of the author may not be used to endorse or promote
.\" products derived from this software without specific prior written
.\" permission.
.\"
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 THE AUTHOR 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.
.\"
.\"
.Dd November 16, 2005
.Dt USERDEL 8
.Os
.Sh NAME
.Nm userdel
.Nd remove a user from the system
.Sh SYNOPSIS
.Nm
.Fl D
.Op Fl p Ar preserve-value
.Nm
.Op Fl rSv
.Op Fl p Ar preserve-value
.Ar user
.Sh DESCRIPTION
The
.Nm
utility removes a user from the system, optionally
removing that user's home directory and any subdirectories.
.Pp
Default values are taken from the information provided in the
.Pa /etc/usermgmt.conf
file, which, if running as root, is created using the built-in
defaults if it does not exist.
.Pp
The first form of the command shown above (using the
.Fl D
option) sets and displays the defaults for the
.Nm
utility.
.Pp
See
.Xr user 8
for more information about
.Dv EXTENSIONS .
.Bl -tag -width Ds
.It Fl D
Without any further options,
.Fl D
will show the current defaults which will be used by the
.Nm
utility.
Together with one of the options shown for the first version
of the command,
.Fl D
will set the default to be the new value.
This option is included if built with
.Dv EXTENSIONS .
.It Fl p Ar preserve-value
Set the preservation value.
If this value is one of
.Ql true ,
.Ql yes ,
or a non-zero number, then the user login information will be
preserved.
This option is included if built with
.Dv EXTENSIONS .
.El
.Pp
In the second form of the command,
after setting any defaults, and then reading values from
.Pa /etc/usermgmt.conf ,
the following command line options are processed:
.Bl -tag -width Ds
.It Fl p Ar preserve-value
Preserve the user information in the password file,
but do not allow the user to login, by switching the
password to an
.Dq impossible
one, and by setting the user's shell to the
.Xr nologin 8
program.
This option can be helpful in preserving a user's
files for later use by members of that person's
group after the user has moved on.
This value can also be set in the
.Pa /etc/usermgmt.conf
file, using the
.Ql preserve
field.
If the field has any of the values
.Ql true ,
.Ql yes ,
or a non-zero number, then user information preservation will take
place.
This option is included if built with
.Dv EXTENSIONS .
.It Fl r
Remove the user's home directory, any subdirectories,
and any files and other entries in them.
.It Fl S
Allow a samba user name (with a trailing dollar sign)
to be deleted.
This option is included if built with
.Dv EXTENSIONS .
.It Fl v
Perform any actions in a verbose manner.
This option is included if built with
.Dv EXTENSIONS .
.El
.Pp
Once the information has been verified,
.Nm
uses
.Xr pwd_mkdb 8
to update the user database.
This is run in the background, and,
at very large sites could take several minutes.
Until this update
is completed, the password file is unavailable for other updates
and the new information is not available to programs.
.Sh EXIT STATUS
.Ex -std userdel
.Sh FILES
.Bl -tag -width /etc/usermgmt.conf -compact
.It Pa /etc/usermgmt.conf
.El
.Sh SEE ALSO
.Xr passwd 5 ,
.Xr usermgmt.conf 5 ,
.Xr group 8 ,
.Xr nologin 8 ,
.Xr pwd_mkdb 8 ,
.Xr user 8 ,
.Xr useradd 8
.Sh HISTORY
The
.Nm
utility first appeared in
.Nx 1.5 .
It is based on the
.Ar addnerd
package by the same author.
.Sh AUTHORS
The
.Nm
utility was written by
.An Alistair G. Crooks
.Aq agc@NetBSD.org .

87
usr.sbin/user/userinfo.8 Normal file
View file

@ -0,0 +1,87 @@
.\" $NetBSD: userinfo.8,v 1.15 2008/02/27 19:12:56 reed Exp $ */
.\"
.\" Copyright (c) 1999 Alistair G. Crooks. 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.
.\" 3. The name of the author may not be used to endorse or promote
.\" products derived from this software without specific prior written
.\" permission.
.\"
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 THE AUTHOR 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.
.\"
.\"
.Dd November 16, 2005
.Dt USERINFO 8
.Os
.Sh NAME
.Nm userinfo
.Nd displays user information
.Sh SYNOPSIS
.Nm
.Op Fl e
.Ar user
.Sh DESCRIPTION
The
.Nm
utility retrieves the user information from the system.
The
.Nm
utility is only available if built with
.Dv EXTENSIONS .
See
.Xr user 8
for more information.
.Pp
The following command line option is recognised:
.Bl -tag -width Ds
.It Fl e
Return 0 if the user exists, and non-zero if the
user does not exist, on the system.
No information is displayed.
This form of the command is useful for
scripts which need to check whether a particular user
name or uid is already in use on the system.
.El
.Pp
The
.Ar user
argument may either be a user's name, or a uid.
.Sh EXIT STATUS
.Ex -std userinfo
.Sh SEE ALSO
.Xr passwd 5 ,
.Xr group 8 ,
.Xr user 8 ,
.Xr useradd 8 ,
.Xr userdel 8
.Sh HISTORY
The
.Nm
utility first appeared in
.Nx 1.5 .
It is based on the
.Ar addnerd
package by the same author.
.Sh AUTHORS
The
.Nm
utility was written by
.An Alistair G. Crooks
.Aq agc@NetBSD.org .

View file

@ -0,0 +1,155 @@
.\" $NetBSD: usermgmt.conf.5,v 1.7 2009/12/31 20:14:19 wiz Exp $
.\"
.\" Copyright (c) 2002 The NetBSD Foundation, Inc.
.\" All rights reserved.
.\"
.\" This document is derived from works contributed to The NetBSD Foundation
.\" by Grant Beattie.
.\"
.\" 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. The name of the author may not be used to endorse or promote products
.\" derived from this software without specific prior written permission.
.\"
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 THE AUTHOR 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.
.\"
.Dd December 31, 2009
.Dt USERMGMT.CONF 5
.Os
.\" turn off hyphenation
.hym 999
.Sh NAME
.Nm usermgmt.conf
.Nd user management tools configuration file
.Sh SYNOPSIS
.Nm usermgmt.conf
.Sh DESCRIPTION
The
.Nm usermgmt.conf
file defines the default values used by the user management tools,
.Xr useradd 8
and friends.
.Pp
Options in this file can be set by manually editing
.Pa /etc/usermgmt.conf
or using the
.Fl D
option to
.Xr useradd 8 .
.Pp
.Bl -tag -width preserveX
.It Ic base_dir
sets the base directory name, in which new users' home directories
are created when using the
.Fl m
option to
.Xr useradd 8 .
.It Ic class
sets the default login class for new users.
See
.Xr login.conf 5
for more information on user login classes.
.It Ic expire
sets the default time at which the current password expires.
This can be used to implement password aging.
Both the
.Ar expire
and
.Ar inactive
fields should be entered in the form
.Dq month day year ,
where month is the month name (the first three characters are
sufficient), day is the day of the month, and year is the year.
Time in seconds since the epoch (UTC) is also valid.
A value of 0 can be used to disable this feature.
.It Ic group
sets the default primary group for new users.
If this is
.Ql =uid ,
then a uid and gid will be picked which are both unique
and the same, and a line will be added to
.Pa /etc/group
to describe the new group.
It has the format:
.br
.Bd -ragged -offset indent -compact
.Ic group
.Ar gid | name | Li =uid
.Ed
.It Ic homeperm
sets the default permissions of the newly created home directory if
.Fl m
is given to
.Xr useradd 8 .
The permission is specified as an octal number, with or without a leading zero.
.It Ic inactive
sets the default time at which new accounts expire.
A value of 0 can be used to disable this feature.
Also see the
.Ar expire
field.
.It Ic password
specifies an already-encrypted default password.
.It Ic preserve
If this value is one of
.Ql true ,
.Ql yes ,
or a non-zero number, then the user login information will be
preserved when removing a user with
.Xr userdel 8 .
.It Ic range
specifies the uid boundaries for new users.
If unspecified, the default is
.Dq 1000..60000 .
It has the format:
.Bd -unfilled -offset indent -compact
.Ic range Ar starting-uid Ns Li .. Ns Ar ending-uid
.Ed
.It Ic gid_range
specifies the gid boundaries for new groups.
If unspecified, the default is
.Dq 1000..60000 .
It has the format:
.Bd -unfilled -offset indent -compact
.Ic gid_range Ar starting-gid Ns Li .. Ns Ar ending-gid
.Ed
.It Ic shell
sets the default login shell for new users.
.It Ic skel_dir
sets the default skeleton directory in which to find files
with which to populate the new user's home directory.
.El
.Sh FILES
.Bl -tag -width /etc/usermgmt.conf -compact
.It Pa /etc/usermgmt.conf
.It Pa /etc/skel/*
.It Pa /etc/login.conf
.El
.Sh SEE ALSO
.Xr login.conf 5 ,
.Xr passwd 5 ,
.Xr user 8 ,
.Xr useradd 8 ,
.Xr userdel 8 ,
.Xr usermod 8
.Sh HISTORY
The
.Nm
configuration file first appeared in
.Nx 1.5 .

47
usr.sbin/user/usermgmt.h Normal file
View file

@ -0,0 +1,47 @@
/* $NetBSD: usermgmt.h,v 1.8 2005/11/25 08:00:18 agc Exp $ */
/*
* Copyright (c) 1999 Alistair G. Crooks. 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.
* 3. The name of the author may not be used to endorse or promote
* products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 THE AUTHOR 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 USERMGMT_H_
#define USERMGMT_H_
int useradd(int, char **);
int usermod(int, char **);
int userdel(int, char **);
int groupadd(int, char **);
int groupdel(int, char **);
int groupmod(int, char **);
#ifdef EXTENSIONS
int userinfo(int, char **);
int groupinfo(int, char **);
#endif
void usermgmt_usage(const char *);
#endif

259
usr.sbin/user/usermod.8 Normal file
View file

@ -0,0 +1,259 @@
.\" $NetBSD: usermod.8,v 1.32 2009/03/11 17:54:03 dyoung Exp $ */
.\"
.\" Copyright (c) 1999 Alistair G. Crooks. 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.
.\" 3. The name of the author may not be used to endorse or promote
.\" products derived from this software without specific prior written
.\" permission.
.\"
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 THE AUTHOR 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.
.\"
.\"
.Dd January 13, 2009
.Dt USERMOD 8
.Os
.Sh NAME
.Nm usermod
.Nd modify user login information
.Sh SYNOPSIS
.Nm
.Op Fl FmoSv
.Op Fl C Ar yes/no
.Op Fl c Ar comment
.Op Fl d Ar home-dir
.Op Fl e Ar expiry-time
.Op Fl f Ar inactive-time
.Op Fl G Ar secondary-group
.Op Fl g Ar gid | name | Li =uid
.Op Fl L Ar login-class
.Op Fl l Ar new-login
.Op Fl p Ar password
.Op Fl s Ar shell
.Op Fl u Ar uid
.Ar user
.Sh DESCRIPTION
The
.Nm
utility modifies user login information on the system.
.Pp
Default values are taken from the information provided in the
.Pa /etc/usermgmt.conf
file, which, if running as root, is created using the built-in defaults if
it does not exist.
.Pp
See
.Xr user 8
for more information about
.Dv EXTENSIONS .
.Pp
After setting any defaults, and then reading values from
.Pa /etc/usermgmt.conf ,
the following command line options are processed:
.Bl -tag -width Ds
.It Fl C Ar yes/no
Enable user accounts to be temporary locked/closed.
The
.Ar yes/no
operand can be given as
.Dq Ar yes
to lock the account or
.Dq Ar no
to unlock the account.
.It Fl c Ar comment
Set the comment field (also, for historical reasons known as the
GECOS field) for the user.
The comment field will typically include
the user's full name and, perhaps, contact information for the user.
.It Fl d Ar home-directory
Set the home directory without populating it; if the
.Fl m
option is specified, tries to move the old home directory to
.Ar home-directory .
.It Fl e Ar expiry-time
Set the time at which the account expires.
This can be used to implement password aging.
It should be entered in the form
.Dq month day year ,
where month is the month name (the first three characters are
sufficient), day is the day of the month, and year is the year.
Time in seconds since the epoch (UTC) is also valid.
A value of 0 can be used to disable this feature.
This value can be preset for all users using the
.Ar expire
field in the
.Pa /etc/usermgmt.conf
file.
See
.Xr usermgmt.conf 5
for more details.
.It Fl F
Force the user to change their password upon next login.
.It Fl f Ar inactive-time
Set the time at which the password expires.
See the
.Fl e
option.
.It Fl G Ar secondary-group
Specify a secondary group to which the user will be added in the
.Pa /etc/group
file.
The
.Ar secondary-group
may be a comma-delimited list for multiple groups.
Or the option may be repeated for multiple groups.
(16 groups maximum.)
.It Fl g Ar gid | name | Li =uid
Give the group name or identifier to be used for the user's primary group.
If this is
.Ql =uid ,
then a uid and gid will be picked which are both unique
and the same, and a line will be added to
.Pa /etc/group
to describe the new group.
This value can be preset for all users by using the
.Ar group
field in the
.Pa /etc/usermgmt.conf
file.
See
.Xr usermgmt.conf 5
for more details.
.It Fl L Ar login-class
Set the login class for the user.
See
.Xr login.conf 5
for more information on user login classes.
This value can be preset for all users by using the
.Ar class
field in the
.Pa /etc/usermgmt.conf
file.
See
.Xr usermgmt.conf 5
for more details.
This option is included if built with
.Dv EXTENSIONS .
.It Fl l Ar new-user
Give the new user name.
It can consist of alphanumeric characters and the characters
.Ql \&. ,
.Ql \&- ,
and
.Ql \&_ .
.It Fl m
Move the home directory from its old position to the new one.
If
.Fl d
is not specified, the
.Ar new-user
argument of the
.Fl l
option is used; one of
.Fl d
and
.Fl l
is needed.
.It Fl o
Allow duplicate uids to be given.
.It Fl p Ar password
Specify an already-encrypted password for the user.
This password can then be changed by using the
.Xr chpass 1
utility.
This value can be preset for all users by using the
.Ar password
field in the
.Pa /etc/usermgmt.conf
file.
See
.Xr usermgmt.conf 5
for more details.
This option is included if built with
.Dv EXTENSIONS .
.It Fl S
Allow samba user names with a trailing dollar sign to be modified.
This option is included if built with
.Dv EXTENSIONS .
.It Fl s Ar shell
Specify the login shell for the user.
This value can be preset for all users by using the
.Ar shell
field in the
.Pa /etc/usermgmt.conf
file.
See
.Xr usermgmt.conf 5
for more details.
.It Fl u Ar uid
Specify a new uid for the user.
Boundaries for this value can be preset for all users by using the
.Ar range
field in the
.Pa /etc/usermgmt.conf
file.
See
.Xr usermgmt.conf 5
for more details.
.It Fl v
Enable verbose mode - explain the commands as they are executed.
This option is included if built with
.Dv EXTENSIONS .
.El
.Pp
Once the information has been verified,
.Nm
uses
.Xr pwd_mkdb 8
to update the user database.
This is run in the background.
At very large sites this can take several minutes.
Until this update
is completed, the password file is unavailable for other updates
and the new information is not available to programs.
.Sh EXIT STATUS
.Ex -std usermod
.Sh FILES
.Bl -tag -width /etc/usermgmt.conf -compact
.It Pa /etc/usermgmt.conf
.El
.Sh SEE ALSO
.Xr chpass 1 ,
.Xr group 5 ,
.Xr passwd 5 ,
.Xr usermgmt.conf 5 ,
.Xr pwd_mkdb 8 ,
.Xr user 8 ,
.Xr useradd 8 ,
.Xr userdel 8
.Sh HISTORY
The
.Nm
utility first appeared in
.Nx 1.5 .
It is based on the
.Ar addnerd
package by the same author.
.Sh AUTHORS
The
.Nm
utility was written by
.An Alistair G. Crooks
.Aq agc@NetBSD.org .

10
usr.sbin/vipw/Makefile Normal file
View file

@ -0,0 +1,10 @@
# $NetBSD: Makefile,v 1.5 1996/05/15 23:23:45 jtc Exp $
# @(#)Makefile 8.1 (Berkeley) 6/6/93
PROG= vipw
SRCS= vipw.c
DPADD= ${LIBUTIL}
LDADD= -lutil
MAN= vipw.8
.include <bsd.prog.mk>

122
usr.sbin/vipw/vipw.8 Normal file
View file

@ -0,0 +1,122 @@
.\" $NetBSD: vipw.8,v 1.15 2005/09/05 03:37:15 hubertf Exp $
.\"
.\" Copyright (c) 1983, 1991, 1993
.\" The Regents of the University of California. 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.
.\" 3. Neither the name of the University nor the names of its contributors
.\" may be used to endorse or promote products derived from this software
.\" without specific prior written permission.
.\"
.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 THE REGENTS 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.
.\"
.\" @(#)vipw.8 8.1 (Berkeley) 6/6/93
.\"
.Dd September 4, 2005
.Dt VIPW 8
.Os
.Sh NAME
.Nm vipw
.Nd edit the password file
.Sh SYNOPSIS
.Nm
.Bk -words
.Op Fl d Ar directory
.Ek
.Sh DESCRIPTION
.Nm
edits the password file after setting the appropriate locks,
and does any necessary processing after the password file is unlocked.
If the password file is already locked for editing by another user,
.Nm
will ask you
to try again later. The default editor for
.Nm
is
.Xr vi 1 .
.Pp
.Nm
performs a number of consistency checks on the password entries,
and will not allow a password file with a
.Dq mangled
entry to be
installed.
If
.Nm
rejects the new password file, the user is prompted to re-enter
the edit session.
.Pp
Once the information has been verified,
.Nm
uses
.Xr pwd_mkdb 8
to update the user database. This is run in the background, and,
at very large sites could take several minutes. Until this update
is completed, the password file is unavailable for other updates
and the new information is not available to programs.
.Pp
The options are as follows:
.Bl -tag -width flag
.It Fl d Ar directory
Change the root directory of the password file from
.Dq Pa /
to
.Ar directory .
.El
.Pp
If a
.Nm
session is killed it may leave
.Dq Pa /etc/ptmp ,
which will cause future
.Nm
executions to fail with
.Dq Pa vipw: the passwd file is busy ,
until it is removed.
.Sh ENVIRONMENT
If the following environment variable exists it will be used by
.Nm :
.Bl -tag -width EDITOR
.It Ev EDITOR
The editor specified by the string
.Ev EDITOR
will be invoked instead of the default editor
.Xr vi 1 .
.El
.Sh FILES
.Bl -tag -width Pa -compact
.It Pa /etc/master.passwd
The current password file.
.It Pa /etc/ptmp
Temporary copy of the password file used while editing.
.El
.Sh SEE ALSO
.Xr chpass 1 ,
.Xr passwd 1 ,
.Xr pwhash 1 ,
.Xr passwd 5 ,
.Xr passwd.conf 5 ,
.Xr pwd_mkdb 8 ,
.Xr user 8
.Sh HISTORY
The
.Nm
command appeared in
.Bx 4.0 .

150
usr.sbin/vipw/vipw.c Normal file
View file

@ -0,0 +1,150 @@
/* $NetBSD: vipw.c,v 1.14 2009/04/19 00:44:49 lukem Exp $ */
/*
* Copyright (c) 1987, 1993, 1994
* The Regents of the University of California. 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.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 THE REGENTS 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.
*/
#include <sys/cdefs.h>
#ifndef lint
__COPYRIGHT("@(#) Copyright (c) 1987, 1993, 1994\
The Regents of the University of California. All rights reserved.");
#endif /* not lint */
#ifndef lint
#if 0
static char sccsid[] = "@(#)vipw.c 8.3 (Berkeley) 4/2/94";
#else
__RCSID("$NetBSD: vipw.c,v 1.14 2009/04/19 00:44:49 lukem Exp $");
#endif
#endif /* not lint */
#include <sys/types.h>
#include <sys/param.h>
#include <sys/stat.h>
#include <err.h>
#include <pwd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <util.h>
int main __P((int, char **));
static void copyfile __P((int, int));
static void usage __P((void));
char mpwd[MAXPATHLEN], mpwdl[MAXPATHLEN];
int
main(int argc, char *argv[])
{
const char *prefix;
int pfd, tfd;
struct stat begin, end;
int ch;
prefix = "";
while ((ch = getopt(argc, argv, "d:")) != -1) {
switch (ch) {
case 'd':
prefix = optarg;
if (pw_setprefix(prefix) < 0)
err(1, "%s", prefix);
break;
case '?':
default:
usage();
}
}
argc -= optind;
argv += optind;
if (argc != 0)
usage();
(void)snprintf(mpwd, sizeof(mpwd), "%s%s", prefix, _PATH_MASTERPASSWD);
(void)snprintf(mpwdl, sizeof(mpwdl), "%s%s", prefix,
_PATH_MASTERPASSWD_LOCK);
pw_init();
tfd = pw_lock(0);
if (tfd < 0) {
if (errno == EEXIST)
errx(1, "the passwd file is busy.");
else
err(1, "%s", mpwdl);
}
pfd = open(mpwd, O_RDONLY, 0);
if (pfd < 0)
pw_error(mpwd, 1, 1);
copyfile(pfd, tfd);
(void)close(tfd);
for (;;) {
if (stat(mpwdl, &begin))
pw_error(mpwdl, 1, 1);
pw_edit(0, NULL);
if (stat(mpwdl, &end))
pw_error(mpwdl, 1, 1);
if (begin.st_mtime == end.st_mtime &&
begin.st_mtimensec == end.st_mtimensec) {
warnx("no changes made");
pw_error((char *)NULL, 0, 0);
}
if (pw_mkdb(NULL, 0) == 0)
break;
pw_prompt();
}
return 0;
}
static void
copyfile(int from, int to)
{
int nr, nw, off;
char buf[8*1024];
while ((nr = read(from, buf, sizeof(buf))) > 0)
for (off = 0; off < nr; nr -= nw, off += nw)
if ((nw = write(to, buf + off, nr)) < 0)
pw_error(mpwdl, 1, 1);
if (nr < 0)
pw_error(mpwd, 1, 1);
}
static void
usage(void)
{
(void)fprintf(stderr, "usage: %s [-d directory]\n", getprogname());
exit(1);
}