new files

git-svn-id: svn://svn.h5l.se/heimdal/trunk/heimdal@1579 ec53bebd-3082-4978-b11e-865c3cabbd6b
This commit is contained in:
Assar Westerlund
1997-04-13 22:18:46 +00:00
parent c688f33a4b
commit 16f56ac4cd
52 changed files with 4686 additions and 0 deletions

18
lib/gssapi/Makefile.am Normal file
View File

@@ -0,0 +1,18 @@
# $Id$
AUTOMAKE_OPTIONS = no-dependencies
INCLUDES = -I$(top_builddir)/include -I$(srcdir)/../krb5
lib_LIBRARIES = libgssapi.a
libgssapi_a_SOURCES = \
accept_sec_context.c add_oid_set_member.c \
create_emtpy_oid_set.c decapsulate.c \
delete_sec_context.c display_name.c \
duplicate_name.c encapsulate.c external.c \
get_mic.c import_name.c indicate_mechs.c \
init.c init_sec_context.c inquire_context.c \
release_buffer.c release_name.c release_oid_set.c \
test_oid_set_member.c unwrap.c verify_mic.c \
wrap.c \

View File

@@ -0,0 +1,132 @@
#include "gssapi_locl.h"
RCSID("$Id$");
OM_uint32 gss_accept_sec_context
(OM_uint32 * minor_status,
gss_ctx_id_t * context_handle,
const gss_cred_id_t acceptor_cred_handle,
const gss_buffer_t input_token_buffer,
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
)
{
krb5_error_code kret;
OM_uint32 ret;
krb5_data indata;
krb5_flags ap_options;
OM_uint32 flags;
krb5_ticket *ticket;
gssapi_krb5_init ();
*context_handle = malloc(sizeof(**context_handle));
if (*context_handle == NULL)
return GSS_S_FAILURE;
(*context_handle)->auth_context = NULL;
(*context_handle)->source = NULL;
(*context_handle)->target = NULL;
(*context_handle)->flags = 0;
(*context_handle)->more_flags = 0;
kret = krb5_auth_con_init (gssapi_krb5_context,
&(*context_handle)->auth_context);
if (kret) {
ret = GSS_S_FAILURE;
goto failure;
}
ret = gssapi_krb5_decapsulate (input_token_buffer,
&indata,
"\x01\x00");
if (ret)
goto failure;
kret = krb5_rd_req (gssapi_krb5_context,
&(*context_handle)->auth_context,
&indata,
/*server*/ NULL, /* XXX */
NULL,
&ap_options,
&ticket);
if (kret) {
ret = GSS_S_FAILURE;
goto failure;
}
kret = krb5_copy_principal (gssapi_krb5_context,
ticket->enc_part2.client,
&(*context_handle)->source);
if (kret) {
ret = GSS_S_FAILURE;
goto failure;
}
if (src_name) {
kret = krb5_copy_principal (gssapi_krb5_context,
ticket->enc_part2.client,
src_name);
if (kret) {
ret = GSS_S_FAILURE;
goto failure;
}
}
flags = 0;
if (ap_options & AP_OPTS_MUTUAL_REQUIRED)
flags |= GSS_C_MUTUAL_FLAG;
flags |= GSS_C_CONF_FLAG;
flags |= GSS_C_INTEG_FLAG;
if (ret_flags)
*ret_flags = flags;
(*context_handle)->flags = flags;
(*context_handle)->more_flags |= OPEN;
if (mech_type)
*mech_type = GSS_KRB5_MECHANISM;
if (time_rec)
*time_rec = GSS_C_INDEFINITE;
if(flags & GSS_C_MUTUAL_FLAG) {
krb5_data outbuf;
kret = krb5_mk_rep (gssapi_krb5_context,
&(*context_handle)->auth_context,
&outbuf);
if (kret) {
krb5_data_free (&outbuf);
ret = GSS_S_FAILURE;
goto failure;
}
ret = gssapi_krb5_encapsulate (&outbuf,
output_token,
"\x02\x00");
if (ret)
goto failure;
} else {
output_token->length = 0;
}
return GSS_S_COMPLETE;
failure:
krb5_auth_con_free (gssapi_krb5_context,
(*context_handle)->auth_context);
if((*context_handle)->source)
krb5_free_principal (gssapi_krb5_context,
(*context_handle)->source);
if((*context_handle)->target)
krb5_free_principal (gssapi_krb5_context,
(*context_handle)->target);
free (*context_handle);
*context_handle = GSS_C_NO_CONTEXT;
return GSS_S_FAILURE;
}

View File

@@ -0,0 +1,21 @@
#include "gssapi_locl.h"
RCSID("$Id$");
OM_uint32 gss_add_oid_set_member (
OM_uint32 * minor_status,
const gss_OID member_oid,
gss_OID_set * oid_set
)
{
size_t n = (*oid_set)->count;
(*oid_set)->elements = realloc ((*oid_set)->elements,
n * sizeof(gss_OID_desc));
if ((*oid_set)->elements == NULL) {
return GSS_S_FAILURE;
}
(*oid_set)->count = n;
(*oid_set)->elements[n-1] = *member_oid;
return GSS_S_COMPLETE;
}

View File

@@ -0,0 +1,17 @@
#include "gssapi_locl.h"
RCSID("$Id$");
OM_uint32 gss_create_empty_oid_set (
OM_uint32 * minor_status,
gss_OID_set * oid_set
)
{
*oid_set = malloc(sizeof(**oid_set));
if (*oid_set == NULL) {
return GSS_S_FAILURE;
}
(*oid_set)->count = 0;
(*oid_set)->elements = NULL;
return GSS_S_COMPLETE;
}

36
lib/gssapi/decapsulate.c Normal file
View File

@@ -0,0 +1,36 @@
#include "gssapi_locl.h"
RCSID("$Id$");
/*
* Remove the GSS-API wrapping from `in_token' giving `out_data.
* Does not copy data, so just free `in_token'.
*/
OM_uint32
gssapi_krb5_decapsulate(
gss_buffer_t input_token_buffer,
krb5_data *out_data,
u_char *type
)
{
u_char *p;
size_t len;
p = input_token_buffer->value;
len = GSS_KRB5_MECHANISM->length + 6;
if (
input_token_buffer->length < len
|| memcmp (p, "\x60\x07\x06\x05", 4) != 0
|| memcmp (p + 4, GSS_KRB5_MECHANISM->elements,
GSS_KRB5_MECHANISM->length) != 0)
return GSS_S_BAD_MECH;
if (memcmp (p + 4 + GSS_KRB5_MECHANISM->length,
type, 2) != 0)
return GSS_S_DEFECTIVE_TOKEN;
out_data->length = input_token_buffer->length - len;
out_data->data = (u_char *)input_token_buffer->value + len;
return GSS_S_COMPLETE;
}

View File

@@ -0,0 +1,24 @@
#include "gssapi_locl.h"
RCSID("$Id$");
OM_uint32 gss_delete_sec_context
(OM_uint32 * minor_status,
gss_ctx_id_t * context_handle,
gss_buffer_t output_token
)
{
gssapi_krb5_init ();
krb5_auth_con_free (gssapi_krb5_context,
(*context_handle)->auth_context);
if((*context_handle)->source)
krb5_free_principal (gssapi_krb5_context,
(*context_handle)->source);
if((*context_handle)->target)
krb5_free_principal (gssapi_krb5_context,
(*context_handle)->target);
free (*context_handle);
if (output_token)
output_token->length = 0;
return GSS_S_COMPLETE;
}

32
lib/gssapi/display_name.c Normal file
View File

@@ -0,0 +1,32 @@
#include "gssapi_locl.h"
RCSID("$Id$");
OM_uint32 gss_display_name
(OM_uint32 * minor_status,
const gss_name_t input_name,
gss_buffer_t output_name_buffer,
gss_OID * output_name_type
)
{
krb5_error_code kret;
char *buf;
size_t len;
gssapi_krb5_init ();
kret = krb5_unparse_name (gssapi_krb5_context,
input_name,
&buf);
if (kret)
return GSS_S_FAILURE;
len = strlen (buf);
output_name_buffer->length = len;
output_name_buffer->value = malloc(len);
if (output_name_buffer->value == NULL) {
free (buf);
return GSS_S_FAILURE;
}
memcpy (output_name_buffer->value, buf, len);
free (buf);
return GSS_S_COMPLETE;
}

View File

@@ -0,0 +1,22 @@
#include "gssapi_locl.h"
RCSID("$Id$");
OM_uint32 gss_duplicate_name (
OM_uint32 * minor_status,
const gss_name_t src_name,
gss_name_t * dest_name
)
{
krb5_error_code kret;
gssapi_krb5_init ();
kret = krb5_copy_principal (gssapi_krb5_context,
src_name,
dest_name);
if (kret)
return GSS_S_FAILURE;
else
return GSS_S_COMPLETE;
}

33
lib/gssapi/encapsulate.c Normal file
View File

@@ -0,0 +1,33 @@
#include "gssapi_locl.h"
RCSID("$Id$");
/*
* Give it a krb5_data and it will encapsulate with extra GSS-API wrappings.
*/
OM_uint32
gssapi_krb5_encapsulate(
krb5_data *in_data,
gss_buffer_t output_token,
u_char *type
)
{
u_char *p;
output_token->length = in_data->length + GSS_KRB5_MECHANISM->length + 6;
output_token->value = malloc (output_token->length);
if (output_token->value == NULL)
return GSS_S_FAILURE;
p = output_token->value;
memcpy (p, "\x60\x07\x06\x05", 4);
p += 4;
memcpy (p, GSS_KRB5_MECHANISM->elements, GSS_KRB5_MECHANISM->length);
p += GSS_KRB5_MECHANISM->length;
memcpy (p, type, 2);
p += 2;
memcpy (p, in_data->data, in_data->length);
krb5_data_free (in_data);
return GSS_S_COMPLETE;
}

172
lib/gssapi/external.c Normal file
View File

@@ -0,0 +1,172 @@
#include "gssapi_locl.h"
RCSID("$Id$");
/*
* The implementation must reserve static storage for a
* gss_OID_desc object containing the value
* {10, (void *)"\x2a\x86\x48\x86\xf7\x12"
* "\x01\x02\x01\x01"},
* corresponding to an object-identifier value of
* {iso(1) member-body(2) United States(840) mit(113554)
* infosys(1) gssapi(2) generic(1) user_name(1)}. The constant
* GSS_C_NT_USER_NAME should be initialized to point
* to that gss_OID_desc.
*/
static gss_OID_desc gss_c_nt_user_name_oid_desc =
{10, (void *)"\x2a\x86\x48\x86\xf7\x12"
"\x01\x02\x01\x01"};
gss_OID GSS_C_NT_USER_NAME = &gss_c_nt_user_name_oid_desc;
/*
* The implementation must reserve static storage for a
* gss_OID_desc object containing the value
* {10, (void *)"\x2a\x86\x48\x86\xf7\x12"
* "\x01\x02\x01\x02"},
* corresponding to an object-identifier value of
* {iso(1) member-body(2) United States(840) mit(113554)
* infosys(1) gssapi(2) generic(1) machine_uid_name(2)}.
* The constant GSS_C_NT_MACHINE_UID_NAME should be
* initialized to point to that gss_OID_desc.
*/
static gss_OID_desc gss_c_nt_machine_uid_name_oid_desc =
{10, (void *)"\x2a\x86\x48\x86\xf7\x12"
"\x01\x02\x01\x02"};
gss_OID GSS_C_NT_MACHINE_UID_NAME = &gss_c_nt_machine_uid_name_oid_desc;
/*
* The implementation must reserve static storage for a
* gss_OID_desc object containing the value
* {10, (void *)"\x2a\x86\x48\x86\xf7\x12"
* "\x01\x02\x01\x03"},
* corresponding to an object-identifier value of
* {iso(1) member-body(2) United States(840) mit(113554)
* infosys(1) gssapi(2) generic(1) string_uid_name(3)}.
* The constant GSS_C_NT_STRING_UID_NAME should be
* initialized to point to that gss_OID_desc.
*/
static gss_OID_desc gss_c_nt_string_uid_name_oid_desc =
{10, (void *)"\x2a\x86\x48\x86\xf7\x12"
"\x01\x02\x01\x03"};
gss_OID GSS_C_NT_STRING_UID_NAME = &gss_c_nt_string_uid_name_oid_desc;
/*
* The implementation must reserve static storage for a
* gss_OID_desc object containing the value
* {6, (void *)"\x2b\x06\x01\x05\x06\x02"},
* corresponding to an object-identifier value of
* {1(iso), 3(org), 6(dod), 1(internet), 5(security),
* 6(nametypes), 2(gss-host-based-services)}. The constant
* GSS_C_NT_HOSTBASED_SERVICE should be initialized to point
* to that gss_OID_desc.
*/
static gss_OID_desc gss_c_nt_hostbased_service_oid_desc =
{6, (void *)"\x2b\x06\x01\x05\x06\x02"};
gss_OID GSS_C_NT_HOSTBASED_SERVICE = &gss_c_nt_hostbased_service_oid_desc;
/*
* The implementation must reserve static storage for a
* gss_OID_desc object containing the value
* {6, (void *)"\x2b\x06\01\x05\x06\x03"},
* corresponding to an object identifier value of
* {1(iso), 3(org), 6(dod), 1(internet), 5(security),
* 6(nametypes), 3(gss-anonymous-name)}. The constant
* and GSS_C_NT_ANONYMOUS should be initialized to point
* to that gss_OID_desc.
*/
static gss_OID_desc gss_c_nt_anonymous_oid_desc =
{6, (void *)"\x2b\x06\01\x05\x06\x03"};
gss_OID GSS_C_NT_ANONYMOUS = &gss_c_nt_anonymous_oid_desc;
/*
* The implementation must reserve static storage for a
* gss_OID_desc object containing the value
* {6, (void *)"\x2b\x06\x01\x05\x06\x04"},
* corresponding to an object-identifier value of
* {1(iso), 3(org), 6(dod), 1(internet), 5(security),
* 6(nametypes), 4(gss-api-exported-name)}. The constant
* GSS_C_NT_EXPORT_NAME should be initialized to point
* to that gss_OID_desc.
*/
static gss_OID_desc gss_c_nt_export_name_oid_desc =
{6, (void *)"\x2b\x06\x01\x05\x06\x04"};
gss_OID GSS_C_NT_EXPORT_NAME = &gss_c_nt_export_name_oid_desc;
/*
* This name form shall be represented by the Object Identifier {iso(1)
* member-body(2) United States(840) mit(113554) infosys(1) gssapi(2)
* krb5(2) krb5_name(1)}. The recommended symbolic name for this type
* is "GSS_KRB5_NT_PRINCIPAL_NAME".
*/
static gss_OID_desc gss_krb5_nt_principal_name_oid_desc =
{10, (void *)"\x2a\x86\x48\x86\xf7\x12\x01\x02\x02\x01"};
gss_OID GSS_KRB5_NT_PRINCIPAL_NAME = &gss_krb5_nt_principal_name_oid_desc;
/*
* This name form shall be represented by the Object Identifier {iso(1)
* member-body(2) United States(840) mit(113554) infosys(1) gssapi(2)
* generic(1) user_name(1)}. The recommended symbolic name for this
* type is "GSS_KRB5_NT_USER_NAME".
*/
gss_OID GSS_KRB5_NT_USER_NAME = &gss_c_nt_user_name_oid_desc;
/*
* This name form shall be represented by the Object Identifier {iso(1)
* member-body(2) United States(840) mit(113554) infosys(1) gssapi(2)
* generic(1) machine_uid_name(2)}. The recommended symbolic name for
* this type is "GSS_KRB5_NT_MACHINE_UID_NAME".
*/
gss_OID GSS_KRB5_NT_MACHINE_UID_NAME = &gss_c_nt_machine_uid_name_oid_desc;
/*
* This name form shall be represented by the Object Identifier {iso(1)
* member-body(2) United States(840) mit(113554) infosys(1) gssapi(2)
* generic(1) string_uid_name(3)}. The recommended symbolic name for
* this type is "GSS_KRB5_NT_STRING_UID_NAME".
*/
gss_OID GSS_KRB5_NT_STRING_UID_NAME = &gss_c_nt_string_uid_name_oid_desc;
/*
* To support ongoing experimentation, testing, and evolution of the
* specification, the Kerberos V5 GSS-API mechanism as defined in this
* and any successor memos will be identified with the following Object
* Identifier, as defined in RFC-1510, until the specification is
* advanced to the level of Proposed Standard RFC:
*
* {iso(1), org(3), dod(5), internet(1), security(5), kerberosv5(2)}
*
* Upon advancement to the level of Proposed Standard RFC, the Kerberos
* V5 GSS-API mechanism will be identified by an Object Identifier
* having the value:
*
* {iso(1) member-body(2) United States(840) mit(113554) infosys(1)
* gssapi(2) krb5(2)}
*/
static gss_OID_desc gss_krb5_mechanism_oid_desc =
{5, (void *)"\x2b\x05\x01\x05\x02"};
gss_OID GSS_KRB5_MECHANISM = &gss_krb5_mechanism_oid_desc;
/*
* Context for krb5 calls.
*/
krb5_context gssapi_krb5_context;

