From e735ad6710a82604a206ad29f6cbcdd7dc4b024c Mon Sep 17 00:00:00 2001 From: Tyler Murphy Date: Sun, 14 May 2023 21:43:02 -0400 Subject: refactor and add su --- lib/args.c | 4 +- lib/args.h | 18 -------- lib/buffer.c | 21 ++++++++- lib/buffer.h | 16 ------- lib/convert.c | 10 ++++- lib/convert.h | 20 --------- lib/def.h | 31 ------------- lib/error.c | 23 +++++++++- lib/error.h | 13 ------ lib/file.c | 14 +++--- lib/file.h | 14 ------ lib/identity.c | 24 ++++++++++ lib/lslib.h | 140 +++++++++++++++++++++++++++++++++++++++++++++++++++++---- lib/password.c | 70 +++++++++++++++++++++++++++++ lib/regex.c | 3 +- lib/regex.h | 54 ---------------------- lib/shell.c | 59 ++++++++++++++++++++++++ lib/stack.c | 6 +-- lib/stack.h | 22 --------- lib/xfuncs.c | 49 ++++++++++++++++++++ 20 files changed, 394 insertions(+), 217 deletions(-) delete mode 100644 lib/args.h delete mode 100644 lib/buffer.h delete mode 100644 lib/convert.h delete mode 100644 lib/def.h delete mode 100644 lib/error.h delete mode 100644 lib/file.h create mode 100644 lib/identity.c create mode 100644 lib/password.c delete mode 100644 lib/regex.h create mode 100644 lib/shell.c delete mode 100644 lib/stack.h create mode 100644 lib/xfuncs.c (limited to 'lib') diff --git a/lib/args.c b/lib/args.c index f907746..5311acf 100644 --- a/lib/args.c +++ b/lib/args.c @@ -1,6 +1,4 @@ -#include "args.h" -#include "error.h" -#include "convert.h" +#include "lslib.h" #include #include diff --git a/lib/args.h b/lib/args.h deleted file mode 100644 index 0b89fca..0000000 --- a/lib/args.h +++ /dev/null @@ -1,18 +0,0 @@ -#ifndef ARGS_H -#define ARGS_H - -#define UNUSED(x) (void)(x) -#define ARG_UNUSED 0 -#define ARG_USED 1 -#define ARG_IGNORE 2 -#define ARG_INVALID 3 - -void check_arg (char* arg); - -void global_help(void (*help)(void)); - -void parse_help (int argc, char** argv, void (*help)(void)); - -int parse_args (int argc, char** argv, void (*help)(void), int (*short_arg)(char, char*), int (*long_arg)(char*, char*)); - -#endif diff --git a/lib/buffer.c b/lib/buffer.c index 2bee94b..cad286a 100644 --- a/lib/buffer.c +++ b/lib/buffer.c @@ -1,5 +1,4 @@ -#include "buffer.h" -#include "convert.h" +#include "lslib.h" #include #include @@ -58,3 +57,21 @@ void pop_path_buffer_2(int i) { bool is_dot_dir(const char* path) { return streql(path, ".") || streql(path, ".."); } + +const char* get_last_component(const char* path) { + const char* last; + char c; + + last = NULL; + + while (c = *path, true) { + if (c == '\\') { + last = path; + } else if (c == '\0') { + break; + } + path++; + } + + return last; +} diff --git a/lib/buffer.h b/lib/buffer.h deleted file mode 100644 index fd47ee7..0000000 --- a/lib/buffer.h +++ /dev/null @@ -1,16 +0,0 @@ -#ifndef BUFFER_H -#define BUFFER_H - -#include "def.h" - -char* get_path_buffer(void); -int push_path_buffer(const char* string); -void pop_path_buffer(int i); - -char* get_path_buffer_2(void); -int push_path_buffer_2(const char* string); -void pop_path_buffer_2(int i); - -bool is_dot_dir(const char* path); - -#endif diff --git a/lib/convert.c b/lib/convert.c index a4639c4..c3e011d 100644 --- a/lib/convert.c +++ b/lib/convert.c @@ -1,5 +1,4 @@ -#include "convert.h" -#include "error.h" +#include "lslib.h" #include #include @@ -124,3 +123,10 @@ void print_file_path(char* path) { printf("%s", path); } } + +void nuke_str(char* type) { + *type = 0; + while(*(++type)) { + *type = 0; + } +} diff --git a/lib/convert.h b/lib/convert.h deleted file mode 100644 index f07614b..0000000 --- a/lib/convert.h +++ /dev/null @@ -1,20 +0,0 @@ -#ifndef CONVERT_H -#define CONVERT_H - -#include "def.h" - -#include -#include - -long int get_number(const char* text); -long int get_blkm(const char* text); -mode_t get_mode(const char* text); - -bool streql(const char* a, const char* b); -bool prefix(const char* pre, const char* str); - -void print_file_size(size_t bytes, char buf[5]); -void print_date_time(time_t mills, char buf[13]); -void print_file_path(char* path); - -#endif diff --git a/lib/def.h b/lib/def.h deleted file mode 100644 index 33a32a0..0000000 --- a/lib/def.h +++ /dev/null @@ -1,31 +0,0 @@ -#ifndef COLOR_H -#define COLOR_H - -#include - -#define ANSCII "\x1b[" -#define NEXT ";" - -#define RESET "0" -#define BOLD "1" - -#define NORMAL "3" -#define BACKGROUND "4" -#define HIGHLIGHT "9" - -#define BLACK "0" -#define RED "1" -#define GREEN "2" -#define YELLOW "3" -#define BLUE "4" -#define MAGENTA "5" -#define TURQUOISE "6" -#define WHITE "7" - -#define COLOR "m" - -typedef uint8_t bool; -#define true 1 -#define false 0 - -#endif diff --git a/lib/error.c b/lib/error.c index 67828c9..0b55edb 100644 --- a/lib/error.c +++ b/lib/error.c @@ -1,17 +1,29 @@ -#include "error.h" +#include "lslib.h" #include #include #include +#include +#include extern char* cmd; +void die (void) { + exit (EXIT_FAILURE); +} + void error_s(const char *format, ...) { va_list list; va_start(list, format); fprintf(stderr, "%s: ", cmd); vfprintf(stderr, format, list); + + if (errno != 0) { + fprintf(stderr, ": %s", strerror(errno)); + errno = 0; + } + fprintf(stderr, "\n"); } @@ -21,8 +33,15 @@ void error(const char *format, ...) { fprintf(stderr, "%s: ", cmd); vfprintf(stderr, format, list); + + if (errno != 0) { + fprintf(stderr, ": %s", strerror(errno)); + errno = 0; + } + fprintf(stderr, "\n"); - exit(EXIT_FAILURE); + + die(); } void output(const char *format, ...) { diff --git a/lib/error.h b/lib/error.h deleted file mode 100644 index bae532e..0000000 --- a/lib/error.h +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef ERROR_H -#define ERROR_H - -__attribute__ ((__format__(printf, 1, 2))) -void error_s(const char* format, ...); - -__attribute__ ((__format__(printf, 1, 2))) -void error(const char* format, ...); - -__attribute__ ((__format__(printf, 1, 2))) -void output(const char* format, ...); - -#endif diff --git a/lib/file.c b/lib/file.c index f89b489..4af665d 100644 --- a/lib/file.c +++ b/lib/file.c @@ -1,6 +1,4 @@ -#include "file.h" -#include "error.h" -#include "convert.h" +#include "lslib.h" #include #include @@ -21,7 +19,7 @@ FILE* get_file_s(const char* path, const char* type) { if (lstat(path, &s) < 0) { if (type[0] != 'r') goto read; - error_s("failed to read %s: %s", path, strerror(errno)); + error_s("failed to read %s", path); return NULL; } @@ -35,7 +33,7 @@ read: file = fopen(path, type); if (file == NULL) { - error_s("failed to %s file %s: %s", type[0] == 'r' ? "read" : "write", path, strerror(errno)); + error_s("failed to %s file %s", type[0] == 'r' ? "read" : "write", path); } return file; @@ -48,8 +46,8 @@ FILE* get_file(const char* path, const char* type) { } int get_tty (void) { - int fd = open(_PATH_TTY, O_RDONLY); - if (fd < 0) error("failed to get tty: %s", strerror(errno)); + int fd = open(_PATH_TTY, O_RDONLY | O_NOCTTY | O_SYNC); + if (fd < 0) error("failed to get tty"); return fd; } @@ -57,7 +55,7 @@ FILE* get_tty_stream(char* type) { int fd = get_tty(); FILE* file = fdopen(fd, type); if (file == NULL) { - error("failed to open tty stream: %s", strerror(errno)); + error("failed to open tty stream"); } return file; } diff --git a/lib/file.h b/lib/file.h deleted file mode 100644 index 0bb5939..0000000 --- a/lib/file.h +++ /dev/null @@ -1,14 +0,0 @@ -#ifndef FILE_H -#define FILE_H - -#include - -FILE* get_file_s(const char* path, const char* type); - -FILE* get_file(const char* path, const char* type); - -int get_tty(void); - -FILE* get_tty_stream(char* type); - -#endif diff --git a/lib/identity.c b/lib/identity.c new file mode 100644 index 0000000..58dcf52 --- /dev/null +++ b/lib/identity.c @@ -0,0 +1,24 @@ +#include "lslib.h" + +#include +#include +#include +#include + +void change_identity(const struct passwd* pw) { + int res; + + res = initgroups(pw->pw_name, pw->pw_gid); + endgrent(); + + if (res != 0) { + if (errno == ENOSYS && pw->pw_uid == getuid()) { + return; + } + + error("can't set groups"); + } + + xsetgid(pw->pw_gid); + xsetuid(pw->pw_uid); +} diff --git a/lib/lslib.h b/lib/lslib.h index dfa1202..7abf7c1 100644 --- a/lib/lslib.h +++ b/lib/lslib.h @@ -3,14 +3,138 @@ #include #include +#include +#include + + +#define ANSCII "\x1b[" +#define NEXT ";" + +#define RESET "0" +#define BOLD "1" + +#define NORMAL "3" +#define BACKGROUND "4" +#define HIGHLIGHT "9" + +#define BLACK "0" +#define RED "1" +#define GREEN "2" +#define YELLOW "3" +#define BLUE "4" +#define MAGENTA "5" +#define TURQUOISE "6" +#define WHITE "7" + +#define COLOR "m" + + +typedef uint8_t bool; +#define true 1 +#define false 0 + + +#define UNUSED(x) (void)(x) +#define ARG_UNUSED 0 +#define ARG_USED 1 +#define ARG_IGNORE 2 +#define ARG_INVALID 3 + +void check_arg (char* arg); +void global_help(void (*help)(void)); +void parse_help (int argc, char** argv, void (*help)(void)); +int parse_args (int argc, char** argv, void (*help)(void), int (*short_arg)(char, char*), int (*long_arg)(char*, char*)); + + +FILE* get_file_s(const char* path, const char* type); +FILE* get_file(const char* path, const char* type); +int get_tty(void); +FILE* get_tty_stream(char* type); +void nuke_str(char* type); + + +char* get_path_buffer(void); +int push_path_buffer(const char* string); +void pop_path_buffer(int i); + +char* get_path_buffer_2(void); +int push_path_buffer_2(const char* string); +void pop_path_buffer_2(int i); + + + +long int get_number(const char* text); +long int get_blkm(const char* text); +mode_t get_mode(const char* text); + +bool streql(const char* a, const char* b); +bool prefix(const char* pre, const char* str); + +void print_file_size(size_t bytes, char buf[5]); +void print_date_time(time_t mills, char buf[13]); +void print_file_path(char* path); +bool is_dot_dir(const char* path); +const char* get_last_component(const char* path); + + +void die (void); + +__attribute__ ((__format__(printf, 1, 2))) +void error_s(const char* format, ...); + +__attribute__ ((__format__(printf, 1, 2))) +void error(const char* format, ...); + +__attribute__ ((__format__(printf, 1, 2))) +void output(const char* format, ...); + + +typedef struct regex_t* re_t; +re_t re_compile(const char* pattern); +int re_matchp(re_t pattern, const char* text, int* matchlength); +int re_match(const char* pattern, const char* text, int* matchlength); + + +struct Stack { + size_t size; + size_t capacity; + void* data; +}; + +void stack_init(struct Stack* stack, size_t size); +void stack_push(struct Stack* stack, void* data, size_t len); +void* stack_pop(struct Stack* stack, size_t len); +void stack_free(struct Stack* stack); + +void stack_push_int(struct Stack* stack, int value); +bool stack_pop_int(struct Stack* stack, int* value); + + +#define DEFAULT_SHELL "/bin/sh" +#define DEFAULT_PATH "/sbin:/usr/sbin:/bin:/usr/bin" + +void setup_environment(const char *shell, bool new_env, bool clear_env, const struct passwd *pw); +void exec_shell(const char *shell, bool loginshell, const char **additional_args); + + +int check_password(const struct passwd *pw, char* plaintext); +int prompt_password(const struct passwd *pw, char* prompt); + + +void change_identity(const struct passwd* pw); + + +void* xalloc(size_t size); +void* xrealloc(void* ptr, size_t size); +void* xzalloc(size_t size); +void xsetenv(const char *name, const char *value); +void xsetuid(uid_t uid); +void xsetgid(gid_t gid); +struct passwd* xgetpwnam(char* name); + +#define PASSWORD_INVALID 0 +#define PASSWORD_VALID 1 +#define PASSWORD_EMPTY 2 -#include "args.h" -#include "buffer.h" -#include "def.h" -#include "convert.h" -#include "error.h" -#include "file.h" -#include "regex.h" -#include "stack.h" #endif diff --git a/lib/password.c b/lib/password.c new file mode 100644 index 0000000..7457878 --- /dev/null +++ b/lib/password.c @@ -0,0 +1,70 @@ +#include "lslib.h" + +#include +#include +#include +#include +#include +#include +#include + +#define SHADOW_BUFSIZE 256 + +static const char* get_passwd(const struct passwd* pw) { + const char *pass; + + if (!pw) + return "aa"; /* "aa" will never match */ + + pass = pw->pw_passwd; + + if ((pass[0] == 'x' || pass[0] == '*') && !pass[1]) { + struct spwd* result; + + errno = 0; + result = getspnam(pw->pw_name); + + if (errno == EACCES) { + errno = 0; + error("binary not properly installed"); + } + + pass = (result == NULL) ? "aa" : result->sp_pwdp; + } + + return pass; +} + +int check_password(const struct passwd *pw, char* plaintext) { + char* encrypted; + char* salt; + char* p; + const char *pw_pass; + int r; + + pw_pass = get_passwd(pw); + if (!pw_pass[0]) { + return PASSWORD_EMPTY; + } + + salt = strdup(pw_pass); + if (salt == NULL) die(); + p = strchr(salt + 1, '$'); + if (p == NULL) die(); + p = strchr(p + 1, '$'); + if (p == NULL) die(); + p[1] = 0; + + encrypted = crypt(plaintext, salt); + r = (strcmp(encrypted, pw_pass) == 0); + + nuke_str(plaintext); + free(salt); + + return r; +} + +int prompt_password(const struct passwd *pw, char* prompt) { + char* plaintext = getpass(prompt); + return check_password(pw, plaintext); +} diff --git a/lib/regex.c b/lib/regex.c index 0e0dc52..cba8a97 100644 --- a/lib/regex.c +++ b/lib/regex.c @@ -29,7 +29,8 @@ -#include "regex.h" +#include "lslib.h" + #include #include diff --git a/lib/regex.h b/lib/regex.h deleted file mode 100644 index d4c61b6..0000000 --- a/lib/regex.h +++ /dev/null @@ -1,54 +0,0 @@ -/* - * - * Mini regex-module inspired by Rob Pike's regex code described in: - * - * http://www.cs.princeton.edu/courses/archive/spr09/cos333/beautiful.html - * - * - * - * Supports: - * --------- - * '.' Dot, matches any character - * '^' Start anchor, matches beginning of string - * '$' End anchor, matches end of string - * '*' Asterisk, match zero or more (greedy) - * '+' Plus, match one or more (greedy) - * '?' Question, match zero or one (non-greedy) - * '[abc]' Character class, match if one of {'a', 'b', 'c'} - * '[^abc]' Inverted class, match if NOT one of {'a', 'b', 'c'} -- NOTE: feature is currently broken! - * '[a-zA-Z]' Character ranges, the character set of the ranges { a-z | A-Z } - * '\s' Whitespace, \t \f \r \n \v and spaces - * '\S' Non-whitespace - * '\w' Alphanumeric, [a-zA-Z0-9_] - * '\W' Non-alphanumeric - * '\d' Digits, [0-9] - * '\D' Non-digits - * - * - */ - -#ifndef _TINY_REGEX_C -#define _TINY_REGEX_C - - -#ifndef RE_DOT_MATCHES_NEWLINE -/* Define to 0 if you DON'T want '.' to match '\r' + '\n' */ -#define RE_DOT_MATCHES_NEWLINE 1 -#endif - -/* Typedef'd pointer to get abstract datatype. */ -typedef struct regex_t* re_t; - -/* Compile regex string pattern to a regex_t-array. */ -re_t re_compile(const char* pattern); - - -/* Find matches of the compiled pattern inside text. */ -int re_matchp(re_t pattern, const char* text, int* matchlength); - - -/* Find matches of the txt pattern inside text (will compile automatically first). */ -int re_match(const char* pattern, const char* text, int* matchlength); - - -#endif /* ifndef _TINY_REGEX_C */ diff --git a/lib/shell.c b/lib/shell.c new file mode 100644 index 0000000..9a38b40 --- /dev/null +++ b/lib/shell.c @@ -0,0 +1,59 @@ +#include "lslib.h" + +#include +#include +#include + +void setup_environment(const char *shell, bool new_env, bool clear_env, const struct passwd *pw) { + if (!shell || !shell[0]) + shell = DEFAULT_SHELL; + + if (clear_env) { + const char* term; + term = getenv("TERM"); + clearenv(); + if (term) + xsetenv("TERM", term); + xsetenv("PATH", DEFAULT_PATH); + } + + if (new_env) { + xsetenv("USER", pw->pw_name); + xsetenv("LOGNAME", pw->pw_name); + xsetenv("HOME", pw->pw_dir); + xsetenv("SHELL", shell); + } +} + +void exec_shell(const char *shell, bool loginshell, const char **additional_args) { + + const char** args; + + args = additional_args; + while (args && *args) + args++; + + args = xzalloc(sizeof(args[0]) * (2 + (args - additional_args))); + + if (!shell || !shell[0]) + shell = DEFAULT_SHELL; + + args[0] = get_last_component(shell); + + if (loginshell) { + size_t len = strlen(shell) + 2; + char* arg = xalloc(len); + arg[0] = '-'; + memcpy(&arg[1], shell, len - 1); + args[0] = arg; + } + + if (additional_args) { + int count = 0; + while (*additional_args) + args[++count] = *additional_args++; + } + + execv(shell, (char**) args); + error("cannot execute '%s'", shell); +} diff --git a/lib/stack.c b/lib/stack.c index acffc1a..02226d3 100644 --- a/lib/stack.c +++ b/lib/stack.c @@ -1,4 +1,4 @@ -#include "stack.h" +#include "lslib.h" #include #include @@ -8,14 +8,14 @@ void stack_init(struct Stack* stack, size_t size) { stack->size = 0; stack->capacity = size; - stack->data = malloc(size); + stack->data = xalloc(size); } void stack_push(struct Stack* stack, void* data, size_t len) { size_t new_size = stack->size + len; if (new_size >= stack->capacity) { stack->capacity = new_size * 2; - stack->data = realloc(stack->data, stack->capacity); + stack->data = xrealloc(stack->data, stack->capacity); } memcpy((uint8_t*)stack->data + stack->size, data, len); stack->size += len; diff --git a/lib/stack.h b/lib/stack.h deleted file mode 100644 index 38fb185..0000000 --- a/lib/stack.h +++ /dev/null @@ -1,22 +0,0 @@ -#ifndef STACK_H -#define STACK_H - -#include "def.h" - -#include - -struct Stack { - size_t size; - size_t capacity; - void* data; -}; - -void stack_init(struct Stack* stack, size_t size); -void stack_push(struct Stack* stack, void* data, size_t len); -void* stack_pop(struct Stack* stack, size_t len); -void stack_free(struct Stack* stack); - -void stack_push_int(struct Stack* stack, int value); -bool stack_pop_int(struct Stack* stack, int* value); - -#endif diff --git a/lib/xfuncs.c b/lib/xfuncs.c new file mode 100644 index 0000000..43242de --- /dev/null +++ b/lib/xfuncs.c @@ -0,0 +1,49 @@ +#include "lslib.h" + +#include +#include +#include +#include + +void* xalloc(size_t size) { + void *ptr = malloc(size); + if (ptr == NULL && size != 0) die(); + return ptr; +} + +void* xrealloc(void* ptr, size_t size) { + ptr = realloc(ptr, size); + if (ptr == NULL && size != 0) die(); + return ptr; +} + +void* xzalloc(size_t size) { + void* ptr = xalloc(size); + memset(ptr, 0, size); + return ptr; +} + +void xsetenv(const char *name, const char *value) { + if (setenv(name, value, 1)) + error("cannot set env"); +} + +void xsetuid(uid_t uid) { + if (setuid(uid)) + error("cannot set uid"); +} + +void xsetgid(gid_t gid) { + if (setgid(gid)) + error("cannot set gid"); +} + +struct passwd* xgetpwnam(char* name) { + struct passwd* pw; + pw = getpwnam(name); + + if (!pw) + error("cannot get user: '%s'", name); + + return pw; +} -- cgit v1.2.3-freya