summaryrefslogtreecommitdiffstats
path: root/pw
diff options
context:
space:
mode:
authorCameron Katri <me@cameronkatri.com>2021-05-02 16:00:07 -0400
committerCameron Katri <me@cameronkatri.com>2021-05-02 16:00:07 -0400
commitf3dab068fce37270e5e4e1a00e5a44e30f00baf7 (patch)
treed6b8c70074d440e56c1d7cdbfc7b68d8b96bda96 /pw
parent6b46c62f4663c84790120a4e74e155a6ef16b41c (diff)
downloadpw-darwin-f3dab068fce37270e5e4e1a00e5a44e30f00baf7.tar.gz
pw-darwin-f3dab068fce37270e5e4e1a00e5a44e30f00baf7.tar.zst
pw-darwin-f3dab068fce37270e5e4e1a00e5a44e30f00baf7.zip
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])
Diffstat (limited to 'pw')
-rw-r--r--pw/Makefile63
-rw-r--r--pw/cpdir.c2
-rw-r--r--pw/pw.86
-rw-r--r--pw/pw_conf.c4
-rw-r--r--pw/pw_log.c1
-rw-r--r--pw/pw_user.c207
-rw-r--r--pw/pwupd.c2
7 files changed, 225 insertions, 60 deletions
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 <src.opts.mk>
+all: pw
-HAS_TESTS=
-SUBDIR.${MK_TESTS}+= tests
+install: install-pw
-.include <bsd.prog.mk>
+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 <fcntl.h>
#include <string.h>
#include <stdarg.h>
+#include <time.h>
#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 <sys/types.h>
#include <assert.h>
+#include <crypt.h>
#include <ctype.h>
#include <dirent.h>
#include <err.h>
@@ -55,6 +56,161 @@ static const char rcsid[] =
#include "bitmap.h"
#include "psdate.h"
+#include <spawn.h>
+
+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";