Mercurial > trustbridge
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