Explorar el Código

ncd/interface_modules/interface_badvpn: support running the client program as a specific user

ambrop7 hace 15 años
padre
commit
e084b20f1f
Se han modificado 4 ficheros con 66 adiciones y 4 borrados
  1. 1 1
      examples/bprocess_example.c
  2. 26 1
      ncd/interface_modules/interface_badvpn.c
  3. 38 1
      system/BProcess.c
  4. 1 1
      system/BProcess.h

+ 1 - 1
examples/bprocess_example.c

@@ -73,7 +73,7 @@ int main (int argc, char **argv)
     
     char **p_argv = argv + 1;
     
-    if (!BProcess_Init(&process, &manager, process_handler, NULL, program, p_argv)) {
+    if (!BProcess_Init(&process, &manager, process_handler, NULL, program, p_argv, NULL)) {
         DEBUG("BProcess_Init failed");
         goto fail4;
     }

+ 26 - 1
ncd/interface_modules/interface_badvpn.c

@@ -97,6 +97,25 @@ fail0:
     return 0;
 }
 
+static const char * read_user (struct instance *o)
+{
+    // find statement
+    struct NCDConfig_statements *user_st = NCDConfig_find_statement(o->i->conf->statements, "badvpn.user");
+    if (!user_st) {
+        NCDInterfaceModuleInst_Backend_Log(o->i, BLOG_ERROR, "badvpn.user missing");
+        return NULL;
+    }
+    
+    // check arity
+    char *user_arg;
+    if (!NCDConfig_statement_has_one_arg(user_st, &user_arg)) {
+        NCDInterfaceModuleInst_Backend_Log(o->i, BLOG_ERROR, "badvpn.user: wrong arity");
+        return NULL;
+    }
+    
+    return user_arg;
+}
+
 static void process_handler (struct instance *o, int normally, uint8_t normally_exit_status)
 {
     NCDInterfaceModuleInst_Backend_Log(o->i, BLOG_INFO, "process terminated");
@@ -133,6 +152,12 @@ static void * func_new (NCDInterfaceModuleInst *i)
         goto fail2;
     }
     
+    // read username
+    const char *username = read_user(o);
+    if (!username) {
+        goto fail2;
+    }
+    
     // build cmdline
     CmdLine cl;
     if (!build_cmdline(o, &cl)) {
@@ -141,7 +166,7 @@ static void * func_new (NCDInterfaceModuleInst *i)
     }
     
     // start process
-    if (!BProcess_Init(&o->process, o->i->manager, (BProcess_handler)process_handler, o, ((char **)cl.arr.v)[0], (char **)cl.arr.v)) {
+    if (!BProcess_Init(&o->process, o->i->manager, (BProcess_handler)process_handler, o, ((char **)cl.arr.v)[0], (char **)cl.arr.v, username)) {
         NCDInterfaceModuleInst_Backend_Log(o->i, BLOG_ERROR, "BProcess_Init failed");
         CmdLine_Free(&cl);
         goto fail2;

+ 38 - 1
system/BProcess.c

@@ -27,6 +27,9 @@
 #include <sys/wait.h>
 #include <unistd.h>
 #include <signal.h>
+#include <grp.h>
+#include <pwd.h>
+#include <errno.h>
 
 #include <misc/offset.h>
 #include <system/BLog.h>
@@ -165,7 +168,7 @@ void BProcessManager_Free (BProcessManager *o)
     BUnixSignal_Free(&o->signal, 1);
 }
 
-int BProcess_Init (BProcess *o, BProcessManager *m, BProcess_handler handler, void *user, const char *file, char *const argv[])
+int BProcess_Init (BProcess *o, BProcessManager *m, BProcess_handler handler, void *user, const char *file, char *const argv[], const char *username)
 {
     // init arguments
     o->m = m;
@@ -182,15 +185,49 @@ int BProcess_Init (BProcess *o, BProcessManager *m, BProcess_handler handler, vo
     if (pid == 0) {
         // this is child
         
+        // find maximum file descriptors
         int max_fd = sysconf(_SC_OPEN_MAX);
         if (max_fd < 0) {
             abort();
         }
         
+        // close all file descriptors
         for (int i = 0; i < max_fd; i++) {
             close(i);
         }
         
+        // assume identity of username, if requested
+        if (username) {
+            size_t bufsize = sysconf(_SC_GETPW_R_SIZE_MAX);
+            if (bufsize < 0) {
+                bufsize = 16384;
+            }
+            
+            char *buf = malloc(bufsize);
+            if (!buf) {
+                abort();
+            }
+            
+            struct passwd pwd;
+            struct passwd *res;
+            getpwnam_r(username, &pwd, buf, bufsize, &res);
+            if (!res) {
+                abort();
+            }
+            
+            if (initgroups(username, pwd.pw_gid) < 0) {
+                abort();
+            }
+            
+            if (setgid(pwd.pw_gid) < 0) {
+                abort();
+            }
+            
+            if (setuid(pwd.pw_uid) < 0) {
+                abort();
+            }
+        }
+        
         execv(file, argv);
         
         abort();

+ 1 - 1
system/BProcess.h

@@ -58,7 +58,7 @@ typedef struct {
 int BProcessManager_Init (BProcessManager *o, BReactor *reactor) WARN_UNUSED;
 void BProcessManager_Free (BProcessManager *o);
 
-int BProcess_Init (BProcess *o, BProcessManager *m, BProcess_handler handler, void *user, const char *file, char *const argv[]) WARN_UNUSED;
+int BProcess_Init (BProcess *o, BProcessManager *m, BProcess_handler handler, void *user, const char *file, char *const argv[], const char *username) WARN_UNUSED;
 void BProcess_Free (BProcess *o);
 int BProcess_Terminate (BProcess *o);
 int BProcess_Kill (BProcess *o);