subu-mk-0 checkpoint
authorThomas Walker Lynch <thomas.lynch@reasoningtechnology.com>
Mon, 11 Feb 2019 12:08:51 +0000 (13:08 +0100)
committerThomas Walker Lynch <thomas.lynch@reasoningtechnology.com>
Mon, 11 Feb 2019 12:08:51 +0000 (13:08 +0100)
src/dispatch.c [new file with mode: 0644]
src/dispatch.h [new file with mode: 0644]
src/dispatch_useradd.c [new file with mode: 0644]
src/dispatch_useradd.h [new file with mode: 0644]
src/run.c [deleted file]
src/run.h [deleted file]
src/subu-mk-0.fi.c
src/subu-mk-0.fi.h
src/useradd.fi.c [deleted file]
src/useradd.fi.h [deleted file]

diff --git a/src/dispatch.c b/src/dispatch.c
new file mode 100644 (file)
index 0000000..b6e122c
--- /dev/null
@@ -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 <sys/types.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <errno.h>
+#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 (file)
index 0000000..8f4ce44
--- /dev/null
@@ -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/dispatch_useradd.c b/src/dispatch_useradd.c
new file mode 100644 (file)
index 0000000..4bfbcf5
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+There is no C library interface to useradd(8), but if there were, these functions
+would be found there instead.
+
+*/
+
+#include <sys/types.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <errno.h>
+#include "local_common.h"
+#include "dispatch_useradd.h"
+
+// we have a contract with the caller that argv[1] is always the subuname
+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");
+    return useradd_ret(USERADD_ERR_ARGC, NULL);
+  }
+  char *subu_name = argv[1];
+  if( run(argv, envp) == -1 ){
+    fprintf(stderr,"%s failed\n", argv[0]);
+    return useradd_ret(USER_ERR_RUN);
+  }
+  struct password *pw_record = getpwnam(subu_name);
+  uint count = 1;
+  while( !pw_record && count <= 3 ){
+    #ifdef DEBUG
+    printf("try %u, getpwnam failed, trying again\n", count);
+    #endif
+    sleep(1);
+    pw_record = getpwnam(subu_name);
+    count++;
+  }
+  if( !pw_record ){
+    return struct useradd_ret(USERADD_ERR_PWREC, NULL);
+  }
+  return struct useradd_ret(0, pw_record);
+}
+
diff --git a/src/dispatch_useradd.h b/src/dispatch_useradd.h
new file mode 100644 (file)
index 0000000..39dc77e
--- /dev/null
@@ -0,0 +1,23 @@
+#ifndef DISPATCH_USERADD_H
+#define DISPATCH_USERADD_H
+
+#include <unistd.h>
+#include <pwd.h>
+#include <sys/types.h>
+
+// some value larger than any wstatus value
+#define USERADD_ERR_UNDEFINED (1 << 16);
+#define USERADD_ERR_ARGCNT (2 << 16);
+#define USERADD_ERR_PWREC (3 << 16);
+
+// only use pw_record if error is zero
+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 dispatch_useradd_ret useradd(char **argv, char **envp);
+
+#endif
+
+
diff --git a/src/run.c b/src/run.c
deleted file mode 100644 (file)
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 <sys/types.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <stdio.h>
-#include <errno.h>
-#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 (file)
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
-
-
index af64072..9d32d7b 100644 (file)
@@ -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 <string.h>
 #include <sys/stat.h>
 #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;
   }
 
index cf2828d..2e13d8c 100644 (file)
@@ -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
diff --git a/src/useradd.fi.c b/src/useradd.fi.c
deleted file mode 100644 (file)
index ff91646..0000000
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
-There is no C library interface to useradd(8), but if there were, these functions
-would be found there instead.
-
-*/
-
-#include <sys/types.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <stdio.h>
-#include <errno.h>
-#include "local_common.h"
-#include "run.h"
-
-// we have a contract with the caller that argv[1] is always the subuname
-useradd_ret 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");
-    return useradd_ret(USERADD_ERR_ARGC, NULL);
-  }
-  char *subu_name = argv[1];
-  if( run(argv, envp) == -1 ){
-    fprintf(stderr,"%s failed\n", argv[0]);
-    return useradd_ret(USER_ERR_RUN);
-  }
-  struct password *pw_record = getpwnam(subu_name);
-  uint count = 1;
-  while( !pw_record && count <= 3 ){
-    #ifdef DEBUG
-    printf("try %u, getpwnam failed, trying again\n", count);
-    #endif
-    sleep(1);
-    pw_record = getpwnam(subu_name);
-    count++;
-  }
-  if( !pw_record ){
-    return struct useradd_ret(USERADD_ERR_PWREC, NULL);
-  }
-  return struct useradd_ret(0, pw_record);
-}
-
diff --git a/src/useradd.fi.h b/src/useradd.fi.h
deleted file mode 100644 (file)
index 0042f1d..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-#ifndef USERADD_FI_H
-#define USERADD_FI_H
-
-#include <unistd.h>
-#include <pwd.h>
-#include <sys/types.h>
-
-// some value larger than any wstatus value
-#define USERADD_ERR_UNDEFINED (1 << 16);
-#define USERADD_ERR_ARGCNT (2 << 16);
-#define USERADD_ERR_PWREC (3 << 16);
-
-// only use pw_record if error is zero
-struct 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);
-
-#endif
-
-