diff cinst/nssstore_linux.c @ 302:fac7e1b0e558

Add nss store calling function and use it in cinst
author Andre Heinecke <andre.heinecke@intevation.de>
date Thu, 03 Apr 2014 14:28:23 +0200
parents
children 4a3febc6d806
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/cinst/nssstore_linux.c	Thu Apr 03 14:28:23 2014 +0200
@@ -0,0 +1,178 @@
+#ifndef WIN32
+
+#include <stdbool.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "nssstore.h"
+#include "logging.h"
+#include "strhelp.h"
+
+/**@brief Start the process to install / remove
+ *
+ * This forks the process and executes the NSS installation
+ * process. It also writes the Instructions to that process.
+ *
+ * @param [in] to_install strv of DER encoded certificates to be added.
+ * @param [in] to_remove strv of DER encoded certificates to be remvoed.
+ * @param [in] uid_t uid of the user to install certificates for.
+ * @param [in] gid_t the gid of the user to install certificates for.
+ * @param [in] homedir the homedir of the user.
+ *
+ * @returns childs pid on success. -1 on failure
+ */
+static int
+start_procces_for_user (char **to_install, char **to_remove,
+                        uid_t uid, gid_t gid, char *homedir)
+{
+  int pipe_fd[2];
+  pid_t pid = 0;
+  char *argv[] = {"mozilla", NULL},
+       *envp[2];
+  size_t homedir_len = 0;
+  int ret = -1,
+      i = 0;
+  FILE *stream = NULL;
+  bool success = false;
+
+  if (homedir == NULL)
+    {
+      ERRORPRINTF ("Invalid call to start_process_for_user\n");
+      return -1;
+    }
+
+  homedir_len = strlen (homedir);
+
+  /* Allocate space for HOME=homedir\0 */
+  envp[0] = xmalloc (homedir_len + 6);
+  envp[1] = NULL;
+
+  ret = snprintf (envp[0], homedir_len + 6, "HOME=%s", homedir);
+
+  if (ret < 0 || (size_t) ret != homedir_len + 5)
+    {
+      ERRORPRINTF ("Error setting home env variable.\n");
+      xfree (envp[0]);
+      return -1;
+    }
+
+  DEBUGPRINTF ("Home: %s \n", envp[0]);
+
+  if (pipe (pipe_fd))
+    {
+      ERRORPRINTF ("Failed to create pipe.\n");
+      return -1;
+    }
+
+  pid = fork();
+
+  if (pid == (pid_t) -1)
+    {
+      ERRORPRINTF ("Failed to fork child.\n");
+      return -1;
+    }
+
+  if (pid == (pid_t) 0)
+    {
+      /* Drop privileges */
+      if (setuid (uid) || setgid (gid))
+        {
+          exit(-1);
+        }
+
+      close (pipe_fd[1]);
+      dup2 (pipe_fd[0], 0);
+      close (pipe_fd[0]);
+      /* TODO find path based on current executable */
+      execve ("mozilla", argv, envp);
+      exit (127);
+    }
+
+  close (pipe_fd[0]);
+  stream = fdopen(pipe_fd[1], "w");
+  if (stream == NULL)
+    {
+      ERRORPRINTF ("Failed to open pipe for writing\n");
+      goto done;
+    }
+
+  /* Send the instructions */
+  for (i = 0; to_install && to_install[i]; i++)
+    {
+      if (fprintf (stream, "I:%s\n", to_install[i]) <= 3)
+        {
+          ERRORPRINTF ("Write failed \n");
+          goto done;
+        }
+    }
+
+  for (i = 0; to_remove && to_remove[i]; i++)
+    {
+      if (fprintf (stream, "R:%s\n", to_remove[i]) <= 3)
+        {
+          ERRORPRINTF ("Write failed \n");
+          goto done;
+        }
+    }
+
+  success = true;
+
+done:
+  if (stream) {
+    fclose (stream);
+  }
+  xfree (envp[0]);
+  close(pipe_fd[0]);
+  close(pipe_fd[1]);
+
+  if (success)
+    {
+      return pid;
+    }
+  return -1;
+}
+
+int
+write_stores_nss (char **to_install, char **to_remove)
+{
+  uid_t my_uid = getuid();
+
+  if (my_uid != 0)
+    {
+      /* Running as a user */
+      char *homedir = getenv ("HOME");
+      pid_t childprocess = -1; /* Only one child for single user installation */
+      int status = -1;
+      if (!homedir)
+        {
+          ERRORPRINTF ("Failed to find home directory\n");
+        }
+
+      childprocess = start_procces_for_user (to_install, to_remove,
+                                             my_uid, getgid(), homedir);
+
+      if (childprocess == -1)
+        {
+          ERRORPRINTF ("Failed to start childprocess!\n");
+          return -1;
+        }
+
+      childprocess = waitpid (childprocess, &status, 0);
+      if (childprocess == -1 || !WIFEXITED(status))
+        {
+          ERRORPRINTF ("Waitpid failed.\n");
+          return -1;
+        }
+      DEBUGPRINTF ("Child returned status: %i", WEXITSTATUS(status));
+
+      return 0;
+    }
+  printf ("Installation as root is not yet implemented\n");
+  /* TODO root parse /etc/passwd for users with a home directory */
+  return 0;
+}
+#endif

http://wald.intevation.org/projects/trustbridge/