58
lib/gssapi/get_mic.c Normal file
View File

@@ -0,0 +1,58 @@
#include "gssapi_locl.h"
#include <des.h>
#include <md5.h>
RCSID("$Id$");
OM_uint32 gss_get_mic
(OM_uint32 * minor_status,
const gss_ctx_id_t context_handle,
gss_qop_t qop_req,
const gss_buffer_t message_buffer,
gss_buffer_t message_token
)
{
u_char *p;
size_t len;
struct md5 md5;
u_char hash[16];
des_key_schedule schedule;
des_cblock key;
des_cblock zero;
len = 28 + GSS_KRB5_MECHANISM->length;
message_token->length = len;
message_token->value = malloc (len);
if (message_token->value == NULL)
return GSS_S_FAILURE;
p = message_token->value;
memcpy (p, "\x60\x07\x06\x05", 4);
p += 4;
memcpy (p, GSS_KRB5_MECHANISM->elements, GSS_KRB5_MECHANISM->length);
p += GSS_KRB5_MECHANISM->length;
memcpy (p, "\x01\x01", 2);
p += 2;
memcpy (p, "\x00\x00", 2);
p += 2;
memcpy (p, "\xff\xff\xff\xff", 4);
p += 4;
memset (p, 0, 16);
p += 16;
md5_init (&md5);
md5_update (&md5, p - 24, 8);
md5_update (&md5, message_buffer->value,
message_buffer->length);
md5_finito (&md5, hash);
memset (&zero, 0, sizeof(zero));
memcpy (&key, context_handle->auth_context->key.contents.data,
sizeof(key));
des_set_key (&key, schedule);
des_cbc_cksum ((des_cblock *)hash,
(des_cblock *)hash, sizeof(hash), schedule, &zero);
memcpy (p - 8, hash, 8);
return GSS_S_COMPLETE;
}

693
lib/gssapi/gssapi.h Normal file
View File

