
An implementation of draft-zhu-negoex-04 for MIT Kerberos was developed in 2011. This has been recently integrated, with many fixes from Greg Hudson. This commit ports it to Heimdal. The implementation has been interoperability tested with MIT Kerberos and Windows, using the GSS EAP mechanism developed as part of the Moonshot project. The SPNEGO code was also updated to import the state machine from Apple which improves mechListMIC processing and avoids discarding initial context tokens generated during mechanism probing, that can be used for optimistic tokens. Finally, to aid in testing, the GSS-API mechanism glue configuration file can be changed using the environment variable GSS_MECH_CONFIG. This environment variable name, along with the format of the configuration file, is compatible with MIT (although it would be difficult for a single mechanism binary to support both implementations).
573 lines
17 KiB
C
573 lines
17 KiB
C
/*
|
|
* Copyright (C) 2019 by the Massachusetts Institute of Technology.
|
|
* All rights reserved.
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions
|
|
* are met:
|
|
*
|
|
* * Redistributions of source code must retain the above copyright
|
|
* notice, this list of conditions and the following disclaimer.
|
|
*
|
|
* * 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 COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
* "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
|
|
* COPYRIGHT HOLDER OR CONTRIBUTORS 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.
|
|
*/
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
#include <config.h>
|
|
#endif
|
|
|
|
#include <roken.h>
|
|
#include <assert.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <stdarg.h>
|
|
|
|
#include <krb5.h>
|
|
#include <der.h>
|
|
#include <gssapi_asn1.h>
|
|
|
|
#include <gssapi/gssapi.h>
|
|
#include <gssapi/gssapi_spnego.h>
|
|
|
|
struct test_context {
|
|
int initiator;
|
|
uint8_t hops; /* hops remaining; 0 means established */
|
|
};
|
|
|
|
OM_uint32 GSSAPI_CALLCONV
|
|
gss_init_sec_context(OM_uint32 *minor_status,
|
|
gss_const_cred_id_t claimant_cred_handle,
|
|
gss_ctx_id_t *context_handle, gss_const_name_t target_name,
|
|
const gss_OID mech_type, OM_uint32 req_flags,
|
|
OM_uint32 time_req,
|
|
const gss_channel_bindings_t input_chan_bindings,
|
|
const gss_buffer_t input_token, gss_OID *actual_mech,
|
|
gss_buffer_t output_token, OM_uint32 *ret_flags,
|
|
OM_uint32 *time_rec)
|
|
{
|
|
struct test_context *ctx = (struct test_context *)*context_handle;
|
|
OM_uint32 major;
|
|
gss_buffer_desc tok;
|
|
const char *envstr;
|
|
uint8_t hops, mech_last_octet;
|
|
|
|
major = gss_duplicate_oid(minor_status, mech_type, actual_mech);
|
|
if (major != GSS_S_COMPLETE)
|
|
return major;
|
|
|
|
if (input_token == GSS_C_NO_BUFFER || input_token->length == 0) {
|
|
envstr = getenv("HOPS");
|
|
hops = (envstr != NULL) ? atoi(envstr) : 1;
|
|
assert(hops > 0);
|
|
} else if (input_token->length == 4 &&
|
|
memcmp(input_token->value, "fail", 4) == 0) {
|
|
*minor_status = 12345;
|
|
return GSS_S_FAILURE;
|
|
} else {
|
|
hops = ((uint8_t *)input_token->value)[0];
|
|
}
|
|
|
|
mech_last_octet = ((uint8_t *)mech_type->elements)[mech_type->length - 1];
|
|
envstr = getenv("INIT_FAIL");
|
|
if (envstr != NULL && atoi(envstr) == mech_last_octet)
|
|
return GSS_S_FAILURE;
|
|
|
|
if (ctx == NULL) {
|
|
ctx = malloc(sizeof(*ctx));
|
|
assert(ctx != NULL);
|
|
ctx->initiator = 1;
|
|
ctx->hops = hops;
|
|
*context_handle = (gss_ctx_id_t)ctx;
|
|
} else if (ctx != NULL) {
|
|
assert(ctx->initiator);
|
|
ctx->hops--;
|
|
assert(ctx->hops == hops);
|
|
}
|
|
|
|
if (ctx->hops > 0) {
|
|
/* Generate a token containing the remaining hop count. */
|
|
ctx->hops--;
|
|
tok.value = &ctx->hops;
|
|
tok.length = 1;
|
|
major = gss_encapsulate_token(&tok, mech_type, output_token);
|
|
assert(major == GSS_S_COMPLETE);
|
|
}
|
|
|
|
return (ctx->hops > 0) ? GSS_S_CONTINUE_NEEDED : GSS_S_COMPLETE;
|
|
}
|
|
|
|
OM_uint32 GSSAPI_CALLCONV
|
|
gss_accept_sec_context(OM_uint32 *minor_status, gss_ctx_id_t *context_handle,
|
|
gss_const_cred_id_t verifier_cred_handle,
|
|
const gss_buffer_t input_token,
|
|
const gss_channel_bindings_t input_chan_bindings,
|
|
gss_name_t *src_name, gss_OID *mech_type,
|
|
gss_buffer_t output_token, OM_uint32 *ret_flags,
|
|
OM_uint32 *time_rec,
|
|
gss_cred_id_t *delegated_cred_handle)
|
|
{
|
|
struct test_context *ctx = (struct test_context *)*context_handle;
|
|
uint8_t hops, mech_last_octet;
|
|
const char *envstr;
|
|
unsigned char mechbuf[64];
|
|
GSSAPIContextToken ct;
|
|
gss_OID_desc oid;
|
|
int ret;
|
|
size_t mech_len;
|
|
|
|
ret = decode_GSSAPIContextToken(input_token->value, input_token->length,
|
|
&ct, NULL);
|
|
if (ret == 0) {
|
|
ret = der_put_oid ((unsigned char *)mechbuf + sizeof(mechbuf) - 1,
|
|
sizeof(mechbuf),
|
|
&ct.thisMech,
|
|
&mech_len);
|
|
}
|
|
if (ret) {
|
|
*minor_status = ret;
|
|
return GSS_S_FAILURE;
|
|
}
|
|
|
|
oid.length = (OM_uint32)mech_len;
|
|
oid.elements = mechbuf + sizeof(mechbuf) - mech_len;
|
|
|
|
gss_duplicate_oid(minor_status, &oid, mech_type);
|
|
|
|
/*
|
|
* The unwrapped token sits at the end and is just one byte giving the
|
|
* remaining number of hops. The final octet of the mech encoding should
|
|
* be just prior to it.
|
|
*/
|
|
assert(input_token->length >= 2);
|
|
hops = ((uint8_t *)input_token->value)[input_token->length - 1];
|
|
mech_last_octet = ((uint8_t *)input_token->value)[input_token->length - 2];
|
|
|
|
envstr = getenv("ACCEPT_FAIL");
|
|
if (envstr != NULL && atoi(envstr) == mech_last_octet) {
|
|
output_token->value = strdup("fail");
|
|
assert(output_token->value != NULL);
|
|
output_token->length = 4;
|
|
return GSS_S_FAILURE;
|
|
}
|
|
|
|
if (*context_handle == GSS_C_NO_CONTEXT) {
|
|
ctx = malloc(sizeof(*ctx));
|
|
assert(ctx != NULL);
|
|
ctx->initiator = 0;
|
|
ctx->hops = hops;
|
|
*context_handle = (gss_ctx_id_t)ctx;
|
|
} else {
|
|
assert(!ctx->initiator);
|
|
ctx->hops--;
|
|
assert(ctx->hops == hops);
|
|
}
|
|
|
|
if (ctx->hops > 0) {
|
|
/* Generate a token containing the remaining hop count. */
|
|
ctx->hops--;
|
|
output_token->value = malloc(1);
|
|
assert(output_token->value != NULL);
|
|
memcpy(output_token->value, &ctx->hops, 1);
|
|
output_token->length = 1;
|
|
}
|
|
|
|
return (ctx->hops > 0) ? GSS_S_CONTINUE_NEEDED : GSS_S_COMPLETE;
|
|
}
|
|
|
|
OM_uint32 GSSAPI_CALLCONV
|
|
gss_delete_sec_context(OM_uint32 *minor_status, gss_ctx_id_t *context_handle,
|
|
gss_buffer_t output_token)
|
|
{
|
|
free(*context_handle);
|
|
*context_handle = GSS_C_NO_CONTEXT;
|
|
return GSS_S_COMPLETE;
|
|
}
|
|
|
|
static int dummy_cred;
|
|
|
|
OM_uint32 GSSAPI_CALLCONV
|
|
gss_acquire_cred(OM_uint32 *minor_status, gss_const_name_t desired_name,
|
|
OM_uint32 time_req, const gss_OID_set desired_mechs,
|
|
gss_cred_usage_t cred_usage,
|
|
gss_cred_id_t *output_cred_handle, gss_OID_set *actual_mechs,
|
|
OM_uint32 *time_rec)
|
|
{
|
|
*minor_status = 0;
|
|
*output_cred_handle = (gss_cred_id_t)&dummy_cred;
|
|
return GSS_S_COMPLETE;
|
|
}
|
|
|
|
OM_uint32 GSSAPI_CALLCONV
|
|
gss_acquire_cred_with_password(OM_uint32 *minor_status,
|
|
gss_const_name_t desired_name,
|
|
const gss_buffer_t password, OM_uint32 time_req,
|
|
const gss_OID_set desired_mechs,
|
|
gss_cred_usage_t cred_usage,
|
|
gss_cred_id_t *output_cred_handle,
|
|
gss_OID_set *actual_mechs, OM_uint32 *time_rec)
|
|
{
|
|
*minor_status = 0;
|
|
*output_cred_handle = (gss_cred_id_t)&dummy_cred;
|
|
return GSS_S_COMPLETE;
|
|
}
|
|
|
|
OM_uint32 GSSAPI_CALLCONV
|
|
gss_release_cred(OM_uint32 *minor_status, gss_cred_id_t *cred_handle)
|
|
{
|
|
return GSS_S_COMPLETE;
|
|
}
|
|
|
|
static int dummy_name;
|
|
|
|
OM_uint32 GSSAPI_CALLCONV
|
|
gss_import_name(OM_uint32 *minor_status, gss_buffer_t input_name_buffer,
|
|
gss_OID input_name_type, gss_name_t *output_name)
|
|
{
|
|
/*
|
|
* We don't need to remember anything about names, but we do need to
|
|
* distinguish them from GSS_C_NO_NAME (to determine the direction of
|
|
* gss_query_meta_data() and gss_exchange_meta_data()), so assign an
|
|
* arbitrary data pointer.
|
|
*/
|
|
*output_name = (gss_name_t)&dummy_name;
|
|
return GSS_S_COMPLETE;
|
|
}
|
|
|
|
OM_uint32 GSSAPI_CALLCONV
|
|
gss_release_name(OM_uint32 *minor_status, gss_name_t *input_name)
|
|
{
|
|
return GSS_S_COMPLETE;
|
|
}
|
|
|
|
OM_uint32 GSSAPI_CALLCONV
|
|
gss_display_status(OM_uint32 *minor_status, OM_uint32 status_value,
|
|
int status_type, gss_OID mech_type,
|
|
OM_uint32 *message_context, gss_buffer_t status_string)
|
|
{
|
|
if (status_type == GSS_C_MECH_CODE && status_value == 12345) {
|
|
status_string->value = strdup("failure from acceptor");
|
|
assert(status_string->value != NULL);
|
|
status_string->length = strlen(status_string->value);
|
|
return GSS_S_COMPLETE;
|
|
}
|
|
return GSS_S_BAD_STATUS;
|
|
}
|
|
|
|
OM_uint32 GSSAPI_CALLCONV
|
|
gssspi_query_meta_data(OM_uint32 *minor_status, gss_const_OID mech_oid,
|
|
gss_cred_id_t cred_handle, gss_ctx_id_t *context_handle,
|
|
gss_const_name_t targ_name, OM_uint32 req_flags,
|
|
gss_buffer_t meta_data)
|
|
{
|
|
const char *envstr;
|
|
uint8_t mech_last_octet;
|
|
int initiator = (targ_name != GSS_C_NO_NAME);
|
|
|
|
mech_last_octet = ((uint8_t *)mech_oid->elements)[mech_oid->length - 1];
|
|
envstr = getenv(initiator ? "INIT_QUERY_FAIL" : "ACCEPT_QUERY_FAIL");
|
|
if (envstr != NULL && atoi(envstr) == mech_last_octet)
|
|
return GSS_S_FAILURE;
|
|
envstr = getenv(initiator ? "INIT_QUERY_NONE" : "ACCEPT_QUERY_NONE");
|
|
if (envstr != NULL && atoi(envstr) == mech_last_octet)
|
|
return GSS_S_COMPLETE;
|
|
|
|
meta_data->value = strdup("X");
|
|
meta_data->length = 1;
|
|
return GSS_S_COMPLETE;
|
|
}
|
|
|
|
OM_uint32 GSSAPI_CALLCONV
|
|
gssspi_exchange_meta_data(OM_uint32 *minor_status, gss_const_OID mech_oid,
|
|
gss_cred_id_t cred_handle,
|
|
gss_ctx_id_t *context_handle,
|
|
gss_const_name_t targ_name, OM_uint32 req_flags,
|
|
gss_const_buffer_t meta_data)
|
|
{
|
|
const char *envstr;
|
|
uint8_t mech_last_octet;
|
|
int initiator = (targ_name != GSS_C_NO_NAME);
|
|
|
|
mech_last_octet = ((uint8_t *)mech_oid->elements)[mech_oid->length - 1];
|
|
envstr = getenv(initiator ? "INIT_EXCHANGE_FAIL" : "ACCEPT_EXCHANGE_FAIL");
|
|
if (envstr != NULL && atoi(envstr) == mech_last_octet)
|
|
return GSS_S_FAILURE;
|
|
|
|
assert(meta_data->length == 1 && memcmp(meta_data->value, "X", 1) == 0);
|
|
return GSS_S_COMPLETE;
|
|
}
|
|
|
|
OM_uint32 GSSAPI_CALLCONV
|
|
gssspi_query_mechanism_info(OM_uint32 *minor_status, gss_const_OID mech_oid,
|
|
unsigned char auth_scheme[16])
|
|
{
|
|
/* Copy the mech OID encoding and right-pad it with zeros. */
|
|
memset(auth_scheme, 0, 16);
|
|
assert(mech_oid->length <= 16);
|
|
memcpy(auth_scheme, mech_oid->elements, mech_oid->length);
|
|
return GSS_S_COMPLETE;
|
|
}
|
|
|
|
OM_uint32 GSSAPI_CALLCONV
|
|
gss_inquire_sec_context_by_oid(OM_uint32 *minor_status,
|
|
gss_const_ctx_id_t context_handle,
|
|
const gss_OID desired_object,
|
|
gss_buffer_set_t *data_set)
|
|
{
|
|
struct test_context *ctx = (struct test_context *)context_handle;
|
|
OM_uint32 major;
|
|
uint8_t keybytes[32] = { 0 };
|
|
uint8_t typebytes[4];
|
|
gss_buffer_desc key, type;
|
|
const char *envstr;
|
|
int ask_verify;
|
|
|
|
if (gss_oid_equal(desired_object, GSS_C_INQ_NEGOEX_KEY))
|
|
ask_verify = 0;
|
|
else if (gss_oid_equal(desired_object, GSS_C_INQ_NEGOEX_VERIFY_KEY))
|
|
ask_verify = 1;
|
|
else
|
|
return GSS_S_UNAVAILABLE;
|
|
|
|
/*
|
|
* By default, make a key available only if the context is established.
|
|
* This can be overridden to "always", "init-always", "accept-always",
|
|
* or "never".
|
|
*/
|
|
envstr = getenv("KEY");
|
|
if (envstr != NULL && strcmp(envstr, "never") == 0) {
|
|
return GSS_S_UNAVAILABLE;
|
|
} else if (ctx->hops > 0) {
|
|
if (envstr == NULL)
|
|
return GSS_S_UNAVAILABLE;
|
|
else if (strcmp(envstr, "init-always") == 0 && !ctx->initiator)
|
|
return GSS_S_UNAVAILABLE;
|
|
else if (strcmp(envstr, "accept-always") == 0 && ctx->initiator)
|
|
return GSS_S_UNAVAILABLE;
|
|
}
|
|
|
|
/* Perturb the key so that each side's verifier key is equal to the other's
|
|
* checksum key. */
|
|
keybytes[0] = ask_verify ^ ctx->initiator;
|
|
|
|
/* Supply an all-zeros aes256-sha1 negoex key. */
|
|
if (gss_oid_equal(desired_object, GSS_C_INQ_NEGOEX_KEY) ||
|
|
gss_oid_equal(desired_object, GSS_C_INQ_NEGOEX_VERIFY_KEY)) {
|
|
OM_uint32 n = ENCTYPE_AES256_CTS_HMAC_SHA1_96;
|
|
|
|
typebytes[0] = (n >> 0 ) & 0xFF;
|
|
typebytes[1] = (n >> 8 ) & 0xFF;
|
|
typebytes[2] = (n >> 16) & 0xFF;
|
|
typebytes[3] = (n >> 24) & 0xFF;
|
|
|
|
key.value = keybytes;
|
|
key.length = sizeof(keybytes);
|
|
type.value = typebytes;
|
|
type.length = sizeof(typebytes);
|
|
major = gss_add_buffer_set_member(minor_status, &key, data_set);
|
|
if (major != GSS_S_COMPLETE)
|
|
return major;
|
|
return gss_add_buffer_set_member(minor_status, &type, data_set);
|
|
}
|
|
|
|
return GSS_S_UNAVAILABLE;
|
|
}
|
|
|
|
GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
|
|
gss_process_context_token(OM_uint32 *minor_status,
|
|
gss_const_ctx_id_t context_handle,
|
|
const gss_buffer_t token_buffer)
|
|
{
|
|
return GSS_S_COMPLETE;
|
|
}
|
|
|
|
GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
|
|
gss_context_time(OM_uint32 *minor_status,
|
|
gss_const_ctx_id_t context_handle,
|
|
OM_uint32 *time_rec)
|
|
{
|
|
*time_rec = 0;
|
|
return GSS_S_COMPLETE;
|
|
}
|
|
|
|
/*
|
|
* We also need to supply a fake MIC in case SPNEGO test negotiates
|
|
* as non-default mechanism
|
|
*/
|
|
#define FAKE_MIC "negoex-fake-mic"
|
|
#define FAKE_MIC_LEN (sizeof(FAKE_MIC) - 1)
|
|
|
|
GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
|
|
gss_get_mic(OM_uint32 *minor_status,
|
|
gss_const_ctx_id_t context_handle,
|
|
gss_qop_t qop_req,
|
|
const gss_buffer_t message_buffer,
|
|
gss_buffer_t message_token)
|
|
{
|
|
message_token->value = strdup(FAKE_MIC);
|
|
message_token->length = FAKE_MIC_LEN;
|
|
|
|
*minor_status = 0;
|
|
return GSS_S_COMPLETE;
|
|
}
|
|
|
|
GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
|
|
gss_verify_mic(OM_uint32 *minor_status,
|
|
gss_const_ctx_id_t context_handle,
|
|
const gss_buffer_t message_buffer,
|
|
const gss_buffer_t token_buffer,
|
|
gss_qop_t *qop_state)
|
|
{
|
|
*minor_status = 0;
|
|
if (token_buffer->length == FAKE_MIC_LEN &&
|
|
memcmp(token_buffer->value, FAKE_MIC, FAKE_MIC_LEN) == 0)
|
|
return GSS_S_COMPLETE;
|
|
else
|
|
return GSS_S_BAD_MIC;
|
|
}
|
|
|
|
GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
|
|
gss_wrap(OM_uint32 *minor_status,
|
|
gss_const_ctx_id_t context_handle,
|
|
int conf_req_flag,
|
|
gss_qop_t qop_req,
|
|
const gss_buffer_t input_message_buffer,
|
|
int *conf_state,
|
|
gss_buffer_t output_message_buffer)
|
|
{
|
|
return GSS_S_UNAVAILABLE;
|
|
}
|
|
|
|
GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
|
|
gss_unwrap(OM_uint32 *minor_status,
|
|
gss_const_ctx_id_t context_handle,
|
|
const gss_buffer_t input_message_buffer,
|
|
gss_buffer_t output_message_buffer,
|
|
int *conf_state,
|
|
gss_qop_t *qop_state)
|
|
{
|
|
return GSS_S_UNAVAILABLE;
|
|
}
|
|
|
|
GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
|
|
gss_compare_name(OM_uint32 *minor_status,
|
|
gss_const_name_t name1_arg,
|
|
gss_const_name_t name2_arg,
|
|
int *name_equal)
|
|
{
|
|
return GSS_S_UNAVAILABLE;
|
|
}
|
|
|
|
GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
|
|
gss_display_name(OM_uint32 *minor_status,
|
|
gss_const_name_t input_name,
|
|
gss_buffer_t output_name_buffer,
|
|
gss_OID *output_name_type)
|
|
{
|
|
return GSS_S_UNAVAILABLE;
|
|
}
|
|
|
|
GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
|
|
gss_export_name(OM_uint32 *minor_status,
|
|
gss_const_name_t input_name,
|
|
gss_buffer_t exported_name)
|
|
{
|
|
return GSS_S_UNAVAILABLE;
|
|
}
|
|
|
|
GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
|
|
gss_inquire_context(OM_uint32 *minor_status,
|
|
gss_const_ctx_id_t context_handle,
|
|
gss_name_t *src_name,
|
|
gss_name_t *targ_name,
|
|
OM_uint32 *lifetime_rec,
|
|
gss_OID *mech_type,
|
|
OM_uint32 *ctx_flags,
|
|
int *locally_initiated,
|
|
int *xopen)
|
|
{
|
|
*lifetime_rec = GSS_C_INDEFINITE;
|
|
return GSS_S_UNAVAILABLE;
|
|
}
|
|
|
|
GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
|
|
gss_wrap_size_limit(OM_uint32 *minor_status,
|
|
gss_const_ctx_id_t context_handle,
|
|
int conf_req_flag,
|
|
gss_qop_t qop_req,
|
|
OM_uint32 req_output_size,
|
|
OM_uint32 *max_input_size)
|
|
{
|
|
return GSS_S_UNAVAILABLE;
|
|
}
|
|
|
|
GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
|
|
gss_import_sec_context(OM_uint32 *minor_status,
|
|
const gss_buffer_t interprocess_token,
|
|
gss_ctx_id_t *context_handle)
|
|
{
|
|
return GSS_S_UNAVAILABLE;
|
|
}
|
|
|
|
GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
|
|
gss_export_sec_context(OM_uint32 *minor_status,
|
|
gss_ctx_id_t *context_handle,
|
|
gss_buffer_t interprocess_token)
|
|
{
|
|
return GSS_S_UNAVAILABLE;
|
|
}
|
|
|
|
GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
|
|
gss_canonicalize_name(OM_uint32 *minor_status,
|
|
gss_const_name_t input_name,
|
|
const gss_OID mech_type,
|
|
gss_name_t *output_name)
|
|
{
|
|
return GSS_S_UNAVAILABLE;
|
|
}
|
|
|
|
GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
|
|
gss_duplicate_name(OM_uint32 *minor_status,
|
|
gss_const_name_t src_name,
|
|
gss_name_t *dest_name)
|
|
{
|
|
return GSS_S_UNAVAILABLE;
|
|
}
|
|
|
|
GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
|
|
gss_inquire_cred(OM_uint32 *minor_status,
|
|
gss_const_cred_id_t cred_handle,
|
|
gss_name_t *name_ret,
|
|
OM_uint32 *lifetime,
|
|
gss_cred_usage_t *cred_usage,
|
|
gss_OID_set *mechanisms)
|
|
{
|
|
if (name_ret)
|
|
*name_ret = (gss_name_t)&dummy_name;
|
|
if (lifetime)
|
|
*lifetime = GSS_C_INDEFINITE;
|
|
if (cred_usage)
|
|
*cred_usage = GSS_C_BOTH;
|
|
if (mechanisms)
|
|
*mechanisms = GSS_C_NO_OID_SET;
|
|
|
|
return GSS_S_COMPLETE;
|
|
}
|
|
|