277 lines
7.8 KiB
C

/*
* Author: NoMachine <developers@nomachine.com>
*
* Copyright (c) 2009, 2011 NoMachine
* All rights reserved
*
* Support functions and system calls' replacements needed to let the
* software run on Win32 based operating systems.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "kerberos.h"
/*
* Handles to runtime loaded MIT KfW libraries.
*/
static HMODULE Krb5_32 = NULL;
static HMODULE Comerr32 = NULL;
static HMODULE Gssapi32 = NULL;
/*
* Pointers to runtime loaded KfW functions.
*/
static struct _MitDispatch
{
/*
* gssapi32.dll.
*/
gss_indicate_mechs_ptr gss_indicate_mechs;
gss_release_buffer_ptr gss_release_buffer;
gss_display_status_ptr gss_display_status;
gss_delete_sec_context_ptr gss_delete_sec_context;
gss_release_name_ptr gss_release_name;
gss_release_cred_ptr gss_release_cred;
gss_init_sec_context_ptr gss_init_sec_context;
gss_import_name_ptr gss_import_name;
gss_get_mic_ptr gss_get_mic;
/*
* krb5_32.dll.
*/
krb5_free_context_ptr krb5_free_context;
krb5_free_principal_ptr krb5_free_principal;
krb5_cc_destroy_ptr krb5_cc_destroy;
} MitDispatch = {0};
/*
* This global variable is exported by gssapi32.dll.
*/
gss_OID gss_nt_service_name;
/*
* Try loads MIT Kerberos for Windows libraries. This function
* must be called before use Kerberos functions.
*
* RETURNS: 0 if OK.
*/
int InitMitKerberos()
{
int exitCode = -1;
void *serviceNamePtr = NULL;
/*
* Load functions from gssapi32.dll.
*/
debug("Loading gssapi32.dll...");
FAIL((Gssapi32 = LoadLibrary("gssapi32.dll")) == NULL);
FAIL((GET_MIT_FUNCTION(Gssapi32, gss_indicate_mechs)) == NULL);
FAIL((GET_MIT_FUNCTION(Gssapi32, gss_release_buffer)) == NULL);
FAIL((GET_MIT_FUNCTION(Gssapi32, gss_display_status)) == NULL);
FAIL((GET_MIT_FUNCTION(Gssapi32, gss_delete_sec_context)) == NULL);
FAIL((GET_MIT_FUNCTION(Gssapi32, gss_release_name)) == NULL);
FAIL((GET_MIT_FUNCTION(Gssapi32, gss_release_cred)) == NULL);
FAIL((GET_MIT_FUNCTION(Gssapi32, gss_init_sec_context)) == NULL);
FAIL((GET_MIT_FUNCTION(Gssapi32, gss_import_name)) == NULL);
FAIL((GET_MIT_FUNCTION(Gssapi32, gss_get_mic)) == NULL);
/*
* This is global variable exported by gssapi32.dll.
* Note, that we reveive POINTER not VALUE, so we need to
* do memcpy in this case.
*/
serviceNamePtr = GetProcAddress(Gssapi32, "gss_nt_service_name");
FAIL(serviceNamePtr == NULL);
memcpy(&gss_nt_service_name, serviceNamePtr, sizeof(gss_OID));
/*
* Load functions from krb5_32.dll.
*/
debug("Loading krb5_32.dll...");
FAIL((Krb5_32 = (HMODULE) LoadLibrary("krb5_32.dll")) == NULL);
FAIL((GET_MIT_FUNCTION(Krb5_32, krb5_free_context)) == NULL);
FAIL((GET_MIT_FUNCTION(Krb5_32, krb5_free_principal)) == NULL);
FAIL((GET_MIT_FUNCTION(Krb5_32, krb5_cc_destroy)) == NULL);
/*
* Error handler.
*/
exitCode = 0;
fail:
if (exitCode)
{
UninitMitKerberos();
error("Cannot load MIT KfW libraries. Error code is: %u.\n"
"Please ensure that path to these libraries is properly "
"set in your PATH variable.\n", GetLastError());
}
return exitCode;
}
/*
* Free MIT KfW libraries if loaded before.
*/
void UninitMitKerberos()
{
FreeLibrary(Krb5_32);
FreeLibrary(Comerr32);
FreeLibrary(Gssapi32);
}
/*
* Fake GSSAPI functions. We pass control to runtime loaded
* KfW libs here.
*/
#ifdef __MINGW32__
KFW_CALL gss_indicate_mechs(OM_uint32 *a, gss_OID_set *b)
#else
OM_uint32 KRB5_CALLCONV gss_indicate_mechs(OM_uint32 *a, gss_OID_set *b)
#endif
{
return MitDispatch.gss_indicate_mechs(a, b);
}
#ifdef __MINGW32__
KFW_CALL gss_release_buffer(OM_uint32 *a, gss_buffer_t b)
#else
OM_uint32 KRB5_CALLCONV gss_release_buffer(OM_uint32 *a, gss_buffer_t b)
#endif
{
return MitDispatch.gss_release_buffer(a, b);
}
#ifdef __MINGW32__
KFW_CALL gss_display_status(OM_uint32 *a, OM_uint32 b, int c, gss_OID d,
OM_uint32 *e, gss_buffer_t f)
#else
OM_uint32 KRB5_CALLCONV gss_display_status(OM_uint32 *a, OM_uint32 b, int c, gss_OID d,
OM_uint32 *e, gss_buffer_t f)
#endif
{
return MitDispatch.gss_display_status(a, b, c, d, e, f);
}
#ifdef __MINGW32__
KFW_CALL gss_delete_sec_context(OM_uint32 *a, gss_ctx_id_t *b, gss_buffer_t c)
#else
OM_uint32 KRB5_CALLCONV gss_delete_sec_context(OM_uint32 *a, gss_ctx_id_t *b, gss_buffer_t c)
#endif
{
return MitDispatch.gss_delete_sec_context(a, b, c);
}
#ifdef __MINGW32__
KFW_CALL gss_release_name(OM_uint32 *a, gss_name_t *b)
#else
OM_uint32 KRB5_CALLCONV gss_release_name(OM_uint32 *a, gss_name_t *b)
#endif
{
return MitDispatch.gss_release_name(a, b);
}
#ifdef __MINGW32__
KFW_CALL gss_release_cred(OM_uint32 *a, gss_cred_id_t *b)
#else
OM_uint32 KRB5_CALLCONV gss_release_cred(OM_uint32 *a, gss_cred_id_t *b)
#endif
{
return MitDispatch.gss_release_cred(a, b);
}
#ifdef __MINGW32__
KFW_CALL gss_init_sec_context(OM_uint32 *a, gss_cred_id_t b,
gss_ctx_id_t *c, gss_name_t d,
gss_OID e, OM_uint32 f,
OM_uint32 g, gss_channel_bindings_t h,
gss_buffer_t i, gss_OID * j,
gss_buffer_t k, OM_uint32 *l,
OM_uint32 *m)
#else
OM_uint32 KRB5_CALLCONV gss_init_sec_context(OM_uint32 *a, gss_cred_id_t b,
gss_ctx_id_t *c, gss_name_t d,
gss_OID e, OM_uint32 f,
OM_uint32 g, gss_channel_bindings_t h,
gss_buffer_t i, gss_OID * j,
gss_buffer_t k, OM_uint32 *l,
OM_uint32 *m)
#endif
{
return MitDispatch.gss_init_sec_context(a, b, c, d, e, f, g, h, i, j, k, l, m);
}
#ifdef __MINGW32__
KFW_CALL gss_import_name(OM_uint32 *a, gss_buffer_t b, gss_OID c, gss_name_t *d)
#else
OM_uint32 KRB5_CALLCONV gss_import_name(OM_uint32 *a, gss_buffer_t b, gss_OID c, gss_name_t *d)
#endif
{
return MitDispatch.gss_import_name(a, b, c, d);
}
#ifdef __MINGW32__
KFW_CALL gss_get_mic(OM_uint32 *a, gss_ctx_id_t b, gss_qop_t c,
gss_buffer_t d, gss_buffer_t e)
#else
OM_uint32 KRB5_CALLCONV gss_get_mic(OM_uint32 *a, gss_ctx_id_t b, gss_qop_t c,
gss_buffer_t d, gss_buffer_t e)
#endif
{
return MitDispatch.gss_get_mic(a, b, c, d, e);
}
/*
* Fake KRB5 functions. We pass control to runtime loaded
* KfW libs here.
*/
void KRB5_CALLCONV krb5_free_context(krb5_context a)
{
MitDispatch.krb5_free_context(a);
}
void KRB5_CALLCONV krb5_free_principal(krb5_context a, krb5_principal b)
{
MitDispatch.krb5_free_principal(a, b);
}
krb5_error_code KRB5_CALLCONV krb5_cc_destroy(krb5_context a, krb5_ccache b)
{
return MitDispatch.krb5_cc_destroy(a, b);
}