@@ -0,0 +1,693 @@
/* $Id$ */
#ifndef GSSAPI_H_
#define GSSAPI_H_
/*
* First, include stddef.h to get size_t defined.
*/
#include <stddef.h>
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <sys/types.h>
#ifdef HAVE_SYS_BITYPES_H
#include <sys/bitypes.h>
#endif
#include <bits.h>
#include <krb5.h>
/*
* Now define the three implementation-dependent types.
*/
typedef u_int32_t OM_uint32;
/*
* XXX - Should we really do it this way?
* I'm not entirely happy with exposing this match of the krb5 stuff
* here, and having to include the <krb5.h> file as well.
*/
typedef krb5_principal gss_name_t;
typedef struct gss_ctx_id_t_desc_struct {
krb5_auth_context auth_context;
gss_name_t source, target;
OM_uint32 flags;
enum { LOCAL = 1, OPEN = 2} more_flags;
} gss_ctx_id_t_desc;
typedef gss_ctx_id_t_desc *gss_ctx_id_t;
typedef int gss_cred_id_t; /* XXX */
typedef struct gss_OID_desc_struct {
OM_uint32 length;
void *elements;
} gss_OID_desc, *gss_OID;
typedef struct gss_OID_set_desc_struct {
size_t count;
gss_OID elements;
} gss_OID_set_desc, *gss_OID_set;
typedef struct gss_buffer_desc_struct {
size_t length;
void *value;
} gss_buffer_desc, *gss_buffer_t;
typedef struct gss_channel_bindings_struct {
OM_uint32 initiator_addrtype;
gss_buffer_desc initiator_address;
OM_uint32 acceptor_addrtype;
gss_buffer_desc acceptor_address;
gss_buffer_desc application_data;
} *gss_channel_bindings_t;
/*
* For now, define a QOP-type as an OM_uint32
*/
typedef OM_uint32 gss_qop_t;
typedef int gss_cred_usage_t;
/*
* Flag bits for context-level services.
*/
#define GSS_C_DELEG_FLAG 1
#define GSS_C_MUTUAL_FLAG 2
#define GSS_C_REPLAY_FLAG 4
#define GSS_C_SEQUENCE_FLAG 8
#define GSS_C_CONF_FLAG 16
#define GSS_C_INTEG_FLAG 32
#define GSS_C_ANON_FLAG 64
#define GSS_C_PROT_READY_FLAG 128
#define GSS_C_TRANS_FLAG 256
/*
* Credential usage options
*/
#define GSS_C_BOTH 0
#define GSS_C_INITIATE 1
#define GSS_C_ACCEPT 2
/*
* Status code types for gss_display_status
*/
#define GSS_C_GSS_CODE 1
#define GSS_C_MECH_CODE 2
/*
* The constant definitions for channel-bindings address families
*/
#define GSS_C_AF_UNSPEC 0
#define GSS_C_AF_LOCAL 1
#define GSS_C_AF_INET 2
#define GSS_C_AF_IMPLINK 3
#define GSS_C_AF_PUP 4
#define GSS_C_AF_CHAOS 5
#define GSS_C_AF_NS 6
#define GSS_C_AF_NBS 7
#define GSS_C_AF_ECMA 8
#define GSS_C_AF_DATAKIT 9
#define GSS_C_AF_CCITT 10
#define GSS_C_AF_SNA 11
#define GSS_C_AF_DECnet 12
#define GSS_C_AF_DLI 13
#define GSS_C_AF_LAT 14
#define GSS_C_AF_HYLINK 15
#define GSS_C_AF_APPLETALK 16
#define GSS_C_AF_BSC 17
#define GSS_C_AF_DSS 18
#define GSS_C_AF_OSI 19
#define GSS_C_AF_X25 21
#define GSS_C_AF_NULLADDR 255
/*
* Various Null values
*/
#define GSS_C_NO_NAME ((gss_name_t) 0)
#define GSS_C_NO_BUFFER ((gss_buffer_t) 0)
#define GSS_C_NO_OID ((gss_OID) 0)
#define GSS_C_NO_OID_SET ((gss_OID_set) 0)
#define GSS_C_NO_CONTEXT ((gss_ctx_id_t) 0)
#define GSS_C_NO_CREDENTIAL ((gss_cred_id_t) 0)
#define GSS_C_NO_CHANNEL_BINDINGS ((gss_channel_bindings_t) 0)
#define GSS_C_EMPTY_BUFFER {0, NULL}
/*
* Some alternate names for a couple of the above
* values. These are defined for V1 compatibility.
*/
#define GSS_C_NULL_OID GSS_C_NO_OID
#define GSS_C_NULL_OID_SET GSS_C_NO_OID_SET
/*
* Define the default Quality of Protection for per-message
* services. Note that an implementation that offers multiple
* levels of QOP may define GSS_C_QOP_DEFAULT to be either zero
* (as done here) to mean "default protection", or to a specific
* explicit QOP value. However, a value of 0 should always be
* interpreted by a GSSAPI implementation as a request for the
* default protection level.
*/
#define GSS_C_QOP_DEFAULT 0
/*
* Expiration time of 2^32-1 seconds means infinite lifetime for a
* credential or security context
*/
#define GSS_C_INDEFINITE 0xfffffffful
/*
* The implementation must reserve static storage for a
* gss_OID_desc object containing the value
* {10, (void *)"\x2a\x86\x48\x86\xf7\x12"
* "\x01\x02\x01\x01"},
* corresponding to an object-identifier value of
* {iso(1) member-body(2) United States(840) mit(113554)
* infosys(1) gssapi(2) generic(1) user_name(1)}. The constant
* GSS_C_NT_USER_NAME should be initialized to point
* to that gss_OID_desc.
*/
extern gss_OID GSS_C_NT_USER_NAME;
/*
* The implementation must reserve static storage for a
* gss_OID_desc object containing the value
* {10, (void *)"\x2a\x86\x48\x86\xf7\x12"
* "\x01\x02\x01\x02"},
* corresponding to an object-identifier value of
* {iso(1) member-body(2) United States(840) mit(113554)
* infosys(1) gssapi(2) generic(1) machine_uid_name(2)}.
* The constant GSS_C_NT_MACHINE_UID_NAME should be
* initialized to point to that gss_OID_desc.
*/
extern gss_OID GSS_C_NT_MACHINE_UID_NAME;
/*
* The implementation must reserve static storage for a
* gss_OID_desc object containing the value
* {10, (void *)"\x2a\x86\x48\x86\xf7\x12"
* "\x01\x02\x01\x03"},
* corresponding to an object-identifier value of
* {iso(1) member-body(2) United States(840) mit(113554)
* infosys(1) gssapi(2) generic(1) string_uid_name(3)}.
* The constant GSS_C_NT_STRING_UID_NAME should be
* initialized to point to that gss_OID_desc.
*/
extern gss_OID GSS_C_NT_STRING_UID_NAME;
/*
* The implementation must reserve static storage for a
* gss_OID_desc object containing the value
* {6, (void *)"\x2b\x06\x01\x05\x06\x02"},
* corresponding to an object-identifier value of
* {1(iso), 3(org), 6(dod), 1(internet), 5(security),
* 6(nametypes), 2(gss-host-based-services)}. The constant
* GSS_C_NT_HOSTBASED_SERVICE should be initialized to point
* to that gss_OID_desc.
*/
extern gss_OID GSS_C_NT_HOSTBASED_SERVICE;
/*
* The implementation must reserve static storage for a
* gss_OID_desc object containing the value
* {6, (void *)"\x2b\x06\01\x05\x06\x03"},
* corresponding to an object identifier value of
* {1(iso), 3(org), 6(dod), 1(internet), 5(security),
* 6(nametypes), 3(gss-anonymous-name)}. The constant
* and GSS_C_NT_ANONYMOUS should be initialized to point
* to that gss_OID_desc.
*/
extern gss_OID GSS_C_NT_ANONYMOUS;
/*
* The implementation must reserve static storage for a
* gss_OID_desc object containing the value
* {6, (void *)"\x2b\x06\x01\x05\x06\x04"},
* corresponding to an object-identifier value of
* {1(iso), 3(org), 6(dod), 1(internet), 5(security),
* 6(nametypes), 4(gss-api-exported-name)}. The constant
* GSS_C_NT_EXPORT_NAME should be initialized to point
* to that gss_OID_desc.
*/
extern gss_OID GSS_C_NT_EXPORT_NAME;
/*
* This if for kerberos5 names.
*/
extern gss_OID GSS_KRB5_NT_PRINCIPAL_NAME;
extern gss_OID GSS_KRB5_NT_PRINCIPAL_NAME;
extern gss_OID GSS_KRB5_NT_USER_NAME;
extern gss_OID GSS_KRB5_NT_MACHINE_UID_NAME;
extern gss_OID GSS_KRB5_NT_STRING_UID_NAME;
extern gss_OID GSS_KRB5_MECHANISM;
/* Major status codes */
#define GSS_S_COMPLETE 0
/*
* Some "helper" definitions to make the status code macros obvious.
*/
#define GSS_C_CALLING_ERROR_OFFSET 24
#define GSS_C_ROUTINE_ERROR_OFFSET 16
#define GSS_C_SUPPLEMENTARY_OFFSET 0
#define GSS_C_CALLING_ERROR_MASK 0377ul
#define GSS_C_ROUTINE_ERROR_MASK 0377ul
#define GSS_C_SUPPLEMENTARY_MASK 0177777ul
/*
* The macros that test status codes for error conditions.
* Note that the GSS_ERROR() macro has changed slightly from
* the V1 GSSAPI so that it now evaluates its argument
* only once.
*/
#define GSS_CALLING_ERROR(x) \
(x & (GSS_C_CALLING_ERROR_MASK << GSS_C_CALLING_ERROR_OFFSET))
#define GSS_ROUTINE_ERROR(x) \
(x & (GSS_C_ROUTINE_ERROR_MASK << GSS_C_ROUTINE_ERROR_OFFSET))
#define GSS_SUPPLEMENTARY_INFO(x) \
(x & (GSS_C_SUPPLEMENTARY_MASK << GSS_C_SUPPLEMENTARY_OFFSET))
#define GSS_ERROR(x) \
(x & ((GSS_C_CALLING_ERROR_MASK << GSS_C_CALLING_ERROR_OFFSET) | \
(GSS_C_ROUTINE_ERROR_MASK << GSS_C_ROUTINE_ERROR_OFFSET)))
/*
* Now the actual status code definitions
*/
/*
* Calling errors:
*/
#define GSS_S_CALL_INACCESSIBLE_READ \
(1ul << GSS_C_CALLING_ERROR_OFFSET)
#define GSS_S_CALL_INACCESSIBLE_WRITE \
(2ul << GSS_C_CALLING_ERROR_OFFSET)
#define GSS_S_CALL_BAD_STRUCTURE \
(3ul << GSS_C_CALLING_ERROR_OFFSET)
/*
* Routine errors:
*/
#define GSS_S_BAD_MECH (1ul << GSS_C_ROUTINE_ERROR_OFFSET)
#define GSS_S_BAD_NAME (2ul << GSS_C_ROUTINE_ERROR_OFFSET)
#define GSS_S_BAD_NAMETYPE (3ul << GSS_C_ROUTINE_ERROR_OFFSET)
#define GSS_S_BAD_BINDINGS (4ul << GSS_C_ROUTINE_ERROR_OFFSET)
#define GSS_S_BAD_STATUS (5ul << GSS_C_ROUTINE_ERROR_OFFSET)
#define GSS_S_BAD_SIG (6ul << GSS_C_ROUTINE_ERROR_OFFSET)
#define GSS_S_BAD_MIC GSS_S_BAD_SIG
#define GSS_S_NO_CRED (7ul << GSS_C_ROUTINE_ERROR_OFFSET)
#define GSS_S_NO_CONTEXT (8ul << GSS_C_ROUTINE_ERROR_OFFSET)
#define GSS_S_DEFECTIVE_TOKEN (9ul << GSS_C_ROUTINE_ERROR_OFFSET)
#define GSS_S_DEFECTIVE_CREDENTIAL (10ul << GSS_C_ROUTINE_ERROR_OFFSET)
#define GSS_S_CREDENTIALS_EXPIRED (11ul << GSS_C_ROUTINE_ERROR_OFFSET)
#define GSS_S_CONTEXT_EXPIRED (12ul << GSS_C_ROUTINE_ERROR_OFFSET)
#define GSS_S_FAILURE (13ul << GSS_C_ROUTINE_ERROR_OFFSET)
#define GSS_S_BAD_QOP (14ul << GSS_C_ROUTINE_ERROR_OFFSET)
#define GSS_S_UNAUTHORIZED (15ul << GSS_C_ROUTINE_ERROR_OFFSET)
#define GSS_S_UNAVAILABLE (16ul << GSS_C_ROUTINE_ERROR_OFFSET)
#define GSS_S_DUPLICATE_ELEMENT (17ul << GSS_C_ROUTINE_ERROR_OFFSET)
#define GSS_S_NAME_NOT_MN (18ul << GSS_C_ROUTINE_ERROR_OFFSET)
/*
* Supplementary info bits:
*/
#define GSS_S_CONTINUE_NEEDED (1ul << (GSS_C_SUPPLEMENTARY_OFFSET + 0))
#define GSS_S_DUPLICATE_TOKEN (1ul << (GSS_C_SUPPLEMENTARY_OFFSET + 1))
#define GSS_S_OLD_TOKEN (1ul << (GSS_C_SUPPLEMENTARY_OFFSET + 2))
#define GSS_S_UNSEQ_TOKEN (1ul << (GSS_C_SUPPLEMENTARY_OFFSET + 3))
#define GSS_S_GAP_TOKEN (1ul << (GSS_C_SUPPLEMENTARY_OFFSET + 4))
/*
* From RFC1964:
*
* 4.1.1. Non-Kerberos-specific codes
*/
#define GSS_KRB5_S_G_BAD_SERVICE_NAME 1
/* "No @ in SERVICE-NAME name string" */
#define GSS_KRB5_S_G_BAD_STRING_UID 2
/* "STRING-UID-NAME contains nondigits" */
#define GSS_KRB5_S_G_NOUSER 3
/* "UID does not resolve to username" */
#define GSS_KRB5_S_G_VALIDATE_FAILED 4
/* "Validation error" */
#define GSS_KRB5_S_G_BUFFER_ALLOC 5
/* "Couldn't allocate gss_buffer_t data" */
#define GSS_KRB5_S_G_BAD_MSG_CTX 6
/* "Message context invalid" */
#define GSS_KRB5_S_G_WRONG_SIZE 7
/* "Buffer is the wrong size" */
#define GSS_KRB5_S_G_BAD_USAGE 8
/* "Credential usage type is unknown" */
#define GSS_KRB5_S_G_UNKNOWN_QOP 9
/* "Unknown quality of protection specified" */
/*
* 4.1.2. Kerberos-specific-codes
*/
#define GSS_KRB5_S_KG_CCACHE_NOMATCH 10
/* "Principal in credential cache does not match desired name" */
#define GSS_KRB5_S_KG_KEYTAB_NOMATCH 11
/* "No principal in keytab matches desired name" */
#define GSS_KRB5_S_KG_TGT_MISSING 12
/* "Credential cache has no TGT" */
#define GSS_KRB5_S_KG_NO_SUBKEY 13
/* "Authenticator has no subkey" */
#define GSS_KRB5_S_KG_CONTEXT_ESTABLISHED 14
/* "Context is already fully established" */
#define GSS_KRB5_S_KG_BAD_SIGN_TYPE 15
/* "Unknown signature type in token" */
#define GSS_KRB5_S_KG_BAD_LENGTH 16
/* "Invalid field length in token" */
#define GSS_KRB5_S_KG_CTX_INCOMPLETE 17
/* "Attempt to use incomplete security context" */
/*
* Finally, function prototypes for the GSS-API routines.
*/
OM_uint32 gss_acquire_cred
(OM_uint32 * minor_status,
const gss_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
);
OM_uint32 gss_release_cred
(OM_uint32 * minor_status,
gss_cred_id_t * cred_handle
);
OM_uint32 gss_init_sec_context
(OM_uint32 * minor_status,
const gss_cred_id_t initiator_cred_handle,
gss_ctx_id_t * context_handle,
const gss_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_type,
gss_buffer_t output_token,
OM_uint32 * ret_flags,
OM_uint32 * time_rec
);
OM_uint32 gss_accept_sec_context
(OM_uint32 * minor_status,
gss_ctx_id_t * context_handle,
const gss_cred_id_t acceptor_cred_handle,
const gss_buffer_t input_token_buffer,
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
);
OM_uint32 gss_process_context_token
(OM_uint32 * minor_status,
const gss_ctx_id_t context_handle,
const gss_buffer_t token_buffer
);
OM_uint32 gss_delete_sec_context
(OM_uint32 * minor_status,
gss_ctx_id_t * context_handle,
gss_buffer_t output_token
);
OM_uint32 gss_context_time
(OM_uint32 * minor_status,
const gss_ctx_id_t context_handle,
OM_uint32 * time_rec
);
OM_uint32 gss_get_mic
(OM_uint32 * minor_status,
const gss_ctx_id_t context_handle,
gss_qop_t qop_req,
const gss_buffer_t message_buffer,
gss_buffer_t message_token
);
OM_uint32 gss_verify_mic
(OM_uint32 * minor_status,
const gss_ctx_id_t context_handle,
const gss_buffer_t message_buffer,
const gss_buffer_t token_buffer,
gss_qop_t * qop_state
);
OM_uint32 gss_wrap
(OM_uint32 * minor_status,
const gss_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
);
OM_uint32 gss_unwrap
(OM_uint32 * minor_status,
const gss_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
);
OM_uint32 gss_display_status
(OM_uint32 * minor_status,
OM_uint32 status_value,
int status_type,
const gss_OID mech_type,
OM_uint32 * message_context,
gss_buffer_t status_string
);
OM_uint32 gss_indicate_mechs
(OM_uint32 * minor_status,
gss_OID_set * mech_set
);
OM_uint32 gss_compare_name
(OM_uint32 * minor_status,
const gss_name_t name1,
const gss_name_t name2,
int * name_equal
);
OM_uint32 gss_display_name
(OM_uint32 * minor_status,
const gss_name_t input_name,
gss_buffer_t output_name_buffer,
gss_OID * output_name_type
);
OM_uint32 gss_import_name
(OM_uint32 * minor_status,
const gss_buffer_t input_name_buffer,
const gss_OID input_name_type,
gss_name_t * output_name
);
OM_uint32 gss_export_name
(OM_uint32 * minor_status,
const gss_name_t input_name,
gss_buffer_t exported_name
);
OM_uint32 gss_release_name
(OM_uint32 * minor_status,
gss_name_t * input_name
);
OM_uint32 gss_release_buffer
(OM_uint32 * minor_status,
gss_buffer_t buffer
);
OM_uint32 gss_release_oid_set
(OM_uint32 * minor_status,
gss_OID_set * set
);
OM_uint32 gss_inquire_cred
(OM_uint32 * minor_status,
const gss_cred_id_t cred_handle,
gss_name_t * name,
OM_uint32 * lifetime,
gss_cred_usage_t * cred_usage,
gss_OID_set * mechanisms
);
OM_uint32 gss_inquire_context (
OM_uint32 * minor_status,
const gss_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 * open
);
OM_uint32 gss_wrap_size_limit (
OM_uint32 * minor_status,
const gss_ctx_id_t context_handle,
int conf_req_flag,
gss_qop_t qop_req,
OM_uint32 req_output_size,
OM_uint32 * max_input_size
);
OM_uint32 gss_add_cred (
OM_uint32 * minor_status,
const gss_cred_id_t input_cred_handle,
const gss_name_t desired_name,
const gss_OID desired_mech,
gss_cred_usage_t cred_usage,
OM_uint32 initiator_time_req,
OM_uint32 acceptor_time_req,
gss_cred_id_t * output_cred_handle,
gss_OID_set * actual_mechs,
OM_uint32 * initiator_time_rec,
OM_uint32 * acceptor_time_rec
);
OM_uint32 gss_inquire_cred_by_mech (
OM_uint32 * minor_status,
const gss_cred_id_t cred_handle,
const gss_OID mech_type,
gss_name_t * name,
OM_uint32 * initiator_lifetime,
OM_uint32 * acceptor_lifetime,
gss_cred_usage_t * cred_usage
);
OM_uint32 gss_export_sec_context (
OM_uint32 * minor_status,
gss_ctx_id_t * context_handle,
gss_buffer_t interprocess_token
);
OM_uint32 gss_import_sec_context (
OM_uint32 * minor_status,
const gss_buffer_t interprocess_token,
gss_ctx_id_t * context_handle
);
OM_uint32 gss_create_empty_oid_set (
OM_uint32 * minor_status,
gss_OID_set * oid_set
);
OM_uint32 gss_add_oid_set_member (
OM_uint32 * minor_status,
const gss_OID member_oid,
gss_OID_set * oid_set
);
OM_uint32 gss_test_oid_set_member (
OM_uint32 * minor_status,
const gss_OID member,
const gss_OID_set set,
int * present
);
OM_uint32 gss_inquire_names_for_mech (
OM_uint32 * minor_status,
const gss_OID mechanism,
gss_OID_set * name_types
);
OM_uint32 gss_inquire_mechs_for_name (
OM_uint32 * minor_status,
const gss_name_t input_name,
gss_OID_set * mech_types
);
OM_uint32 gss_canonicalize_name (
OM_uint32 * minor_status,
const gss_name_t input_name,
const gss_OID mech_type,
gss_name_t * output_name
);
OM_uint32 gss_duplicate_name (
OM_uint32 * minor_status,
const gss_name_t src_name,
gss_name_t * dest_name
);
/*
* The following routines are obsolete variants of gss_get_mic,
* gss_verify_mic, gss_wrap and gss_unwrap. They should be
* provided by GSSAPI V2 implementations for backwards
* compatibility with V1 applications. Distinct entrypoints
* (as opposed to #defines) should be provided, both to allow
* GSSAPI V1 applications to link against GSSAPI V2 implementations,
* and to retain the slight parameter type differences between the
* obsolete versions of these routines and their current forms.
*/
OM_uint32 gss_sign
(OM_uint32 * minor_status,
gss_ctx_id_t context_handle,
int qop_req,
gss_buffer_t message_buffer,
gss_buffer_t message_token
);
OM_uint32 gss_verify
(OM_uint32 * minor_status,
gss_ctx_id_t context_handle,
gss_buffer_t message_buffer,
gss_buffer_t token_buffer,
int * qop_state
);
OM_uint32 gss_seal
(OM_uint32 * minor_status,
gss_ctx_id_t context_handle,
int conf_req_flag,
int qop_req,
gss_buffer_t input_message_buffer,
int * conf_state,
gss_buffer_t output_message_buffer
);
OM_uint32 gss_unseal
(OM_uint32 * minor_status,
gss_ctx_id_t context_handle,
gss_buffer_t input_message_buffer,
gss_buffer_t output_message_buffer,
int * conf_state,
int * qop_state
);
#endif /* GSSAPI_H_ */

30
lib/gssapi/gssapi_locl.h Normal file
View File

@@ -0,0 +1,30 @@
/* $Id$ */
#ifndef GSSAPI_LOCL_H
#define GSSAPI_LOCL_H
#include <stdlib.h>
#include <string.h>
#include <gssapi.h>
#include <krb5.h>
#include <krb5_locl.h>
extern krb5_context gssapi_krb5_context;
void gssapi_krb5_init (void);
OM_uint32
gssapi_krb5_encapsulate(
krb5_data *in_data,
gss_buffer_t output_token,
u_char *type);
OM_uint32
gssapi_krb5_decapsulate(
gss_buffer_t input_token_buffer,
krb5_data *out_data,
u_char *type);
#endif

36
lib/gssapi/import_name.c Normal file
View File

@@ -0,0 +1,36 @@
#include "gssapi_locl.h"
RCSID("$Id$");
OM_uint32 gss_import_name
(OM_uint32 * minor_status,
const gss_buffer_t input_name_buffer,
const gss_OID input_name_type,
gss_name_t * output_name
)
{
krb5_error_code kerr;
char *tmp;
gssapi_krb5_init ();
tmp = malloc (input_name_buffer->length + 1);
if (tmp == NULL) {
return GSS_S_FAILURE;
}
memcpy (tmp,
input_name_buffer->value,
input_name_buffer->length);
tmp[input_name_buffer->length] = '\0';
kerr = krb5_parse_name (gssapi_krb5_context,
tmp,
output_name);
free (tmp);
if (kerr == 0)
return GSS_S_COMPLETE;
else if (kerr = KRB5_PARSE_ILLCHAR || kerr == KRB5_PARSE_MALFORMED)
return GSS_S_BAD_NAME;
else
return GSS_S_FAILURE;
}

View File

@@ -0,0 +1,22 @@
#include "gssapi_locl.h"
RCSID("$Id$");
OM_uint32 gss_indicate_mechs
(OM_uint32 * minor_status,
gss_OID_set * mech_set
)
{
*mech_set = malloc(sizeof(**mech_set));
if (*mech_set == NULL) {
return GSS_S_FAILURE;
}
(*mech_set)->count = 1;
(*mech_set)->elements = malloc((*mech_set)->count * sizeof(gss_OID_desc));
if ((*mech_set)->elements == NULL) {
free (*mech_set);
return GSS_S_FAILURE;
}
(*mech_set)->elements[0] = *GSS_KRB5_MECHANISM;
return GSS_S_COMPLETE;
}

15
lib/gssapi/init.c Normal file
View File

@@ -0,0 +1,15 @@
#include "gssapi_locl.h"
RCSID("$Id$");
void
gssapi_krb5_init (void)
{
static int donep = 0;
if (donep)
return;
krb5_init_context (&gssapi_krb5_context);
donep = 1;
}

View File

