ubase

suckless linux base utils
git clone git://git.2f30.org/ubase.git
Log | Files | Refs | README | LICENSE

commit ff2e11638f03fb259b0d698996e998bd7a431974
parent 8c2bbb8fb32e539e384ad695c00a611ee93b8ae4
Author: sin <sin@2f30.org>
Date:   Thu Oct 17 23:02:55 +0100

Add initial su(1)

Diffstat:
Makefile | 1+
config.mk | 4++--
su.c | 94+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 97 insertions(+), 2 deletions(-)
diff --git a/Makefile b/Makefile @@ -36,6 +36,7 @@ SRC = \ pivot_root.c \ ps.c \ rmmod.c \ + su.c \ swapoff.c \ swapon.c \ truncate.c \ diff --git a/config.mk b/config.mk @@ -10,10 +10,10 @@ MANPREFIX = $(PREFIX)/share/man LD = $(CC) CPPFLAGS = -D_BSD_SOURCE -D_GNU_SOURCE CFLAGS = -g -ansi -Wall -Wno-long-long $(CPPFLAGS) -LDFLAGS = -g +LDFLAGS = -g -lcrypt #CC = tcc #LD = $(CC) #CPPFLAGS = -D_BSD_SOURCE -D_GNU_SOURCE #CFLAGS = -Os -Wall $(CPPFLAGS) -#LDFLAGS = +#LDFLAGS = -lcrypt diff --git a/su.c b/su.c @@ -0,0 +1,94 @@ +/* See LICENSE file for copyright and license details. */ +#include <sys/types.h> +#include <unistd.h> +#include <errno.h> +#include <pwd.h> +#include <grp.h> +#include <shadow.h> +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include "util.h" + +static void +usage(void) +{ + eprintf("usage: %s [username]\n", argv0); +} + +int +main(int argc, char **argv) +{ + char *usr, *pass, *cryptpass; + char **newargv; + struct spwd *spw; + struct passwd *pw; + uid_t uid; + int i; + + ARGBEGIN { + default: + usage(); + } ARGEND; + + if (argc < 1) + usr = "root"; + else if (argc == 1) + usr = argv[0]; + else + usage(); + + uid = getuid(); + + spw = getspnam(usr); + if (!spw) + eprintf("getspnam: %s:", usr); + + switch (spw->sp_pwdp[0]) { + case '!': + case '*': + enprintf(EXIT_FAILURE, "Denied\n"); + case '$': + break; + default: + enprintf(EXIT_FAILURE, "Invalid shadow record\n"); + } + + if (uid) { + pass = getpass("Password: "); + if (!pass) + eprintf("getpass:"); + } + + cryptpass = crypt(pass, spw->sp_pwdp); + for (i = 0; pass[i]; i++) + pass[i] = '\0'; + if (!cryptpass) + eprintf("crypt:"); + + if (strcmp(cryptpass, spw->sp_pwdp) != 0) + enprintf(EXIT_FAILURE, "Denied\n"); + + errno = 0; + pw = getpwnam(usr); + if (errno) + eprintf("getpwnam: %s", usr); + else if (!pw) + enprintf(EXIT_FAILURE, "getpwnam: %s: no such user\n", usr); + + if (initgroups(usr, pw->pw_gid) < 0) + eprintf("initgroups:"); + if (setgid(pw->pw_gid) < 0) + eprintf("setgid:"); + if (setuid(pw->pw_uid) < 0) + eprintf("setuid:"); + + newargv = malloc(2 * sizeof(char *)); + if (!newargv) + eprintf("malloc:"); + newargv[0] = pw->pw_shell; + newargv[1] = NULL; + setenv("HOME", pw->pw_dir, 1); + execve(pw->pw_shell, newargv, environ); + return (errno == ENOENT) ? 127 : 126; +}