Mercurial > trustbridge
view cinst/nssstore_linux.c @ 321:824ef90a6721
Move is_elevated into common/util.c file for better reuse
author | Andre Heinecke <aheinecke@intevation.de> |
---|---|
date | Mon, 07 Apr 2014 10:58:47 +0000 |
parents | 4a3febc6d806 |
children | 5eb7ee4ee819 |
line wrap: on
line source
#ifndef WIN32 /* @file @brief Linux implementation of nssstore process control. */ #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\n", 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