@@ -0,0 +1,312 @@
#include "gssapi_locl.h"
RCSID("$Id$");
static krb5_error_code
create_8003_checksum (
const gss_channel_bindings_t input_chan_bindings,
OM_uint32 flags,
Checksum *result)
{
u_char *p;
u_int32_t val;
result->cksumtype = 0x8003;
result->checksum.length = 24;
result->checksum.data = malloc (result->checksum.length);
if (result->checksum.data == NULL)
return ENOMEM;
p = result->checksum.data;
val = 16;
*p++ = (val >> 0) & 0xFF;
*p++ = (val >> 8) & 0xFF;
*p++ = (val >> 16) & 0xFF;
*p++ = (val >> 24) & 0xFF;
memset (p, 0, 16);
p += 16;
val = flags;
*p++ = (val >> 0) & 0xFF;
*p++ = (val >> 8) & 0xFF;
*p++ = (val >> 16) & 0xFF;
*p++ = (val >> 24) & 0xFF;
if (p - (u_char *)result->checksum.data != result->checksum.length)
abort ();
return 0;
}
static OM_uint32
init_auth
(OM_uint32 * minor_status,
const gss_cred_id_t initiator_cred_handle,
gss_ctx_id_t * context_handle,
const gss_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_type,
gss_buffer_t output_token,
OM_uint32 * ret_flags,
OM_uint32 * time_rec
)
{
OM_uint32 ret;
krb5_error_code kret;
krb5_flags ap_options;
krb5_creds this_cred, *cred;
krb5_data outbuf;
krb5_ccache ccache;
u_int32_t flags;
Authenticator *auth;
krb5_data authenticator;
Checksum cksum;
gssapi_krb5_init ();
outbuf.length = 0;
outbuf.data = NULL;
*context_handle = malloc(sizeof(**context_handle));
if (*context_handle == NULL)
return GSS_S_FAILURE;
(*context_handle)->auth_context = NULL;
(*context_handle)->source = NULL;
(*context_handle)->target = NULL;
(*context_handle)->flags = 0;
(*context_handle)->more_flags = 0;
kret = krb5_auth_con_init (gssapi_krb5_context,
&(*context_handle)->auth_context);
if (kret) {
ret = GSS_S_FAILURE;
goto failure;
}
if (actual_mech_type)
*actual_mech_type = GSS_KRB5_MECHANISM;
flags = 0;
ap_options = 0;
if (req_flags & GSS_C_DELEG_FLAG)
; /* XXX */
if (req_flags & GSS_C_MUTUAL_FLAG) {
flags |= GSS_C_MUTUAL_FLAG;
ap_options |= AP_OPTS_MUTUAL_REQUIRED;
}
if (req_flags & GSS_C_REPLAY_FLAG)
; /* XXX */
if (req_flags & GSS_C_SEQUENCE_FLAG)
; /* XXX */
if (req_flags & GSS_C_ANON_FLAG)
; /* XXX */
flags |= GSS_C_CONF_FLAG;
flags |= GSS_C_INTEG_FLAG;
if (ret_flags)
*ret_flags = flags;
(*context_handle)->flags = flags;
(*context_handle)->more_flags = LOCAL;
kret = krb5_cc_default (gssapi_krb5_context, &ccache);
if (kret) {
ret = GSS_S_FAILURE;
goto failure;
}
kret = krb5_cc_get_principal (gssapi_krb5_context,
ccache,
&(*context_handle)->source);
if (kret) {
ret = GSS_S_FAILURE;
goto failure;
}
kret = krb5_copy_principal (gssapi_krb5_context,
target_name,
&(*context_handle)->target);
if (kret) {
ret = GSS_S_FAILURE;
goto failure;
}
this_cred.client = (*context_handle)->source;
this_cred.server = (*context_handle)->target;
this_cred.times.endtime = 0;
kret = krb5_get_credentials (gssapi_krb5_context,
0,
ccache,
&this_cred,
&cred);
if (kret) {
ret = GSS_S_FAILURE;
goto failure;
}
(*context_handle)->auth_context->key.keytype = cred->session.keytype;
krb5_data_copy (&(*context_handle)->auth_context->key.contents,
cred->session.contents.data,
cred->session.contents.length);
kret = create_8003_checksum (input_chan_bindings,
flags,
&cksum);
if (kret) {
ret = GSS_S_FAILURE;
goto failure;
}
kret = krb5_build_authenticator (gssapi_krb5_context,
(*context_handle)->auth_context,
cred,
&cksum,
&auth,
&authenticator);
if (kret) {
ret = GSS_S_FAILURE;
goto failure;
}
kret = krb5_build_ap_req (gssapi_krb5_context,
cred,
ap_options,
authenticator,
&outbuf);
krb5_data_free (&authenticator);
if (kret) {
ret = GSS_S_FAILURE;
goto failure;
}
ret = gssapi_krb5_encapsulate (&outbuf,
output_token,
"\x01\x00");
if (ret)
goto failure;
if (flags & GSS_C_MUTUAL_FLAG) {
return GSS_S_CONTINUE_NEEDED;
} else {
(*context_handle)->more_flags |= OPEN;
return GSS_S_COMPLETE;
}
failure:
krb5_auth_con_free (gssapi_krb5_context,
(*context_handle)->auth_context);
if((*context_handle)->source)
krb5_free_principal (gssapi_krb5_context,
(*context_handle)->source);
if((*context_handle)->target)
krb5_free_principal (gssapi_krb5_context,
(*context_handle)->target);
free (*context_handle);
krb5_data_free (&outbuf);
*context_handle = GSS_C_NO_CONTEXT;
return GSS_S_FAILURE;
}
static OM_uint32
repl_mutual
(OM_uint32 * minor_status,
const gss_cred_id_t initiator_cred_handle,
gss_ctx_id_t * context_handle,
const gss_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_type,
gss_buffer_t output_token,
OM_uint32 * ret_flags,
OM_uint32 * time_rec
)
{
OM_uint32 ret;
krb5_error_code kret;
krb5_data indata;
krb5_ap_rep_enc_part *repl;
ret = gssapi_krb5_decapsulate (input_token,
&indata,
"\x02\x00");
if (ret) {
/* XXX - Handle AP_ERROR */
return GSS_S_FAILURE;
}
kret = krb5_rd_rep (gssapi_krb5_context,
(*context_handle)->auth_context,
&indata,
&repl);
if (kret)
return GSS_S_FAILURE;
krb5_free_ap_rep_enc_part (gssapi_krb5_context,
repl);
(*context_handle)->more_flags |= OPEN;
return GSS_S_COMPLETE;
}
/*
* gss_init_sec_context
*/
OM_uint32 gss_init_sec_context
(OM_uint32 * minor_status,
const gss_cred_id_t initiator_cred_handle,
gss_ctx_id_t * context_handle,
const gss_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_type,
gss_buffer_t output_token,
OM_uint32 * ret_flags,
OM_uint32 * time_rec
)
{
gssapi_krb5_init ();
if (input_token == GSS_C_NO_BUFFER || input_token->length == 0)
return init_auth (minor_status,
initiator_cred_handle,
context_handle,
target_name,
mech_type,
req_flags,
time_req,
input_chan_bindings,
input_token,
actual_mech_type,
output_token,
ret_flags,
time_rec);
else
return repl_mutual(minor_status,
initiator_cred_handle,
context_handle,
target_name,
mech_type,
req_flags,
time_req,
input_chan_bindings,
input_token,
actual_mech_type,
output_token,
ret_flags,
time_rec);
}

View File

@@ -0,0 +1,51 @@
#include "gssapi_locl.h"
RCSID("$Id$");
OM_uint32 gss_inquire_context (
OM_uint32 * minor_status,
const gss_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 * open
)
{
OM_uint32 ret;
if (src_name) {
ret = gss_duplicate_name (minor_status,
context_handle->source,
src_name);
if (ret)
return ret;
}
if (targ_name) {
ret = gss_duplicate_name (minor_status,
context_handle->target,
targ_name);
if (ret)
return ret;
}
if (lifetime_rec)
*lifetime_rec = GSS_C_INDEFINITE;
if (mech_type)
*mech_type = GSS_KRB5_MECHANISM;
if (ctx_flags)
*ctx_flags = context_handle->flags;
if (locally_initiated)
*locally_initiated = context_handle->more_flags & LOCAL;
if (open)
*open = context_handle->more_flags & OPEN;
return GSS_S_COMPLETE;
}

View File

@@ -0,0 +1,18 @@
# $Id$
AUTOMAKE_OPTIONS = no-dependencies
INCLUDES = -I$(top_builddir)/include -I$(srcdir)/../krb5
lib_LIBRARIES = libgssapi.a
libgssapi_a_SOURCES = \
accept_sec_context.c add_oid_set_member.c \
create_emtpy_oid_set.c decapsulate.c \
delete_sec_context.c display_name.c \
duplicate_name.c encapsulate.c external.c \
get_mic.c import_name.c indicate_mechs.c \
init.c init_sec_context.c inquire_context.c \
release_buffer.c release_name.c release_oid_set.c \
test_oid_set_member.c unwrap.c verify_mic.c \
wrap.c \

View File

@@ -0,0 +1,132 @@
#include "gssapi_locl.h"
RCSID("$Id$");
OM_uint32 gss_accept_sec_context
(OM_uint32 * minor_status,
gss_ctx_id_t * context_handle,
const gss_cred_id_t acceptor_cred_handle,
const gss_buffer_t input_token_buffer,
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
)
{
krb5_error_code kret;
OM_uint32 ret;
krb5_data indata;
krb5_flags ap_options;
OM_uint32 flags;
krb5_ticket *ticket;
gssapi_krb5_init ();
*context_handle = malloc(sizeof(**context_handle));
if (*context_handle == NULL)
return GSS_S_FAILURE;
(*context_handle)->auth_context = NULL;
(*context_handle)->source = NULL;
(*context_handle)->target = NULL;
(*context_handle)->flags = 0;
(*context_handle)->more_flags = 0;
kret = krb5_auth_con_init (gssapi_krb5_context,
&(*context_handle)->auth_context);
if (kret) {
ret = GSS_S_FAILURE;
goto failure;
}
ret = gssapi_krb5_decapsulate (input_token_buffer,
&indata,
"\x01\x00");
if (ret)
goto failure;
kret = krb5_rd_req (gssapi_krb5_context,
&(*context_handle)->auth_context,
&indata,
/*server*/ NULL, /* XXX */
NULL,
&ap_options,
&ticket);
if (kret) {
ret = GSS_S_FAILURE;
goto failure;
}
kret = krb5_copy_principal (gssapi_krb5_context,
ticket->enc_part2.client,
&(*context_handle)->source);
if (kret) {
ret = GSS_S_FAILURE;
goto failure;
}
if (src_name) {
kret = krb5_copy_principal (gssapi_krb5_context,
ticket->enc_part2.client,
src_name);
if (kret) {
ret = GSS_S_FAILURE;
goto failure;
}
}
flags = 0;
if (ap_options & AP_OPTS_MUTUAL_REQUIRED)
flags |= GSS_C_MUTUAL_FLAG;
flags |= GSS_C_CONF_FLAG;
flags |= GSS_C_INTEG_FLAG;
if (ret_flags)
*ret_flags = flags;
(*context_handle)->flags = flags;
(*context_handle)->more_flags |= OPEN;
if (mech_type)
*mech_type = GSS_KRB5_MECHANISM;
if (time_rec)
*time_rec = GSS_C_INDEFINITE;
if(flags & GSS_C_MUTUAL_FLAG) {
krb5_data outbuf;
kret = krb5_mk_rep (gssapi_krb5_context,
&(*context_handle)->auth_context,
&outbuf);
if (kret) {
krb5_data_free (&outbuf);
ret = GSS_S_FAILURE;
goto failure;
}
ret = gssapi_krb5_encapsulate (&outbuf,
output_token,
"\x02\x00");
if (ret)
goto failure;
} else {
output_token->length = 0;
}
return GSS_S_COMPLETE;
failure:
krb5_auth_con_free (gssapi_krb5_context,
(*context_handle)->auth_context);
if((*context_handle)->source)
krb5_free_principal (gssapi_krb5_context,
(*context_handle)->source);
if((*context_handle)->target)
krb5_free_principal (gssapi_krb5_context,
(*context_handle)->target);
free (*context_handle);
*context_handle = GSS_C_NO_CONTEXT;
return GSS_S_FAILURE;
}

View File

@@ -0,0 +1,21 @@
#include "gssapi_locl.h"
RCSID("$Id$");
OM_uint32 gss_add_oid_set_member (
OM_uint32 * minor_status,
const gss_OID member_oid,
gss_OID_set * oid_set
)
{
size_t n = (*oid_set)->count;
(*oid_set)->elements = realloc ((*oid_set)->elements,
n * sizeof(gss_OID_desc));
if ((*oid_set)->elements == NULL) {
return GSS_S_FAILURE;
}
(*oid_set)->count = n;
(*oid_set)->elements[n-1] = *member_oid;
return GSS_S_COMPLETE;
}

View File

@@ -0,0 +1,17 @@
#include "gssapi_locl.h"
RCSID("$Id$");
OM_uint32 gss_create_empty_oid_set (
OM_uint32 * minor_status,
gss_OID_set * oid_set
)
{
*oid_set = malloc(sizeof(**oid_set));
if (*oid_set == NULL) {
return GSS_S_FAILURE;
}
(*oid_set)->count = 0;
(*oid_set)->elements = NULL;
return GSS_S_COMPLETE;
}

View File

@@ -0,0 +1,36 @@
#include "gssapi_locl.h"
RCSID("$Id$");
/*
* Remove the GSS-API wrapping from `in_token' giving `out_data.
* Does not copy data, so just free `in_token'.
*/
OM_uint32
gssapi_krb5_decapsulate(
gss_buffer_t input_token_buffer,
krb5_data *out_data,
u_char *type
)
{
u_char *p;
size_t len;
p = input_token_buffer->value;
len = GSS_KRB5_MECHANISM->length + 6;
if (
input_token_buffer->length < len
|| memcmp (p, "\x60\x07\x06\x05", 4) != 0
|| memcmp (p + 4, GSS_KRB5_MECHANISM->elements,
GSS_KRB5_MECHANISM->length) != 0)
return GSS_S_BAD_MECH;
if (memcmp (p + 4 + GSS_KRB5_MECHANISM->length,
type, 2) != 0)
return GSS_S_DEFECTIVE_TOKEN;
out_data->length = input_token_buffer->length - len;
out_data->data = (u_char *)input_token_buffer->value + len;
return GSS_S_COMPLETE;
}

View File

@@ -0,0 +1,24 @@
#include "gssapi_locl.h"
RCSID("$Id$");
OM_uint32 gss_delete_sec_context
(OM_uint32 * minor_status,
gss_ctx_id_t * context_handle,
gss_buffer_t output_token
)
{
gssapi_krb5_init ();
krb5_auth_con_free (gssapi_krb5_context,
(*context_handle)->auth_context);
if((*context_handle)->source)
krb5_free_principal (gssapi_krb5_context,
(*context_handle)->source);
if((*context_handle)->target)
krb5_free_principal (gssapi_krb5_context,
(*context_handle)->target);
free (*context_handle);
if (output_token)
output_token->length = 0;
return GSS_S_COMPLETE;
}

View File

