--- /dev/null
+/*
+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;
+ }
+}
--- /dev/null
+#ifndef DISPATCH_FI_H
+#define DISPATCH_FI_H
+#include "local_common.h"
+
+int dispatch(char **argv, char **envp);
+
+#endif
+
+
--- /dev/null
+/*
+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);
+}
+
--- /dev/null
+#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
+
+
+++ /dev/null
-/*
-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;
- }
-}
+++ /dev/null
-#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
-
-
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
... 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
*/
#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
//--------------------------------------------------------------------------------
// 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;
}
#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;
}
//--------------------------------------------------------------------------------
- // 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;
}
#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
#define ERR_FAILED_USERADD 8
-struct uid_gid subu_mk_0(char *subu_name);
+struct uid_gid subu_mk_0(char *subuname);
#endif
+++ /dev/null
-/*
-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);
-}
-
+++ /dev/null
-#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
-
-