# HG changeset patch # User Andre Heinecke # Date 1396528103 -7200 # Node ID fac7e1b0e5588bc4b1c7681e1cf029610bb5fb85 # Parent aec9008c3b300bfc91e956d4aba461d0a05ab565 Add nss store calling function and use it in cinst diff -r aec9008c3b30 -r fac7e1b0e558 cinst/CMakeLists.txt --- a/cinst/CMakeLists.txt Thu Apr 03 14:26:43 2014 +0200 +++ b/cinst/CMakeLists.txt Thu Apr 03 14:28:23 2014 +0200 @@ -6,6 +6,7 @@ set(CINST_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/windowsstore.c + ${CMAKE_CURRENT_SOURCE_DIR}/nssstore_linux.c ${CMAKE_CURRENT_SOURCE_DIR}/main.c ) add_executable(cinst ${CINST_SOURCES}) diff -r aec9008c3b30 -r fac7e1b0e558 cinst/main.c --- a/cinst/main.c Thu Apr 03 14:26:43 2014 +0200 +++ b/cinst/main.c Thu Apr 03 14:28:23 2014 +0200 @@ -40,6 +40,7 @@ #include "logging.h" #include "errorcodes.h" #include "windowsstore.h" +#include "nssstore.h" /* The certificate list + instructions may only be so long as * twice the accepted certificatelist size */ @@ -200,11 +201,6 @@ list_status_t list_status; bool do_uninstall = false; - for (ret = 0; ret < argc; ret++) - { - printf("Arg %i : %s \n", ret, argv[ret]); - } - /* Some very static argument parsing. list= and instructions= is only added to make it more transparent how this programm is called if a user looks at the detailed uac dialog. */ @@ -260,11 +256,14 @@ if (do_uninstall) { #ifdef WIN32 - return write_stores_win (NULL, all_valid_certs); -#else - /*TODO*/ - return 0; + ret = write_stores_win (NULL, all_valid_certs); + if (ret != 0) + { + ERRORPRINTF ("Failed to write windows stores retval: %i\n", ret); + } #endif + ret = write_stores_nss (NULL, all_valid_certs); + return ret; } ret = read_instructions_file (instruction_file_name, &to_install, @@ -300,8 +299,18 @@ } #ifdef WIN32 - return write_stores_win (to_install, to_remove); + ret = write_stores_win (to_install, to_remove); + if (ret != 0) + { + ERRORPRINTF ("Failed to write windows stores retval: %i\n", ret); + } #endif + ret = write_stores_nss (to_install, to_remove); + + if (ret != 0) + { + ERRORPRINTF ("Failed to write nss stores"); + } /* Make valgrind happy */ strv_free (to_install); diff -r aec9008c3b30 -r fac7e1b0e558 cinst/nssstore.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/cinst/nssstore.h Thu Apr 03 14:28:23 2014 +0200 @@ -0,0 +1,27 @@ +#ifndef NSSSTORE_H +#define NSSSTORE_H +/** @file + * @brief Helper functions controlling the NSS installation process. + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** @brief Write into NSS stores + * + * Starts the nss installation process for all users + * we have the right to impersonate and installs / removes + * the certificates in their stores. + + * @param [in] to_install strv of DER encoded certificates to be added. + * @param [in] to_remove strv of DER encoded certificates to be remvoed. + * @returns 0 on success an errorcode otherwise. + */ +int write_stores_nss (char **to_install, char **to_remove); + +#ifdef __cplusplus +} +#endif + +#endif // NSSSTORE_H diff -r aec9008c3b30 -r fac7e1b0e558 cinst/nssstore_linux.c --- /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 +#include +#include +#include +#include +#include +#include + +#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