@@ -0,0 +1,32 @@
#include "gssapi_locl.h"
RCSID("$Id$");
OM_uint32 gss_display_name
(OM_uint32 * minor_status,
const gss_name_t input_name,
gss_buffer_t output_name_buffer,
gss_OID * output_name_type
)
{
krb5_error_code kret;
char *buf;
size_t len;
gssapi_krb5_init ();
kret = krb5_unparse_name (gssapi_krb5_context,
input_name,
&buf);
if (kret)
return GSS_S_FAILURE;
len = strlen (buf);
output_name_buffer->length = len;
output_name_buffer->value = malloc(len);
if (output_name_buffer->value == NULL) {
free (buf);
return GSS_S_FAILURE;
}
memcpy (output_name_buffer->value, buf, len);
free (buf);
return GSS_S_COMPLETE;
}

View File

@@ -0,0 +1,22 @@
#include "gssapi_locl.h"
RCSID("$Id$");
OM_uint32 gss_duplicate_name (
OM_uint32 * minor_status,
const gss_name_t src_name,
gss_name_t * dest_name
)
{
krb5_error_code kret;
gssapi_krb5_init ();
kret = krb5_copy_principal (gssapi_krb5_context,
src_name,
dest_name);
if (kret)
return GSS_S_FAILURE;
else
return GSS_S_COMPLETE;
}

View File

@@ -0,0 +1,33 @@
#include "gssapi_locl.h"
RCSID("$Id$");
/*
* Give it a krb5_data and it will encapsulate with extra GSS-API wrappings.
*/
OM_uint32
gssapi_krb5_encapsulate(
krb5_data *in_data,
gss_buffer_t output_token,
u_char *type
)
{
u_char *p;
output_token->length = in_data->length + GSS_KRB5_MECHANISM->length + 6;
output_token->value = malloc (output_token->length);
if (output_token->value == NULL)
return GSS_S_FAILURE;
p = output_token->value;
memcpy (p, "\x60\x07\x06\x05", 4);
p += 4;
memcpy (p, GSS_KRB5_MECHANISM->elements, GSS_KRB5_MECHANISM->length);
p += GSS_KRB5_MECHANISM->length;
memcpy (p, type, 2);
p += 2;
memcpy (p, in_data->data, in_data->length);
krb5_data_free (in_data);
return GSS_S_COMPLETE;
}

172
lib/gssapi/krb5/external.c Normal file
View File

@@ -0,0 +1,172 @@
#include "gssapi_locl.h"
RCSID("$Id$");
/*
* The implementation must reserve static storage for a
* gss_OID_desc object containing the value
* {10, (void *)"\x2a\x86\x48\x86\xf7\x12"
* "\x01\x02\x01\x01"},
* corresponding to an object-identifier value of
* {iso(1) member-body(2) United States(840) mit(113554)
* infosys(1) gssapi(2) generic(1) user_name(1)}. The constant
* GSS_C_NT_USER_NAME should be initialized to point
* to that gss_OID_desc.
*/
static gss_OID_desc gss_c_nt_user_name_oid_desc =
{10, (void *)"\x2a\x86\x48\x86\xf7\x12"
"\x01\x02\x01\x01"};
gss_OID GSS_C_NT_USER_NAME = &gss_c_nt_user_name_oid_desc;
/*
* The implementation must reserve static storage for a
* gss_OID_desc object containing the value
* {10, (void *)"\x2a\x86\x48\x86\xf7\x12"
* "\x01\x02\x01\x02"},
* corresponding to an object-identifier value of
* {iso(1) member-body(2) United States(840) mit(113554)
* infosys(1) gssapi(2) generic(1) machine_uid_name(2)}.
* The constant GSS_C_NT_MACHINE_UID_NAME should be
* initialized to point to that gss_OID_desc.
*/
static gss_OID_desc gss_c_nt_machine_uid_name_oid_desc =
{10, (void *)"\x2a\x86\x48\x86\xf7\x12"
"\x01\x02\x01\x02"};
gss_OID GSS_C_NT_MACHINE_UID_NAME = &gss_c_nt_machine_uid_name_oid_desc;
/*
* The implementation must reserve static storage for a
* gss_OID_desc object containing the value
* {10, (void *)"\x2a\x86\x48\x86\xf7\x12"
* "\x01\x02\x01\x03"},
* corresponding to an object-identifier value of
* {iso(1) member-body(2) United States(840) mit(113554)
* infosys(1) gssapi(2) generic(1) string_uid_name(3)}.
* The constant GSS_C_NT_STRING_UID_NAME should be
* initialized to point to that gss_OID_desc.
*/
static gss_OID_desc gss_c_nt_string_uid_name_oid_desc =
{10, (void *)"\x2a\x86\x48\x86\xf7\x12"
"\x01\x02\x01\x03"};
gss_OID GSS_C_NT_STRING_UID_NAME = &gss_c_nt_string_uid_name_oid_desc;
/*
* The implementation must reserve static storage for a
* gss_OID_desc object containing the value
* {6, (void *)"\x2b\x06\x01\x05\x06\x02"},
* corresponding to an object-identifier value of
* {1(iso), 3(org), 6(dod), 1(internet), 5(security),
* 6(nametypes), 2(gss-host-based-services)}. The constant
* GSS_C_NT_HOSTBASED_SERVICE should be initialized to point
* to that gss_OID_desc.
*/
static gss_OID_desc gss_c_nt_hostbased_service_oid_desc =
{6, (void *)"\x2b\x06\x01\x05\x06\x02"};
gss_OID GSS_C_NT_HOSTBASED_SERVICE = &gss_c_nt_hostbased_service_oid_desc;
/*
* The implementation must reserve static storage for a
* gss_OID_desc object containing the value
* {6, (void *)"\x2b\x06\01\x05\x06\x03"},
* corresponding to an object identifier value of
* {1(iso), 3(org), 6(dod), 1(internet), 5(security),
* 6(nametypes), 3(gss-anonymous-name)}. The constant
* and GSS_C_NT_ANONYMOUS should be initialized to point
* to that gss_OID_desc.
*/
static gss_OID_desc gss_c_nt_anonymous_oid_desc =
{6, (void *)"\x2b\x06\01\x05\x06\x03"};
gss_OID GSS_C_NT_ANONYMOUS = &gss_c_nt_anonymous_oid_desc;
/*
* The implementation must reserve static storage for a
* gss_OID_desc object containing the value
* {6, (void *)"\x2b\x06\x01\x05\x06\x04"},
* corresponding to an object-identifier value of
* {1(iso), 3(org), 6(dod), 1(internet), 5(security),
* 6(nametypes), 4(gss-api-exported-name)}. The constant
* GSS_C_NT_EXPORT_NAME should be initialized to point
* to that gss_OID_desc.
*/
static gss_OID_desc gss_c_nt_export_name_oid_desc =
{6, (void *)"\x2b\x06\x01\x05\x06\x04"};
gss_OID GSS_C_NT_EXPORT_NAME = &gss_c_nt_export_name_oid_desc;
/*
* This name form shall be represented by the Object Identifier {iso(1)
* member-body(2) United States(840) mit(113554) infosys(1) gssapi(2)
* krb5(2) krb5_name(1)}. The recommended symbolic name for this type
* is "GSS_KRB5_NT_PRINCIPAL_NAME".
*/
static gss_OID_desc gss_krb5_nt_principal_name_oid_desc =
{10, (void *)"\x2a\x86\x48\x86\xf7\x12\x01\x02\x02\x01"};
gss_OID GSS_KRB5_NT_PRINCIPAL_NAME = &gss_krb5_nt_principal_name_oid_desc;
/*
* This name form shall be represented by the Object Identifier {iso(1)
* member-body(2) United States(840) mit(113554) infosys(1) gssapi(2)
* generic(1) user_name(1)}. The recommended symbolic name for this
* type is "GSS_KRB5_NT_USER_NAME".
*/
gss_OID GSS_KRB5_NT_USER_NAME = &gss_c_nt_user_name_oid_desc;
/*
* This name form shall be represented by the Object Identifier {iso(1)
* member-body(2) United States(840) mit(113554) infosys(1) gssapi(2)
* generic(1) machine_uid_name(2)}. The recommended symbolic name for
* this type is "GSS_KRB5_NT_MACHINE_UID_NAME".
*/
gss_OID GSS_KRB5_NT_MACHINE_UID_NAME = &gss_c_nt_machine_uid_name_oid_desc;
/*
* This name form shall be represented by the Object Identifier {iso(1)
* member-body(2) United States(840) mit(113554) infosys(1) gssapi(2)
* generic(1) string_uid_name(3)}. The recommended symbolic name for
* this type is "GSS_KRB5_NT_STRING_UID_NAME".
*/
gss_OID GSS_KRB5_NT_STRING_UID_NAME = &gss_c_nt_string_uid_name_oid_desc;
/*
* To support ongoing experimentation, testing, and evolution of the
* specification, the Kerberos V5 GSS-API mechanism as defined in this
* and any successor memos will be identified with the following Object
* Identifier, as defined in RFC-1510, until the specification is
* advanced to the level of Proposed Standard RFC:
*
* {iso(1), org(3), dod(5), internet(1), security(5), kerberosv5(2)}
*
* Upon advancement to the level of Proposed Standard RFC, the Kerberos
* V5 GSS-API mechanism will be identified by an Object Identifier
* having the value:
*
* {iso(1) member-body(2) United States(840) mit(113554) infosys(1)
* gssapi(2) krb5(2)}
*/
static gss_OID_desc gss_krb5_mechanism_oid_desc =
{5, (void *)"\x2b\x05\x01\x05\x02"};
gss_OID GSS_KRB5_MECHANISM = &gss_krb5_mechanism_oid_desc;
/*
* Context for krb5 calls.
*/
krb5_context gssapi_krb5_context;

58
lib/gssapi/krb5/get_mic.c Normal file
View File

@@ -0,0 +1,58 @@
#include "gssapi_locl.h"
#include <des.h>
#include <md5.h>
RCSID("$Id$");
OM_uint32 gss_get_mic
(OM_uint32 * minor_status,
const gss_ctx_id_t context_handle,
gss_qop_t qop_req,
const gss_buffer_t message_buffer,
gss_buffer_t message_token
)
{
u_char *p;
size_t len;
struct md5 md5;
u_char hash[16];
des_key_schedule schedule;
des_cblock key;
des_cblock zero;
len = 28 + GSS_KRB5_MECHANISM->length;
message_token->length = len;
message_token->value = malloc (len);
if (message_token->value == NULL)
return GSS_S_FAILURE;
p = message_token->value;
memcpy (p, "\x60\x07\x06\x05", 4);
p += 4;
memcpy (p, GSS_KRB5_MECHANISM->elements, GSS_KRB5_MECHANISM->length);
p += GSS_KRB5_MECHANISM->length;
memcpy (p, "\x01\x01", 2);
p += 2;
memcpy (p, "\x00\x00", 2);
p += 2;
memcpy (p, "\xff\xff\xff\xff", 4);
p += 4;
memset (p, 0, 16);
p += 16;
md5_init (&md5);
md5_update (&md5, p - 24, 8);
md5_update (&md5, message_buffer->value,
message_buffer->length);
md5_finito (&md5, hash);
memset (&zero, 0, sizeof(zero));
memcpy (&key, context_handle->auth_context->key.contents.data,
sizeof(key));
des_set_key (&key, schedule);
des_cbc_cksum ((des_cblock *)hash,
(des_cblock *)hash, sizeof(hash), schedule, &zero);
memcpy (p - 8, hash, 8);
return GSS_S_COMPLETE;
}

693
lib/gssapi/krb5/gssapi.h Normal file
View File

