X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=src%2Futil%2Fos_installation.c;h=30e729dc63b36360daec7297501bd85aa664346e;hb=69f9662283ade69910b500e00f491a47c1b4eb8c;hp=b63a19d2e9d6c9ffcf86fd27997ccd57de890229;hpb=20b9651856311306abda3619741e28817da3a8d1;p=oweals%2Fgnunet.git diff --git a/src/util/os_installation.c b/src/util/os_installation.c index b63a19d2e..30e729dc6 100644 --- a/src/util/os_installation.c +++ b/src/util/os_installation.c @@ -4,7 +4,7 @@ GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published - by the Free Software Foundation; either version 2, or (at your + by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but @@ -30,11 +30,7 @@ #include /* for u16_to_u8 */ #include "platform.h" -#include "gnunet_common.h" -#include "gnunet_configuration_lib.h" -#include "gnunet_disk_lib.h" -#include "gnunet_os_lib.h" -#include "gnunet_strings_lib.h" +#include "gnunet_util_lib.h" #if DARWIN #include #include @@ -47,6 +43,7 @@ #define LOG_STRERROR_FILE(kind,syscall,filename) GNUNET_log_from_strerror_file (kind, "util", syscall, filename) + #if LINUX /** * Try to determine path by reading /proc/PID/exe @@ -119,12 +116,13 @@ get_path_from_proc_exe () } #endif -#if WINDOWS +#if WINDOWS static HINSTANCE dll_instance; -/* GNUNET_util_cl_init() in common_logging.c is preferred. +/** + * GNUNET_util_cl_init() in common_logging.c is preferred. * This function is only for thread-local storage (not used in GNUnet) * and hInstance saving. */ @@ -230,6 +228,7 @@ get_path_from_module_filename () } #endif + #if DARWIN /** * Signature of the '_NSGetExecutablePath" function. @@ -295,7 +294,7 @@ get_path_from_dyld_image () c = _dyld_image_count (); for (i = 0; i < c; i++) { - if (_dyld_get_image_header (i) != &_mh_dylib_header) + if (((const void *) _dyld_get_image_header (i)) != (const void *)&_mh_dylib_header) continue; path = _dyld_get_image_name (i); if ( (NULL == path) || (0 == strlen (path)) ) @@ -419,8 +418,7 @@ os_get_gnunet_path () return ret; /* other attempts here */ LOG (GNUNET_ERROR_TYPE_ERROR, - _ - ("Could not determine installation path for %s. Set `%s' environment variable.\n"), + _("Could not determine installation path for %s. Set `%s' environment variable.\n"), "GNUnet", "GNUNET_PREFIX"); return NULL; } @@ -456,7 +454,7 @@ os_get_exec_path () /** * @brief get the path to a specific GNUnet installation directory or, - * with GNUNET_IPK_SELF_PREFIX, the current running apps installation directory + * with #GNUNET_OS_IPK_SELF_PREFIX, the current running apps installation directory * @author Milan * @return a pointer to the dir path (to be freed by the caller) */ @@ -629,19 +627,24 @@ GNUNET_OS_installation_get_path (enum GNUNET_OS_InstallationPathKind dirkind) char * GNUNET_OS_get_libexec_binary_path (const char *progname) { + static char *cache; char *libexecdir; char *binary; - if (DIR_SEPARATOR == progname[0]) + if ( (DIR_SEPARATOR == progname[0]) || + (GNUNET_YES == GNUNET_STRINGS_path_is_absolute (progname, GNUNET_NO, NULL, NULL)) ) return GNUNET_strdup (progname); - libexecdir = GNUNET_OS_installation_get_path (GNUNET_OS_IPK_LIBEXECDIR); + if (NULL != cache) + libexecdir = cache; + else + libexecdir = GNUNET_OS_installation_get_path (GNUNET_OS_IPK_LIBEXECDIR); if (NULL == libexecdir) return GNUNET_strdup (progname); GNUNET_asprintf (&binary, "%s%s", libexecdir, progname); - GNUNET_free (libexecdir); + cache = libexecdir; return binary; } @@ -654,12 +657,17 @@ GNUNET_OS_get_libexec_binary_path (const char *progname) * * @param binary the name of the file to check. * W32: must not have an .exe suffix. - * @return GNUNET_YES if the file is SUID, - * GNUNET_NO if not SUID (but binary exists) - * GNUNET_SYSERR on error (no such binary or not executable) + * @param check_suid input true if the binary should be checked for SUID (*nix) + * W32: checks if the program has sufficient privileges by executing this + * binary with the -d flag. -d omits a programs main loop and only + * executes all privileged operations in an binary. + * @param params parameters used for w32 privilege checking (can be NULL for != w32 ) + * @return #GNUNET_YES if the file is SUID (*nix) or can be executed with current privileges (W32), + * #GNUNET_NO if not SUID (but binary exists), + * #GNUNET_SYSERR on error (no such binary or not executable) */ int -GNUNET_OS_check_helper_binary (const char *binary) +GNUNET_OS_check_helper_binary (const char *binary, int check_suid, const char *params) { struct stat statbuf; char *p; @@ -701,7 +709,8 @@ GNUNET_OS_check_helper_binary (const char *binary) #endif if (NULL == p) { - LOG (GNUNET_ERROR_TYPE_INFO, _("Could not find binary `%s' in PATH!\n"), + LOG (GNUNET_ERROR_TYPE_INFO, + _("Could not find binary `%s' in PATH!\n"), binary); return GNUNET_SYSERR; } @@ -725,24 +734,64 @@ GNUNET_OS_check_helper_binary (const char *binary) GNUNET_free (p); return GNUNET_SYSERR; } + if (check_suid){ #ifndef MINGW - if ((0 != (statbuf.st_mode & S_ISUID)) && (0 == statbuf.st_uid)) - { - GNUNET_free (p); - return GNUNET_YES; - } - /* binary exists, but not SUID */ + if ((0 != (statbuf.st_mode & S_ISUID)) && (0 == statbuf.st_uid)) + { + GNUNET_free (p); + return GNUNET_YES; + } + /* binary exists, but not SUID */ #else - return GNUNET_YES; - /* FIXME: - * no suid for windows possible! - * permissions-checking is too specific(as in non-portable) - * user/group checking is pointless (users/applications can drop privileges) - * using token checking for elevated permissions would limit gnunet - * to run only on winserver 2008 and 2012! - * - * thus, ad add "dryrun" checking */ + STARTUPINFO start; + char parameters[512]; + PROCESS_INFORMATION proc; + DWORD exit_value; + + GNUNET_snprintf (parameters, + sizeof (parameters), + "-d %s", params); + memset (&start, 0, sizeof (start)); + start.cb = sizeof (start); + memset (&proc, 0, sizeof (proc)); + + + // Start the child process. + if ( ! (CreateProcess( p, // current windows (2k3 and up can handle / instead of \ in paths)) + parameters, // execute dryrun/priviliege checking mode + NULL, // Process handle not inheritable + NULL, // Thread handle not inheritable + FALSE, // Set handle inheritance to FALSE + CREATE_DEFAULT_ERROR_MODE, // No creation flags + NULL, // Use parent's environment block + NULL, // Use parent's starting directory + &start, // Pointer to STARTUPINFO structure + &proc ) // Pointer to PROCESS_INFORMATION structure + )) + { + LOG (GNUNET_ERROR_TYPE_ERROR, + _("CreateProcess failed for binary %s (%d).\n"), + p, GetLastError()); + return GNUNET_SYSERR; + } + + // Wait until child process exits. + WaitForSingleObject( proc.hProcess, INFINITE ); + + if ( ! GetExitCodeProcess (proc.hProcess, &exit_value)){ + LOG (GNUNET_ERROR_TYPE_ERROR, + _("GetExitCodeProcess failed for binary %s (%d).\n"), + p, GetLastError() ); + return GNUNET_SYSERR; + } + // Close process and thread handles. + CloseHandle( proc.hProcess ); + CloseHandle( proc.hThread ); + + if (!exit_value) + return GNUNET_YES; #endif + } GNUNET_free (p); return GNUNET_NO; }