]> asedeno.scripts.mit.edu Git - PuTTY.git/blobdiff - windows/winmisc.c
first pass
[PuTTY.git] / windows / winmisc.c
index c74f1e7a6b90164eb3ab39f0c418073554a5a5da..8bd4c77f88171fbea6672425a5eabed1817ba4bc 100644 (file)
@@ -5,6 +5,9 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include "putty.h"
+#ifndef SECURITY_WIN32
+#define SECURITY_WIN32
+#endif
 #include <security.h>
 
 OSVERSIONINFO osVersion;
@@ -68,6 +71,13 @@ Filename *filename_deserialise(void *vdata, int maxsize, int *used)
     return filename_from_str(data);
 }
 
+char filename_char_sanitise(char c)
+{
+    if (strchr("<>:\"/\\|?*", c))
+        return '.';
+    return c;
+}
+
 #ifndef NO_SECUREZEROMEMORY
 /*
  * Windows implementation of smemclr (see misc.c) using SecureZeroMemory.
@@ -139,6 +149,52 @@ char *get_username(void)
     return got_username ? user : NULL;
 }
 
+void dll_hijacking_protection(void)
+{
+    /*
+     * If the OS provides it, call SetDefaultDllDirectories() to
+     * prevent DLLs from being loaded from the directory containing
+     * our own binary, and instead only load from system32.
+     *
+     * This is a protection against hijacking attacks, if someone runs
+     * PuTTY directly from their web browser's download directory
+     * having previously been enticed into clicking on an unwise link
+     * that downloaded a malicious DLL to the same directory under one
+     * of various magic names that seem to be things that standard
+     * Windows DLLs delegate to.
+     *
+     * It shouldn't break deliberate loading of user-provided DLLs
+     * such as GSSAPI providers, because those are specified by their
+     * full pathname by the user-provided configuration.
+     */
+    static HMODULE kernel32_module;
+    DECL_WINDOWS_FUNCTION(static, BOOL, SetDefaultDllDirectories, (DWORD));
+
+    if (!kernel32_module) {
+        kernel32_module = load_system32_dll("kernel32.dll");
+        GET_WINDOWS_FUNCTION(kernel32_module, SetDefaultDllDirectories);
+    }
+
+    if (p_SetDefaultDllDirectories) {
+        /* LOAD_LIBRARY_SEARCH_SYSTEM32 | LOAD_LIBRARY_SEARCH_USER_DIRS only */
+        p_SetDefaultDllDirectories(0x800|0x400);
+    }
+}
+
+void dll_hijacking_protection_add_path(const wchar_t *path)
+{
+    static HMODULE kernel32_module;
+    DECL_WINDOWS_FUNCTION(static, BOOL, AddDllDirectory, (PCWSTR));
+
+    if (!kernel32_module) {
+        kernel32_module = load_system32_dll("kernel32.dll");
+        GET_WINDOWS_FUNCTION(kernel32_module, AddDllDirectory);
+    }
+
+    if (p_AddDllDirectory) {
+        p_AddDllDirectory(path);
+    }
+}
 BOOL init_winver(void)
 {
     ZeroMemory(&osVersion, sizeof(osVersion));
@@ -173,12 +229,72 @@ HMODULE load_system32_dll(const char *libname)
     return ret;
 }
 
+/*
+ * A tree234 containing mappings from system error codes to strings.
+ */
+
+struct errstring {
+    int error;
+    char *text;
+};
+
+static int errstring_find(void *av, void *bv)
+{
+    int *a = (int *)av;
+    struct errstring *b = (struct errstring *)bv;
+    if (*a < b->error)
+        return -1;
+    if (*a > b->error)
+        return +1;
+    return 0;
+}
+static int errstring_compare(void *av, void *bv)
+{
+    struct errstring *a = (struct errstring *)av;
+    return errstring_find(&a->error, bv);
+}
+
+static tree234 *errstrings = NULL;
+
+const char *win_strerror(int error)
+{
+    struct errstring *es;
+
+    if (!errstrings)
+        errstrings = newtree234(errstring_compare);
+
+    es = find234(errstrings, &error, errstring_find);
+
+    if (!es) {
+        char msgtext[65536]; /* maximum size for FormatMessage is 64K */
+
+        es = snew(struct errstring);
+        es->error = error;
+        if (!FormatMessage((FORMAT_MESSAGE_FROM_SYSTEM |
+                            FORMAT_MESSAGE_IGNORE_INSERTS), NULL, error,
+                           MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+                           msgtext, lenof(msgtext)-1, NULL)) {
+            sprintf(msgtext,
+                    "(unable to format: FormatMessage returned %u)",
+                    (unsigned int)GetLastError());
+        } else {
+            int len = strlen(msgtext);
+            if (len > 0 && msgtext[len-1] == '\n')
+                msgtext[len-1] = '\0';
+        }
+        es->text = dupprintf("Error %d: %s", error, msgtext);
+        add234(errstrings, es);
+    }
+
+    return es->text;
+}
+
 #ifdef DEBUG
 static FILE *debug_fp = NULL;
 static HANDLE debug_hdl = INVALID_HANDLE_VALUE;
 static int debug_got_console = 0;
 
-void dputs(char *buf)
+void dputs(const char *buf)
 {
     DWORD dw;