@@ -0,0 +1,693 @@
/* $Id$ */
#ifndef GSSAPI_H_
#define GSSAPI_H_
/*
* First, include stddef.h to get size_t defined.
*/
#include <stddef.h>
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <sys/types.h>
#ifdef HAVE_SYS_BITYPES_H
#include <sys/bitypes.h>
#endif
#include <bits.h>
#include <krb5.h>
/*
* Now define the three implementation-dependent types.
*/
typedef u_int32_t OM_uint32;
/*
* XXX - Should we really do it this way?
* I'm not entirely happy with exposing this match of the krb5 stuff
* here, and having to include the <krb5.h> file as well.
*/
typedef krb5_principal gss_name_t;
typedef struct gss_ctx_id_t_desc_struct {
krb5_auth_context auth_context;
gss_name_t source, target;
OM_uint32 flags;
enum { LOCAL = 1, OPEN = 2} more_flags;
} gss_ctx_id_t_desc;
typedef gss_ctx_id_t_desc *gss_ctx_id_t;
typedef int gss_cred_id_t; /* XXX */
typedef struct gss_OID_desc_struct {
OM_uint32 length;
void *elements;
} gss_OID_desc, *gss_OID;
typedef struct gss_OID_set_desc_struct {
size_t count;
gss_OID elements;
} gss_OID_set_desc, *gss_OID_set;
typedef struct gss_buffer_desc_struct {
size_t length;
void *value;
} gss_buffer_desc, *gss_buffer_t;
typedef struct gss_channel_bindings_struct {
OM_uint32 initiator_addrtype;
gss_buffer_desc initiator_address;
OM_uint32 acceptor_addrtype;
gss_buffer_desc acceptor_address;
gss_buffer_desc application_data;
} *gss_channel_bindings_t;
/*
* For now, define a QOP-type as an OM_uint32
*/
typedef OM_uint32 gss_qop_t;
typedef int gss_cred_usage_t;
/*
* Flag bits for context-level services.
*/
#define GSS_C_DELEG_FLAG 1
#define GSS_C_MUTUAL_FLAG 2
#define GSS_C_REPLAY_FLAG 4
#define GSS_C_SEQUENCE_FLAG 8
#define GSS_C_CONF_FLAG 16
#define GSS_C_INTEG_FLAG 32
#define GSS_C_ANON_FLAG 64
#define GSS_C_PROT_READY_FLAG 128
#define GSS_C_TRANS_FLAG 256
/*
* Credential usage options
*/
#define GSS_C_BOTH 0
#define GSS_C_INITIATE 1
#define GSS_C_ACCEPT 2
/*
* Status code types for gss_display_status
*/
#define GSS_C_GSS_CODE 1
#define GSS_C_MECH_CODE 2
/*
* The constant definitions for channel-bindings address families
*/
#define GSS_C_AF_UNSPEC 0
#define GSS_C_AF_LOCAL 1
#define GSS_C_AF_INET 2
#define GSS_C_AF_IMPLINK 3
#define GSS_C_AF_PUP 4
#define GSS_C_AF_CHAOS 5
#define GSS_C_AF_NS 6
#define GSS_C_AF_NBS 7
#define GSS_C_AF_ECMA 8
#define GSS_C_AF_DATAKIT 9
#define GSS_C_AF_CCITT 10
#define GSS_C_AF_SNA 11
#define GSS_C_AF_DECnet 12
#define GSS_C_AF_DLI 13
#define GSS_C_AF_LAT 14
#define GSS_C_AF_HYLINK 15
#define GSS_C_AF_APPLETALK 16
#define GSS_C_AF_BSC 17
#define GSS_C_AF_DSS 18
#define GSS_C_AF_OSI 19
#define GSS_C_AF_X25 21
#define GSS_C_AF_NULLADDR 255
/*
* Various Null values
*/
#define GSS_C_NO_NAME ((gss_name_t) 0)
#define GSS_C_NO_BUFFER ((gss_buffer_t) 0)
#define GSS_C_NO_OID ((gss_OID) 0)
#define GSS_C_NO_OID_SET ((gss_OID_set) 0)
#define GSS_C_NO_CONTEXT ((gss_ctx_id_t) 0)
#define GSS_C_NO_CREDENTIAL ((gss_cred_id_t) 0)
#define GSS_C_NO_CHANNEL_BINDINGS ((gss_channel_bindings_t) 0)
#define GSS_C_EMPTY_BUFFER {0, NULL}
/*
* Some alternate names for a couple of the above
* values. These are defined for V1 compatibility.
*/
#define GSS_C_NULL_OID GSS_C_NO_OID
#define GSS_C_NULL_OID_SET GSS_C_NO_OID_SET
/*
* Define the default Quality of Protection for per-message
* services. Note that an implementation that offers multiple
* levels of QOP may define GSS_C_QOP_DEFAULT to be either zero
* (as done here) to mean "default protection", or to a specific
* explicit QOP value. However, a value of 0 should always be
* interpreted by a GSSAPI implementation as a request for the
* default protection level.
*/
#define GSS_C_QOP_DEFAULT 0
/*
* Expiration time of 2^32-1 seconds means infinite lifetime for a
* credential or security context
*/
#define GSS_C_INDEFINITE 0xfffffffful
/*
* The implementation must reserve static storage for a
* gss_OID_desc object containing the value
* {10, (void *)"\x2a\x86\x48\x86\xf7\x12"
* "\x01\x02\x01\x01"},
* corresponding to an object-identifier value of
* {iso(1) member-body(2) United States(840) mit(113554)
* infosys(1) gssapi(2) generic(1) user_name(1)}. The constant
* GSS_C_NT_USER_NAME should be initialized to point
* to that gss_OID_desc.
*/
extern gss_OID GSS_C_NT_USER_NAME;
/*
* The implementation must reserve static storage for a
* gss_OID_desc object containing the value
* {10, (void *)"\x2a\x86\x48\x86\xf7\x12"
* "\x01\x02\x01\x02"},
* corresponding to an object-identifier value of
* {iso(1) member-body(2) United States(840) mit(113554)
* infosys(1) gssapi(2) generic(1) machine_uid_name(2)}.
* The constant GSS_C_NT_MACHINE_UID_NAME should be
* initialized to point to that gss_OID_desc.
*/
extern gss_OID GSS_C_NT_MACHINE_UID_NAME;
/*
* The implementation must reserve static storage for a
* gss_OID_desc object containing the value
* {10, (void *)"\x2a\x86\x48\x86\xf7\x12"
* "\x01\x02\x01\x03"},
* corresponding to an object-identifier value of
* {iso(1) member-body(2) United States(840) mit(113554)
* infosys(1) gssapi(2) generic(1) string_uid_name(3)}.
* The constant GSS_C_NT_STRING_UID_NAME should be
* initialized to point to that gss_OID_desc.
*/
extern gss_OID GSS_C_NT_STRING_UID_NAME;
/*
* The implementation must reserve static storage for a
* gss_OID_desc object containing the value
* {6, (void *)"\x2b\x06\x01\x05\x06\x02"},
* corresponding to an object-identifier value of
* {1(iso), 3(org), 6(dod), 1(internet), 5(security),
* 6(nametypes), 2(gss-host-based-services)}. The constant
* GSS_C_NT_HOSTBASED_SERVICE should be initialized to point
* to that gss_OID_desc.
*/
extern gss_OID GSS_C_NT_HOSTBASED_SERVICE;
/*
* The implementation must reserve static storage for a
* gss_OID_desc object containing the value
* {6, (void *)"\x2b\x06\01\x05\x06\x03"},
* corresponding to an object identifier value of
* {1(iso), 3(org), 6(dod), 1(internet), 5(security),
* 6(nametypes), 3(gss-anonymous-name)}. The constant
* and GSS_C_NT_ANONYMOUS should be initialized to point
* to that gss_OID_desc.
*/
extern gss_OID GSS_C_NT_ANONYMOUS;
/*
* The implementation must reserve static storage for a
* gss_OID_desc object containing the value
* {6, (void *)"\x2b\x06\x01\x05\x06\x04"},
* corresponding to an object-identifier value of
* {1(iso), 3(org), 6(dod), 1(internet), 5(security),
* 6(nametypes), 4(gss-api-exported-name)}. The constant
* GSS_C_NT_EXPORT_NAME should be initialized to point
* to that gss_OID_desc.
*/
extern gss_OID GSS_C_NT_EXPORT_NAME;
/*
* This if for kerberos5 names.
*/
extern gss_OID GSS_KRB5_NT_PRINCIPAL_NAME;
extern gss_OID GSS_KRB5_NT_PRINCIPAL_NAME;
extern gss_OID GSS_KRB5_NT_USER_NAME;
extern gss_OID GSS_KRB5_NT_MACHINE_UID_NAME;
extern gss_OID GSS_KRB5_NT_STRING_UID_NAME;
extern gss_OID GSS_KRB5_MECHANISM;
/* Major status codes */
#define GSS_S_COMPLETE 0
/*
* Some "helper" definitions to make the status code macros obvious.
*/
#define GSS_C_CALLING_ERROR_OFFSET 24
#define GSS_C_ROUTINE_ERROR_OFFSET 16
#define GSS_C_SUPPLEMENTARY_OFFSET 0
#define GSS_C_CALLING_ERROR_MASK 0377ul
#define GSS_C_ROUTINE_ERROR_MASK 0377ul
#define GSS_C_SUPPLEMENTARY_MASK 0177777ul
/*
* The macros that test status codes for error conditions.
* Note that the GSS_ERROR() macro has changed slightly from
* the V1 GSSAPI so that it now evaluates its argument
* only once.
*/
#define GSS_CALLING_ERROR(x) \
(x & (GSS_C_CALLING_ERROR_MASK << GSS_C_CALLING_ERROR_OFFSET))
#define GSS_ROUTINE_ERROR(x) \
(x & (GSS_C_ROUTINE_ERROR_MASK << GSS_C_ROUTINE_ERROR_OFFSET))
#define GSS_SUPPLEMENTARY_INFO(x) \
(x & (GSS_C_SUPPLEMENTARY_MASK << GSS_C_SUPPLEMENTARY_OFFSET))
#define GSS_ERROR(x) \
(x & ((GSS_C_CALLING_ERROR_MASK << GSS_C_CALLING_ERROR_OFFSET) | \
(GSS_C_ROUTINE_ERROR_MASK << GSS_C_ROUTINE_ERROR_OFFSET)))
/*
* Now the actual status code definitions
*/
/*
* Calling errors:
*/
#define GSS_S_CALL_INACCESSIBLE_READ \
(1ul << GSS_C_CALLING_ERROR_OFFSET)
#define GSS_S_CALL_INACCESSIBLE_WRITE \
(2ul << GSS_C_CALLING_ERROR_OFFSET)
#define GSS_S_CALL_BAD_STRUCTURE \
(3ul << GSS_C_CALLING_ERROR_OFFSET)
/*
* Routine errors:
*/
#define GSS_S_BAD_MECH (1ul << GSS_C_ROUTINE_ERROR_OFFSET)
#define GSS_S_BAD_NAME (2ul << GSS_C_ROUTINE_ERROR_OFFSET)
#define GSS_S_BAD_NAMETYPE (3ul << GSS_C_ROUTINE_ERROR_OFFSET)
#define GSS_S_BAD_BINDINGS (4ul << GSS_C_ROUTINE_ERROR_OFFSET)
#define GSS_S_BAD_STATUS (5ul << GSS_C_ROUTINE_ERROR_OFFSET)
#define GSS_S_BAD_SIG (6ul << GSS_C_ROUTINE_ERROR_OFFSET)
#define GSS_S_BAD_MIC GSS_S_BAD_SIG
#define GSS_S_NO_CRED (7ul << GSS_C_ROUTINE_ERROR_OFFSET)
#define GSS_S_NO_CONTEXT (8ul << GSS_C_ROUTINE_ERROR_OFFSET)
#define GSS_S_DEFECTIVE_TOKEN (9ul << GSS_C_ROUTINE_ERROR_OFFSET)
#define GSS_S_DEFECTIVE_CREDENTIAL (10ul << GSS_C_ROUTINE_ERROR_OFFSET)
#define GSS_S_CREDENTIALS_EXPIRED (11ul << GSS_C_ROUTINE_ERROR_OFFSET)
#define GSS_S_CONTEXT_EXPIRED (12ul << GSS_C_ROUTINE_ERROR_OFFSET)
#define GSS_S_FAILURE (13ul << GSS_C_ROUTINE_ERROR_OFFSET)
#define GSS_S_BAD_QOP (14ul << GSS_C_ROUTINE_ERROR_OFFSET)
#define GSS_S_UNAUTHORIZED (15ul << GSS_C_ROUTINE_ERROR_OFFSET)
#define GSS_S_UNAVAILABLE (16ul << GSS_C_ROUTINE_ERROR_OFFSET)
#define GSS_S_DUPLICATE_ELEMENT (17ul << GSS_C_ROUTINE_ERROR_OFFSET)
#define GSS_S_NAME_NOT_MN (18ul << GSS_C_ROUTINE_ERROR_OFFSET)
/*
* Supplementary info bits:
*/
#define GSS_S_CONTINUE_NEEDED (1ul << (GSS_C_SUPPLEMENTARY_OFFSET + 0))
#define GSS_S_DUPLICATE_TOKEN (1ul << (GSS_C_SUPPLEMENTARY_OFFSET + 1))
#define GSS_S_OLD_TOKEN (1ul << (GSS_C_SUPPLEMENTARY_OFFSET + 2))
#define GSS_S_UNSEQ_TOKEN (1ul << (GSS_C_SUPPLEMENTARY_OFFSET + 3))
#define GSS_S_GAP_TOKEN (1ul << (GSS_C_SUPPLEMENTARY_OFFSET + 4))
/*
* From RFC1964:
*
* 4.1.1. Non-Kerberos-specific codes
*/
#define GSS_KRB5_S_G_BAD_SERVICE_NAME 1
/* "No @ in SERVICE-NAME name string" */
#define GSS_KRB5_S_G_BAD_STRING_UID 2
/* "STRING-UID-NAME contains nondigits" */
#define GSS_KRB5_S_G_NOUSER 3
/* "UID does not resolve to username" */
#define GSS_KRB5_S_G_VALIDATE_FAILED 4
/* "Validation error" */
#define GSS_KRB5_S_G_BUFFER_ALLOC 5
/* "Couldn't allocate gss_buffer_t data" */
#define GSS_KRB5_S_G_BAD_MSG_CTX 6
/* "Message context invalid" */
#define GSS_KRB5_S_G_WRONG_SIZE 7
/* "Buffer is the wrong size" */
#define GSS_KRB5_S_G_BAD_USAGE 8
/* "Credential usage type is unknown" */
#define GSS_KRB5_S_G_UNKNOWN_QOP 9
/* "Unknown quality of protection specified" */
/*
* 4.1.2. Kerberos-specific-codes
*/
#define GSS_KRB5_S_KG_CCACHE_NOMATCH 10
/* "Principal in credential cache does not match desired name" */
#define GSS_KRB5_S_KG_KEYTAB_NOMATCH 11
/* "No principal in keytab matches desired name" */
#define GSS_KRB5_S_KG_TGT_MISSING 12
/* "Credential cache has no TGT" */
#define GSS_KRB5_S_KG_NO_SUBKEY 13
/* "Authenticator has no subkey" */
#define GSS_KRB5_S_KG_CONTEXT_ESTABLISHED 14
/* "Context is already fully established" */
#define GSS_KRB5_S_KG_BAD_SIGN_TYPE 15
/* "Unknown signature type in token" */
#define GSS_KRB5_S_KG_BAD_LENGTH 16
/* "Invalid field length in token" */
#define GSS_KRB5_S_KG_CTX_INCOMPLETE 17
/* "Attempt to use incomplete security context" */
/*
* Finally, function prototypes for the GSS-API routines.
*/
OM_uint32 gss_acquire_cred
(OM_uint32 * minor_status,
const gss_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
);
OM_uint32 gss_release_cred
(OM_uint32 * minor_status,
gss_cred_id_t * cred_handle
);
OM_uint32 gss_init_sec_context
(OM_uint32 * minor_status,
const gss_cred_id_t initiator_cred_handle,
gss_ctx_id_t * context_handle,
const gss_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_type,
gss_buffer_t output_token,
OM_uint32 * ret_flags,
OM_uint32 * time_rec
);
OM_uint32 gss_accept_sec_context
(OM_uint32 * minor_status,
gss_ctx_id_t * context_handle,
const gss_cred_id_t acceptor_cred_handle,
const gss_buffer_t input_token_buffer,
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
);
OM_uint32 gss_process_context_token
(OM_uint32 * minor_status,
const gss_ctx_id_t context_handle,
const gss_buffer_t token_buffer
);
OM_uint32 gss_delete_sec_context
(OM_uint32 * minor_status,
gss_ctx_id_t * context_handle,
gss_buffer_t output_token
);
OM_uint32 gss_context_time
(OM_uint32 * minor_status,
const gss_ctx_id_t context_handle,
OM_uint32 * time_rec
);
OM_uint32 gss_get_mic
(OM_uint32 * minor_status,
const gss_ctx_id_t context_handle,
gss_qop_t qop_req,
const gss_buffer_t message_buffer,
gss_buffer_t message_token
);
OM_uint32 gss_verify_mic
(OM_uint32 * minor_status,
const gss_ctx_id_t context_handle,
const gss_buffer_t message_buffer,
const gss_buffer_t token_buffer,
gss_qop_t * qop_state
);
OM_uint32 gss_wrap
(OM_uint32 * minor_status,
const gss_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
);
OM_uint32 gss_unwrap
(OM_uint32 * minor_status,
const gss_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
);
OM_uint32 gss_display_status
(OM_uint32 * minor_status,
OM_uint32 status_value,
int status_type,
const gss_OID mech_type,
OM_uint32 * message_context,
gss_buffer_t status_string
);
OM_uint32 gss_indicate_mechs
(OM_uint32 * minor_status,
gss_OID_set * mech_set
);
OM_uint32 gss_compare_name
(OM_uint32 * minor_status,
const gss_name_t name1,
const gss_name_t name2,
int * name_equal
);
OM_uint32 gss_display_name
(OM_uint32 * minor_status,
const gss_name_t input_name,
gss_buffer_t output_name_buffer,
gss_OID * output_name_type
);
OM_uint32 gss_import_name
(OM_uint32 * minor_status,
const gss_buffer_t input_name_buffer,
const gss_OID input_name_type,
gss_name_t * output_name
);
OM_uint32 gss_export_name
(OM_uint32 * minor_status,
const gss_name_t input_name,
gss_buffer_t exported_name
);
OM_uint32 gss_release_name
(OM_uint32 * minor_status,
gss_name_t * input_name
);
OM_uint32 gss_release_buffer
(OM_uint32 * minor_status,
gss_buffer_t buffer
);
OM_uint32 gss_release_oid_set
(OM_uint32 * minor_status,
gss_OID_set * set
);
OM_uint32 gss_inquire_cred
(OM_uint32 * minor_status,
const gss_cred_id_t cred_handle,
gss_name_t * name,
OM_uint32 * lifetime,
gss_cred_usage_t * cred_usage,
gss_OID_set * mechanisms
);
OM_uint32 gss_inquire_context (
OM_uint32 * minor_status,
const gss_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 * open
);
OM_uint32 gss_wrap_size_limit (
OM_uint32 * minor_status,
const gss_ctx_id_t context_handle,
int conf_req_flag,
gss_qop_t qop_req,
OM_uint32 req_output_size,
OM_uint32 * max_input_size
);
OM_uint32 gss_add_cred (
OM_uint32 * minor_status,
const gss_cred_id_t input_cred_handle,
const gss_name_t desired_name,
const gss_OID desired_mech,
gss_cred_usage_t cred_usage,
OM_uint32 initiator_time_req,
OM_uint32 acceptor_time_req,
gss_cred_id_t * output_cred_handle,
gss_OID_set * actual_mechs,
OM_uint32 * initiator_time_rec,
OM_uint32 * acceptor_time_rec
);
OM_uint32 gss_inquire_cred_by_mech (
OM_uint32 * minor_status,
const gss_cred_id_t cred_handle,
const gss_OID mech_type,
gss_name_t * name,
OM_uint32 * initiator_lifetime,
OM_uint32 * acceptor_lifetime,
gss_cred_usage_t * cred_usage
);
OM_uint32 gss_export_sec_context (
OM_uint32 * minor_status,
gss_ctx_id_t * context_handle,
gss_buffer_t interprocess_token
);
OM_uint32 gss_import_sec_context (
OM_uint32 * minor_status,
const gss_buffer_t interprocess_token,
gss_ctx_id_t * context_handle
);
OM_uint32 gss_create_empty_oid_set (
OM_uint32 * minor_status,
gss_OID_set * oid_set
);
OM_uint32 gss_add_oid_set_member (
OM_uint32 * minor_status,
const gss_OID member_oid,
gss_OID_set * oid_set
);
OM_uint32 gss_test_oid_set_member (
OM_uint32 * minor_status,
const gss_OID member,
const gss_OID_set set,
int * present
);
OM_uint32 gss_inquire_names_for_mech (
OM_uint32 * minor_status,
const gss_OID mechanism,
gss_OID_set * name_types
);
OM_uint32 gss_inquire_mechs_for_name (
OM_uint32 * minor_status,
const gss_name_t input_name,
gss_OID_set * mech_types
);
OM_uint32 gss_canonicalize_name (
OM_uint32 * minor_status,
const gss_name_t input_name,
const gss_OID mech_type,
gss_name_t * output_name
);
OM_uint32 gss_duplicate_name (
OM_uint32 * minor_status,
const gss_name_t src_name,
gss_name_t * dest_name
);
/*
* The following routines are obsolete variants of gss_get_mic,
* gss_verify_mic, gss_wrap and gss_unwrap. They should be
* provided by GSSAPI V2 implementations for backwards
* compatibility with V1 applications. Distinct entrypoints
* (as opposed to #defines) should be provided, both to allow
* GSSAPI V1 applications to link against GSSAPI V2 implementations,
* and to retain the slight parameter type differences between the
* obsolete versions of these routines and their current forms.
*/
OM_uint32 gss_sign
(OM_uint32 * minor_status,
gss_ctx_id_t context_handle,
int qop_req,
gss_buffer_t message_buffer,
gss_buffer_t message_token
);
OM_uint32 gss_verify
(OM_uint32 * minor_status,
gss_ctx_id_t context_handle,
gss_buffer_t message_buffer,
gss_buffer_t token_buffer,
int * qop_state
);
OM_uint32 gss_seal
(OM_uint32 * minor_status,
gss_ctx_id_t context_handle,
int conf_req_flag,
int qop_req,
gss_buffer_t input_message_buffer,
int * conf_state,
gss_buffer_t output_message_buffer
);
OM_uint32 gss_unseal
(OM_uint32 * minor_status,
gss_ctx_id_t context_handle,
gss_buffer_t input_message_buffer,
gss_buffer_t output_message_buffer,
int * conf_state,
int * qop_state
);
#endif /* GSSAPI_H_ */

