[popt] secure_getenv.c: secure_getenv() wrapper for systems that don't have it. bugfix/popt-1.16-apply-patches github/bugfix/popt-1.16-apply-patches
authorDavid Korth <gerbilsoft@gerbilsoft.com>
Mon, 7 Sep 2015 21:17:40 +0000 (17:17 -0400)
committerDavid Korth <gerbilsoft@gerbilsoft.com>
Mon, 7 Sep 2015 21:17:40 +0000 (17:17 -0400)
On Windows, this just calls getenv(), since there's no real way to
implement "security" here.

On non-Windows systems, it checks if euid == uid and egid == gid.
If either of them are incorrect, security restrictions will be enabled,
and popt_secure_getenv() will always return NULL. Otherwise, security
restrictions will be disabled, and popt_secure_getenv() will simply
call getenv() with the specified parameter.

system.h: Declare and use popt_secure_getenv() if the system doesn't
have secure_getenv() or __secure_getenv().

extlib/popt/CMakeLists.txt
extlib/popt/secure_getenv.c [new file with mode: 0644]
extlib/popt/system.h

index 6918375..d1ba3eb 100644 (file)
@@ -102,6 +102,10 @@ SET(popt_SRCS
        poptparse.c
        )
 
+IF(NOT HAVE_SECURE_GETENV AND NOT HAVE___SECURE_GETENV)
+       SET(popt_SRCS ${popt_SRCS} secure_getenv.c)
+ENDIF(NOT HAVE_SECURE_GETENV AND NOT HAVE___SECURE_GETENV)
+
 # Internal header files.
 SET(popt_H_INT
        poptint.h
diff --git a/extlib/popt/secure_getenv.c b/extlib/popt/secure_getenv.c
new file mode 100644 (file)
index 0000000..17678a1
--- /dev/null
@@ -0,0 +1,51 @@
+/**
+ * secure_getenv() replacement for systems that don't have it.
+ * For popt-1.16.
+ */
+
+#include "system.h"
+
+#ifndef _WIN32
+static int enable_secure_decided = 0;
+static int enable_secure = 1;
+#endif
+
+/**
+ * secure_getenv() replacement for systems that don't have it.
+ * @param name Variable name.
+ * @return Value, or NULL if not found or not available due to security restrictions.
+ */
+char *popt_secure_getenv(const char *name)
+{
+#ifdef _WIN32
+       // TODO: There's no uid/gid on Windows...
+       return getenv(name);
+#else /* !_WIN32 */
+       // glibc's secure_getenv() checks if
+       // euid == uid and egid == gid.
+       // If either of them don't match,
+       // always return NULL.
+       if (!enable_secure_decided) {
+               if (geteuid() == getuid() &&
+                   getegid() == getgid())
+               {
+                       // UID/GID matches.
+                       // Security restrictions can be dropped.
+                       enable_secure = 0;
+               } else {
+                       // UID or GID does not match.
+                       // Enable security restrictions.
+                       enable_secure = 1;
+               }
+               enable_secure_decided = 1;
+       }
+
+       if (enable_secure) {
+               // Security restrictions are enabled.
+               return NULL;
+       }
+
+       // Get the environment variable.
+       return getenv(name);
+#endif /* _WIN32 */
+}
index f9afe3c..8ea7dfc 100644 (file)
@@ -156,11 +156,10 @@ static inline char * stpcpy (char *dest, const char * src) {
 #  ifdef HAVE___SECURE_GETENV
 #    define secure_getenv __secure_getenv
 #  else
-/* Gens/GS II: FIXME: Implement secure_getenv() for non-GNU systems.
-#    error neither secure_getenv nor __secure_getenv is available
-*/
-#    pragma message("WARNING: secure_getenv() is unavailable; please implement a replacement.")
-#    define secure_getenv(_s) getenv(_s)
+     /* Gens/GS II: secure_getenv() is implemented in system.h. */
+/*#    error neither secure_getenv nor __secure_getenv is available*/
+char *popt_secure_getenv(const char *name);
+#    define secure_getenv popt_secure_getenv
 #  endif
 #endif