+const char *gsslogmsg = NULL;
+
+static void ssh_sspi_bind_fns(struct ssh_gss_library *lib);
+
+struct ssh_gss_liblist *ssh_gss_setup(Conf *conf)
+{
+ HMODULE module;
+ HKEY regkey;
+ struct ssh_gss_liblist *list = snew(struct ssh_gss_liblist);
+ char *path;
+
+ list->libraries = snewn(3, struct ssh_gss_library);
+ list->nlibraries = 0;
+
+ /* MIT Kerberos GSSAPI implementation */
+ /* TODO: For 64-bit builds, check for gssapi64.dll */
+ module = NULL;
+ if (RegOpenKey(HKEY_LOCAL_MACHINE, "SOFTWARE\\MIT\\Kerberos", ®key)
+ == ERROR_SUCCESS) {
+ DWORD type, size;
+ LONG ret;
+ char *buffer;
+
+ /* Find out the string length */
+ ret = RegQueryValueEx(regkey, "InstallDir", NULL, &type, NULL, &size);
+
+ if (ret == ERROR_SUCCESS && type == REG_SZ) {
+ buffer = snewn(size + 20, char);
+ ret = RegQueryValueEx(regkey, "InstallDir", NULL,
+ &type, buffer, &size);
+ if (ret == ERROR_SUCCESS && type == REG_SZ) {
+ strcat(buffer, "\\bin\\gssapi32.dll");
+ module = LoadLibrary(buffer);
+ }
+ sfree(buffer);
+ }
+ RegCloseKey(regkey);
+ }
+ if (module) {
+ struct ssh_gss_library *lib =
+ &list->libraries[list->nlibraries++];
+
+ lib->id = 0;
+ lib->gsslogmsg = "Using GSSAPI from GSSAPI32.DLL";
+ lib->handle = (void *)module;
+
+#define BIND_GSS_FN(name) \
+ lib->u.gssapi.name = (t_gss_##name) GetProcAddress(module, "gss_" #name)
+
+ BIND_GSS_FN(delete_sec_context);
+ BIND_GSS_FN(display_status);
+ BIND_GSS_FN(get_mic);
+ BIND_GSS_FN(import_name);
+ BIND_GSS_FN(init_sec_context);
+ BIND_GSS_FN(release_buffer);
+ BIND_GSS_FN(release_cred);
+ BIND_GSS_FN(release_name);
+
+#undef BIND_GSS_FN
+
+ ssh_gssapi_bind_fns(lib);
+ }
+
+ /* Microsoft SSPI Implementation */
+ module = load_system32_dll("secur32.dll");
+ if (module) {
+ struct ssh_gss_library *lib =
+ &list->libraries[list->nlibraries++];
+
+ lib->id = 1;
+ lib->gsslogmsg = "Using SSPI from SECUR32.DLL";
+ lib->handle = (void *)module;
+
+ GET_WINDOWS_FUNCTION(module, AcquireCredentialsHandleA);
+ GET_WINDOWS_FUNCTION(module, InitializeSecurityContextA);
+ GET_WINDOWS_FUNCTION(module, FreeContextBuffer);
+ GET_WINDOWS_FUNCTION(module, FreeCredentialsHandle);
+ GET_WINDOWS_FUNCTION(module, DeleteSecurityContext);
+ GET_WINDOWS_FUNCTION(module, QueryContextAttributesA);
+ GET_WINDOWS_FUNCTION(module, MakeSignature);
+
+ ssh_sspi_bind_fns(lib);
+ }
+
+ /*
+ * Custom GSSAPI DLL.
+ */
+ module = NULL;
+ path = conf_get_filename(conf, CONF_ssh_gss_custom)->path;
+ if (*path) {
+ module = LoadLibrary(path);
+ }
+ if (module) {
+ struct ssh_gss_library *lib =
+ &list->libraries[list->nlibraries++];
+
+ lib->id = 2;
+ lib->gsslogmsg = dupprintf("Using GSSAPI from user-specified"
+ " library '%s'", path);
+ lib->handle = (void *)module;
+
+#define BIND_GSS_FN(name) \
+ lib->u.gssapi.name = (t_gss_##name) GetProcAddress(module, "gss_" #name)
+
+ BIND_GSS_FN(delete_sec_context);
+ BIND_GSS_FN(display_status);
+ BIND_GSS_FN(get_mic);
+ BIND_GSS_FN(import_name);
+ BIND_GSS_FN(init_sec_context);
+ BIND_GSS_FN(release_buffer);
+ BIND_GSS_FN(release_cred);
+ BIND_GSS_FN(release_name);
+
+#undef BIND_GSS_FN
+
+ ssh_gssapi_bind_fns(lib);
+ }
+
+
+ return list;
+}
+
+void ssh_gss_cleanup(struct ssh_gss_liblist *list)