View File

@@ -0,0 +1,30 @@
/* $Id$ */
#ifndef GSSAPI_LOCL_H
#define GSSAPI_LOCL_H
#include <stdlib.h>
#include <string.h>
#include <gssapi.h>
#include <krb5.h>
#include <krb5_locl.h>
extern krb5_context gssapi_krb5_context;
void gssapi_krb5_init (void);
OM_uint32
gssapi_krb5_encapsulate(
krb5_data *in_data,
gss_buffer_t output_token,
u_char *type);
OM_uint32
gssapi_krb5_decapsulate(
gss_buffer_t input_token_buffer,
krb5_data *out_data,
u_char *type);
#endif

View File

@@ -0,0 +1,36 @@
#include "gssapi_locl.h"
RCSID("$Id$");
OM_uint32 gss_import_name
(OM_uint32 * minor_status,
const gss_buffer_t input_name_buffer,
const gss_OID input_name_type,
gss_name_t * output_name
)
{
krb5_error_code kerr;
char *tmp;
gssapi_krb5_init ();
tmp = malloc (input_name_buffer->length + 1);
if (tmp == NULL) {
return GSS_S_FAILURE;
}
memcpy (tmp,
input_name_buffer->value,
input_name_buffer->length);
tmp[input_name_buffer->length] = '\0';
kerr = krb5_parse_name (gssapi_krb5_context,
tmp,
output_name);
free (tmp);
if (kerr == 0)
return GSS_S_COMPLETE;
else if (kerr = KRB5_PARSE_ILLCHAR || kerr == KRB5_PARSE_MALFORMED)
return GSS_S_BAD_NAME;
else
return GSS_S_FAILURE;
}

View File

@@ -0,0 +1,22 @@
#include "gssapi_locl.h"
RCSID("$Id$");
OM_uint32 gss_indicate_mechs
(OM_uint32 * minor_status,
gss_OID_set * mech_set
)
{
*mech_set = malloc(sizeof(**mech_set));
if (*mech_set == NULL) {
return GSS_S_FAILURE;
}
(*mech_set)->count = 1;
(*mech_set)->elements = malloc((*mech_set)->count * sizeof(gss_OID_desc));
if ((*mech_set)->elements == NULL) {
free (*mech_set);
return GSS_S_FAILURE;
}
(*mech_set)->elements[0] = *GSS_KRB5_MECHANISM;
return GSS_S_COMPLETE;
}

15
lib/gssapi/krb5/init.c Normal file
View File

@@ -0,0 +1,15 @@
#include "gssapi_locl.h"
RCSID("$Id$");
void
gssapi_krb5_init (void)
{
static int donep = 0;
if (donep)
return;
krb5_init_context (&gssapi_krb5_context);
donep = 1;
}

View File

@@ -0,0 +1,312 @@
#include "gssapi_locl.h"
RCSID("$Id$");
static krb5_error_code
create_8003_checksum (
const gss_channel_bindings_t input_chan_bindings,
OM_uint32 flags,
Checksum *result)
{
u_char *p;
u_int32_t val;
result->cksumtype = 0x8003;
result->checksum.length = 24;
result->checksum.data = malloc (result->checksum.length);
if (result->checksum.data == NULL)
return ENOMEM;
p = result->checksum.data;
val = 16;
*p++ = (val >> 0) & 0xFF;
*p++ = (val >> 8) & 0xFF;
*p++ = (val >> 16) & 0xFF;
*p++ = (val >> 24) & 0xFF;
memset (p, 0, 16);
p += 16;
val = flags;
*p++ = (val >> 0) & 0xFF;
*p++ = (val >> 8) & 0xFF;
*p++ = (val >> 16) & 0xFF;
*p++ = (val >> 24) & 0xFF;
if (p - (u_char *)result->checksum.data != result->checksum.length)
abort ();
return 0;
}
static OM_uint32
init_auth
(OM_uint32 * minor_status,
const gss_cred_id_t initiator_cred_handle,
gss_ctx_id_t * context_handle,
const gss_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_type,
gss_buffer_t output_token,
OM_uint32 * ret_flags,
OM_uint32 * time_rec
)
{
OM_uint32 ret;
krb5_error_code kret;
krb5_flags ap_options;
krb5_creds this_cred, *cred;
krb5_data outbuf;
krb5_ccache ccache;
u_int32_t flags;
Authenticator *auth;
krb5_data authenticator;
Checksum cksum;
gssapi_krb5_init ();
outbuf.length = 0;
outbuf.data = NULL;
*context_handle = malloc(sizeof(**context_handle));
if (*context_handle == NULL)
return GSS_S_FAILURE;
(*context_handle)->auth_context = NULL;
(*context_handle)->source = NULL;
(*context_handle)->target = NULL;
(*context_handle)->flags = 0;
(*context_handle)->more_flags = 0;
kret = krb5_auth_con_init (gssapi_krb5_context,
&(*context_handle)->auth_context);
if (kret) {
ret = GSS_S_FAILURE;
goto failure;
}
if (actual_mech_type)
*actual_mech_type = GSS_KRB5_MECHANISM;
flags = 0;
ap_options = 0;
if (req_flags & GSS_C_DELEG_FLAG)
; /* XXX */
if (req_flags & GSS_C_MUTUAL_FLAG) {
flags |= GSS_C_MUTUAL_FLAG;
ap_options |= AP_OPTS_MUTUAL_REQUIRED;
}
if (req_flags & GSS_C_REPLAY_FLAG)
; /* XXX */
if (req_flags & GSS_C_SEQUENCE_FLAG)
; /* XXX */
if (req_flags & GSS_C_ANON_FLAG)
; /* XXX */
flags |= GSS_C_CONF_FLAG;
flags |= GSS_C_INTEG_FLAG;
if (ret_flags)
*ret_flags = flags;
(*context_handle)->flags = flags;
(*context_handle)->more_flags = LOCAL;
kret = krb5_cc_default (gssapi_krb5_context, &ccache);
if (kret) {
ret = GSS_S_FAILURE;
goto failure;
}
kret = krb5_cc_get_principal (gssapi_krb5_context,
ccache,
&(*context_handle)->source);
if (kret) {
ret = GSS_S_FAILURE;
goto failure;
}
kret = krb5_copy_principal (gssapi_krb5_context,
target_name,
&(*context_handle)->target);
if (kret) {
ret = GSS_S_FAILURE;
goto failure;
}
this_cred.client = (*context_handle)->source;
this_cred.server = (*context_handle)->target;
this_cred.times.endtime = 0;
kret = krb5_get_credentials (gssapi_krb5_context,
0,
ccache,
&this_cred,
&cred);
if (kret) {
ret = GSS_S_FAILURE;
goto failure;
}
(*context_handle)->auth_context->key.keytype = cred->session.keytype;
krb5_data_copy (&(*context_handle)->auth_context->key.contents,
cred->session.contents.data,
cred->session.contents.length);
kret = create_8003_checksum (input_chan_bindings,
flags,
&cksum);
if (kret) {
ret = GSS_S_FAILURE;
goto failure;
}
kret = krb5_build_authenticator (gssapi_krb5_context,
(*context_handle)->auth_context,
cred,
&cksum,
&auth,
&authenticator);
if (kret) {
ret = GSS_S_FAILURE;
goto failure;
}
kret = krb5_build_ap_req (gssapi_krb5_context,
cred,
ap_options,
authenticator,
&outbuf);
krb5_data_free (&authenticator);
if (kret) {
ret = GSS_S_FAILURE;
goto failure;
}
ret = gssapi_krb5_encapsulate (&outbuf,
output_token,
"\x01\x00");
if (ret)
goto failure;
if (flags & GSS_C_MUTUAL_FLAG) {
return GSS_S_CONTINUE_NEEDED;
} else {
(*context_handle)->more_flags |= OPEN;
return GSS_S_COMPLETE;
}
failure:
krb5_auth_con_free (gssapi_krb5_context,
(*context_handle)->auth_context);
if((*context_handle)->source)
krb5_free_principal (gssapi_krb5_context,
(*context_handle)->source);
if((*context_handle)->target)
krb5_free_principal (gssapi_krb5_context,
(*context_handle)->target);
free (*context_handle);
krb5_data_free (&outbuf);
*context_handle = GSS_C_NO_CONTEXT;
return GSS_S_FAILURE;
}
static OM_uint32
repl_mutual
(OM_uint32 * minor_status,
const gss_cred_id_t initiator_cred_handle,
gss_ctx_id_t * context_handle,
const gss_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_type,
gss_buffer_t output_token,
OM_uint32 * ret_flags,
OM_uint32 * time_rec
)
{
OM_uint32 ret;
krb5_error_code kret;
krb5_data indata;
krb5_ap_rep_enc_part *repl;
ret = gssapi_krb5_decapsulate (input_token,
&indata,
"\x02\x00");
if (ret) {
/* XXX - Handle AP_ERROR */
return GSS_S_FAILURE;
}
kret = krb5_rd_rep (gssapi_krb5_context,
(*context_handle)->auth_context,
&indata,
&repl);
if (kret)
return GSS_S_FAILURE;
krb5_free_ap_rep_enc_part (gssapi_krb5_context,
repl);
(*context_handle)->more_flags |= OPEN;
return GSS_S_COMPLETE;
}
/*
* gss_init_sec_context
*/
OM_uint32 gss_init_sec_context
(OM_uint32 * minor_status,
const gss_cred_id_t initiator_cred_handle,
gss_ctx_id_t * context_handle,
const gss_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_type,
gss_buffer_t output_token,
OM_uint32 * ret_flags,
OM_uint32 * time_rec
)
{
gssapi_krb5_init ();
if (input_token == GSS_C_NO_BUFFER || input_token->length == 0)
return init_auth (minor_status,
initiator_cred_handle,
context_handle,
target_name,
mech_type,
req_flags,
time_req,
input_chan_bindings,
input_token,
actual_mech_type,
output_token,
ret_flags,
time_rec);
else
return repl_mutual(minor_status,
initiator_cred_handle,
context_handle,
target_name,
mech_type,
req_flags,
time_req,
input_chan_bindings,
input_token,
actual_mech_type,
output_token,
ret_flags,
time_rec);
}

View File

