X-Git-Url: https://git.distorted.org.uk/u/mdw/putty/blobdiff_plain/865570570435c638831294d39fbef4c2fd665727..52a1ed228f79b38a867d6d46e7f2d33a31be5b8a:/windows/wingss.c diff --git a/windows/wingss.c b/windows/wingss.c index 222b34fa..5f45c98b 100644 --- a/windows/wingss.c +++ b/windows/wingss.c @@ -1,44 +1,55 @@ #ifndef NO_GSSAPI -#include -#define SECURITY_WIN32 +#include "putty.h" + #include + +#include "pgssapi.h" #include "sshgss.h" +#include "sshgssc.h" + #include "misc.h" -#define NOTHING -#define DECL_SSPI_FUNCTION(linkage, rettype, name, params) \ - typedef rettype (WINAPI *t_##name) params; \ - linkage t_##name p_##name -#define GET_SSPI_FUNCTION(module, name) \ - p_##name = module ? (t_##name) GetProcAddress(module, #name) : NULL - -DECL_SSPI_FUNCTION(static, SECURITY_STATUS, - AcquireCredentialsHandleA, - (SEC_CHAR *, SEC_CHAR *, ULONG, PLUID, - PVOID, SEC_GET_KEY_FN, PVOID, PCredHandle, PTimeStamp)); -DECL_SSPI_FUNCTION(static, SECURITY_STATUS, - InitializeSecurityContextA, - (PCredHandle, PCtxtHandle, SEC_CHAR *, ULONG, ULONG, - ULONG, PSecBufferDesc, ULONG, PCtxtHandle, - PSecBufferDesc, PULONG, PTimeStamp)); -DECL_SSPI_FUNCTION(static, SECURITY_STATUS, - FreeContextBuffer, - (PVOID)); -DECL_SSPI_FUNCTION(static, SECURITY_STATUS, - FreeCredentialsHandle, - (PCredHandle)); -DECL_SSPI_FUNCTION(static, SECURITY_STATUS, - DeleteSecurityContext, - (PCtxtHandle)); -DECL_SSPI_FUNCTION(static, SECURITY_STATUS, - QueryContextAttributesA, - (PCtxtHandle, ULONG, PVOID)); -DECL_SSPI_FUNCTION(static, SECURITY_STATUS, - MakeSignature, - (PCtxtHandle, ULONG, PSecBufferDesc, ULONG)); - -static HMODULE security_module = NULL; +/* Windows code to set up the GSSAPI library list. */ + +struct ssh_gss_library ssh_gss_libraries[2]; +int n_ssh_gss_libraries = 0; +static int initialised = FALSE; + +const int ngsslibs = 2; +const char *const gsslibnames[2] = { + "GSSAPI32.DLL (MIT Kerberos)", + "SSPI.DLL (Microsoft SSPI)", +}; +const struct keyval gsslibkeywords[] = { + { "gssapi32", 0 }, + { "sspi", 1 }, +}; + +DECL_WINDOWS_FUNCTION(static, SECURITY_STATUS, + AcquireCredentialsHandleA, + (SEC_CHAR *, SEC_CHAR *, ULONG, PLUID, + PVOID, SEC_GET_KEY_FN, PVOID, PCredHandle, PTimeStamp)); +DECL_WINDOWS_FUNCTION(static, SECURITY_STATUS, + InitializeSecurityContextA, + (PCredHandle, PCtxtHandle, SEC_CHAR *, ULONG, ULONG, + ULONG, PSecBufferDesc, ULONG, PCtxtHandle, + PSecBufferDesc, PULONG, PTimeStamp)); +DECL_WINDOWS_FUNCTION(static, SECURITY_STATUS, + FreeContextBuffer, + (PVOID)); +DECL_WINDOWS_FUNCTION(static, SECURITY_STATUS, + FreeCredentialsHandle, + (PCredHandle)); +DECL_WINDOWS_FUNCTION(static, SECURITY_STATUS, + DeleteSecurityContext, + (PCtxtHandle)); +DECL_WINDOWS_FUNCTION(static, SECURITY_STATUS, + QueryContextAttributesA, + (PCtxtHandle, ULONG, PVOID)); +DECL_WINDOWS_FUNCTION(static, SECURITY_STATUS, + MakeSignature, + (PCtxtHandle, ULONG, PSecBufferDesc, ULONG)); typedef struct winSsh_gss_ctx { unsigned long maj_stat; @@ -52,33 +63,75 @@ typedef struct winSsh_gss_ctx { const Ssh_gss_buf gss_mech_krb5={9,"\x2A\x86\x48\x86\xF7\x12\x01\x02\x02"}; -int ssh_gss_init(void) +const char *gsslogmsg = NULL; + +static void ssh_sspi_bind_fns(struct ssh_gss_library *lib); + +void ssh_gss_init(void) { - if (security_module) - return 1; /* already initialised */ - - security_module = LoadLibrary("secur32.dll"); - if (security_module) { - GET_SSPI_FUNCTION(security_module, AcquireCredentialsHandleA); - GET_SSPI_FUNCTION(security_module, InitializeSecurityContextA); - GET_SSPI_FUNCTION(security_module, FreeContextBuffer); - GET_SSPI_FUNCTION(security_module, FreeCredentialsHandle); - GET_SSPI_FUNCTION(security_module, DeleteSecurityContext); - GET_SSPI_FUNCTION(security_module, QueryContextAttributesA); - GET_SSPI_FUNCTION(security_module, MakeSignature); - return 1; + HMODULE module; + + if (initialised) return; + initialised = TRUE; + + /* MIT Kerberos GSSAPI implementation */ + /* TODO: For 64-bit builds, check for gssapi64.dll */ + module = LoadLibrary("gssapi32.dll"); + if (module) { + struct ssh_gss_library *lib = + &ssh_gss_libraries[n_ssh_gss_libraries++]; + + lib->id = 0; + lib->gsslogmsg = "Using GSSAPI from GSSAPI32.DLL"; + +#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 = LoadLibrary("secur32.dll"); + if (module) { + struct ssh_gss_library *lib = + &ssh_gss_libraries[n_ssh_gss_libraries++]; + + lib->id = 1; + lib->gsslogmsg = "Using SSPI from SECUR32.DLL"; + + 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); } - return 0; } -Ssh_gss_stat ssh_gss_indicate_mech(Ssh_gss_buf *mech) +static Ssh_gss_stat ssh_sspi_indicate_mech(struct ssh_gss_library *lib, + Ssh_gss_buf *mech) { *mech = gss_mech_krb5; return SSH_GSS_OK; } -Ssh_gss_stat ssh_gss_import_name(char *host, Ssh_gss_name *srv_name) +static Ssh_gss_stat ssh_sspi_import_name(struct ssh_gss_library *lib, + char *host, Ssh_gss_name *srv_name) { char *pStr; @@ -93,7 +146,8 @@ Ssh_gss_stat ssh_gss_import_name(char *host, Ssh_gss_name *srv_name) return SSH_GSS_OK; } -Ssh_gss_stat ssh_gss_acquire_cred(Ssh_gss_ctx *ctx) +static Ssh_gss_stat ssh_sspi_acquire_cred(struct ssh_gss_library *lib, + Ssh_gss_ctx *ctx) { winSsh_gss_ctx *winctx = snew(winSsh_gss_ctx); memset(winctx, 0, sizeof(winSsh_gss_ctx)); @@ -122,11 +176,12 @@ Ssh_gss_stat ssh_gss_acquire_cred(Ssh_gss_ctx *ctx) } -Ssh_gss_stat ssh_gss_init_sec_context(Ssh_gss_ctx *ctx, - Ssh_gss_name srv_name, - int to_deleg, - Ssh_gss_buf *recv_tok, - Ssh_gss_buf *send_tok) +static Ssh_gss_stat ssh_sspi_init_sec_context(struct ssh_gss_library *lib, + Ssh_gss_ctx *ctx, + Ssh_gss_name srv_name, + int to_deleg, + Ssh_gss_buf *recv_tok, + Ssh_gss_buf *send_tok) { winSsh_gss_ctx *winctx = (winSsh_gss_ctx *) *ctx; SecBuffer wsend_tok = {send_tok->length,SECBUFFER_TOKEN,send_tok->value}; @@ -164,7 +219,8 @@ Ssh_gss_stat ssh_gss_init_sec_context(Ssh_gss_ctx *ctx, return SSH_GSS_FAILURE; } -Ssh_gss_stat ssh_gss_free_tok(Ssh_gss_buf *send_tok) +static Ssh_gss_stat ssh_sspi_free_tok(struct ssh_gss_library *lib, + Ssh_gss_buf *send_tok) { /* check input */ if (send_tok == NULL) return SSH_GSS_FAILURE; @@ -176,7 +232,8 @@ Ssh_gss_stat ssh_gss_free_tok(Ssh_gss_buf *send_tok) return SSH_GSS_OK; } -Ssh_gss_stat ssh_gss_release_cred(Ssh_gss_ctx *ctx) +static Ssh_gss_stat ssh_sspi_release_cred(struct ssh_gss_library *lib, + Ssh_gss_ctx *ctx) { winSsh_gss_ctx *winctx= (winSsh_gss_ctx *) *ctx; @@ -195,7 +252,8 @@ Ssh_gss_stat ssh_gss_release_cred(Ssh_gss_ctx *ctx) } -Ssh_gss_stat ssh_gss_release_name(Ssh_gss_name *srv_name) +static Ssh_gss_stat ssh_sspi_release_name(struct ssh_gss_library *lib, + Ssh_gss_name *srv_name) { char *pStr= (char *) *srv_name; @@ -206,7 +264,8 @@ Ssh_gss_stat ssh_gss_release_name(Ssh_gss_name *srv_name) return SSH_GSS_OK; } -Ssh_gss_stat ssh_gss_display_status(Ssh_gss_ctx ctx, Ssh_gss_buf *buf) +static Ssh_gss_stat ssh_sspi_display_status(struct ssh_gss_library *lib, + Ssh_gss_ctx ctx, Ssh_gss_buf *buf) { winSsh_gss_ctx *winctx = (winSsh_gss_ctx *) ctx; char *msg; @@ -251,13 +310,14 @@ Ssh_gss_stat ssh_gss_display_status(Ssh_gss_ctx ctx, Ssh_gss_buf *buf) } buf->value = dupstr(msg); - buf->length = strlen(buf->length); + buf->length = strlen(buf->value); return SSH_GSS_OK; } -Ssh_gss_stat ssh_gss_get_mic(Ssh_gss_ctx ctx, Ssh_gss_buf *buf, - Ssh_gss_buf *hash) +static Ssh_gss_stat ssh_sspi_get_mic(struct ssh_gss_library *lib, + Ssh_gss_ctx ctx, Ssh_gss_buf *buf, + Ssh_gss_buf *hash) { winSsh_gss_ctx *winctx= (winSsh_gss_ctx *) ctx; SecPkgContext_Sizes ContextSizes; @@ -301,20 +361,34 @@ Ssh_gss_stat ssh_gss_get_mic(Ssh_gss_ctx ctx, Ssh_gss_buf *buf, return winctx->maj_stat; } -Ssh_gss_stat ssh_gss_free_mic(Ssh_gss_buf *hash) +static Ssh_gss_stat ssh_sspi_free_mic(struct ssh_gss_library *lib, + Ssh_gss_buf *hash) { sfree(hash->value); return SSH_GSS_OK; } +static void ssh_sspi_bind_fns(struct ssh_gss_library *lib) +{ + lib->indicate_mech = ssh_sspi_indicate_mech; + lib->import_name = ssh_sspi_import_name; + lib->release_name = ssh_sspi_release_name; + lib->init_sec_context = ssh_sspi_init_sec_context; + lib->free_tok = ssh_sspi_free_tok; + lib->acquire_cred = ssh_sspi_acquire_cred; + lib->release_cred = ssh_sspi_release_cred; + lib->get_mic = ssh_sspi_get_mic; + lib->free_mic = ssh_sspi_free_mic; + lib->display_status = ssh_sspi_display_status; +} + #else /* Dummy function so this source file defines something if NO_GSSAPI is defined. */ -int ssh_gss_init(void) +void ssh_gss_init(void) { - return 0; } #endif