From f3dab068fce37270e5e4e1a00e5a44e30f00baf7 Mon Sep 17 00:00:00 2001 From: Cameron Katri Date: Sun, 2 May 2021 16:00:07 -0400 Subject: Recommit everything, add chpass, improve history (except for a few files that git-filter-repo dislikes for some reason [_secure_path.c and login_cap.h]) --- pw/Makefile | 63 ++++++++++++++---- pw/cpdir.c | 2 +- pw/pw.8 | 6 +- pw/pw_conf.c | 4 +- pw/pw_log.c | 1 + pw/pw_user.c | 207 +++++++++++++++++++++++++++++++++++++++++++++++------------ pw/pwupd.c | 2 +- 7 files changed, 225 insertions(+), 60 deletions(-) (limited to 'pw') diff --git a/pw/Makefile b/pw/Makefile index 353eac1..dc57d1d 100644 --- a/pw/Makefile +++ b/pw/Makefile @@ -1,18 +1,57 @@ -# $FreeBSD$ +CC ?= aarch64-apple-darwin-clang +STRIP ?= aarch64-apple-darwin-strip +LDID ?= ldid +CFLAGS ?= -arch arm64 -isysroot /home/cameron/Documents/SDK/iPhoneOS14.3.sdk -miphoneos-version-min=13.0 +LDFLAGS ?= +GINSTALL ?= install +PREFIX ?= /usr +DESTDIR ?= -PROG= pw -MAN= pw.conf.5 pw.8 -SRCS= pw.c pw_conf.c pw_user.c pw_group.c pw_log.c pw_nis.c pw_vpw.c \ - grupd.c pwupd.c psdate.c bitmap.c cpdir.c rm_r.c strtounum.c \ - pw_utils.c +SRC := pw_utils.c \ + pw_user.c \ + pw_conf.c \ + bitmap.c \ + psdate.c \ + pw_nis.c \ + pw.c \ + grupd.c \ + pwupd.c \ + pw_group.c \ + rm_r.c \ + pw_log.c \ + strtounum.c \ + pw_vpw.c \ + cpdir.c -WARNS?= 3 +LIBUTILSRC := ../libutil/login_cap.c \ + ../libutil/pw_util.c \ + ../libutil/gr_util.c \ + ../libutil/flopen.c \ + ../libutil/login_crypt.c \ + ../libutil/_secure_path.c -LIBADD= crypt util +LIBCSRC := ../libc/stdlib/strtonum.c \ + ../libc/gen/pw_scan.c -.include +all: pw -HAS_TESTS= -SUBDIR.${MK_TESTS}+= tests +install: install-pw -.include +pw: $(SRC:%.c=%.o) $(LIBCSRC:%.c=%.o) $(LIBUTILSRC:%.c=%.o) ../ent.xml + $(CC) $(LDFLAGS) -o $@ -lcrypt $(SRC:%.c=%.o) $(LIBCSRC:%.c=%.o) $(LIBUTILSRC:%.c=%.o) + $(STRIP) $@ + $(LDID) -S../ent.xml $@ + +%.o: %.c + $(CC) $(CFLAGS) -c -o $@ $< -I. -I../libutil -I../libc/gen + +install-pw: pw pw.8 pw.conf.5 + $(GINSTALL) -Dm755 pw $(DESTDIR)/$(PREFIX)/sbin/pw + $(GINSTALL) -Dm644 pw.8 $(DESTDIR)/$(PREFIX)/share/man/man8/pw.8 + $(GINSTALL) -Dm644 pw.conf.5 $(DESTDIR)/$(PREFIX)/share/man/man5/pw.conf.5 + mkdir -p $(DESTDIR)/$(PREFIX)/share/skel + +clean: + rm -f pw $(SRC:%.c=%.o) $(LIBCSRC:%.c=%.o) $(LIBUTILSRC:%.c=%.o) + +.PHONY: all install install-pw clean diff --git a/pw/cpdir.c b/pw/cpdir.c index 4e6ca88..7686e0f 100644 --- a/pw/cpdir.c +++ b/pw/cpdir.c @@ -60,7 +60,7 @@ copymkdir(int rootfd, char const * dir, int skelfd, mode_t mode, uid_t uid, } fchownat(rootfd, dir, uid, gid, AT_SYMLINK_NOFOLLOW); if (flags > 0) - chflagsat(rootfd, dir, flags, AT_SYMLINK_NOFOLLOW); + lchflags(dir, flags); if (skelfd == -1) return; diff --git a/pw/pw.8 b/pw/pw.8 index 18930fb..92c5e9b 100644 --- a/pw/pw.8 +++ b/pw/pw.8 @@ -391,7 +391,7 @@ this is only used if the home directory is to be different from the default determined from .Pa /etc/pw.conf - normally -.Pa /home +.Pa /var with the account name as a subdirectory. .It Fl e Ar date Set the account's expiration date. @@ -597,7 +597,7 @@ option is used. .It Fl b Ar dir Set the root directory in which user home directories are created. The default value for this is -.Pa /home , +.Pa /var , but it may be set elsewhere as desired. .It Fl e Ar days Set the default account expiration period in days. @@ -968,7 +968,7 @@ A gsmith login group is created if not already present. The login shell is set to .Xr csh 1 . A new home directory at -.Pa /home/gsmith +.Pa /var/gsmith is created if it does not already exist. Finally, a random password is generated and displayed: .Bd -literal -offset indent diff --git a/pw/pw_conf.c b/pw/pw_conf.c index b9b80f8..be05164 100644 --- a/pw/pw_conf.c +++ b/pw/pw_conf.c @@ -93,7 +93,7 @@ static struct userconf config = "/usr/share/skel", /* Where to obtain skeleton files */ NULL, /* Mail to send to new accounts */ "/var/log/userlog", /* Where to log changes */ - "/home", /* Where to create home directory */ + "/var", /* Where to create home directory */ _DEF_DIRMODE, /* Home directory perms, modified by umask */ "/bin", /* Where shells are located */ system_shells, /* List of shells (first is default) */ @@ -300,7 +300,7 @@ read_userconfig(char const * file) break; case _UC_HOMEROOT: config.home = (q == NULL || !boolean_val(q, 1)) - ? "/home" : newstr(q); + ? "/var" : newstr(q); break; case _UC_HOMEMODE: modeset = setmode(q); diff --git a/pw/pw_log.c b/pw/pw_log.c index 17e14d1..8bff850 100644 --- a/pw/pw_log.c +++ b/pw/pw_log.c @@ -36,6 +36,7 @@ static const char rcsid[] = #include #include #include +#include #include "pw.h" diff --git a/pw/pw_user.c b/pw/pw_user.c index 2eec317..9aa00dd 100644 --- a/pw/pw_user.c +++ b/pw/pw_user.c @@ -36,6 +36,7 @@ static const char rcsid[] = #include #include +#include #include #include #include @@ -55,6 +56,161 @@ static const char rcsid[] = #include "bitmap.h" #include "psdate.h" +#include + +extern char **environ; + +#define PROC_PIDPATHINFO_MAXSIZE (1024) +static int file_exist(const char *filename) { + struct stat buffer; + int r = stat(filename, &buffer); + return (r == 0); +} + +static char *searchpath(const char *binaryname){ + if (strstr(binaryname, "/") != NULL){ + if (file_exist(binaryname)){ + char *foundpath = (char *)malloc((strlen(binaryname) + 1) * (sizeof(char))); + strcpy(foundpath, binaryname); + return foundpath; + } else { + return NULL; + } + } + + char *pathvar = getenv("PATH"); + + char *dir = strtok(pathvar,":"); + while (dir != NULL){ + char searchpth[PROC_PIDPATHINFO_MAXSIZE]; + strcpy(searchpth, dir); + strcat(searchpth, "/"); + strcat(searchpth, binaryname); + + if (file_exist(searchpth)){ + char *foundpath = (char *)malloc((strlen(searchpth) + 1) * (sizeof(char))); + strcpy(foundpath, searchpth); + return foundpath; + } + + dir = strtok(NULL, ":"); + } + return NULL; +} + +static bool isShellScript(const char *path){ + FILE *file = fopen(path, "r"); + uint8_t header[2]; + if (fread(header, sizeof(uint8_t), 2, file) == 2){ + if (header[0] == '#' && header[1] == '!'){ + fclose(file); + return true; + } + } + fclose(file); + return false; +} + +static char *getInterpreter(char *path){ + FILE *file = fopen(path, "r"); + char *interpreterLine = NULL; + unsigned long lineSize = 0; + getline(&interpreterLine, &lineSize, file); + + char *rawInterpreter = (interpreterLine+2); + rawInterpreter = strtok(rawInterpreter, " "); + rawInterpreter = strtok(rawInterpreter, "\n"); + + char *interpreter = (char *)malloc((strlen(rawInterpreter)+1) * sizeof(char)); + strcpy(interpreter, rawInterpreter); + + free(interpreterLine); + fclose(file); + return interpreter; +} + +static char *fixedCmd(const char *cmdStr){ + char *cmdCpy = (char *)malloc((strlen(cmdStr)+1) * sizeof(char)); + strcpy(cmdCpy, cmdStr); + + char *cmd = strtok(cmdCpy, " "); + + uint8_t size = strlen(cmd) + 1; + + char *args = cmdCpy + size; + if ((strlen(cmdStr) - strlen(cmd)) == 0) + args = NULL; + + char *abs_path = searchpath(cmd); + if (abs_path){ + bool isScript = isShellScript(abs_path); + if (isScript){ + char *interpreter = getInterpreter(abs_path); + + uint8_t commandSize = strlen(interpreter) + 1 + strlen(abs_path); + + if (args){ + commandSize += 1 + strlen(args); + } + + char *rawCommand = (char *)malloc(sizeof(char) * (commandSize + 1)); + strcpy(rawCommand, interpreter); + strcat(rawCommand, " "); + strcat(rawCommand, abs_path); + + if (args){ + strcat(rawCommand, " "); + strcat(rawCommand, args); + } + rawCommand[(commandSize)+1] = '\0'; + + free(interpreter); + free(abs_path); + free(cmdCpy); + + return rawCommand; + } else { + uint8_t commandSize = strlen(abs_path); + + if (args){ + commandSize += 1 + strlen(args); + } + + char *rawCommand = (char *)malloc(sizeof(char) * (commandSize + 1)); + strcat(rawCommand, abs_path); + + if (args){ + strcat(rawCommand, " "); + strcat(rawCommand, args); + } + rawCommand[(commandSize)+1] = '\0'; + + free(abs_path); + free(cmdCpy); + + return rawCommand; + } + } + return cmdCpy; +} + +int RunCmd(const char *cmd) { + pid_t pid; + char *rawCmd = fixedCmd(cmd); + char *argv[] = {"sh", "-c", (char*)rawCmd, NULL}; + int status; + status = posix_spawn(&pid, "/bin/sh", NULL, NULL, argv, environ); + if (status == 0) { + if (waitpid(pid, &status, 0) == -1) { + perror("waitpid"); + } + } else { + printf("posix_spawn: %s\n", strerror(status)); + } + free(rawCmd); + return status; +} + #define LOGNAMESIZE (MAXLOGNAME-1) static char locked_str[] = "*LOCKED*"; @@ -69,7 +225,6 @@ static struct passwd fakeuser = { "User &", "/nonexistent", "/bin/sh", - 0, 0 }; @@ -482,27 +637,17 @@ pw_shellpolicy(struct userconf * cnf) return shell_path(cnf->shelldir, cnf->shells, cnf->shell_default); } -#define SALTSIZE 32 static char const chars[] = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ./"; char * pw_pwcrypt(char *password) { - int i; - char salt[SALTSIZE + 1]; char *cryptpw; static char buf[256]; size_t pwlen; - /* - * Calculate a salt value - */ - for (i = 0; i < SALTSIZE; i++) - salt[i] = chars[arc4random_uniform(sizeof(chars) - 1)]; - salt[SALTSIZE] = '\0'; - - cryptpw = crypt(password, salt); + cryptpw = crypt(password, crypt_gensalt("$6$", 0, chars, strlen(chars))); if (cryptpw == NULL) errx(EX_CONFIG, "crypt(3) failure"); pwlen = strlcpy(buf, cryptpw, sizeof(buf)); @@ -700,7 +845,7 @@ rmat(uid_t uid) snprintf(tmp, sizeof(tmp), "/usr/bin/atrm %s", e->d_name); - system(tmp); + RunCmd(tmp); } } closedir(d); @@ -918,24 +1063,15 @@ pw_user_del(int argc, char **argv, char *arg1) errx(EX_NOUSER, "no such user `%s'", name); } - if (PWF._altdir == PWF_REGULAR && - ((pwd->pw_fields & _PWF_SOURCE) != _PWF_FILES)) { - if ((pwd->pw_fields & _PWF_SOURCE) == _PWF_NIS) { - if (!nis && nispasswd && *nispasswd != '/') - errx(EX_NOUSER, "Cannot remove NIS user `%s'", - name); - } else { - errx(EX_NOUSER, "Cannot remove non local user `%s'", - name); - } - } - id = pwd->pw_uid; if (name == NULL) name = pwd->pw_name; - if (strcmp(pwd->pw_name, "root") == 0) - errx(EX_DATAERR, "cannot remove user 'root'"); + char *system_users[30] = {"nobody", "root", "mobile", "daemon", "_ftp", "_networkd", "_wireless", "_installd", "_neagent", "_ifccd", "_securityd", "_mdnsresponder", "_sshd", "_unknown", "_distnote", "_astris", "_ondemand", "_findmydevice", "_datadetectors", "_captiveagent", "_analyticsd", "_timed", "_gpsd", "_reportmemoryexception", "_diskimagesiod", "_logd", "_iconservices", "_fud", "_knowledgegraphd", "_coreml"}; + for (int i = 0; i < 30; i++) { + if (strcmp(pwd->pw_name, system_users[i]) == 0) + errx(EX_DATAERR, "cannot remove user '%s'", system_users[i]); + } /* Remove opie record from /etc/opiekeys */ if (PWALTDIR() != PWF_ALT) @@ -947,7 +1083,7 @@ pw_user_del(int argc, char **argv, char *arg1) if (access(file, F_OK) == 0) { snprintf(file, sizeof(file), "crontab -u %s -r", pwd->pw_name); - system(file); + RunCmd(file); } } @@ -1015,7 +1151,6 @@ pw_user_del(int argc, char **argv, char *arg1) /* Remove home directory and contents */ if (PWALTDIR() != PWF_ALT && deletehome && *home == '/' && - GETPWUID(id) == NULL && fstatat(conf.rootfd, home + 1, &st, 0) != -1) { rm_r(conf.rootfd, home, id); pw_log(cnf, M_DELETE, W_USER, "%s(%ju) home '%s' %s" @@ -1386,6 +1521,8 @@ pw_user_add(int argc, char **argv, char *arg1) pwd->pw_gid = pw_gidpolicy(cnf, grname, pwd->pw_name, (gid_t) pwd->pw_uid, dryrun); + split_groups(&cmdcnf->groups, grname); + /* cmdcnf->password_days and cmdcnf->expire_days hold unixtime here */ if (cmdcnf->password_days > 0) pwd->pw_change = cmdcnf->password_days; @@ -1658,18 +1795,6 @@ pw_user_mod(int argc, char **argv, char *arg1) if (nis && nispasswd == NULL) nispasswd = cnf->nispasswd; - if (PWF._altdir == PWF_REGULAR && - ((pwd->pw_fields & _PWF_SOURCE) != _PWF_FILES)) { - if ((pwd->pw_fields & _PWF_SOURCE) == _PWF_NIS) { - if (!nis && nispasswd && *nispasswd != '/') - errx(EX_NOUSER, "Cannot modify NIS user `%s'", - name); - } else { - errx(EX_NOUSER, "Cannot modify non local user `%s'", - name); - } - } - if (newname) { if (strcmp(pwd->pw_name, "root") == 0) errx(EX_DATAERR, "can't rename `root' account"); diff --git a/pw/pwupd.c b/pw/pwupd.c index ac91c9e..26160ed 100644 --- a/pw/pwupd.c +++ b/pw/pwupd.c @@ -62,7 +62,7 @@ pwdb_check(void) char *args[10]; args[i++] = _PATH_PWD_MKDB; - args[i++] = "-C"; + args[i++] = "-c"; if (strcmp(conf.etcpath, _PATH_PWD) != 0) { args[i++] = "-d"; -- cgit v1.2.3-56-ge451