@@ -0,0 +1,51 @@
#include "gssapi_locl.h"
RCSID("$Id$");
OM_uint32 gss_inquire_context (
OM_uint32 * minor_status,
const gss_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 * open
)
{
OM_uint32 ret;
if (src_name) {
ret = gss_duplicate_name (minor_status,
context_handle->source,
src_name);
if (ret)
return ret;
}
if (targ_name) {
ret = gss_duplicate_name (minor_status,
context_handle->target,
targ_name);
if (ret)
return ret;
}
if (lifetime_rec)
*lifetime_rec = GSS_C_INDEFINITE;
if (mech_type)
*mech_type = GSS_KRB5_MECHANISM;
if (ctx_flags)
*ctx_flags = context_handle->flags;
if (locally_initiated)
*locally_initiated = context_handle->more_flags & LOCAL;
if (open)
*open = context_handle->more_flags & OPEN;
return GSS_S_COMPLETE;
}

View File

@@ -0,0 +1,13 @@
#include "gssapi_locl.h"
RCSID("$Id$");
OM_uint32 gss_release_buffer
(OM_uint32 * minor_status,
gss_buffer_t buffer
)
{
free (buffer->value);
buffer->length = 0;
return GSS_S_COMPLETE;
}

View File

@@ -0,0 +1,13 @@
#include "gssapi_locl.h"
RCSID("$Id$");
OM_uint32 gss_release_oid_set
(OM_uint32 * minor_status,
gss_OID_set * set
)
{
free ((*set)->elements);
free (*set);
return GSS_S_COMPLETE;
}

View File

@@ -0,0 +1,24 @@
#include "gssapi_locl.h"
RCSID("$Id$");
OM_uint32 gss_test_oid_set_member (
OM_uint32 * minor_status,
const gss_OID member,
const gss_OID_set set,
int * present
)
{
size_t i;
*present = 0;
for (i = 0; i < set->count; ++i)
if (member->length = set->elements[i].length
&& memcmp (member->elements,
set->elements[i].elements,
member->length) == 0) {
*present = 1;
break;
}
return GSS_S_COMPLETE;
}

69
lib/gssapi/krb5/unwrap.c Normal file
View File

@@ -0,0 +1,69 @@
#include "gssapi_locl.h"
#include <des.h>
#include <md5.h>
RCSID("$Id$");
OM_uint32 gss_unwrap
(OM_uint32 * minor_status,
const gss_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
)
{
u_char *p;
size_t len;
struct md5 md5;
u_char hash[16];
des_key_schedule schedule;
des_cblock key;
des_cblock zero;
p = input_message_buffer->value;
len = GSS_KRB5_MECHANISM->length + 28;
if (
input_message_buffer->length < len
|| memcmp (p, "\x60\x07\x06\x05", 4) != 0
|| memcmp (p + 4, GSS_KRB5_MECHANISM->elements,
GSS_KRB5_MECHANISM->length) != 0)
return GSS_S_BAD_MECH;
if (memcmp (p + 4 + GSS_KRB5_MECHANISM->length, "\x02\x01", 2) != 0)
return GSS_S_DEFECTIVE_TOKEN;
p += 6 + GSS_KRB5_MECHANISM->length;
if (memcmp (p, "\x00\x00", 2) != 0)
return GSS_S_BAD_SIG;
p += 2;
if (memcmp (p, "\xff\xff", 2) != 0)
return GSS_S_BAD_MIC;
p += 2;
if (memcmp (p, "\xff\xff", 2) != 0)
return GSS_S_DEFECTIVE_TOKEN;
p += 2;
p += 16;
md5_init (&md5);
md5_update (&md5, p - 24, 8);
md5_update (&md5, p, input_message_buffer->length - len);
md5_finito (&md5, hash);
memset (&zero, 0, sizeof(zero));
memcpy (&key, context_handle->auth_context->key.contents.data,
sizeof(key));
des_set_key (&key, schedule);
des_cbc_cksum ((des_cblock *)hash,
(des_cblock *)hash, sizeof(hash), schedule, &zero);
if (memcmp (p - 8, hash, 8) != 0)
return GSS_S_BAD_MIC;
output_message_buffer->length = input_message_buffer->length - len;
output_message_buffer->value = malloc(output_message_buffer->length);
if(output_message_buffer->value == NULL)
return GSS_S_FAILURE;
memcpy (output_message_buffer->value,
p,
output_message_buffer->length);
return GSS_S_COMPLETE;
}

View File

@@ -0,0 +1,59 @@
#include "gssapi_locl.h"
#include <des.h>
#include <md5.h>
RCSID("$Id$");
OM_uint32 gss_verify_mic
(OM_uint32 * minor_status,
const gss_ctx_id_t context_handle,
const gss_buffer_t message_buffer,
const gss_buffer_t token_buffer,
gss_qop_t * qop_state
)
{
u_char *p;
size_t len;
struct md5 md5;
u_char hash[16];
des_key_schedule schedule;
des_cblock key;
des_cblock zero;
p = token_buffer->value;
len = GSS_KRB5_MECHANISM->length + 28;
if (
token_buffer->length < len
|| memcmp (p, "\x60\x07\x06\x05", 4) != 0
|| memcmp (p + 4, GSS_KRB5_MECHANISM->elements,
GSS_KRB5_MECHANISM->length) != 0)
return GSS_S_BAD_MECH;
if (memcmp (p + 4 + GSS_KRB5_MECHANISM->length, "\x01\x01", 2) != 0)
return GSS_S_DEFECTIVE_TOKEN;
p += 6 + GSS_KRB5_MECHANISM->length;
if (memcmp (p, "\x00\x00", 2) != 0)
return GSS_S_BAD_SIG;
p += 2;
if (memcmp (p, "\xff\xff\xff\xff", 4) != 0)
return GSS_S_BAD_MIC;
p += 4;
p += 16;
md5_init (&md5);
md5_update (&md5, p - 24, 8);
md5_update (&md5, message_buffer->value,
message_buffer->length);
md5_finito (&md5, hash);
memset (&zero, 0, sizeof(zero));
memcpy (&key, context_handle->auth_context->key.contents.data,
sizeof(key));
des_set_key (&key, schedule);
des_cbc_cksum ((des_cblock *)hash,
(des_cblock *)hash, sizeof(hash), schedule, &zero);
if (memcmp (p - 8, hash, 8) != 0)
return GSS_S_BAD_MIC;
return GSS_S_COMPLETE;
}

63
lib/gssapi/krb5/wrap.c Normal file
View File

@@ -0,0 +1,63 @@
#include "gssapi_locl.h"
#include <des.h>
#include <md5.h>
RCSID("$Id$");
OM_uint32 gss_wrap
(OM_uint32 * minor_status,
const gss_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
)
{
u_char *p;
size_t len;
struct md5 md5;
u_char hash[16];
des_key_schedule schedule;
des_cblock key;
des_cblock zero;
len = input_message_buffer->length + 28 + GSS_KRB5_MECHANISM->length;
output_message_buffer->length = len;
output_message_buffer->value = malloc (len);
if (output_message_buffer->value == NULL)
return GSS_S_FAILURE;
p = output_message_buffer->value;
memcpy (p, "\x60\x07\x06\x05", 4);
p += 4;
memcpy (p, GSS_KRB5_MECHANISM->elements, GSS_KRB5_MECHANISM->length);
p += GSS_KRB5_MECHANISM->length;
memcpy (p, "\x02\x01", 2);
p += 2;
memcpy (p, "\x00\x00", 2);
p += 2;
memcpy (p, "\xff\xff", 2);
p += 2;
memcpy (p, "\xff\xff", 2);
p += 2;
memset (p, 0, 16);
p += 16;
memcpy (p, input_message_buffer->value,
input_message_buffer->length);
md5_init (&md5);
md5_update (&md5, p - 24, 8);
md5_update (&md5, p, input_message_buffer->length);
md5_finito (&md5, hash);
memset (&zero, 0, sizeof(zero));
memcpy (&key, context_handle->auth_context->key.contents.data,
sizeof(key));
des_set_key (&key, schedule);
des_cbc_cksum ((des_cblock *)hash,
(des_cblock *)hash, sizeof(hash), schedule, &zero);
memcpy (p - 8, hash, 8);
return GSS_S_COMPLETE;
}

View File

@@ -0,0 +1,13 @@
#include "gssapi_locl.h"
RCSID("$Id$");
OM_uint32 gss_release_buffer
(OM_uint32 * minor_status,
gss_buffer_t buffer
)
{
free (buffer->value);
buffer->length = 0;
return GSS_S_COMPLETE;
}

View File

@@ -0,0 +1,13 @@
#include "gssapi_locl.h"
RCSID("$Id$");
OM_uint32 gss_release_oid_set
(OM_uint32 * minor_status,
gss_OID_set * set
)
{
free ((*set)->elements);
free (*set);
return GSS_S_COMPLETE;
}

View File

@@ -0,0 +1,24 @@
#include "gssapi_locl.h"
RCSID("$Id$");
OM_uint32 gss_test_oid_set_member (
OM_uint32 * minor_status,
const gss_OID member,
const gss_OID_set set,
int * present
)
{
size_t i;
*present = 0;
for (i = 0; i < set->count; ++i)
if (member->length = set->elements[i].length
&& memcmp (member->elements,
set->elements[i].elements,
member->length) == 0) {
*present = 1;
break;
}
return GSS_S_COMPLETE;
}

69
lib/gssapi/unwrap.c Normal file
View File

@@ -0,0 +1,69 @@
#include "gssapi_locl.h"
#include <des.h>
#include <md5.h>
RCSID("$Id$");
OM_uint32 gss_unwrap
(OM_uint32 * minor_status,
const gss_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
)
{
u_char *p;
size_t len;
struct md5 md5;
u_char hash[16];
des_key_schedule schedule;
des_cblock key;
des_cblock zero;
p = input_message_buffer->value;
len = GSS_KRB5_MECHANISM->length + 28;
if (
input_message_buffer->length < len
|| memcmp (p, "\x60\x07\x06\x05", 4) != 0
|| memcmp (p + 4, GSS_KRB5_MECHANISM->elements,
GSS_KRB5_MECHANISM->length) != 0)
return GSS_S_BAD_MECH;
if (memcmp (p + 4 + GSS_KRB5_MECHANISM->length, "\x02\x01", 2) != 0)
return GSS_S_DEFECTIVE_TOKEN;
p += 6 + GSS_KRB5_MECHANISM->length;
if (memcmp (p, "\x00\x00", 2) != 0)
return GSS_S_BAD_SIG;
p += 2;
if (memcmp (p, "\xff\xff", 2) != 0)
return GSS_S_BAD_MIC;
p += 2;
if (memcmp (p, "\xff\xff", 2) != 0)
return GSS_S_DEFECTIVE_TOKEN;
p += 2;
p += 16;
md5_init (&md5);
md5_update (&md5, p - 24, 8);
md5_update (&md5, p, input_message_buffer->length - len);
md5_finito (&md5, hash);
memset (&zero, 0, sizeof(zero));
memcpy (&key, context_handle->auth_context->key.contents.data,
sizeof(key));
des_set_key (&key, schedule);
des_cbc_cksum ((des_cblock *)hash,
(des_cblock *)hash, sizeof(hash), schedule, &zero);
if (memcmp (p - 8, hash, 8) != 0)
return GSS_S_BAD_MIC;
output_message_buffer->length = input_message_buffer->length - len;
output_message_buffer->value = malloc(output_message_buffer->length);
if(output_message_buffer->value == NULL)
return GSS_S_FAILURE;
memcpy (output_message_buffer->value,
p,
output_message_buffer->length);
return GSS_S_COMPLETE;
}

59
lib/gssapi/verify_mic.c Normal file
View File

@@ -0,0 +1,59 @@
#include "gssapi_locl.h"
#include <des.h>
#include <md5.h>
RCSID("$Id$");
OM_uint32 gss_verify_mic
(OM_uint32 * minor_status,
const gss_ctx_id_t context_handle,
const gss_buffer_t message_buffer,
const gss_buffer_t token_buffer,
gss_qop_t * qop_state
)
{
u_char *p;
size_t len;
struct md5 md5;
u_char hash[16];
des_key_schedule schedule;
des_cblock key;
des_cblock zero;
p = token_buffer->value;
len = GSS_KRB5_MECHANISM->length + 28;
if (
token_buffer->length < len
|| memcmp (p, "\x60\x07\x06\x05", 4) != 0
|| memcmp (p + 4, GSS_KRB5_MECHANISM->elements,
GSS_KRB5_MECHANISM->length) != 0)
return GSS_S_BAD_MECH;
if (memcmp (p + 4 + GSS_KRB5_MECHANISM->length, "\x01\x01", 2) != 0)
return GSS_S_DEFECTIVE_TOKEN;
p += 6 + GSS_KRB5_MECHANISM->length;
if (memcmp (p, "\x00\x00", 2) != 0)
return GSS_S_BAD_SIG;
p += 2;
if (memcmp (p, "\xff\xff\xff\xff", 4) != 0)
return GSS_S_BAD_MIC;
p += 4;
p += 16;
md5_init (&md5);
md5_update (&md5, p - 24, 8);
md5_update (&md5, message_buffer->value,
message_buffer->length);
md5_finito (&md5, hash);
memset (&zero, 0, sizeof(zero));
memcpy (&key, context_handle->auth_context->key.contents.data,
sizeof(key));
des_set_key (&key, schedule);
des_cbc_cksum ((des_cblock *)hash,
(des_cblock *)hash, sizeof(hash), schedule, &zero);
if (memcmp (p - 8, hash, 8) != 0)
return GSS_S_BAD_MIC;
return GSS_S_COMPLETE;
}

63
lib/gssapi/wrap.c Normal file
View File

@@ -0,0 +1,63 @@
#include "gssapi_locl.h"
#include <des.h>
#include <md5.h>
RCSID("$Id$");
OM_uint32 gss_wrap
(OM_uint32 * minor_status,
const gss_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
)
{
u_char *p;
size_t len;
struct md5 md5;
u_char hash[16];
des_key_schedule schedule;
des_cblock key;
des_cblock zero;
len = input_message_buffer->length + 28 + GSS_KRB5_MECHANISM->length;
output_message_buffer->length = len;
output_message_buffer->value = malloc (len);
if (output_message_buffer->value == NULL)
return GSS_S_FAILURE;
p = output_message_buffer->value;
memcpy (p, "\x60\x07\x06\x05", 4);
p += 4;
memcpy (p, GSS_KRB5_MECHANISM->elements, GSS_KRB5_MECHANISM->length);
p += GSS_KRB5_MECHANISM->length;
memcpy (p, "\x02\x01", 2);
p += 2;
memcpy (p, "\x00\x00", 2);
p += 2;
memcpy (p, "\xff\xff", 2);
p += 2;
memcpy (p, "\xff\xff", 2);
p += 2;
memset (p, 0, 16);
p += 16;
memcpy (p, input_message_buffer->value,
input_message_buffer->length);
md5_init (&md5);
md5_update (&md5, p - 24, 8);
md5_update (&md5, p, input_message_buffer->length);
md5_finito (&md5, hash);
memset (&zero, 0, sizeof(zero));
memcpy (&key, context_handle->auth_context->key.contents.data,
sizeof(key));
des_set_key (&key, schedule);
des_cbc_cksum ((des_cblock *)hash,
(des_cblock *)hash, sizeof(hash), schedule, &zero);
memcpy (p - 8, hash, 8);
return GSS_S_COMPLETE;
}