From ac8354d805c47d4ba28c2c5956ac20f2a6202b20 Mon Sep 17 00:00:00 2001 From: Kevin Lange Date: Thu, 26 Jan 2012 22:46:18 -0600 Subject: [PATCH] Add some system calls, plus a fakish /bin/login --- kernel/include/process.h | 2 + kernel/include/syscall.h | 3 + kernel/sys/syscall.c | 32 +++++++++++ loader/syscall.c | 3 + userspace/esh.c | 14 +++++ userspace/login.c | 117 +++++++++++++++++++++++++++++++++++++++ userspace/terminal.c | 4 +- 7 files changed, 173 insertions(+), 2 deletions(-) create mode 100644 userspace/login.c diff --git a/kernel/include/process.h b/kernel/include/process.h index 93a56983..6f41e7cf 100644 --- a/kernel/include/process.h +++ b/kernel/include/process.h @@ -15,6 +15,8 @@ typedef unsigned int user_t; typedef unsigned int group_t; typedef unsigned char status_t; +#define USER_ROOT_UID (user_t)0 + /* Unix waitpid() options */ enum wait_option{ WCONTINUED, diff --git a/kernel/include/syscall.h b/kernel/include/syscall.h index 95f68b65..0e6d22f3 100644 --- a/kernel/include/syscall.h +++ b/kernel/include/syscall.h @@ -84,6 +84,9 @@ DECL_SYSCALL0(getgraphicswidth); DECL_SYSCALL0(getgraphicsheight); DECL_SYSCALL0(getgraphicsdepth); +DECL_SYSCALL0(getuid); +DECL_SYSCALL1(setuid, unsigned int); + #endif /* diff --git a/kernel/sys/syscall.c b/kernel/sys/syscall.c index 118b4bef..40257336 100644 --- a/kernel/sys/syscall.c +++ b/kernel/sys/syscall.c @@ -9,6 +9,7 @@ #include #include #include +#include #define SPECIAL_CASE_STDIO @@ -232,6 +233,34 @@ static int dup2(int old, int new) { return new; } +static int getuid() { + return current_process->user; +} + +static int setuid(user_t new_uid) { + if (current_process->user != USER_ROOT_UID) { + current_process->user = new_uid; + return 0; + } + return -1; +} + +static int kernel_name_XXX(char * buffer) { + char version_number[1024]; + sprintf(version_number, __kernel_version_format, + __kernel_version_major, + __kernel_version_minor, + __kernel_version_lower, + __kernel_version_suffix); + return sprintf(buffer, "%s %s %s %s %s %s", + __kernel_name, + version_number, + __kernel_version_codename, + __kernel_build_date, + __kernel_build_time, + __kernel_arch); +} + /* * System Call Internals */ @@ -261,6 +290,9 @@ static uintptr_t syscalls[] = { (uintptr_t)&getgraphicsdepth, /* 20 */ (uintptr_t)&mkpipe, (uintptr_t)&dup2, + (uintptr_t)&getuid, + (uintptr_t)&setuid, /* 24 */ + (uintptr_t)&kernel_name_XXX, 0 }; uint32_t num_syscalls; diff --git a/loader/syscall.c b/loader/syscall.c index 323f2c21..2814cf90 100644 --- a/loader/syscall.c +++ b/loader/syscall.c @@ -17,3 +17,6 @@ DEFN_SYSCALL1(wait, 17, int) DEFN_SYSCALL0(getgraphicswidth, 18) DEFN_SYSCALL0(getgraphicsheight, 19) DEFN_SYSCALL0(getgraphicsdepth, 20) + +DEFN_SYSCALL0(getuid, 23) +DEFN_SYSCALL1(setuid, 24, unsigned int) diff --git a/userspace/esh.c b/userspace/esh.c index dc09f979..f16b332f 100644 --- a/userspace/esh.c +++ b/userspace/esh.c @@ -68,6 +68,20 @@ int main(int argc, char ** argv) { int nowait = 0; int free_cmd = 0; int last_ret = 0; + + FILE * motd = fopen("/etc/motd", "r"); + if (motd) { + size_t s = 0; + fseek(motd, 0, SEEK_END); + s = ftell(motd); + fseek(motd, 0, SEEK_SET); + char * m = malloc(sizeof(char) * s); + fread(m, s, 1, motd); + fwrite(m, s, 1, stdout); + fprintf(stdout, "\n"); + fflush(stdout); + } + while (1) { char * cmd = malloc(sizeof(char) * 1024); diff --git a/userspace/login.c b/userspace/login.c new file mode 100644 index 00000000..a229961f --- /dev/null +++ b/userspace/login.c @@ -0,0 +1,117 @@ +/* vim: tabstop=4 shiftwidth=4 noexpandtab + * + * Login Service + * + */ + +#include +#include +#include +#include +#include +#include +#include + +DEFN_SYSCALL1(wait, 17, unsigned int); +DEFN_SYSCALL1(setuid, 24, unsigned int); +DEFN_SYSCALL1(kernel_string_XXX, 25, char *); + +typedef struct { + int uid; + char * name; + char * pass; +} user_combo; + +user_combo users[] = { + {0, "root", "toor"}, + {1, "klange", "herp"} +}; + +int n_users = 2; + +int readline(char * buf, size_t size, uint8_t display) { + size_t collected = 0; + while (collected < size - 1) { + char * cmd = malloc(2); + size_t nread = fread(cmd, 1, 1, stdin); + if (nread > 0) { + if (cmd[0] < 10 || (cmd[0] > 10 && cmd[0] < 32) || cmd[0] > 126) { + continue; + } + buf[collected] = cmd[0]; + if (display || buf[collected] == '\n') { + printf("%c", cmd[0]); + } + fflush(stdout); + if (buf[collected] == '\n') { + goto _done; + } + collected++; + } + } +_done: + buf[collected] = '\0'; + return collected; +} + +int checkUserPass(char * user, char * pass) { + for (int i = 0; i < n_users; ++i) { + if (!strcmp(user, users[0].name)) { + if (!strcmp(pass, users[0].pass)) { + return users[0].uid; + } + } + } + return -1; +} + +int main(int argc, char ** argv) { + /* TODO: Read /etc/shadow */ + + /* TODO: uname() */ + char * _uname = malloc(sizeof(char) * 1024); + syscall_kernel_string_XXX(_uname); + + fprintf(stdout, "\n%s\n\n", _uname); + + while (1) { + char * username = malloc(sizeof(char) * 1024); + char * password = malloc(sizeof(char) * 1024); + + /* TODO: gethostname() */ + char * _hostname = "test"; + + fprintf(stdout, "%s login: ", _hostname); + fflush(stdout); + readline(username, 1024, 1); + + fprintf(stdout, "password: "); + fflush(stdout); + readline(password, 1024, 0); + + int uid = checkUserPass(username, password); + + if (uid < 0) { + fprintf(stdout, "\nLogin failed.\n"); + continue; + } + + pid_t pid = getpid(); + + uint32_t f = fork(); + if (getpid() != pid) { + char * args[] = { + "/bin/esh", + NULL + }; + syscall_setuid(uid); + int i = execve(args[0], args, NULL); + } else { + syscall_wait(f); + } + free(username); + free(password); + } + + return 0; +} diff --git a/userspace/terminal.c b/userspace/terminal.c index ffd3a0f7..8bfb7f28 100644 --- a/userspace/terminal.c +++ b/userspace/terminal.c @@ -2853,8 +2853,8 @@ int main(int argc, char ** argv) { //syscall_dup2(ifd, 0); syscall_dup2(ofd, 1); syscall_dup2(ofd, 2); - char * tokens[] = {"/bin/esh",NULL}; - int i = execve("/bin/esh", tokens, NULL); + char * tokens[] = {"/bin/login",NULL}; + int i = execve(tokens[0], tokens, NULL); return 0; } else { char buf[1024];