From ad68ae150f17cf6e0b2c605c9331cf0aedfce1d0 Mon Sep 17 00:00:00 2001 From: Christian Fuchs Date: Mon, 15 Apr 2013 12:36:37 +0000 Subject: extended the GNUNET_OS_check_helper_binary parameters to do previlege checking in windows. To do so, tested binaries must still be supplied with valid commandline arguments, but on windows gnunet will utilize the -d flag to run the programs initialization phase or privileged operations only. In these modes, a program will not enter its mainloop or communicate with the outside. updated relevant function calls gnunet-wide to meet the extended function parameters. --- src/util/os_installation.c | 79 +++++++++++++++++++++++++++++++++++----------- src/util/os_priority.c | 4 +-- 2 files changed, 63 insertions(+), 20 deletions(-) (limited to 'src/util') diff --git a/src/util/os_installation.c b/src/util/os_installation.c index b63a19d2e..8445fd1cc 100644 --- a/src/util/os_installation.c +++ b/src/util/os_installation.c @@ -654,12 +654,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) + * @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, const boolean check_suid, const char *params) { struct stat statbuf; char *p; @@ -725,24 +730,62 @@ 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 (¶meters, 512, "-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; } diff --git a/src/util/os_priority.c b/src/util/os_priority.c index b8b854963..e86de968a 100644 --- a/src/util/os_priority.c +++ b/src/util/os_priority.c @@ -634,7 +634,7 @@ start_process (int pipe_control, int fd_stdin_read; int fd_stdin_write; - if (GNUNET_SYSERR == GNUNET_OS_check_helper_binary (filename)) + if (GNUNET_SYSERR == GNUNET_OS_check_helper_binary (filename, FALSE, NULL)) return NULL; /* not executable */ if (GNUNET_YES == pipe_control) { @@ -865,7 +865,7 @@ start_process (int pipe_control, BOOL bresult; DWORD error_code; - if (GNUNET_SYSERR == GNUNET_OS_check_helper_binary (filename)) + if (GNUNET_SYSERR == GNUNET_OS_check_helper_binary (filename, FALSE, NULL)) return NULL; /* not executable */ /* Search in prefix dir (hopefully - the directory from which -- cgit v1.2.3