Add stricter checks for netnames.
[tinc] / src / script.c
index 6389cb4..d4db889 100644 (file)
@@ -1,7 +1,7 @@
 /*
     script.c -- call an external script
     Copyright (C) 1999-2005 Ivo Timmermans,
-                  2000-2013 Guus Sliepen <guus@tinc-vpn.org>
+                  2000-2015 Guus Sliepen <guus@tinc-vpn.org>
 
     This program is free software; you can redistribute it and/or modify
     it under the terms of the GNU General Public License as published by
 #include "script.h"
 #include "xalloc.h"
 
+#ifdef HAVE_PUTENV
+static void unputenv(const char *p) {
+       const char *e = strchr(p, '=');
+       if(!e)
+               return;
+       int len = e - p;
+#ifndef HAVE_UNSETENV
+#ifdef HAVE_MINGW
+       // Windows requires putenv("FOO=") to unset %FOO%
+       len++;
+#endif
+#endif
+       char var[len + 1];
+       strncpy(var, p, len);
+       var[len] = 0;
+#ifdef HAVE_UNSETENV
+       unsetenv(var);
+#else
+       // We must keep what we putenv() around in memory.
+       // To do this without memory leaks, keep things in a list and reuse if possible.
+       static list_t list = {};
+       for list_each(char, data, &list) {
+               if(!strcmp(data, var)) {
+                       putenv(data);
+                       return;
+               }
+       }
+       char *data = xstrdup(var);
+       list_insert_tail(&list, data);
+       putenv(data);
+#endif
+}
+#else
+static void putenv(const char *p) {}
+static void unputenv(const char *p) {}
+#endif
+
 bool execute_script(const char *name, char **envp) {
-#ifdef HAVE_SYSTEM
-       char *scriptname;
+       char scriptname[PATH_MAX];
        char *command;
 
-       xasprintf(&scriptname, "%s" SLASH "%s%s", confbase, name, scriptextension);
+       snprintf(scriptname, sizeof scriptname, "%s" SLASH "%s%s", confbase, name, scriptextension);
 
        /* First check if there is a script */
 
 #ifdef HAVE_MINGW
        if(!*scriptextension) {
                const char *pathext = getenv("PATHEXT") ?: ".COM;.EXE;.BAT;.CMD";
-               char fullname[strlen(scriptname) + strlen(pathext)];
-               char *ext = fullname + strlen(scriptname);
-               strcpy(fullname, scriptname);
+               size_t pathlen = strlen(pathext);
+               size_t scriptlen = strlen(scriptname);
+               char fullname[scriptlen + pathlen + 1];
+               char *ext = fullname + scriptlen;
+               strncpy(fullname, scriptname, sizeof fullname);
 
                const char *p = pathext;
                bool found = false;
@@ -51,32 +89,26 @@ bool execute_script(const char *name, char **envp) {
                                ext[q - p] = 0;
                                q++;
                        } else {
-                               strcpy(ext, p);
+                               strncpy(ext, p, pathlen + 1);
                        }
                        if((found = !access(fullname, F_OK)))
                                break;
                        p = q;
                }
-               if(!found) {
-                       free(scriptname);
+               if(!found)
                        return true;
-               }
        } else
 #endif
 
-       if(access(scriptname, F_OK)) {
-               free(scriptname);
+       if(access(scriptname, F_OK))
                return true;
-       }
 
        logger(DEBUG_STATUS, LOG_INFO, "Executing script %s", name);
 
-#ifdef HAVE_PUTENV
        /* Set environment */
 
        for(int i = 0; envp[i]; i++)
                putenv(envp[i]);
-#endif
 
        if(scriptinterpreter)
                xasprintf(&command, "%s \"%s\"", scriptinterpreter, scriptname);
@@ -86,19 +118,11 @@ bool execute_script(const char *name, char **envp) {
        int status = system(command);
 
        free(command);
-       free(scriptname);
 
        /* Unset environment */
 
-       for(int i = 0; envp[i]; i++) {
-               char *e = strchr(envp[i], '=');
-               if(e) {
-                       char p[e - envp[i] + 1];
-                       strncpy(p, envp[i], e - envp[i]);
-                       p[e - envp[i]] = '\0';
-                       putenv(p);
-               }
-       }
+       for(int i = 0; envp[i]; i++)
+               unputenv(envp[i]);
 
        if(status != -1) {
 #ifdef WEXITSTATUS
@@ -121,6 +145,6 @@ bool execute_script(const char *name, char **envp) {
                logger(DEBUG_ALWAYS, LOG_ERR, "System call `%s' failed: %s", "system", strerror(errno));
                return false;
        }
-#endif
+
        return true;
 }