Add initial implementation of passwd(1)
No shadow support yet.
This commit is contained in:
parent
d3709f91a2
commit
1ec996439a
5
Makefile
5
Makefile
|
@ -3,15 +3,17 @@ include config.mk
|
||||||
.POSIX:
|
.POSIX:
|
||||||
.SUFFIXES: .c .o
|
.SUFFIXES: .c .o
|
||||||
|
|
||||||
HDR = arg.h config.def.h proc.h reboot.h rtc.h util.h
|
HDR = arg.h config.def.h passwd.h proc.h reboot.h rtc.h text.h util.h
|
||||||
LIB = \
|
LIB = \
|
||||||
util/agetcwd.o \
|
util/agetcwd.o \
|
||||||
|
util/agetline.o \
|
||||||
util/apathmax.o \
|
util/apathmax.o \
|
||||||
util/ealloc.o \
|
util/ealloc.o \
|
||||||
util/eprintf.o \
|
util/eprintf.o \
|
||||||
util/estrtol.o \
|
util/estrtol.o \
|
||||||
util/estrtoul.o \
|
util/estrtoul.o \
|
||||||
util/explicit_bzero.o \
|
util/explicit_bzero.o \
|
||||||
|
util/passwd.o \
|
||||||
util/proc.o \
|
util/proc.o \
|
||||||
util/putword.o \
|
util/putword.o \
|
||||||
util/recurse.o \
|
util/recurse.o \
|
||||||
|
@ -43,6 +45,7 @@ SRC = \
|
||||||
mount.c \
|
mount.c \
|
||||||
mountpoint.c \
|
mountpoint.c \
|
||||||
pagesize.c \
|
pagesize.c \
|
||||||
|
passwd.c \
|
||||||
pidof.c \
|
pidof.c \
|
||||||
pivot_root.c \
|
pivot_root.c \
|
||||||
ps.c \
|
ps.c \
|
||||||
|
|
6
README
6
README
|
@ -8,9 +8,9 @@ The following programs are currently implemented:
|
||||||
|
|
||||||
chvt clear ctrlaltdel dd df dmesg eject fallocate free getty halt
|
chvt clear ctrlaltdel dd df dmesg eject fallocate free getty halt
|
||||||
hwclock id insmod killall5 login lsmod lsusb mknod mkswap mount
|
hwclock id insmod killall5 login lsmod lsusb mknod mkswap mount
|
||||||
mountpoint pagesize pidof pivot_root ps respawn rmmod stat su
|
mountpoint pagesize passwd pidof pivot_root ps respawn rmmod stat
|
||||||
swapoff swapon switch_root sysctl truncate umount unshare uptime
|
su swapoff swapon switch_root sysctl truncate umount unshare
|
||||||
watch who
|
uptime watch who
|
||||||
|
|
||||||
The complement of ubase is sbase[1] which mostly follows POSIX and
|
The complement of ubase is sbase[1] which mostly follows POSIX and
|
||||||
provides all the portable tools. Together they are intended to form a
|
provides all the portable tools. Together they are intended to form a
|
||||||
|
|
1
TODO
1
TODO
|
@ -9,7 +9,6 @@ Tools to be implemented
|
||||||
* losetup(8)
|
* losetup(8)
|
||||||
* lspci
|
* lspci
|
||||||
* mkswap [-L]
|
* mkswap [-L]
|
||||||
* passwd
|
|
||||||
* adduser
|
* adduser
|
||||||
* addgroup
|
* addgroup
|
||||||
* rmuser
|
* rmuser
|
||||||
|
|
142
passwd.c
Normal file
142
passwd.c
Normal file
|
@ -0,0 +1,142 @@
|
||||||
|
/* See LICENSE file for copyright and license details. */
|
||||||
|
#include <errno.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <pwd.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include "passwd.h"
|
||||||
|
#include "util.h"
|
||||||
|
|
||||||
|
static void
|
||||||
|
usage(void)
|
||||||
|
{
|
||||||
|
eprintf("usage: %s login\n", argv0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
char *pass, *cryptpass1, *cryptpass2, *cryptpass3;
|
||||||
|
char *p;
|
||||||
|
char template[] = "/tmp/pw.XXXXXX";
|
||||||
|
struct passwd *pw;
|
||||||
|
int ffd, tfd;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
ARGBEGIN {
|
||||||
|
default:
|
||||||
|
usage();
|
||||||
|
} ARGEND;
|
||||||
|
|
||||||
|
if (argc != 1)
|
||||||
|
usage();
|
||||||
|
|
||||||
|
errno = 0;
|
||||||
|
pw = getpwnam(argv[0]);
|
||||||
|
if (errno)
|
||||||
|
eprintf("getpwnam: %s:", argv[0]);
|
||||||
|
else if (!pw)
|
||||||
|
eprintf("who are you?\n");
|
||||||
|
|
||||||
|
switch (pw->pw_passwd[0]) {
|
||||||
|
case '!':
|
||||||
|
case '*':
|
||||||
|
eprintf("denied\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pw->pw_passwd[0] == '\0')
|
||||||
|
goto newpass;
|
||||||
|
|
||||||
|
if (pw->pw_passwd[0] == 'x' && pw->pw_passwd[1] == '\0')
|
||||||
|
eprintf("no shadow support\n");
|
||||||
|
|
||||||
|
/* Flush pending input */
|
||||||
|
ioctl(STDIN_FILENO, TCFLSH, (void *)0);
|
||||||
|
|
||||||
|
pass = getpass("Current password: ");
|
||||||
|
putchar('\n');
|
||||||
|
if (!pass)
|
||||||
|
eprintf("getpass:");
|
||||||
|
p = crypt(pass, pw->pw_passwd);
|
||||||
|
if (!p)
|
||||||
|
eprintf("crypt:");
|
||||||
|
cryptpass1 = estrdup(p);
|
||||||
|
if (strcmp(cryptpass1, pw->pw_passwd) != 0)
|
||||||
|
eprintf("incorrect password\n");
|
||||||
|
|
||||||
|
newpass:
|
||||||
|
/* Flush pending input */
|
||||||
|
ioctl(STDIN_FILENO, TCFLSH, (void *)0);
|
||||||
|
|
||||||
|
pass = getpass("Enter new password: ");
|
||||||
|
putchar('\n');
|
||||||
|
if (!pass)
|
||||||
|
eprintf("getpass:");
|
||||||
|
p = crypt(pass, pw->pw_passwd);
|
||||||
|
if (!p)
|
||||||
|
eprintf("crypt:");
|
||||||
|
cryptpass2 = estrdup(p);
|
||||||
|
if (strcmp(cryptpass1, cryptpass2) == 0)
|
||||||
|
eprintf("password left unchanged\n");
|
||||||
|
|
||||||
|
/* Flush pending input */
|
||||||
|
ioctl(STDIN_FILENO, TCFLSH, (void *)0);
|
||||||
|
|
||||||
|
pass = getpass("Retype new password: ");
|
||||||
|
putchar('\n');
|
||||||
|
if (!pass)
|
||||||
|
eprintf("getpass:");
|
||||||
|
p = crypt(pass, pw->pw_passwd);
|
||||||
|
if (!p)
|
||||||
|
eprintf("crypt:");
|
||||||
|
cryptpass3 = estrdup(p);
|
||||||
|
if (strcmp(cryptpass2, cryptpass3) != 0)
|
||||||
|
eprintf("passwords don't match\n");
|
||||||
|
|
||||||
|
pw->pw_passwd = cryptpass3;
|
||||||
|
|
||||||
|
ffd = open("/etc/passwd", O_RDWR);
|
||||||
|
if (ffd < 0)
|
||||||
|
eprintf("open %s:", "/etc/passwd");
|
||||||
|
|
||||||
|
tfd = mkostemp(template, O_RDWR);
|
||||||
|
if (tfd < 0)
|
||||||
|
eprintf("mkstemp:");
|
||||||
|
|
||||||
|
r = pw_copy(ffd, tfd, pw);
|
||||||
|
if (r < 0) {
|
||||||
|
unlink(template);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
r = lseek(ffd, 0, SEEK_SET);
|
||||||
|
if (r < 0) {
|
||||||
|
unlink(template);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
r = lseek(tfd, 0, SEEK_SET);
|
||||||
|
if (r < 0) {
|
||||||
|
unlink(template);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
r = pw_copy(tfd, ffd, NULL);
|
||||||
|
if (r < 0) {
|
||||||
|
unlink(template);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
close(tfd);
|
||||||
|
close(ffd);
|
||||||
|
unlink(template);
|
||||||
|
free(cryptpass3);
|
||||||
|
free(cryptpass2);
|
||||||
|
free(cryptpass1);
|
||||||
|
|
||||||
|
return EXIT_SUCCESS;
|
||||||
|
}
|
4
passwd.h
Normal file
4
passwd.h
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
/* See LICENSE file for copyright and license details. */
|
||||||
|
/* passwd.c */
|
||||||
|
int pw_scan(char *, struct passwd *);
|
||||||
|
int pw_copy(int, int, const struct passwd *);
|
11
text.h
Normal file
11
text.h
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
/* See LICENSE file for copyright and license details. */
|
||||||
|
|
||||||
|
struct linebuf {
|
||||||
|
char **lines;
|
||||||
|
long nlines;
|
||||||
|
long capacity;
|
||||||
|
};
|
||||||
|
#define EMPTY_LINEBUF {NULL, 0, 0,}
|
||||||
|
void getlines(FILE *, struct linebuf *);
|
||||||
|
|
||||||
|
ssize_t agetline(char **, size_t *, FILE *);
|
13
util/agetline.c
Normal file
13
util/agetline.c
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
/* See LICENSE file for copyright and license details. */
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "../text.h"
|
||||||
|
#include "../util.h"
|
||||||
|
|
||||||
|
ssize_t
|
||||||
|
agetline(char **p, size_t *size, FILE *fp)
|
||||||
|
{
|
||||||
|
return getline(p, size, fp);
|
||||||
|
}
|
113
util/passwd.c
Normal file
113
util/passwd.c
Normal file
|
@ -0,0 +1,113 @@
|
||||||
|
/* See LICENSE file for copyright and license details. */
|
||||||
|
#include <pwd.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "../text.h"
|
||||||
|
#include "../util.h"
|
||||||
|
|
||||||
|
int
|
||||||
|
pw_scan(char *bp, struct passwd *pw)
|
||||||
|
{
|
||||||
|
char *p;
|
||||||
|
|
||||||
|
memset(pw, 0, sizeof(*pw));
|
||||||
|
|
||||||
|
/* login name */
|
||||||
|
p = strsep(&bp, ":");
|
||||||
|
if (!p || *p == '\0')
|
||||||
|
goto corrupt;
|
||||||
|
pw->pw_name = p;
|
||||||
|
|
||||||
|
/* passwd */
|
||||||
|
p = strsep(&bp, ":");
|
||||||
|
if (!p)
|
||||||
|
goto corrupt;
|
||||||
|
pw->pw_passwd = p;
|
||||||
|
|
||||||
|
/* uid */
|
||||||
|
p = strsep(&bp, ":");
|
||||||
|
if (!p)
|
||||||
|
goto corrupt;
|
||||||
|
pw->pw_uid = estrtol(p, 10);
|
||||||
|
|
||||||
|
/* gid */
|
||||||
|
p = strsep(&bp, ":");
|
||||||
|
if (!p)
|
||||||
|
goto corrupt;
|
||||||
|
pw->pw_gid = estrtol(p, 10);
|
||||||
|
|
||||||
|
/* user name or comment */
|
||||||
|
p = strsep(&bp, ":");
|
||||||
|
if (!p)
|
||||||
|
goto corrupt;
|
||||||
|
pw->pw_gecos = p;
|
||||||
|
|
||||||
|
/* home directory */
|
||||||
|
p = strsep(&bp, ":");
|
||||||
|
if (!p)
|
||||||
|
goto corrupt;
|
||||||
|
pw->pw_dir = p;
|
||||||
|
|
||||||
|
/* optional shell */
|
||||||
|
p = strsep(&bp, ":");
|
||||||
|
if (!p)
|
||||||
|
goto corrupt;
|
||||||
|
pw->pw_shell = p;
|
||||||
|
|
||||||
|
/* look for redundant entries */
|
||||||
|
p = strsep(&bp, ":");
|
||||||
|
if (p)
|
||||||
|
goto corrupt;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
corrupt:
|
||||||
|
weprintf("corrupted passwd entry\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
pw_copy(int ffd, int tfd, const struct passwd *newpw)
|
||||||
|
{
|
||||||
|
struct passwd pw;
|
||||||
|
char *buf = NULL, *p;
|
||||||
|
size_t size = 0;
|
||||||
|
FILE *from, *to;
|
||||||
|
|
||||||
|
from = fdopen(ffd, "r");
|
||||||
|
if (!from) {
|
||||||
|
weprintf("fdopen:");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
to = fdopen(tfd, "w");
|
||||||
|
if (!to) {
|
||||||
|
weprintf("fdopen:");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
while (agetline(&buf, &size, from) != -1) {
|
||||||
|
p = strdup(buf);
|
||||||
|
if (!p) {
|
||||||
|
weprintf("strdup:");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (newpw) {
|
||||||
|
if (pw_scan(p, &pw) < 0)
|
||||||
|
return -1;
|
||||||
|
if (strcmp(pw.pw_name, newpw->pw_name) == 0) {
|
||||||
|
fprintf(to, "%s:%s:%u:%u:%s:%s:%s\n",
|
||||||
|
newpw->pw_name,
|
||||||
|
newpw->pw_passwd,
|
||||||
|
newpw->pw_uid,
|
||||||
|
newpw->pw_gid,
|
||||||
|
newpw->pw_gecos,
|
||||||
|
newpw->pw_dir,
|
||||||
|
newpw->pw_shell);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fprintf(to, "%s", buf);
|
||||||
|
free(p);
|
||||||
|
}
|
||||||
|
fflush(to);
|
||||||
|
return 0;
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user