From 369034229c6e8d1878f2fdb6ea8325c3bbe3a2b2 Mon Sep 17 00:00:00 2001 From: Thomas Walker Lynch Date: Mon, 11 Feb 2019 13:08:51 +0100 Subject: [PATCH] subu-mk-0 checkpoint --- src/dispatch.c | 52 +++++++++++ src/dispatch.h | 9 ++ src/{useradd.fi.c => dispatch_useradd.c} | 4 +- src/{useradd.fi.h => dispatch_useradd.h} | 8 +- src/run.c | 46 ---------- src/run.h | 29 ------ src/subu-mk-0.fi.c | 109 ++++++++++++++--------- src/subu-mk-0.fi.h | 4 +- 8 files changed, 136 insertions(+), 125 deletions(-) create mode 100644 src/dispatch.c create mode 100644 src/dispatch.h rename src/{useradd.fi.c => dispatch_useradd.c} (92%) rename src/{useradd.fi.h => dispatch_useradd.h} (75%) delete mode 100644 src/run.c delete mode 100644 src/run.h diff --git a/src/dispatch.c b/src/dispatch.c new file mode 100644 index 0000000..b6e122c --- /dev/null +++ b/src/dispatch.c @@ -0,0 +1,52 @@ +/* +fork/exec/wait a command + +if the error values returned by the exec'd program +are less than 1 << 16, then + +*/ + +#include +#include +#include +#include +#include +#include "local_common.h" +#include "dispatch.h" + +/* + returns -1 upon failure + + The wstatus returned from wait() might be either the error we returned when exec failed, + or the return value from the exec'ed process. We don't know what the possible return + values are from exec'ed process might be, so we have no way of multiplexing a unique + exec error code with it. + + specific dispatch versions can be made for specific functions. +*/ + + +int dispatch(char **argv, char **envp){ + if( !argv || !argv[0] ){ + fprintf(stderr, "argv[0] null on call to dispatch().\n"); + return -1; + } + pid_t pid = fork(void); + if( pid == -1 ){ + fprintf(stderr, "fork() failed in dispatch().\n"); + return -1; + } + if( pid == 0 ){ // we are the child + execvpe(argv[0], argv, envp); + // exec will only return if it has an error .. + perror(command); + return -1; + }else{ // we are the parent + int wstatus; + wait(1, &wstatus, 0); + if(wstatus) + return -1; + else + return 0; + } +} diff --git a/src/dispatch.h b/src/dispatch.h new file mode 100644 index 0000000..8f4ce44 --- /dev/null +++ b/src/dispatch.h @@ -0,0 +1,9 @@ +#ifndef DISPATCH_FI_H +#define DISPATCH_FI_H +#include "local_common.h" + +int dispatch(char **argv, char **envp); + +#endif + + diff --git a/src/useradd.fi.c b/src/dispatch_useradd.c similarity index 92% rename from src/useradd.fi.c rename to src/dispatch_useradd.c index ff91646..4bfbcf5 100644 --- a/src/useradd.fi.c +++ b/src/dispatch_useradd.c @@ -10,10 +10,10 @@ would be found there instead. #include #include #include "local_common.h" -#include "run.h" +#include "dispatch_useradd.h" // we have a contract with the caller that argv[1] is always the subuname -useradd_ret useradd(char **argv, char **envp){ +useradd_ret dispatch_useradd(char **argv, char **envp){ run_err_init(run_err); if( !argv || !argv[0] || !argv[1]){ fprintf(stderr,"useradd() needs a first argument as the name of the user to be made"); diff --git a/src/useradd.fi.h b/src/dispatch_useradd.h similarity index 75% rename from src/useradd.fi.h rename to src/dispatch_useradd.h index 0042f1d..39dc77e 100644 --- a/src/useradd.fi.h +++ b/src/dispatch_useradd.h @@ -1,5 +1,5 @@ -#ifndef USERADD_FI_H -#define USERADD_FI_H +#ifndef DISPATCH_USERADD_H +#define DISPATCH_USERADD_H #include #include @@ -11,12 +11,12 @@ #define USERADD_ERR_PWREC (3 << 16); // only use pw_record if error is zero -struct useradd_ret{ +struct dispatch_useradd_ret{ useradd_ret(error=USERADD_ERR_UNDEFINED,pwd=NULL):error(error),pwd(pwd){} int error; struct password *pw_record;// as per getpwnam man page do not free() this. }; -struct useradd_ret useradd(char **argv, char **envp); +struct dispatch_useradd_ret useradd(char **argv, char **envp); #endif diff --git a/src/run.c b/src/run.c deleted file mode 100644 index 6823a06..0000000 --- a/src/run.c +++ /dev/null @@ -1,46 +0,0 @@ -/* -fork/exec/wait a command - -if the error values returned by the exec'd program -are less than 1 << 16, then - -*/ - -#include -#include -#include -#include -#include -#include "local_common.h" - -struct run_err_struct run_err; - -int run(char **argv, char **envp){ - run_err_init(run_err); - if( !argv || !argv[0] ){ - fprintf(stderr, "argv[0] null on call to run().\n"); - run_err.admin = ADMIN_ERR_NO_COMMAND; - return; - } - pid_t pid = fork(void); - if( pid == -1 ){ - fprintf(stderr, "fork() failed in run().\n"); - run_err.admin = ADMIN_ERR_FORK; - return; - } - if( pid == 0 ){ // we are the child - int run_err = execvpe(argv[0], argv, envp); - // exec will only return if it has an error .. - perror(command); - run_err.exec = errno; - return errno; - }else{ // we are the parent - int wstatus; - wait(1, &wstatus, 0); - if(wstatus != 0) run_err.process = wstatus; - if( run_err_has(run_err) ) - return -1; - else - return 0; - } -} diff --git a/src/run.h b/src/run.h deleted file mode 100644 index 8dbff3c..0000000 --- a/src/run.h +++ /dev/null @@ -1,29 +0,0 @@ -#ifndef RUN_FI_H -#define RUN_FI_H - -#include "local_common.h" - -#define ADMIN_ERR_NO_COMMAND 1 -#define ADMIN_ERR_FORK 2 -#define ADMIN_ERR_ARGC 3 - -struct run_err_struct{ - int admin; // admin error - int exec; // errno from failed exec call - int process; // err code returned from process as reported by wait() -}; -inline run_err_init(struct run_err_struct re){ - re.admin = 0; - re.exec = 0; - re.process = 0; -} -inline run_err_has(struct run_err_struct re){ - return re.admin || re.exec || re.process -} - -extern struct run_err_struct run_err; -uint run(char **argv, char **envp); - -#endif - - diff --git a/src/subu-mk-0.fi.c b/src/subu-mk-0.fi.c index af64072..9d32d7b 100644 --- a/src/subu-mk-0.fi.c +++ b/src/subu-mk-0.fi.c @@ -7,7 +7,7 @@ to work with. 2. Then we add user access via setfacl to masteru's home directory and to - subu_land, so that we have permissions to make the home directory. + subuland, so that we have permissions to make the home directory. 3. Then we create the subu home directory. .. I wonder where the system gets the umask for this? Perhaps we should create the dir, and then change @@ -18,7 +18,7 @@ ... then finished, good part is that we never need to move back to root. setfacl -m u:subu:x masteru -setfacl -m u:subu:x masteru/subu_land +setfacl -m u:subu:x masteru/subuland setfacl -m d:u:masteru:rwX,u:masteru:rwX subu */ @@ -34,11 +34,12 @@ setfacl -m d:u:masteru:rwX,u:masteru:rwX subu #include #include #include "config.h" -#include "subu_mk_0.fi.h" +#include "useradd.h" +#include "subu-mk-0.fi.h" typedef unsigned int uint; -uid_gid subu_mk_0(char *subu_name){ +uid_gid subu_mk_0(char *subuname){ //-------------------------------------------------------------------------------- // we must be invoked from a user account and be running as root @@ -56,12 +57,12 @@ uid_gid subu_mk_0(char *subu_name){ //-------------------------------------------------------------------------------- // who are these people anyway? - size_t subu_name_len; + size_t subuname_len; char *masteru_name; { - // subu_name is the first argument passed in - // verify that subu_name is legal! --> code goes here ... - subu_name_len = strlen(subu_name); + // subuname is the first argument passed in + // verify that subuname is legal! --> code goes here ... + subuname_len = strlen(subuname); struct passwd *masteru_pw_record_pt = getpwuid(uid); masteru_name = materu_pw_record_pt->pw_name; } @@ -70,61 +71,73 @@ uid_gid subu_mk_0(char *subu_name){ #endif //-------------------------------------------------------------------------------- - // build the subu_land path - char *subu_land; - size_t subu_land_len; + // build the subuland path + char *masteru_home; + char *subuland; + size_t subuland_len; { - char *masteru_home_dir = passwd_record_pt->pw_dir; - size_t masteru_home_dir_len = strlen(masteru_home_dir); - if( masteru_home_dir_len == 0 || masteru_home_dir[0] == '(' ){ + masteru_home = passwd_record_pt->pw_dir; + size_t masteru_home_len = strlen(masteru_home); + if( masteru_home_len == 0 || masteru_home[0] == '(' ){ fprintf(stderr,"strange, %s has no home directory\n", masteru_name); return ERR_BAD_MASTERU_HOME; } - char *subu_land_extension = "/subu_land/"; - size_t subu_land_extension_len = strlen(subu_land_extension); - // add space in the subu_land buffer to append the subu_name later - subu_land = (char *)malloc( masteru_home_dir_len + subu_land_extension_len + subu_name_len + 1 ); - strcpy(subu_land, masteru_home_dir); - strcpy(subu_land + masteru_home_dir_len, subu_land_extension); - subu_land_len = masteru_home_dir_len + subu_land_extension_len + subu_name_len; + char *subuland_extension = "/subuland/"; + size_t subuland_extension_len = strlen(subuland_extension); + subuland = (char *)malloc( masteru_home_len + subuland_extension_len + 1 ); + strcpy(subuland, masteru_home); + strcpy(subuland + masteru_home_len, subuland_extension); + subuland_len = masteru_home_len + subuland_extension_len + subuname_len; } #ifdef DEBUG - printf("The path to subu_land: \"%s\"\n", subu_land); + printf("The path to subuland: \"%s\"\n", subuland); #endif //-------------------------------------------------------------------------------- - // Just because masteru_home_dir is referenced in /etc/passwd does not mean it exists. - // We also require that the subu_land sub directory exists. + // Just because masteru_home is referenced in /etc/passwd does not mean it exists. + // We also require that the subuland sub directory exists. { struct stat st; - if( stat(masteru_home_dir, &st) == -1) { - fprintf(stderr, "Strange, masteru home does not exist, \"%s\".", masteru_home_dir); + if( stat(masteru_home, &st) == -1) { + fprintf(stderr, "Strange, masteru home does not exist, \"%s\".", masteru_home); return ERR_NOT_EXIST_MASTERU_HOME; } - if( stat(subu_land, &st) == -1) { - fprintf(stderr, "$masteru_home/subu_land not exist"); - return ERR_NOT_EXIST_SUBU_LAND; + if( stat(subuland, &st) == -1) { + fprintf(stderr, "$masteru_home/subuland not exist"); + return ERR_NOT_EXIST_SUBULAND; } } //-------------------------------------------------------------------------------- - // the name for the subu home directory, which is subu_land/subu_name - strcpy (subu_land + subu_land_len, subu_name); // we had left room in the subu_land buffer for subu_name - char *subu_home_path = subu_land; // the buffer now holds the subu_home_path, so we call it as such + // the name for the subu home directory, which is subuland/subuname + char subuhome; + { + subuhome_len = subuland_len + subuname_len; + subuhome = (char *)malloc(subuhome_len + 1); + strcpy (subuhome, subuland); + strcpy (subuhome + subuland_len, subuname); + } #ifdef DEBUG - printf("subu home: %s\n", subu_home_path); + printf("subuhome: %s\n", subuhome); #endif - //-------------------------------------------------------------------------------- - // make the subservient user account + /*-------------------------------------------------------------------------------- + make the subservient user account + We can't make the home directory yet, because we need to add execute access rights to + masteru home and subuland so that the subu user can cd to subuhome. + -d, --home-dir HOME_DIR + The new user will be created using HOME_DIR as the value for the user's login directory. The default + is to append the LOGIN name to BASE_DIR and use that as the login directory name. The directory + HOME_DIR does not have to exist but will not be created if it is missing. + */ uid_t subu_uid; tid_t subu_gid; { char *argv[5]; - argv[0] = command; - argv[1] = subu_name; + argv[0] = "/usr/bin/useradd"; + argv[1] = subuname; argv[2] = "-d"; - argv[3] = subu_home_path; + argv[3] = subuhome; argv[4] = (char *) NULL; char *envp[1]; envp[0] (char *) NULL; @@ -138,18 +151,32 @@ uid_gid subu_mk_0(char *subu_name){ } //-------------------------------------------------------------------------------- - // Set acls on the subu home directory - + // give subu x access to masteru and subuland + { + char access[2 + subuname_len + 2 + 1]; + strcpy(access, "u:"); + strcpy(access + 2, subuname); + strcpy(access + 2 + subuname_len, ":x"); + + char *argv[]; + argv[0] = "/usr/bin/setfacl"; + argv[1] = "-m"; + argv[2] = access; + argv[3] = masteru_home + + } // subu sets acls to allow masteru access + free(subuland); + free(subuhome); return 0; } /* // change to subu space if( seteuid(subu_uid) == -1 || setegid(subu_gid) == -1 ){ // we are root so this should never happen - fprintf(stderr,"Strangely, root could not seteuid/setegid to %s\n", subu_name); + fprintf(stderr,"Strangely, root could not seteuid/setegid to %s\n", subuname); return ERR_FAILED_MKDIR_SUBU; } diff --git a/src/subu-mk-0.fi.h b/src/subu-mk-0.fi.h index cf2828d..2e13d8c 100644 --- a/src/subu-mk-0.fi.h +++ b/src/subu-mk-0.fi.h @@ -1,8 +1,6 @@ #ifndef SUBU_MK_0_H #define SUBU_MK_0_H -#include "useradd.fi.h" - #define ERR_ARG_CNT 1 #define ERR_SETUID_ROOT 2 #define ERR_BAD_MASTERU_HOME 3 @@ -13,6 +11,6 @@ #define ERR_FAILED_USERADD 8 -struct uid_gid subu_mk_0(char *subu_name); +struct uid_gid subu_mk_0(char *subuname); #endif -- 2.20.1