myfulldir=lib/gssapi
mydir=.
BUILDTOP=$(REL)..$(S)..
-LOCAL_SUBDIRS= generic krb5
+LOCAL_SUBDIRS= generic mechglue krb5
##DOSLIBNAME=$(OUTPRE)gssapi.lib
##DOSOBJFILELIST=@$(OUTPRE)generic.lst @$(OUTPRE)krb5.lst @$(OUTPRE)gssapi.lst
##DOS##DLL_EXP_TYPE=GSS
-LOCALINCLUDES = -Igeneric -I$(srcdir)/generic -Ikrb5 -I$(srcdir)/krb5
+LOCALINCLUDES = -Igeneric -I$(srcdir)/generic -Ikrb5 -I$(srcdir)/krb5 -I$(srcdir)/mechglue
STLIBOBJS=\
gss_libinit.o
LIBMINOR=2
LIBINITFUNC=gssint_lib_init
LIBFINIFUNC=gssint_lib_fini
-STOBJLISTS=OBJS.ST generic/OBJS.ST krb5/OBJS.ST
-SUBDIROBJLISTS=generic/OBJS.ST krb5/OBJS.ST
+STOBJLISTS=OBJS.ST generic/OBJS.ST mechglue/OBJS.ST krb5/OBJS.ST
+SUBDIROBJLISTS=generic/OBJS.ST mechglue/OBJS.ST krb5/OBJS.ST
SHLIB_EXPDEPS=\
$(KRB5_DEPLIB) $(CRYPTO_DEPLIB) $(SUPPORT_DEPLIB) $(COM_ERR_DEPLIB)
SHLIB_EXPLIBS=-lkrb5 -lk5crypto -lcom_err $(SUPPORT_LIB) $(LIBS)
AC_SUBST(include_xom)
KRB5_BUILD_LIBOBJS
KRB5_BUILD_LIBRARY_WITH_DEPS
-V5_AC_OUTPUT_MAKEFILE(. generic krb5)
+V5_AC_OUTPUT_MAKEFILE(. generic krb5 mechglue)
$(srcdir)/disp_com_err_status.c \
$(srcdir)/disp_major_status.c \
$(srcdir)/gssapi_generic.c \
- $(srcdir)/oid_ops.c \
$(srcdir)/rel_buffer.c \
$(srcdir)/rel_oid_set.c \
$(srcdir)/util_buffer.c \
$(OUTPRE)disp_com_err_status.$(OBJEXT) \
$(OUTPRE)disp_major_status.$(OBJEXT) \
$(OUTPRE)gssapi_generic.$(OBJEXT) \
- $(OUTPRE)oid_ops.$(OBJEXT) \
$(OUTPRE)rel_buffer.$(OBJEXT) \
$(OUTPRE)rel_oid_set.$(OBJEXT) \
$(OUTPRE)util_buffer.$(OBJEXT) \
disp_com_err_status.o \
disp_major_status.o \
gssapi_generic.o \
- oid_ops.o \
rel_buffer.o \
rel_oid_set.o \
util_buffer.o \
gss_OID_set * /* name_types */
);
+/* New for V2 */
+OM_uint32 KRB5_CALLCONV gss_inquire_mechs_for_name(
+ OM_uint32 *, /* minor_status */
+ const gss_name_t, /* input_name */
+ gss_OID_set * /* mech_types */
+);
+
/*
* The following routines are obsolete variants of gss_get_mic, gss_wrap,
* gss_verify_mic and gss_unwrap. They should be provided by GSSAPI V2
error_code G_TOK_TRUNC, "Token is missing data"
error_code G_REFLECT, "Token was reflected"
error_code G_WRONG_TOKID, "Received token ID does not match expected token ID"
+error_code G_CRED_USAGE_MISMATCH, "The given credential's usage does not match the requested usage"
+error_code G_STORE_ACCEPTOR_CRED_NOSUPP, "Storing of acceptor credentials is not supported by the mechanism"
+error_code G_STORE_NON_DEFAULT_CRED_NOSUPP, "Storing of non-default credentials is not supported by the mechanism"
end
#include "gss_libinit.h"
#include "k5-platform.h"
+#include "mglueP.h"
+
/*
* Initialize the GSSAPI library.
*/
add_error_table(&et_k5g_error_table);
add_error_table(&et_ggss_error_table);
#endif
+ err = gssint_mechglue_init();
+ if (err)
+ return err;
err = k5_mutex_finish_init(&gssint_krb5_keytab_lock);
if (err)
return err;
k5_key_delete(K5_KEY_GSS_KRB5_CCACHE_NAME);
k5_mutex_destroy(&kg_vdb.mutex);
k5_mutex_destroy(&gssint_krb5_keytab_lock);
+ gssint_mechglue_fini();
}
OM_uint32 gssint_initialize_library (void)
myfulldir=lib/gssapi/krb5
mydir=krb5
BUILDTOP=$(REL)..$(S)..$(S)..
-LOCALINCLUDES = -I. -I$(srcdir) -I$(srcdir)/.. -I../generic -I$(srcdir)/../generic
+LOCALINCLUDES = -I. -I$(srcdir) -I$(srcdir)/.. -I../generic -I$(srcdir)/../generic -I../mechglue -I$(srcdir)/../mechglue
##DOS##BUILDTOP = ..\..\..
##DOS##PREFIXDIR=krb5
#include "gssapiP_krb5.h"
OM_uint32 KRB5_CALLCONV
-gss_krb5_copy_ccache(minor_status, cred_handle, out_ccache)
+gss_krb5int_copy_ccache(minor_status, cred_handle, out_ccache)
OM_uint32 *minor_status;
gss_cred_id_t cred_handle;
krb5_ccache out_ccache;
*/
OM_uint32 KRB5_CALLCONV
-gss_krb5_get_tkt_flags(minor_status, context_handle, ticket_flags)
+gss_krb5int_get_tkt_flags(minor_status, context_handle, ticket_flags)
OM_uint32 *minor_status;
gss_ctx_id_t context_handle;
krb5_flags *ticket_flags;
/** constants **/
+#define GSS_MECH_KRB5_OID_LENGTH 9
+#define GSS_MECH_KRB5_OID "\052\206\110\206\367\022\001\002\002"
+
#define CKSUMTYPE_KG_CB 0x8003
#define KG_TOK_CTX_AP_REQ 0x0100
int *conf_state, int *qop_state,
int toktype);
+/*
+ * These take unglued krb5-mech-specific contexts.
+ */
+
+OM_uint32 KRB5_CALLCONV gss_krb5int_get_tkt_flags
+ (OM_uint32 *minor_status,
+ gss_ctx_id_t context_handle,
+ krb5_flags *ticket_flags);
+
+OM_uint32 KRB5_CALLCONV gss_krb5int_copy_ccache
+ (OM_uint32 *minor_status,
+ gss_cred_id_t cred_handle,
+ krb5_ccache out_ccache);
+
+OM_uint32 KRB5_CALLCONV
+gss_krb5int_set_allowable_enctypes(OM_uint32 *minor_status,
+ gss_cred_id_t cred,
+ OM_uint32 num_ktypes,
+ krb5_enctype *ktypes);
+
+OM_uint32 KRB5_CALLCONV
+gss_krb5int_export_lucid_sec_context(OM_uint32 *minor_status,
+ gss_ctx_id_t *context_handle,
+ OM_uint32 version,
+ void **kctx);
+
+
#endif /* _GSSAPIP_KRB5_H_ */
const gss_OID_desc krb5_gss_oid_array[] = {
/* this is the official, rfc-specified OID */
- {9, "\052\206\110\206\367\022\001\002\002"},
+ {GSS_MECH_KRB5_OID_LENGTH, GSS_MECH_KRB5_OID},
/* this is the unofficial, wrong OID */
{5, "\053\005\001\005\002"},
/* this is the v2 assigned OID */
*/
#include "gssapiP_krb5.h"
+#include "mglueP.h"
-OM_uint32 KRB5_CALLCONV
-gss_accept_sec_context(minor_status, context_handle, verifier_cred_handle,
+/** mechglue wrappers **/
+
+static OM_uint32 k5glue_acquire_cred
+(void *, OM_uint32*, /* minor_status */
+ gss_name_t, /* desired_name */
+ OM_uint32, /* time_req */
+ 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 */
+ );
+
+static OM_uint32 k5glue_release_cred
+(void *, OM_uint32*, /* minor_status */
+ gss_cred_id_t* /* cred_handle */
+ );
+
+static OM_uint32 k5glue_init_sec_context
+(void *, OM_uint32*, /* minor_status */
+ gss_cred_id_t, /* claimant_cred_handle */
+ gss_ctx_id_t*, /* context_handle */
+ gss_name_t, /* target_name */
+ gss_OID, /* mech_type */
+ OM_uint32, /* req_flags */
+ OM_uint32, /* time_req */
+ gss_channel_bindings_t,
+ /* input_chan_bindings */
+ gss_buffer_t, /* input_token */
+ gss_OID*, /* actual_mech_type */
+ gss_buffer_t, /* output_token */
+ OM_uint32*, /* ret_flags */
+ OM_uint32* /* time_rec */
+ );
+
+static OM_uint32 k5glue_accept_sec_context
+(void *, OM_uint32*, /* minor_status */
+ gss_ctx_id_t*, /* context_handle */
+ gss_cred_id_t, /* verifier_cred_handle */
+ gss_buffer_t, /* input_token_buffer */
+ 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 */
+ );
+
+static OM_uint32 k5glue_process_context_token
+(void *, OM_uint32*, /* minor_status */
+ gss_ctx_id_t, /* context_handle */
+ gss_buffer_t /* token_buffer */
+ );
+
+static OM_uint32 k5glue_delete_sec_context
+(void *, OM_uint32*, /* minor_status */
+ gss_ctx_id_t*, /* context_handle */
+ gss_buffer_t /* output_token */
+ );
+
+static OM_uint32 k5glue_context_time
+(void *, OM_uint32*, /* minor_status */
+ gss_ctx_id_t, /* context_handle */
+ OM_uint32* /* time_rec */
+ );
+
+static OM_uint32 k5glue_sign
+(void *, OM_uint32*, /* minor_status */
+ gss_ctx_id_t, /* context_handle */
+ int, /* qop_req */
+ gss_buffer_t, /* message_buffer */
+ gss_buffer_t /* message_token */
+ );
+
+static OM_uint32 k5glue_verify
+(void *, OM_uint32*, /* minor_status */
+ gss_ctx_id_t, /* context_handle */
+ gss_buffer_t, /* message_buffer */
+ gss_buffer_t, /* token_buffer */
+ int* /* qop_state */
+ );
+
+static OM_uint32 k5glue_seal
+(void *, 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 */
+ );
+
+static OM_uint32 k5glue_unseal
+(void *, 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 */
+ );
+
+static OM_uint32 k5glue_display_status
+(void *, OM_uint32*, /* minor_status */
+ OM_uint32, /* status_value */
+ int, /* status_type */
+ gss_OID, /* mech_type */
+ OM_uint32*, /* message_context */
+ gss_buffer_t /* status_string */
+ );
+
+static OM_uint32 k5glue_indicate_mechs
+(void *, OM_uint32*, /* minor_status */
+ gss_OID_set* /* mech_set */
+ );
+
+static OM_uint32 k5glue_compare_name
+(void *, OM_uint32*, /* minor_status */
+ gss_name_t, /* name1 */
+ gss_name_t, /* name2 */
+ int* /* name_equal */
+ );
+
+static OM_uint32 k5glue_display_name
+(void *, OM_uint32*, /* minor_status */
+ gss_name_t, /* input_name */
+ gss_buffer_t, /* output_name_buffer */
+ gss_OID* /* output_name_type */
+ );
+
+static OM_uint32 k5glue_import_name
+(void *, OM_uint32*, /* minor_status */
+ gss_buffer_t, /* input_name_buffer */
+ gss_OID, /* input_name_type */
+ gss_name_t* /* output_name */
+ );
+
+static OM_uint32 k5glue_release_name
+(void *, OM_uint32*, /* minor_status */
+ gss_name_t* /* input_name */
+ );
+
+static OM_uint32 k5glue_inquire_cred
+(void *, OM_uint32 *, /* minor_status */
+ gss_cred_id_t, /* cred_handle */
+ gss_name_t *, /* name */
+ OM_uint32 *, /* lifetime */
+ gss_cred_usage_t*,/* cred_usage */
+ gss_OID_set * /* mechanisms */
+ );
+
+static OM_uint32 k5glue_inquire_context
+(void *, OM_uint32*, /* minor_status */
+ gss_ctx_id_t, /* context_handle */
+ gss_name_t*, /* initiator_name */
+ gss_name_t*, /* acceptor_name */
+ OM_uint32*, /* lifetime_rec */
+ gss_OID*, /* mech_type */
+ OM_uint32*, /* ret_flags */
+ int*, /* locally_initiated */
+ int* /* open */
+ );
+
+#if 0
+/* New V2 entry points */
+static OM_uint32 k5glue_get_mic
+(void *, OM_uint32 *, /* minor_status */
+ gss_ctx_id_t, /* context_handle */
+ gss_qop_t, /* qop_req */
+ gss_buffer_t, /* message_buffer */
+ gss_buffer_t /* message_token */
+ );
+
+static OM_uint32 k5glue_verify_mic
+(void *, OM_uint32 *, /* minor_status */
+ gss_ctx_id_t, /* context_handle */
+ gss_buffer_t, /* message_buffer */
+ gss_buffer_t, /* message_token */
+ gss_qop_t * /* qop_state */
+ );
+
+static OM_uint32 k5glue_wrap
+(void *, OM_uint32 *, /* minor_status */
+ gss_ctx_id_t, /* context_handle */
+ int, /* conf_req_flag */
+ gss_qop_t, /* qop_req */
+ gss_buffer_t, /* input_message_buffer */
+ int *, /* conf_state */
+ gss_buffer_t /* output_message_buffer */
+ );
+
+static OM_uint32 k5glue_unwrap
+(void *, 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 */
+ gss_qop_t * /* qop_state */
+ );
+#endif
+
+static OM_uint32 k5glue_wrap_size_limit
+(void *, OM_uint32 *, /* minor_status */
+ 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 */
+ );
+
+#if 0
+static OM_uint32 k5glue_import_name_object
+(void *, OM_uint32 *, /* minor_status */
+ void *, /* input_name */
+ gss_OID, /* input_name_type */
+ gss_name_t * /* output_name */
+ );
+
+static OM_uint32 k5glue_export_name_object
+(void *, OM_uint32 *, /* minor_status */
+ gss_name_t, /* input_name */
+ gss_OID, /* desired_name_type */
+ void * * /* output_name */
+ );
+#endif
+
+static OM_uint32 k5glue_add_cred
+(void *, OM_uint32 *, /* minor_status */
+ gss_cred_id_t, /* input_cred_handle */
+ gss_name_t, /* desired_name */
+ 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 */
+ );
+
+static OM_uint32 k5glue_inquire_cred_by_mech
+(void *, OM_uint32 *, /* minor_status */
+ gss_cred_id_t, /* cred_handle */
+ gss_OID, /* mech_type */
+ gss_name_t *, /* name */
+ OM_uint32 *, /* initiator_lifetime */
+ OM_uint32 *, /* acceptor_lifetime */
+ gss_cred_usage_t * /* cred_usage */
+ );
+
+static OM_uint32 k5glue_export_sec_context
+(void *, OM_uint32 *, /* minor_status */
+ gss_ctx_id_t *, /* context_handle */
+ gss_buffer_t /* interprocess_token */
+ );
+
+static OM_uint32 k5glue_import_sec_context
+(void *, OM_uint32 *, /* minor_status */
+ gss_buffer_t, /* interprocess_token */
+ gss_ctx_id_t * /* context_handle */
+ );
+
+krb5_error_code k5glue_ser_init(krb5_context);
+
+static OM_uint32 k5glue_release_oid
+(void *, OM_uint32 *, /* minor_status */
+ gss_OID * /* oid */
+ );
+
+static OM_uint32 k5glue_inquire_names_for_mech
+(void *, OM_uint32 *, /* minor_status */
+ gss_OID, /* mechanism */
+ gss_OID_set * /* name_types */
+ );
+
+#if 0
+static OM_uint32 k5glue_canonicalize_name
+(void *, OM_uint32 *, /* minor_status */
+ const gss_name_t, /* input_name */
+ const gss_OID, /* mech_type */
+ gss_name_t * /* output_name */
+ );
+#endif
+
+static OM_uint32 k5glue_export_name
+(void *, OM_uint32 *, /* minor_status */
+ const gss_name_t, /* input_name */
+ gss_buffer_t /* exported_name */
+ );
+
+#if 0
+static OM_uint32 k5glue_duplicate_name
+(void *, OM_uint32 *, /* minor_status */
+ const gss_name_t, /* input_name */
+ gss_name_t * /* dest_name */
+ );
+#endif
+
+#if 0
+static OM_uint32 k5glue_validate_cred
+(void *, OM_uint32 *, /* minor_status */
+ gss_cred_id_t /* cred */
+ );
+#endif
+
+struct gss_config krb5_mechanism = {
+ { GSS_MECH_KRB5_OID_LENGTH, GSS_MECH_KRB5_OID },
+ NULL,
+ k5glue_acquire_cred,
+ k5glue_release_cred,
+ k5glue_init_sec_context,
+ k5glue_accept_sec_context,
+ k5glue_process_context_token,
+ k5glue_delete_sec_context,
+ k5glue_context_time,
+ k5glue_sign,
+ k5glue_verify,
+ k5glue_seal,
+ k5glue_unseal,
+ k5glue_display_status,
+ k5glue_indicate_mechs,
+ k5glue_compare_name,
+ k5glue_display_name,
+ k5glue_import_name,
+ k5glue_release_name,
+ k5glue_inquire_cred,
+ k5glue_add_cred,
+ k5glue_export_sec_context,
+ k5glue_import_sec_context,
+ k5glue_inquire_cred_by_mech,
+ k5glue_inquire_names_for_mech,
+ k5glue_inquire_context,
+ k5glue_release_oid,
+ k5glue_wrap_size_limit,
+ NULL, /* pname_to_uid */
+ NULL, /* userok */
+ k5glue_export_name,
+ NULL /* store_cred */
+};
+
+#ifdef KRB5_MECH_MODULE
+gss_mechanism
+gss_mech_initialize(const gss_OID oid)
+{
+ if (oid == NULL ||
+ !g_OID_equal(oid, &krb5_mechanism.mech_type)) {
+ return NULL;
+ }
+ return &krb5_mechanism;
+}
+#endif
+
+static OM_uint32
+k5glue_accept_sec_context(ctx, minor_status, context_handle, verifier_cred_handle,
input_token, input_chan_bindings, src_name, mech_type,
output_token, ret_flags, time_rec, delegated_cred_handle)
+ void *ctx;
OM_uint32 *minor_status;
gss_ctx_id_t *context_handle;
gss_cred_id_t verifier_cred_handle;
delegated_cred_handle));
}
-OM_uint32 KRB5_CALLCONV
-gss_acquire_cred(minor_status, desired_name, time_req, desired_mechs,
+static OM_uint32
+k5glue_acquire_cred(ctx, minor_status, desired_name, time_req, desired_mechs,
cred_usage, output_cred_handle, actual_mechs, time_rec)
+ void *ctx;
OM_uint32 *minor_status;
gss_name_t desired_name;
OM_uint32 time_req;
}
/* V2 */
-OM_uint32 KRB5_CALLCONV
-gss_add_cred(minor_status, input_cred_handle, desired_name, desired_mech,
+static OM_uint32
+k5glue_add_cred(ctx, minor_status, input_cred_handle, desired_name, desired_mech,
cred_usage, initiator_time_req, acceptor_time_req,
output_cred_handle, actual_mechs, initiator_time_rec,
acceptor_time_rec)
+ void *ctx;
OM_uint32 *minor_status;
gss_cred_id_t input_cred_handle;
gss_name_t desired_name;
acceptor_time_rec));
}
+#if 0
/* V2 */
-OM_uint32 KRB5_CALLCONV
-gss_add_oid_set_member(minor_status, member_oid, oid_set)
+static OM_uint32
+k5glue_add_oid_set_member(ctx, minor_status, member_oid, oid_set)
+ void *ctx;
OM_uint32 *minor_status;
gss_OID member_oid;
gss_OID_set *oid_set;
{
return(generic_gss_add_oid_set_member(minor_status, member_oid, oid_set));
}
+#endif
-OM_uint32 KRB5_CALLCONV
-gss_compare_name(minor_status, name1, name2, name_equal)
+static OM_uint32
+k5glue_compare_name(ctx, minor_status, name1, name2, name_equal)
+ void *ctx;
OM_uint32 *minor_status;
gss_name_t name1;
gss_name_t name2;
name2, name_equal));
}
-OM_uint32 KRB5_CALLCONV
-gss_context_time(minor_status, context_handle, time_rec)
+static OM_uint32
+k5glue_context_time(ctx, minor_status, context_handle, time_rec)
+ void *ctx;
OM_uint32 *minor_status;
gss_ctx_id_t context_handle;
OM_uint32 *time_rec;
time_rec));
}
+#if 0
/* V2 */
-OM_uint32 KRB5_CALLCONV
-gss_create_empty_oid_set(minor_status, oid_set)
+static OM_uint32
+k5glue_create_empty_oid_set(ctx, minor_status, oid_set)
+ void *ctx;
OM_uint32 *minor_status;
gss_OID_set *oid_set;
{
return(generic_gss_create_empty_oid_set(minor_status, oid_set));
}
+#endif
-OM_uint32 KRB5_CALLCONV
-gss_delete_sec_context(minor_status, context_handle, output_token)
+static OM_uint32
+k5glue_delete_sec_context(ctx, minor_status, context_handle, output_token)
+ void *ctx;
OM_uint32 *minor_status;
gss_ctx_id_t *context_handle;
gss_buffer_t output_token;
context_handle, output_token));
}
-OM_uint32 KRB5_CALLCONV
-gss_display_name(minor_status, input_name, output_name_buffer, output_name_type)
+static OM_uint32
+k5glue_display_name(ctx, minor_status, input_name, output_name_buffer, output_name_type)
+ void *ctx;
OM_uint32 *minor_status;
gss_name_t input_name;
gss_buffer_t output_name_buffer;
output_name_buffer, output_name_type));
}
-OM_uint32 KRB5_CALLCONV
-gss_display_status(minor_status, status_value, status_type,
+static OM_uint32
+k5glue_display_status(ctx, minor_status, status_value, status_type,
mech_type, message_context, status_string)
+ void *ctx;
OM_uint32 *minor_status;
OM_uint32 status_value;
int status_type;
}
/* V2 */
-OM_uint32 KRB5_CALLCONV
-gss_export_sec_context(minor_status, context_handle, interprocess_token)
+static OM_uint32
+k5glue_export_sec_context(ctx, minor_status, context_handle, interprocess_token)
+ void *ctx;
OM_uint32 *minor_status;
gss_ctx_id_t *context_handle;
gss_buffer_t interprocess_token;
interprocess_token));
}
+#if 0
/* V2 */
-OM_uint32 KRB5_CALLCONV
-gss_get_mic(minor_status, context_handle, qop_req,
+static OM_uint32
+k5glue_get_mic(ctx, minor_status, context_handle, qop_req,
message_buffer, message_token)
+ void *ctx;
OM_uint32 *minor_status;
gss_ctx_id_t context_handle;
gss_qop_t qop_req;
return(krb5_gss_get_mic(minor_status, context_handle,
qop_req, message_buffer, message_token));
}
+#endif
-OM_uint32 KRB5_CALLCONV
-gss_import_name(minor_status, input_name_buffer, input_name_type, output_name)
+static OM_uint32
+k5glue_import_name(ctx, minor_status, input_name_buffer, input_name_type, output_name)
+ void *ctx;
OM_uint32 *minor_status;
gss_buffer_t input_name_buffer;
gss_OID input_name_type;
gss_name_t *output_name;
{
+#if 0
OM_uint32 err;
err = gssint_initialize_library();
if (err) {
*minor_status = err;
return GSS_S_FAILURE;
}
+#endif
return(krb5_gss_import_name(minor_status, input_name_buffer,
input_name_type, output_name));
}
/* V2 */
-OM_uint32 KRB5_CALLCONV
-gss_import_sec_context(minor_status, interprocess_token, context_handle)
+static OM_uint32
+k5glue_import_sec_context(ctx, minor_status, interprocess_token, context_handle)
+ void *ctx;
OM_uint32 *minor_status;
gss_buffer_t interprocess_token;
gss_ctx_id_t *context_handle;
context_handle));
}
-OM_uint32 KRB5_CALLCONV
-gss_indicate_mechs(minor_status, mech_set)
+static OM_uint32
+k5glue_indicate_mechs(ctx, minor_status, mech_set)
+ void *ctx;
OM_uint32 *minor_status;
gss_OID_set *mech_set;
{
return(krb5_gss_indicate_mechs(minor_status, mech_set));
}
-OM_uint32 KRB5_CALLCONV
-gss_init_sec_context(minor_status, claimant_cred_handle, context_handle,
+static OM_uint32
+k5glue_init_sec_context(ctx, minor_status, claimant_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)
+ void *ctx;
OM_uint32 *minor_status;
gss_cred_id_t claimant_cred_handle;
gss_ctx_id_t *context_handle;
time_rec));
}
-OM_uint32 KRB5_CALLCONV
-gss_inquire_context(minor_status, context_handle, initiator_name, acceptor_name,
+static OM_uint32
+k5glue_inquire_context(ctx, minor_status, context_handle, initiator_name, acceptor_name,
lifetime_rec, mech_type, ret_flags,
locally_initiated, open)
+ void *ctx;
OM_uint32 *minor_status;
gss_ctx_id_t context_handle;
gss_name_t *initiator_name;
open));
}
-OM_uint32 KRB5_CALLCONV
-gss_inquire_cred(minor_status, cred_handle, name, lifetime_ret,
+static OM_uint32
+k5glue_inquire_cred(ctx, minor_status, cred_handle, name, lifetime_ret,
cred_usage, mechanisms)
+ void *ctx;
OM_uint32 *minor_status;
gss_cred_id_t cred_handle;
gss_name_t *name;
}
/* V2 */
-OM_uint32 KRB5_CALLCONV
-gss_inquire_cred_by_mech(minor_status, cred_handle, mech_type, name,
+static OM_uint32
+k5glue_inquire_cred_by_mech(ctx, minor_status, cred_handle, mech_type, name,
initiator_lifetime, acceptor_lifetime, cred_usage)
+ void *ctx;
OM_uint32 *minor_status;
gss_cred_id_t cred_handle;
gss_OID mech_type;
}
/* V2 */
-OM_uint32 KRB5_CALLCONV
-gss_inquire_names_for_mech(minor_status, mechanism, name_types)
+static OM_uint32
+k5glue_inquire_names_for_mech(ctx, minor_status, mechanism, name_types)
+ void *ctx;
OM_uint32 *minor_status;
gss_OID mechanism;
gss_OID_set *name_types;
name_types));
}
+#if 0
/* V2 */
-OM_uint32 KRB5_CALLCONV
-gss_oid_to_str(minor_status, oid, oid_str)
+static OM_uint32
+k5glue_oid_to_str(ctx, minor_status, oid, oid_str)
+ void *ctx;
OM_uint32 *minor_status;
gss_OID oid;
gss_buffer_t oid_str;
{
return(generic_gss_oid_to_str(minor_status, oid, oid_str));
}
+#endif
-OM_uint32 KRB5_CALLCONV
-gss_process_context_token(minor_status, context_handle, token_buffer)
+static OM_uint32
+k5glue_process_context_token(ctx, minor_status, context_handle, token_buffer)
+ void *ctx;
OM_uint32 *minor_status;
gss_ctx_id_t context_handle;
gss_buffer_t token_buffer;
context_handle, token_buffer));
}
-OM_uint32 KRB5_CALLCONV
-gss_release_cred(minor_status, cred_handle)
+static OM_uint32
+k5glue_release_cred(ctx, minor_status, cred_handle)
+ void *ctx;
OM_uint32 *minor_status;
gss_cred_id_t *cred_handle;
{
return(krb5_gss_release_cred(minor_status, cred_handle));
}
-OM_uint32 KRB5_CALLCONV
-gss_release_name(minor_status, input_name)
+static OM_uint32
+k5glue_release_name(ctx, minor_status, input_name)
+ void *ctx;
OM_uint32 *minor_status;
gss_name_t *input_name;
{
return(krb5_gss_release_name(minor_status, input_name));
}
-OM_uint32 KRB5_CALLCONV
-gss_release_buffer(minor_status, buffer)
+#if 0
+static OM_uint32
+k5glue_release_buffer(ctx, minor_status, buffer)
+ void *ctx;
OM_uint32 *minor_status;
gss_buffer_t buffer;
{
return(generic_gss_release_buffer(minor_status,
buffer));
}
+#endif
/* V2 */
-OM_uint32 KRB5_CALLCONV
-gss_release_oid(minor_status, oid)
+static OM_uint32
+k5glue_release_oid(ctx, minor_status, oid)
+ void *ctx;
OM_uint32 *minor_status;
gss_OID *oid;
{
return(krb5_gss_release_oid(minor_status, oid));
}
-OM_uint32 KRB5_CALLCONV
-gss_release_oid_set(minor_status, set)
+#if 0
+static OM_uint32
+k5glue_release_oid_set(ctx, minor_status, set)
+ void *ctx;
OM_uint32 * minor_status;
gss_OID_set *set;
{
return(generic_gss_release_oid_set(minor_status, set));
}
+#endif
/* V1 only */
-OM_uint32 KRB5_CALLCONV
-gss_seal(minor_status, context_handle, conf_req_flag, qop_req,
+static OM_uint32
+k5glue_seal(ctx, minor_status, context_handle, conf_req_flag, qop_req,
input_message_buffer, conf_state, output_message_buffer)
+ void *ctx;
OM_uint32 *minor_status;
gss_ctx_id_t context_handle;
int conf_req_flag;
conf_state, output_message_buffer));
}
-OM_uint32 KRB5_CALLCONV
-gss_sign(minor_status, context_handle,
+static OM_uint32
+k5glue_sign(ctx, minor_status, context_handle,
qop_req, message_buffer,
message_token)
+ void *ctx;
OM_uint32 *minor_status;
gss_ctx_id_t context_handle;
int qop_req;
qop_req, message_buffer, message_token));
}
+#if 0
/* V2 */
-OM_uint32 KRB5_CALLCONV
-gss_verify_mic(minor_status, context_handle,
+static OM_uint32
+k5glue_verify_mic(ctx, minor_status, context_handle,
message_buffer, token_buffer, qop_state)
+ void *ctx;
OM_uint32 *minor_status;
gss_ctx_id_t context_handle;
gss_buffer_t message_buffer;
}
/* V2 */
-OM_uint32 KRB5_CALLCONV
-gss_wrap(minor_status, context_handle, conf_req_flag, qop_req,
+static OM_uint32
+k5glue_wrap(ctx, minor_status, context_handle, conf_req_flag, qop_req,
input_message_buffer, conf_state, output_message_buffer)
+ void *ctx;
OM_uint32 *minor_status;
gss_ctx_id_t context_handle;
int conf_req_flag;
}
/* V2 */
-OM_uint32 KRB5_CALLCONV
-gss_str_to_oid(minor_status, oid_str, oid)
+static OM_uint32
+k5glue_str_to_oid(ctx, minor_status, oid_str, oid)
+ void *ctx;
OM_uint32 *minor_status;
gss_buffer_t oid_str;
gss_OID *oid;
}
/* V2 */
-OM_uint32 KRB5_CALLCONV
-gss_test_oid_set_member(minor_status, member, set, present)
+static OM_uint32
+k5glue_test_oid_set_member(ctx, minor_status, member, set, present)
+ void *ctx;
OM_uint32 *minor_status;
gss_OID member;
gss_OID_set set;
return(generic_gss_test_oid_set_member(minor_status, member, set,
present));
}
+#endif
/* V1 only */
-OM_uint32 KRB5_CALLCONV
-gss_unseal(minor_status, context_handle, input_message_buffer,
+static OM_uint32
+k5glue_unseal(ctx, minor_status, context_handle, input_message_buffer,
output_message_buffer, conf_state, qop_state)
+ void *ctx;
OM_uint32 *minor_status;
gss_ctx_id_t context_handle;
gss_buffer_t input_message_buffer;
conf_state, qop_state));
}
+#if 0
/* V2 */
-OM_uint32 KRB5_CALLCONV
-gss_unwrap(minor_status, context_handle, input_message_buffer,
+static OM_uint32
+k5glue_unwrap(ctx, minor_status, context_handle, input_message_buffer,
output_message_buffer, conf_state, qop_state)
+ void *ctx;
OM_uint32 *minor_status;
gss_ctx_id_t context_handle;
gss_buffer_t input_message_buffer;
return(krb5_gss_unwrap(minor_status, context_handle, input_message_buffer,
output_message_buffer, conf_state, qop_state));
}
+#endif
/* V1 only */
-OM_uint32 KRB5_CALLCONV
-gss_verify(minor_status, context_handle, message_buffer,
+static OM_uint32
+k5glue_verify(ctx, minor_status, context_handle, message_buffer,
token_buffer, qop_state)
+ void *ctx;
OM_uint32 *minor_status;
gss_ctx_id_t context_handle;
gss_buffer_t message_buffer;
}
/* V2 interface */
-OM_uint32 KRB5_CALLCONV
-gss_wrap_size_limit(minor_status, context_handle, conf_req_flag,
+static OM_uint32
+k5glue_wrap_size_limit(ctx, minor_status, context_handle, conf_req_flag,
qop_req, req_output_size, max_input_size)
+ void *ctx;
OM_uint32 *minor_status;
gss_ctx_id_t context_handle;
int conf_req_flag;
req_output_size, max_input_size));
}
+#if 0
/* V2 interface */
-OM_uint32 KRB5_CALLCONV
-gss_canonicalize_name(minor_status, input_name, mech_type, output_name)
+static OM_uint32
+k5glue_canonicalize_name(ctx, minor_status, input_name, mech_type, output_name)
+ void *ctx;
OM_uint32 *minor_status;
const gss_name_t input_name;
const gss_OID mech_type;
return krb5_gss_canonicalize_name(minor_status, input_name,
mech_type, output_name);
}
-
+#endif
/* V2 interface */
-OM_uint32 KRB5_CALLCONV
-gss_export_name(minor_status, input_name, exported_name)
+static OM_uint32
+k5glue_export_name(ctx, minor_status, input_name, exported_name)
+ void *ctx;
OM_uint32 *minor_status;
const gss_name_t input_name;
gss_buffer_t exported_name;
return krb5_gss_export_name(minor_status, input_name, exported_name);
}
+#if 0
/* V2 interface */
-OM_uint32 KRB5_CALLCONV
-gss_duplicate_name(minor_status, input_name, dest_name)
+static OM_uint32
+k5glue_duplicate_name(ctx, minor_status, input_name, dest_name)
+ void *ctx;
OM_uint32 *minor_status;
const gss_name_t input_name;
gss_name_t *dest_name;
{
return krb5_gss_duplicate_name(minor_status, input_name, dest_name);
}
+#endif
+OM_uint32 KRB5_CALLCONV
+gss_krb5_get_tkt_flags(
+ OM_uint32 *minor_status,
+ gss_ctx_id_t context_handle,
+ krb5_flags *ticket_flags)
+{
+ gss_union_ctx_id_t uctx;
+ uctx = (gss_union_ctx_id_t)context_handle;
+ if (!g_OID_equal(uctx->mech_type, &krb5_mechanism.mech_type))
+ return GSS_S_BAD_MECH;
+ return gss_krb5int_get_tkt_flags(minor_status, uctx->internal_ctx_id,
+ ticket_flags);
+}
+OM_uint32 KRB5_CALLCONV
+gss_krb5_copy_ccache(
+ OM_uint32 *minor_status,
+ gss_cred_id_t cred_handle,
+ krb5_ccache out_ccache)
+{
+ gss_union_cred_t ucred;
+ gss_cred_id_t mcred;
+
+ ucred = (gss_union_cred_t)cred_handle;
+ mcred = __gss_get_mechanism_cred(ucred, &krb5_mechanism.mech_type);
+ if (mcred == NULL)
+ return GSS_S_DEFECTIVE_CREDENTIAL;
+ return gss_krb5int_copy_ccache(minor_status, mcred, out_ccache);
+}
+
+/* XXX need to delete mechglue ctx too */
+OM_uint32 KRB5_CALLCONV
+gss_krb5_export_lucid_sec_context(
+ OM_uint32 *minor_status,
+ gss_ctx_id_t *context_handle,
+ OM_uint32 version,
+ void **kctx)
+{
+ gss_union_ctx_id_t uctx;
+
+ uctx = (gss_union_ctx_id_t)*context_handle;
+ if (!g_OID_equal(uctx->mech_type, &krb5_mechanism.mech_type))
+ return GSS_S_BAD_MECH;
+ return gss_krb5int_export_lucid_sec_context(minor_status,
+ &uctx->internal_ctx_id,
+ version, kctx);
+}
+
+OM_uint32 KRB5_CALLCONV
+gss_krb5_set_allowable_enctypes(
+ OM_uint32 *minor_status,
+ gss_cred_id_t cred,
+ OM_uint32 num_ktypes,
+ krb5_enctype *ktypes)
+{
+ gss_union_cred_t ucred;
+ gss_cred_id_t mcred;
+
+ ucred = (gss_union_cred_t)cred;
+ mcred = __gss_get_mechanism_cred(ucred, &krb5_mechanism.mech_type);
+ if (mcred == NULL)
+ return GSS_S_DEFECTIVE_CREDENTIAL;
+ return gss_krb5int_set_allowable_enctypes(minor_status, mcred,
+ num_ktypes, ktypes);
+}
*/
OM_uint32 KRB5_CALLCONV
-gss_krb5_export_lucid_sec_context(
+gss_krb5int_export_lucid_sec_context(
OM_uint32 *minor_status,
gss_ctx_id_t *context_handle,
OM_uint32 version,
#include "gssapi_krb5.h"
OM_uint32 KRB5_CALLCONV
-gss_krb5_set_allowable_enctypes(OM_uint32 *minor_status,
- gss_cred_id_t cred_handle,
- OM_uint32 num_ktypes,
- krb5_enctype *ktypes)
+gss_krb5int_set_allowable_enctypes(OM_uint32 *minor_status,
+ gss_cred_id_t cred_handle,
+ OM_uint32 num_ktypes,
+ krb5_enctype *ktypes)
{
int i;
krb5_enctype * new_ktypes;
-thisconfigdir=..
+thisconfigdir=./..
myfulldir=lib/gssapi/mechglue
-mydir=.
+mydir=mechglue
BUILDTOP=$(REL)..$(S)..$(S)..
-LOCALINCLUDES = -I. -I$(srcdir)
+LOCALINCLUDES = -I. -I$(srcdir) -I$(srcdir)/.. -I../generic -I$(srcdir)/../generic
##DOSBUILDTOP = ..\..\..
##DOSLIBNAME=..\$(OUTPRE)gssapi.$(LIBEXT)
##DOS##DLL_EXP_TYPE=GSS
-LIBDONE=DONE
-LIB_SUBDIRS=.
-DEPLIBS=
-SHLIB_LDFLAGS= $(LDFLAGS) @SHLIB_RPATH_DIRS@ \
- $(LD_UNRESOLVED_PREFIX)krb5_gss_initialize
-
-
-SHLIB_LIBDIRS= @SHLIB_LIBDIRS@
-
-SRCS = $(srcdir)/g_acquire_cred.c \
- $(srcdir)/g_rel_cred.c \
- $(srcdir)/g_init_sec_context.c \
- $(srcdir)/g_accept_sec_context.c \
- $(srcdir)/g_process_context.c \
- $(srcdir)/g_delete_sec_context.c \
- $(srcdir)/g_imp_sec_context.c \
- $(srcdir)/g_exp_sec_context.c \
- $(srcdir)/g_context_time.c \
- $(srcdir)/g_sign.c \
- $(srcdir)/g_verify.c \
- $(srcdir)/g_seal.c \
- $(srcdir)/g_unseal.c \
- $(srcdir)/g_dsp_status.c \
- $(srcdir)/g_indicate_mechs.c \
- $(srcdir)/g_compare_name.c \
- $(srcdir)/g_dsp_name.c \
- $(srcdir)/g_imp_name.c \
- $(srcdir)/g_rel_name.c \
- $(srcdir)/g_rel_buffer.c \
- $(srcdir)/g_rel_oid_set.c \
- $(srcdir)/g_oid_ops.c \
- $(srcdir)/g_inq_cred.c \
- $(srcdir)/g_inq_context.c \
- $(srcdir)/g_inq_names.c \
- $(srcdir)/g_initialize.c \
- $(srcdir)/g_glue.c \
- $(srcdir)/gssd_pname_to_uid.c \
- $(srcdir)/gen_oids.c \
- $(srcdir)/oid_ops.c \
- $(srcdir)/g_mechname.c
-
-OBJS = $(OUTPRE)g_acquire_cred.$(OBJEXT) \
- $(OUTPRE)g_rel_cred.$(OBJEXT) \
- $(OUTPRE)g_init_sec_context.$(OBJEXT) \
- $(OUTPRE)g_accept_sec_context.$(OBJEXT) \
- $(OUTPRE)g_process_context.$(OBJEXT) \
- $(OUTPRE)g_delete_sec_context.$(OBJEXT) \
- $(OUTPRE)g_imp_sec_context.$(OBJEXT) \
- $(OUTPRE)g_exp_sec_context.$(OBJEXT) \
- $(OUTPRE)g_context_time.$(OBJEXT) \
- $(OUTPRE)g_sign.$(OBJEXT) \
- $(OUTPRE)g_verify.$(OBJEXT) \
- $(OUTPRE)g_seal.$(OBJEXT) \
- $(OUTPRE)g_unseal.$(OBJEXT) \
- $(OUTPRE)g_dsp_status.$(OBJEXT) \
- $(OUTPRE)g_indicate_mechs.$(OBJEXT) \
- $(OUTPRE)g_compare_name.$(OBJEXT) \
- $(OUTPRE)g_dsp_name.$(OBJEXT) \
- $(OUTPRE)g_imp_name.$(OBJEXT) \
- $(OUTPRE)g_rel_name.$(OBJEXT) \
- $(OUTPRE)g_rel_buffer.$(OBJEXT) \
- $(OUTPRE)g_rel_oid_set.$(OBJEXT) \
- $(OUTPRE)g_oid_ops.$(OBJEXT) \
- $(OUTPRE)g_inq_cred.$(OBJEXT) \
- $(OUTPRE)g_inq_context.$(OBJEXT) \
- $(OUTPRE)g_inq_names.$(OBJEXT) \
- $(OUTPRE)g_initialize.$(OBJEXT) \
- $(OUTPRE)g_glue.$(OBJEXT) \
- $(OUTPRE)gssd_pname_to_uid.$(OBJEXT) \
- $(OUTPRE)gen_oids.$(OBJEXT) \
- $(OUTPRE)oid_ops.$(OBJEXT) \
- $(OUTPRE)g_mechname.$(OBJEXT)
+SRCS = \
+ $(srcdir)/g_accept_sec_context.c \
+ $(srcdir)/g_acquire_cred.c \
+ $(srcdir)/g_canon_name.c \
+ $(srcdir)/g_compare_name.c \
+ $(srcdir)/g_context_time.c \
+ $(srcdir)/g_delete_sec_context.c \
+ $(srcdir)/g_dsp_name.c \
+ $(srcdir)/g_dsp_status.c \
+ $(srcdir)/g_dup_name.c \
+ $(srcdir)/g_exp_sec_context.c \
+ $(srcdir)/g_export_name.c \
+ $(srcdir)/g_glue.c \
+ $(srcdir)/g_imp_name.c \
+ $(srcdir)/g_imp_sec_context.c \
+ $(srcdir)/g_init_sec_context.c \
+ $(srcdir)/g_initialize.c \
+ $(srcdir)/g_inq_context.c \
+ $(srcdir)/g_inq_cred.c \
+ $(srcdir)/g_inq_names.c \
+ $(srcdir)/g_mechname.c \
+ $(srcdir)/g_oid_ops.c \
+ $(srcdir)/g_process_context.c \
+ $(srcdir)/g_rel_buffer.c \
+ $(srcdir)/g_rel_cred.c \
+ $(srcdir)/g_rel_name.c \
+ $(srcdir)/g_rel_oid_set.c \
+ $(srcdir)/g_seal.c \
+ $(srcdir)/g_sign.c \
+ $(srcdir)/g_store_cred.c \
+ $(srcdir)/g_unseal.c \
+ $(srcdir)/g_userok.c \
+ $(srcdir)/g_utils.c \
+ $(srcdir)/g_verify.c \
+ $(srcdir)/gssd_pname_to_uid.c \
+ $(srcdir)/oid_ops.c
+
+STLIBOBJS = \
+ g_accept_sec_context.o \
+ g_acquire_cred.o \
+ g_canon_name.o \
+ g_compare_name.o \
+ g_context_time.o \
+ g_delete_sec_context.o \
+ g_dsp_name.o \
+ g_dsp_status.o \
+ g_dup_name.o \
+ g_exp_sec_context.o \
+ g_export_name.o \
+ g_glue.o \
+ g_imp_name.o \
+ g_imp_sec_context.o \
+ g_init_sec_context.o \
+ g_initialize.o \
+ g_inq_context.o \
+ g_inq_cred.o \
+ g_inq_names.o \
+ g_mechname.o \
+ g_oid_ops.o \
+ g_process_context.o \
+ g_rel_buffer.o \
+ g_rel_cred.o \
+ g_rel_name.o \
+ g_rel_oid_set.o \
+ g_seal.o \
+ g_sign.o \
+ g_store_cred.o \
+ g_unseal.o \
+ g_userok.o \
+ g_utils.o \
+ g_verify.o \
+ gssd_pname_to_uid.o \
+ oid_ops.o
EHDRDIR= $(BUILDTOP)$(S)include$(S)gssapi
EXPORTED_HEADERS = mechglue.h
-all:: all-$(WHAT)
-
-all-unix:: shared includes $(OBJS)
-
-all-windows:: includes $(OBJS)
- if not exist $(EHDRDIR)\nul mkdir $(EHDRDIR)
- copy mechglue.h $(EHDRDIR)
-
-shared:
- mkdir shared
+all-unix:: all-libobjs
-libgssapi.$(STEXT): $(OBJS)
- $(RM) $@
- $(ARADD) $@ $(OBJS)
- $(RANLIB) $@
-
-
-#libgssapi.$(LIBEXT): $(OBJS)
-# $(ARCHIVE) $@ $(OBJS)
-# $(RANLIB) $@
-
-clean:: clean-$(WHAT)
-
-clean-unix::
- $(RM) shared/*
-
-clean-windows::
- $(RM) $(EHDRDIR)\gssapi.h $(EHDRDIR)\gssapi_generic.h
- if exist $(EHDRDIR)\nul rmdir $(EHDRDIR)
+clean-unix:: clean-libobjs
# Krb5InstallHeaders($(EXPORTED_HEADERS), $(KRB5_INCDIR)/krb5)
install::
done
includes::
+
+# @libobj_frag@
-/* #ident "@(#)gss_accept_sec_context.c 1.19 95/08/07 SMI" */
+/* #pragma ident "@(#)g_accept_sec_context.c 1.19 04/02/23 SMI" */
/*
* Copyright 1996 by Sun Microsystems, Inc.
output_token,
ret_flags,
time_rec,
- delegated_cred_handle)
+ d_cred)
OM_uint32 * minor_status;
gss_ctx_id_t * context_handle;
gss_buffer_t output_token;
OM_uint32 * ret_flags;
OM_uint32 * time_rec;
-gss_cred_id_t * delegated_cred_handle;
+gss_cred_id_t * d_cred;
{
OM_uint32 status, temp_status, temp_minor_status;
gss_union_ctx_id_t union_ctx_id;
gss_union_cred_t union_cred;
gss_cred_id_t input_cred_handle = GSS_C_NO_CREDENTIAL;
- gss_name_t internal_name;
+ gss_cred_id_t tmp_d_cred = GSS_C_NO_CREDENTIAL;
+ gss_name_t internal_name = GSS_C_NO_NAME;
+ gss_name_t tmp_src_name = GSS_C_NO_NAME;
gss_OID_desc token_mech_type_desc;
gss_OID token_mech_type = &token_mech_type_desc;
gss_mechanism mech;
- gss_initialize();
+ /* check parameters first */
+ if (minor_status == NULL)
+ return (GSS_S_CALL_INACCESSIBLE_WRITE);
+ *minor_status = 0;
+
+ if (context_handle == NULL || output_token == NULL)
+ return (GSS_S_CALL_INACCESSIBLE_WRITE);
+
+ /* clear optional fields */
+ output_token->value = NULL;
+ output_token->length = 0;
+ if (src_name)
+ *src_name = NULL;
- if (context_handle == NULL)
- return GSS_S_NO_CONTEXT;
+ if (mech_type)
+ *mech_type = NULL;
+ if (d_cred)
+ *d_cred = NULL;
/*
* if context_handle is GSS_C_NO_CONTEXT, allocate a union context
* descriptor to hold the mech type information as well as the
if(*context_handle == GSS_C_NO_CONTEXT) {
+ if (GSS_EMPTY_BUFFER(input_token_buffer))
+ return (GSS_S_CALL_INACCESSIBLE_READ);
+
/* Get the token mech type */
status = __gss_get_mech_type(token_mech_type, input_token_buffer);
if (status)
status = GSS_S_FAILURE;
union_ctx_id = (gss_union_ctx_id_t)
malloc(sizeof(gss_union_ctx_id_desc));
- if (!union_ctx_id) {
- *minor_status = ENOMEM;
- goto error_out;
- }
+ if (!union_ctx_id)
+ return (GSS_S_FAILURE);
- union_ctx_id->mech_type = (gss_OID) malloc(sizeof(gss_OID_desc));
- if (!union_ctx_id->mech_type) {
- *minor_status = ENOMEM;
- goto error_out;
+ union_ctx_id->internal_ctx_id = GSS_C_NO_CONTEXT;
+ status = generic_gss_copy_oid(&temp_minor_status,
+ token_mech_type,
+ &union_ctx_id->mech_type);
+ if (status != GSS_S_COMPLETE) {
+ free(union_ctx_id);
+ return (status);
}
-
- union_ctx_id->mech_type->elements = (void *)
- malloc(token_mech_type->length);
- if (!union_ctx_id->mech_type->elements) {
- *minor_status = ENOMEM;
- goto error_out;
- }
-
- union_ctx_id->mech_type->length = token_mech_type->length;
- memcpy(union_ctx_id->mech_type->elements,
- token_mech_type->elements,
- token_mech_type->length);
- /* copy the supplied context handle */
-
- union_ctx_id->internal_ctx_id = *context_handle;
+ /* set the new context handle to caller's data */
+ *context_handle = (gss_ctx_id_t)union_ctx_id;
} else {
- union_ctx_id = *context_handle;
+ union_ctx_id = (gss_union_ctx_id_t)*context_handle;
token_mech_type = union_ctx_id->mech_type;
}
output_token,
ret_flags,
time_rec,
- delegated_cred_handle);
+ d_cred ? &tmp_d_cred : NULL);
/* If there's more work to do, keep going... */
if (status == GSS_S_CONTINUE_NEEDED)
* then call gss_import_name() to create
* the union name struct cast to src_name
*/
- if (src_name != NULL && status == GSS_S_COMPLETE) {
+ if (internal_name != NULL) {
temp_status = __gss_convert_name_to_union_name(
- &temp_minor_status, mech, internal_name, src_name);
+ &temp_minor_status, mech,
+ internal_name, &tmp_src_name);
if (temp_status != GSS_S_COMPLETE) {
- if (minor_status)
- *minor_status = temp_minor_status;
- gss_release_buffer(&temp_minor_status, output_token);
- __gss_release_internal_name(&temp_minor_status,
- &mech->mech_type, &internal_name);
+ *minor_status = temp_minor_status;
+ if (output_token->length)
+ (void) gss_release_buffer(&temp_minor_status,
+ output_token);
+ if (internal_name != GSS_C_NO_NAME)
+ mech->gss_release_name(
+ mech->context,
+ &temp_minor_status,
+ &internal_name);
return (temp_status);
}
+ if (src_name != NULL) {
+ *src_name = tmp_src_name;
+ }
+ } else if (src_name != NULL) {
+ *src_name = GSS_C_NO_NAME;
+ }
+
+ /* Ensure we're returning correct creds format */
+ if ((ret_flags && GSS_C_DELEG_FLAG) &&
+ tmp_d_cred != GSS_C_NO_CREDENTIAL) {
+ gss_union_cred_t d_u_cred = NULL;
+
+ d_u_cred = malloc(sizeof (gss_union_cred_desc));
+ if (d_u_cred == NULL) {
+ status = GSS_S_FAILURE;
+ goto error_out;
+ }
+ (void) memset(d_u_cred, 0,
+ sizeof (gss_union_cred_desc));
+
+ d_u_cred->count = 1;
+
+ status = generic_gss_copy_oid(&temp_minor_status,
+ token_mech_type,
+ &d_u_cred->mechs_array);
+
+ if (status != GSS_S_COMPLETE) {
+ free(d_u_cred);
+ goto error_out;
+ }
+
+ d_u_cred->cred_array = malloc(sizeof (gss_cred_id_t));
+ if (d_u_cred->cred_array != NULL) {
+ d_u_cred->cred_array[0] = tmp_d_cred;
+ } else {
+ free(d_u_cred);
+ status = GSS_S_FAILURE;
+ goto error_out;
+ }
+
+ if (status != GSS_S_COMPLETE) {
+ free(d_u_cred->cred_array);
+ free(d_u_cred);
+ goto error_out;
+ }
+
+ internal_name = GSS_C_NO_NAME;
+
+ d_u_cred->auxinfo.creation_time = time(0);
+ d_u_cred->auxinfo.time_rec = 0;
+
+ if (mech->gss_inquire_cred) {
+ status = mech->gss_inquire_cred(mech->context,
+ minor_status,
+ tmp_d_cred,
+ &internal_name,
+ &d_u_cred->auxinfo.time_rec,
+ &d_u_cred->auxinfo.cred_usage,
+ NULL);
+ }
+
+ if (internal_name != NULL) {
+ temp_status = __gss_convert_name_to_union_name(
+ &temp_minor_status, mech,
+ internal_name, &tmp_src_name);
+ if (temp_status != GSS_S_COMPLETE) {
+ *minor_status = temp_minor_status;
+ if (output_token->length)
+ (void) gss_release_buffer(
+ &temp_minor_status,
+ output_token);
+ free(d_u_cred->cred_array);
+ free(d_u_cred);
+ return (temp_status);
+ }
+ }
+
+ if (tmp_src_name != NULL) {
+ status = gss_display_name(
+ &temp_minor_status,
+ tmp_src_name,
+ &d_u_cred->auxinfo.name,
+ &d_u_cred->auxinfo.name_type);
+ }
+
+ *d_cred = (gss_cred_id_t)d_u_cred;
}
- if(*context_handle == GSS_C_NO_CONTEXT)
- *context_handle = (gss_ctx_id_t *) union_ctx_id;
+ if (src_name == NULL && tmp_src_name != NULL)
+ (void) gss_release_name(&temp_minor_status,
+ &tmp_src_name);
+ return (status);
+ } else {
- return(status);
+ status = GSS_S_BAD_MECH;
}
- return(GSS_S_BAD_MECH);
-
error_out:
if (union_ctx_id) {
if (union_ctx_id->mech_type) {
if (union_ctx_id->mech_type->elements)
free(union_ctx_id->mech_type->elements);
free(union_ctx_id->mech_type);
+ *context_handle = GSS_C_NO_CONTEXT;
}
free(union_ctx_id);
}
+
+ if (output_token->length)
+ (void) gss_release_buffer(&temp_minor_status, output_token);
+
+ if (src_name)
+ *src_name = GSS_C_NO_NAME;
+
+ if (tmp_src_name != GSS_C_NO_NAME)
+ (void) gss_release_buffer(&temp_minor_status,
+ (gss_buffer_t)tmp_src_name);
+
return (status);
}
-/* #ident "@(#)gss_acquire_cred.c 1.19 95/08/07 SMI" */
+/* #pragma ident "@(#)g_acquire_cred.c 1.22 04/02/23 SMI" */
/*
* Copyright 1996 by Sun Microsystems, Inc.
#include <errno.h>
#include <time.h>
-#define g_OID_equal(o1,o2) \
- (((o1)->length == (o2)->length) && \
- (memcmp((o1)->elements,(o2)->elements,(int) (o1)->length) == 0))
-
static gss_OID_set
-create_actual_mechs(creds)
- gss_union_cred_t creds;
+create_actual_mechs(mechs_array, count)
+ const gss_OID mechs_array;
+ int count;
{
gss_OID_set actual_mechs;
int i;
+ OM_uint32 minor;
actual_mechs = (gss_OID_set) malloc(sizeof(gss_OID_set_desc));
if (!actual_mechs)
return NULL;
actual_mechs->elements = (gss_OID)
- malloc(sizeof(gss_OID_desc) * creds->count);
+ malloc(sizeof (gss_OID_desc) * count);
if (!actual_mechs->elements) {
free(actual_mechs);
return NULL;
}
- actual_mechs->count = creds->count;
+ actual_mechs->count = 0;
- for (i=0; i < creds->count; i++) {
- actual_mechs->elements[i].length = creds->mechs_array[i].length;
+ for (i = 0; i < count; i++) {
actual_mechs->elements[i].elements = (void *)
- malloc(creds->mechs_array[i].length);
- memcpy(actual_mechs->elements[i].elements,
- creds->mechs_array[i].elements, creds->mechs_array[i].length);
+ malloc(mechs_array[i].length);
+ if (actual_mechs->elements[i].elements == NULL) {
+ (void) gss_release_oid_set(&minor, &actual_mechs);
+ return (NULL);
+ }
+ g_OID_copy(&actual_mechs->elements[i], &mechs_array[i]);
+ actual_mechs->count++;
}
return actual_mechs;
OM_uint32 * time_rec;
{
- OM_uint32 status, temp_minor_status, temp_time_rec = ~0;
- unsigned int i, j, creds_acquired = 0;
- int k;
- gss_union_name_t union_name;
- gss_name_t internal_name;
- gss_union_cred_t creds;
- gss_OID_set_desc default_OID_set;
- gss_OID_desc default_OID;
- gss_OID specific_mech_type = 0;
- gss_mechanism mech;
-
- /*
- * This struct is used to keep track of which mech_types are
- * actually available and to store the credentials returned
- * from them by each mechanism specific gss_acquire_cred() call.
- * The results are used to construct the final union_cred
- * structure returned by the glue layer gss_acquire_cred() call
- * and the actual_mechs gss_OID_set returned.
- */
-
- struct creds_returned {
- unsigned char available;
- gss_cred_id_t cred;
- } *creds_returned;
+ OM_uint32 major = GSS_S_FAILURE;
+ OM_uint32 initTimeOut, acceptTimeOut, outTime = GSS_C_INDEFINITE;
+ gss_OID_set_desc default_OID_set;
+ gss_OID_set mechs;
+ gss_OID_desc default_OID;
+ gss_mechanism mech;
+ int i;
+ gss_union_cred_t creds;
+
+ /* start by checking parameters */
+ if (!minor_status)
+ return (GSS_S_CALL_INACCESSIBLE_WRITE);
+ *minor_status = 0;
- gss_initialize();
+ if (!output_cred_handle)
+ return (GSS_S_CALL_INACCESSIBLE_WRITE | GSS_S_NO_CRED);
- /* Set this to NULL for now */
+ *output_cred_handle = GSS_C_NO_CREDENTIAL;
+ /* Set output parameters to NULL for now */
if (actual_mechs)
*actual_mechs = GSS_C_NULL_OID_SET;
- if (minor_status)
- *minor_status = 0;
-
- /* No need to continue if we don't have a place to store the creds */
- if (output_cred_handle == NULL)
- return GSS_S_COMPLETE;
-
- /* get desired_name cast as a union_name type */
-
- union_name = (gss_union_name_t) desired_name;
+ if (time_rec)
+ *time_rec = 0;
- if (union_name)
- specific_mech_type = union_name->mech_type;
-
/*
* if desired_mechs equals GSS_C_NULL_OID_SET, then pick an
- * appropriate default.
+ * appropriate default. We use the first mechanism in the
+ * mechansim list as the default. This set is created with
+ * statics thus needs not be freed
*/
if(desired_mechs == GSS_C_NULL_OID_SET) {
- /*
- * If union_name->mech_type is NULL then we get the default
- * mechanism; otherwise, we get the mechanism for the
- * mechanism-specific name.
- */
- mech = __gss_get_mechanism(specific_mech_type);
+ mech = __gss_get_mechanism(NULL);
if (mech == NULL)
return (GSS_S_BAD_MECH);
-
- desired_mechs = &default_OID_set;
- default_OID_set.count = 1 ;
+
+ mechs = &default_OID_set;
+ default_OID_set.count = 1;
default_OID_set.elements = &default_OID;
default_OID.length = mech->mech_type.length;
default_OID.elements = mech->mech_type.elements;
- }
-
- /*
- * Now allocate the creds returned array. There is one element
- * for each member of the desired_mechs argument.
- */
-
- creds_returned = (struct creds_returned *)
- malloc(sizeof(struct creds_returned) * desired_mechs->count);
-
- /*
- * For each requested mechanism in desired_mechs, determine if it
- * is supported. If so, mark the corresponding element in
- * creds_returned->available as 1 and call the mechanism
- * specific gss_acquire_cred(), placing the returned cred in
- * creds_returned->cred. If not, mark creds_returned->available as
- * 0.
- */
- status = GSS_S_BAD_MECH;
- for (j=0; j < desired_mechs->count; j++) {
- creds_returned[j].available = 0;
-
- mech = __gss_get_mechanism (&desired_mechs->elements[j]);
- if (!mech || !mech->gss_acquire_cred)
- continue;
- /*
- * If this is a mechanism-specific name, then only use the
- * mechanism of the name.
- */
- if (specific_mech_type && !g_OID_equal(specific_mech_type,
- &mech->mech_type))
- continue;
- /*
- * If this is not a mechanism-specific name, then we need to
- * do an import the external name in union_name first.
- */
- if (union_name == 0)
- internal_name = (gss_name_t) 0;
- else if (!union_name->mech_type) {
- if (__gss_import_internal_name(&temp_minor_status,
- &mech->mech_type,
- union_name, &internal_name)) {
- continue;
+ } else
+ mechs = desired_mechs;
+
+ if (mechs->count == 0)
+ return (GSS_S_BAD_MECH);
+
+ /* allocate the output credential structure */
+ creds = (gss_union_cred_t)malloc(sizeof (gss_union_cred_desc));
+ if (creds == NULL)
+ return (GSS_S_FAILURE);
+
+ /* initialize to 0s */
+ (void) memset(creds, 0, sizeof (gss_union_cred_desc));
+
+ /* for each requested mech attempt to obtain a credential */
+ for (i = 0; i < mechs->count; i++) {
+ major = gss_add_cred(minor_status, (gss_cred_id_t)creds,
+ desired_name,
+ &mechs->elements[i],
+ cred_usage, time_req, time_req, NULL,
+ NULL, &initTimeOut, &acceptTimeOut);
+ if (major == GSS_S_COMPLETE) {
+ /* update the credential's time */
+ if (cred_usage == GSS_C_ACCEPT) {
+ if (outTime > acceptTimeOut)
+ outTime = acceptTimeOut;
+ } else if (cred_usage == GSS_C_INITIATE) {
+ if (outTime > initTimeOut)
+ outTime = initTimeOut;
+ } else {
+ /*
+ * time_rec is the lesser of the
+ * init/accept times
+ */
+ if (initTimeOut > acceptTimeOut)
+ outTime = (outTime > acceptTimeOut) ?
+ acceptTimeOut : outTime;
+ else
+ outTime = (outTime > initTimeOut) ?
+ initTimeOut : outTime;
}
- } else
- internal_name = union_name->mech_name;
-
- status = mech->gss_acquire_cred(mech->context, minor_status,
- internal_name, time_req,
- desired_mechs, cred_usage,
- &creds_returned[j].cred,
- NULL, &temp_time_rec);
-
- /* Release the internal name, if allocated above */
- if (union_name && !union_name->mech_type) {
- (void) __gss_release_internal_name(&temp_minor_status,
- &mech->mech_type,
- &internal_name);
}
+ } /* for */
- if (status != GSS_S_COMPLETE)
- continue;
-
- /*
- * Add this into the creds_returned structure, if we got
- * a good credential for this mechanism.
- */
- if (time_rec) {
- *time_rec = *time_rec > temp_time_rec ? temp_time_rec : *time_rec;
- temp_time_rec = *time_rec;
- }
-
- creds_returned[j].available = 1;
- creds_acquired++;
-
- /*
- * If union_name is set, then we're done. Continue, and
- * declare success. Otherwise, if do an inquire credentials
- * from the first mechanism that succeeds and use that as the
- * union name.
- */
- if (union_name)
- continue;
-
- status = mech->gss_inquire_cred(mech->context, &temp_minor_status,
- creds_returned[j].cred,
- &internal_name, 0, 0, 0);
- if (status) {
- /* Should never happen */
- creds_returned[j].available = 0;
- creds_acquired--;
- if (mech->gss_release_cred)
- mech->gss_release_cred(mech->context, minor_status,
- &creds_returned[j].cred);
- continue;
- }
-
- status = __gss_convert_name_to_union_name(&temp_minor_status, mech,
- internal_name,
- (gss_name_t *) &union_name);
+ /* ensure that we have at least one credential element */
+ if (creds->count < 1) {
+ free(creds);
+ return (major);
}
-
- /*
- * Now allocate the creds struct, which will be cast as a gss_cred_id_t
- * and returned in the output_cred_handle argument. If there were
- * no credentials found, return an error. Also, allocate the
- * actual_mechs data.
- */
- if (creds_acquired == 0) {
- free (creds_returned);
- return (status);
- }
-
- creds = (gss_union_cred_t) malloc(sizeof(gss_union_cred_desc));
-
- creds->count = creds_acquired;
-
- creds->mechs_array = (gss_OID)
- malloc(sizeof(gss_OID_desc) * creds_acquired);
-
- creds->cred_array = (gss_cred_id_t *)
- malloc(sizeof(gss_cred_id_t) * creds_acquired);
-
- if(actual_mechs != NULL) {
- *actual_mechs = (gss_OID_set) malloc(sizeof(gss_OID_set_desc));
-
- (*actual_mechs)->count = creds_acquired;
- (*actual_mechs)->elements = (gss_OID)
- malloc(sizeof(gss_OID_desc) * creds_acquired);
- }
-
- /*
- * copy the mechanisms found and their allocated credentials into the
- * creds structure. At the same time, build up the actual_mechs
- * data.
- */
-
- j = 0;
-
- for (i=0; i<desired_mechs->count; i++) {
- if(creds_returned[i].available) {
-
- creds->mechs_array[j].length =
- desired_mechs->elements[i].length;
- creds->mechs_array[j].elements = (void *)
- malloc(desired_mechs->elements[i].length);
- memcpy(creds->mechs_array[j].elements,
- desired_mechs->elements[i].elements,
- desired_mechs->elements[i].length);
- creds->cred_array[j] = creds_returned[i].cred;
- if (actual_mechs) {
- (*actual_mechs)->elements[j].length =
- desired_mechs->elements[i].length;
- (*actual_mechs)->elements[j].elements = (void *)
- malloc(desired_mechs->elements[i].length);
- memcpy((*actual_mechs)->elements[j].elements,
- desired_mechs->elements[i].elements,
- desired_mechs->elements[i].length);
- }
- j++;
- }
- }
-
- /* free the creds_returned struct, since we are done with it. */
-
- free(creds_returned);
-
- /* record the information needed for gss_inquire_cred() */
-
- creds->auxinfo.creation_time = time(0);
- creds->auxinfo.time_rec = temp_time_rec;
- creds->auxinfo.cred_usage = cred_usage;
-
/*
- * we can't just record the internal name, desired_name, since
- * it may be destroyed between now and the time gss_inquire_cred()
- * is called. So we must record the printable name in a
- * gss_buffer_t, calling gss_display_name() to fill it in. When
- * gss_inquire_name() is called, we must then call gss_import_name()
- * to get the internal name that is required at that point.
+ * fill in output parameters
+ * setup the actual mechs output parameter
*/
- if (desired_name) {
- status = gss_display_name(&temp_minor_status, desired_name,
- &creds->auxinfo.name,
- &creds->auxinfo.name_type);
- if (status) {
- status = GSS_S_BAD_NAME;
- goto error_out;
+ if (actual_mechs != NULL) {
+ if ((*actual_mechs = create_actual_mechs(creds->mechs_array,
+ creds->count)) == NULL) {
+ (void) gss_release_cred(minor_status,
+ (gss_cred_id_t *)&creds);
+ *minor_status = 0;
+ return (GSS_S_FAILURE);
}
- } else {
- status = gss_display_name(&temp_minor_status, union_name,
- &creds->auxinfo.name,
- &creds->auxinfo.name_type);
- if (status) {
- status = GSS_S_BAD_NAME;
- goto error_out;
- }
- }
-
- *output_cred_handle = (gss_cred_id_t) creds;
- return(GSS_S_COMPLETE);
-
-error_out:
- for (k=0; k < creds->count; k++) {
- free(creds->mechs_array[k].elements);
- if (actual_mechs)
- free((*actual_mechs)->elements[k].elements);
}
-
- if (actual_mechs) {
- free((*actual_mechs)->elements);
- free(*actual_mechs);
- *actual_mechs = GSS_C_NULL_OID_SET;
- }
- free(creds->cred_array);
- free(creds->mechs_array);
- free(creds);
-
- return(status);
+
+ if (time_rec)
+ *time_rec = outTime;
+
+
+ *output_cred_handle = (gss_cred_id_t)creds;
+ return (GSS_S_COMPLETE);
}
/* V2 KRB5_CALLCONV */
OM_uint32 time_req, time_rec;
gss_union_name_t union_name;
gss_union_cred_t new_union_cred, union_cred;
- gss_name_t internal_name;
+ gss_name_t internal_name = GSS_C_NO_NAME;
+ gss_name_t allocated_name = GSS_C_NO_NAME;
gss_mechanism mech;
- gss_cred_id_t cred;
- gss_OID new_mechs_array;
- gss_cred_id_t * new_cred_array;
+ gss_cred_id_t cred = NULL;
+ gss_OID new_mechs_array = NULL;
+ gss_cred_id_t * new_cred_array = NULL;
+
+ /* check input parameters */
+ if (minor_status == NULL)
+ return (GSS_S_CALL_INACCESSIBLE_WRITE);
+ *minor_status = 0;
+
+ if (input_cred_handle == GSS_C_NO_CREDENTIAL &&
+ output_cred_handle == NULL)
+ return (GSS_S_CALL_INACCESSIBLE_WRITE | GSS_S_NO_CRED);
+
+ if (output_cred_handle)
+ *output_cred_handle = GSS_C_NO_CREDENTIAL;
- if (input_cred_handle == GSS_C_NO_CREDENTIAL)
- return GSS_S_NO_CRED;
+ if (actual_mechs)
+ *actual_mechs = NULL;
+
+ if (acceptor_time_rec)
+ *acceptor_time_rec = 0;
- union_cred = (gss_union_cred_t) input_cred_handle;
+ if (initiator_time_rec)
+ *initiator_time_rec = 0;
mech = __gss_get_mechanism(desired_mech);
if (!mech)
return GSS_S_BAD_MECH;
+ else if (!mech->gss_acquire_cred)
+ return (GSS_S_UNAVAILABLE);
- if (__gss_get_mechanism_cred(union_cred, desired_mech) !=
- GSS_C_NO_CREDENTIAL)
- return GSS_S_DUPLICATE_ELEMENT;
+ if (input_cred_handle == GSS_C_NO_CREDENTIAL) {
+ union_cred = malloc(sizeof (gss_union_cred_desc));
+ if (union_cred == NULL)
+ return (GSS_S_FAILURE);
- union_name = (gss_union_name_t) desired_name;
- if (union_name->mech_type) {
- if (!g_OID_equal(desired_mech, union_name->mech_type))
- return GSS_S_BAD_NAMETYPE;
- internal_name = union_name->mech_name;
+ (void) memset(union_cred, 0, sizeof (gss_union_cred_desc));
+
+ /* for default credentials we will use GSS_C_NO_NAME */
+ internal_name = GSS_C_NO_NAME;
} else {
- if (__gss_import_internal_name(minor_status, desired_mech,
- union_name, &internal_name))
- return (GSS_S_BAD_NAME);
+ union_cred = (gss_union_cred_t)input_cred_handle;
+ if (__gss_get_mechanism_cred(union_cred, desired_mech) !=
+ GSS_C_NO_CREDENTIAL)
+ return (GSS_S_DUPLICATE_ELEMENT);
+
+ /* may need to create a mechanism specific name */
+ if (desired_name) {
+ union_name = (gss_union_name_t)desired_name;
+ if (union_name->mech_type &&
+ g_OID_equal(union_name->mech_type,
+ &mech->mech_type))
+ internal_name = union_name->mech_name;
+ else {
+ if (__gss_import_internal_name(minor_status,
+ &mech->mech_type, union_name,
+ &allocated_name) != GSS_S_COMPLETE)
+ return (GSS_S_BAD_NAME);
+ internal_name = allocated_name;
+ }
+ }
}
+
if (cred_usage == GSS_C_ACCEPT)
time_req = acceptor_time_req;
else if (cred_usage == GSS_C_INITIATE)
internal_name, time_req,
GSS_C_NULL_OID_SET, cred_usage,
&cred, NULL, &time_rec);
+
if (status != GSS_S_COMPLETE)
goto errout;
+ /* may need to set credential auxinfo strucutre */
+ if (union_cred->auxinfo.creation_time == 0) {
+ union_cred->auxinfo.creation_time = time(NULL);
+ union_cred->auxinfo.time_rec = time_rec;
+ union_cred->auxinfo.cred_usage = cred_usage;
+
+ /*
+ * we must set the name; if name is not supplied
+ * we must do inquire cred to get it
+ */
+ if (internal_name == NULL) {
+ if (mech->gss_inquire_cred == NULL ||
+ ((status = mech->gss_inquire_cred(
+ mech->context,
+ &temp_minor_status, cred,
+ &allocated_name, NULL, NULL,
+ NULL)) != GSS_S_COMPLETE))
+ goto errout;
+ internal_name = allocated_name;
+ }
+
+ if ((status = mech->gss_display_name(mech->context,
+ &temp_minor_status, internal_name,
+ &union_cred->auxinfo.name,
+ &union_cred->auxinfo.name_type)) !=
+ GSS_S_COMPLETE)
+ goto errout;
+ }
+
+ /* now add the new credential elements */
new_mechs_array = (gss_OID)
- malloc(sizeof(gss_OID_desc) * (union_cred->count+1));
-
+ malloc(sizeof (gss_OID_desc) * (union_cred->count+1));
+
new_cred_array = (gss_cred_id_t *)
- malloc(sizeof(gss_cred_id_t) * (union_cred->count+1));
+ malloc(sizeof (gss_cred_id_t) * (union_cred->count+1));
if (!new_mechs_array || !new_cred_array) {
- *minor_status = ENOMEM;
status = GSS_S_FAILURE;
goto errout;
}
-
if (acceptor_time_rec)
if (cred_usage == GSS_C_ACCEPT || cred_usage == GSS_C_BOTH)
*acceptor_time_rec = time_rec;
*initiator_time_rec = time_rec;
/*
- * OK, expand the mechanism array in the union credentials
- * (Look for the union label...)
+ * OK, expand the mechanism array and the credential array
*/
- memcpy(new_mechs_array, union_cred->mechs_array,
- sizeof(gss_OID_desc) * union_cred->count);
- memcpy(new_cred_array, union_cred->cred_array,
- sizeof(gss_cred_id_t) * union_cred->count);
-
+ (void) memcpy(new_mechs_array, union_cred->mechs_array,
+ sizeof (gss_OID_desc) * union_cred->count);
+ (void) memcpy(new_cred_array, union_cred->cred_array,
+ sizeof (gss_cred_id_t) * union_cred->count);
+
new_cred_array[union_cred->count] = cred;
- new_mechs_array[union_cred->count].length = desired_mech->length;
- new_mechs_array[union_cred->count].elements = malloc(desired_mech->length);
- if (!new_mechs_array[union_cred->count].elements) {
- *minor_status = ENOMEM;
+ if ((new_mechs_array[union_cred->count].elements =
+ malloc(mech->mech_type.length)) == NULL)
goto errout;
+
+ g_OID_copy(&new_mechs_array[union_cred->count],
+ &mech->mech_type);
+
+ if (actual_mechs) {
+ *actual_mechs = create_actual_mechs(new_mechs_array,
+ union_cred->count + 1);
+ if (*actual_mechs == NULL) {
+ free(new_mechs_array[union_cred->count].elements);
+ goto errout;
+ }
}
- memcpy(new_mechs_array[union_cred->count].elements, desired_mech->elements,
- desired_mech->length);
if (output_cred_handle == NULL) {
free(union_cred->mechs_array);
free(union_cred->cred_array);
new_union_cred = union_cred;
} else {
- new_union_cred = malloc(sizeof(gss_union_cred_desc));
+ new_union_cred = malloc(sizeof (gss_union_cred_desc));
if (new_union_cred == NULL) {
- *minor_status = ENOMEM;
+ free(new_mechs_array[union_cred->count].elements);
goto errout;
}
*new_union_cred = *union_cred;
- *output_cred_handle = new_union_cred;
+ *output_cred_handle = (gss_cred_id_t)new_union_cred;
}
+
new_union_cred->mechs_array = new_mechs_array;
new_union_cred->cred_array = new_cred_array;
new_union_cred->count++;
- new_mechs_array = 0;
- new_cred_array = 0;
- if (actual_mechs)
- *actual_mechs = create_actual_mechs(new_union_cred);
-
- status = GSS_S_COMPLETE;
-
+ /* We're done with the internal name. Free it if we allocated it. */
+
+ if (allocated_name)
+ (void) __gss_release_internal_name(&temp_minor_status,
+ &mech->mech_type,
+ &allocated_name);
+
+ return (GSS_S_COMPLETE);
+
errout:
if (new_mechs_array)
free(new_mechs_array);
if (new_cred_array)
free(new_cred_array);
- if (!union_name->mech_type) {
+
+ if (cred != NULL && mech->gss_release_cred)
+ mech->gss_release_cred(mech->context,
+ &temp_minor_status, &cred);
+
+ if (allocated_name)
(void) __gss_release_internal_name(&temp_minor_status,
- desired_mech, &internal_name);
+ &mech->mech_type,
+ &allocated_name);
+
+ if (input_cred_handle == GSS_C_NO_CREDENTIAL && union_cred) {
+ if (union_cred->auxinfo.name.value)
+ free(union_cred->auxinfo.name.value);
+ free(union_cred);
}
- return(status);
+ return (status);
}
--- /dev/null
+/*
+ * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/* #pragma ident "@(#)g_canon_name.c 1.15 04/02/23 SMI" */
+
+/*
+ * routine gss_canonicalize_name
+ *
+ * This routine is used to produce a mechanism specific
+ * representation of name that has been previously
+ * imported with gss_import_name. The routine uses the mechanism
+ * specific implementation of gss_import_name to implement this
+ * function.
+ *
+ * We allow a NULL output_name, in which case we modify the
+ * input_name to include the mechanism specific name.
+ */
+
+#include <mglueP.h>
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#include <string.h>
+#include <errno.h>
+
+OM_uint32
+gss_canonicalize_name(minor_status,
+ input_name,
+ mech_type,
+ output_name)
+OM_uint32 *minor_status;
+const gss_name_t input_name;
+const gss_OID mech_type;
+gss_name_t *output_name;
+{
+ gss_union_name_t in_union, out_union = NULL, dest_union = NULL;
+ OM_uint32 major_status = GSS_S_FAILURE;
+
+ if (minor_status == NULL)
+ return (GSS_S_CALL_INACCESSIBLE_WRITE);
+
+ *minor_status = 0;
+
+ if (output_name)
+ *output_name = 0;
+
+ /* check the input parameters */
+ if (input_name == NULL || mech_type == GSS_C_NULL_OID)
+ return (GSS_S_CALL_INACCESSIBLE_READ);
+
+ in_union = (gss_union_name_t)input_name;
+ /*
+ * If the caller wants to reuse the name, and the name has already
+ * been converted, then there is nothing for us to do.
+ */
+ if (!output_name && in_union->mech_type &&
+ g_OID_equal(in_union->mech_type, mech_type))
+ return (GSS_S_COMPLETE);
+
+ /* ok, then we need to do something - start by creating data struct */
+ if (output_name) {
+ out_union =
+ (gss_union_name_t)malloc(sizeof (gss_union_name_desc));
+ if (!out_union)
+ goto allocation_failure;
+
+ out_union->mech_type = 0;
+ out_union->mech_name = 0;
+ out_union->name_type = 0;
+ out_union->external_name = 0;
+
+ /* Allocate the buffer for the user specified representation */
+ if (__gss_create_copy_buffer(in_union->external_name,
+ &out_union->external_name, 1))
+ goto allocation_failure;
+
+ if (in_union->name_type != GSS_C_NULL_OID) {
+ if ((major_status = generic_gss_copy_oid(minor_status,
+ in_union->name_type, &out_union->name_type)))
+ goto allocation_failure;
+ }
+
+ }
+
+ /*
+ * might need to delete any old mechanism names if we are
+ * reusing the buffer.
+ */
+ if (!output_name) {
+ if (in_union->mech_type) {
+ (void) __gss_release_internal_name(minor_status,
+ in_union->mech_type,
+ &in_union->mech_name);
+ (void) gss_release_oid(minor_status,
+ &in_union->mech_type);
+ in_union->mech_type = 0;
+ }
+ dest_union = in_union;
+ } else
+ dest_union = out_union;
+
+ /* now let's create the new mech name */
+ if (major_status = generic_gss_copy_oid(minor_status, mech_type,
+ &dest_union->mech_type))
+ goto allocation_failure;
+
+ if (major_status =
+ __gss_import_internal_name(minor_status, mech_type,
+ dest_union,
+ &dest_union->mech_name))
+ goto allocation_failure;
+
+ if (output_name)
+ *output_name = (gss_name_t)dest_union;
+
+ return (GSS_S_COMPLETE);
+
+allocation_failure:
+ /* do not delete the src name external name format */
+ if (output_name) {
+ if (out_union->external_name) {
+ if (out_union->external_name->value)
+ free(out_union->external_name->value);
+ free(out_union->external_name);
+ }
+ if (out_union->name_type)
+ (void) gss_release_oid(minor_status,
+ &out_union->name_type);
+
+ dest_union = out_union;
+ } else
+ dest_union = in_union;
+
+ /*
+ * delete the partially created mech specific name
+ * applies for both src and dest which ever is being used for output
+ */
+
+ if (dest_union->mech_name) {
+ (void) __gss_release_internal_name(minor_status,
+ dest_union->mech_type,
+ &dest_union->mech_name);
+ }
+
+ if (dest_union->mech_type)
+ (void) gss_release_oid(minor_status, &dest_union->mech_type);
+
+
+ if (output_name)
+ free(out_union);
+
+ return (major_status);
+} /********** gss_canonicalize_name ********/
-/* #ident "@(#)gss_compare_name.c 1.13 95/08/02 SMI" */
+/* #pragma ident "@(#)g_compare_name.c 1.16 04/02/23 SMI" */
/*
* Copyright 1996 by Sun Microsystems, Inc.
#endif
#include <string.h>
-#define g_OID_equal(o1,o2) \
- (((o1)->length == (o2)->length) && \
- (memcmp((o1)->elements,(o2)->elements,(int) (o1)->length) == 0))
-
OM_uint32 KRB5_CALLCONV
gss_compare_name (minor_status,
name1,
gss_mechanism mech;
gss_name_t internal_name;
- gss_initialize();
+ if (minor_status == NULL)
+ return (GSS_S_CALL_INACCESSIBLE_WRITE);
+ *minor_status = 0;
- if (name1 == 0 || name2 == 0) {
- if (name_equal)
- *name_equal = 0;
- return GSS_S_BAD_NAME;
- }
+ if (name1 == 0 || name2 == 0)
+ return (GSS_S_CALL_INACCESSIBLE_READ | GSS_S_BAD_NAME);
+
+ if (name_equal == NULL)
+ return (GSS_S_CALL_INACCESSIBLE_WRITE);
union_name1 = (gss_union_name_t) name1;
union_name2 = (gss_union_name_t) name2;
if (!mech)
return (GSS_S_BAD_MECH);
if (!mech->gss_compare_name)
- return (GSS_S_BAD_BINDINGS);
+ return (GSS_S_UNAVAILABLE);
}
- if (name_equal == NULL)
- return GSS_S_COMPLETE;
-
*name_equal = 0; /* Default to *not* equal.... */
/*
* gss_import_name().
*/
if (!union_name1->mech_type && !union_name2->mech_type) {
- if (!g_OID_equal(union_name1->name_type, union_name2->name_type))
+ /*
+ * Second case, first sub-case... one name has null
+ * name_type, the other doesn't.
+ *
+ * Not knowing a mech_type we can't import the name with
+ * null name_type so we can't compare.
+ */
+ if ((union_name1->name_type == GSS_C_NULL_OID &&
+ union_name2->name_type != GSS_C_NULL_OID) ||
+ (union_name1->name_type != GSS_C_NULL_OID &&
+ union_name2->name_type == GSS_C_NULL_OID))
+ return (GSS_S_COMPLETE);
+ /*
+ * Second case, second sub-case... both names have
+ * name_types, but they are different.
+ */
+ if ((union_name1->name_type != GSS_C_NULL_OID &&
+ union_name2->name_type != GSS_C_NULL_OID) &&
+ !g_OID_equal(union_name1->name_type,
+ union_name2->name_type))
return (GSS_S_COMPLETE);
+ /*
+ * Second case, third sub-case... both names have equal
+ * name_types (and both have no mech_types) so we just
+ * compare the external_names.
+ */
if ((union_name1->external_name->length !=
union_name2->external_name->length) ||
(memcmp(union_name1->external_name->value,
union_name2,
&internal_name);
if (major_status != GSS_S_COMPLETE)
- return (GSS_S_COMPLETE);
+ return (GSS_S_COMPLETE); /* return complete, but not equal */
+
major_status = mech->gss_compare_name(mech->context, minor_status,
union_name1->mech_name,
internal_name, name_equal);
-/* #ident "@(#)gss_context_time.c 1.8 95/08/07 SMI" */
+/* #pragma ident "@(#)g_context_time.c 1.12 98/01/22 SMI" */
/*
* Copyright 1996 by Sun Microsystems, Inc.
gss_union_ctx_id_t ctx;
gss_mechanism mech;
- gss_initialize();
+ if (minor_status == NULL)
+ return (GSS_S_CALL_INACCESSIBLE_WRITE);
+ *minor_status = 0;
+
+ if (time_rec == NULL)
+ return (GSS_S_CALL_INACCESSIBLE_WRITE);
if (context_handle == GSS_C_NO_CONTEXT)
- return GSS_S_NO_CONTEXT;
-
+ return (GSS_S_CALL_INACCESSIBLE_READ | GSS_S_NO_CONTEXT);
+
/*
* select the approprate underlying mechanism routine and
* call it.
ctx->internal_ctx_id,
time_rec);
else
- status = GSS_S_BAD_BINDINGS;
+ status = GSS_S_UNAVAILABLE;
return(status);
}
- return(GSS_S_NO_CONTEXT);
+ return (GSS_S_BAD_MECH);
}
-/* #ident "@(#)gss_delete_sec_context.c 1.10 95/08/07 SMI" */
+/* #pragma ident "@(#)g_delete_sec_context.c 1.11 97/11/09 SMI" */
/*
* Copyright 1996 by Sun Microsystems, Inc.
gss_union_ctx_id_t ctx;
gss_mechanism mech;
- gss_initialize();
+ if (minor_status == NULL)
+ return (GSS_S_CALL_INACCESSIBLE_WRITE);
+
+ if (output_token != GSS_C_NO_BUFFER) {
+ output_token->length = 0;
+ output_token->value = NULL;
+ }
/* if the context_handle is Null, return NO_CONTEXT error */
-
if(context_handle == NULL || *context_handle == GSS_C_NO_CONTEXT)
- return(GSS_S_NO_CONTEXT);
-
+ return (GSS_S_CALL_INACCESSIBLE_READ | GSS_S_NO_CONTEXT);
+
/*
* select the approprate underlying mechanism routine and
* call it.
&ctx->internal_ctx_id,
output_token);
else
- status = GSS_S_BAD_BINDINGS;
+ status = GSS_S_UNAVAILABLE;
/* now free up the space for the union context structure */
-
free(ctx->mech_type->elements);
free(ctx->mech_type);
free(*context_handle);
return(status);
}
-
- return(GSS_S_NO_CONTEXT);
+
+ return (GSS_S_BAD_MECH);
}
-/* #ident "@(#)g_dsp_name.c 1.2 96/02/06 SMI" */
+/* #pragma ident "@(#)g_dsp_name.c 1.13 04/02/23 SMI" */
/*
* Copyright 1996 by Sun Microsystems, Inc.
OM_uint32 major_status;
gss_union_name_t union_name;
+ if (minor_status == NULL)
+ return (GSS_S_CALL_INACCESSIBLE_WRITE);
+ *minor_status = 0;
+
if (input_name == 0)
- return GSS_S_BAD_NAME;
+ return (GSS_S_CALL_INACCESSIBLE_READ | GSS_S_BAD_NAME);
+
+ if (output_name_buffer == NULL)
+ return (GSS_S_CALL_INACCESSIBLE_WRITE);
+
+ if (output_name_type)
+ *output_name_type = NULL;
union_name = (gss_union_name_t) input_name;
* name into the output_name_buffer and point the output_name_type
* to the name_type component of union_name
*/
- if (output_name_type != NULL) {
+ if (output_name_type != NULL &&
+ union_name->name_type != GSS_C_NULL_OID) {
major_status = generic_gss_copy_oid(minor_status,
union_name->name_type,
output_name_type);
- if (major_status)
+ if (major_status != GSS_S_COMPLETE)
return (major_status);
}
-
- if (output_name_buffer != NULL) {
- output_name_buffer->length = union_name->external_name->length;
-
- output_name_buffer->value =
- (void *) malloc(output_name_buffer->length);
- memcpy(output_name_buffer->value,
- union_name->external_name->value,
- output_name_buffer->length);
+ if ((output_name_buffer->value =
+ malloc(union_name->external_name->length + 1)) == NULL) {
+ if (output_name_type && *output_name_type != GSS_C_NULL_OID) {
+ (void) generic_gss_release_oid(minor_status,
+ output_name_type);
+ *output_name_type = NULL;
+ }
+ return (GSS_S_FAILURE);
}
-
- if (minor_status)
- *minor_status = 0;
+ output_name_buffer->length = union_name->external_name->length;
+ (void) memcpy(output_name_buffer->value,
+ union_name->external_name->value,
+ union_name->external_name->length);
+ ((char *)output_name_buffer->value)[output_name_buffer->length] = '\0';
return(GSS_S_COMPLETE);
}
-/* #ident "@(#)gss_display_status.c 1.8 95/08/07 SMI" */
+/* #pragma ident "@(#)g_dsp_status.c 1.17 04/02/23 SMI" */
/*
* Copyright 1996 by Sun Microsystems, Inc.
#include "mglueP.h"
#include <stdio.h>
-#ifdef HAVE_STDLIB_H
#include <stdlib.h>
-#endif
+#include <string.h>
+
+/* local function */
+static OM_uint32 displayMajor(OM_uint32, OM_uint32 *, gss_buffer_t);
OM_uint32 KRB5_CALLCONV
gss_display_status (minor_status,
gss_buffer_t status_string;
{
- OM_uint32 status;
gss_OID mech_type = (gss_OID) req_mech_type;
gss_mechanism mech;
- gss_initialize();
+ /* check the input parameters */
+ if (!minor_status)
+ return (GSS_S_CALL_INACCESSIBLE_WRITE);
+
+ *minor_status = 0;
+
+ if (!message_context || status_string == NULL)
+ return (GSS_S_CALL_INACCESSIBLE_WRITE);
+
+ status_string->length = 0;
+ status_string->value = NULL;
+
+ /* we handle major status codes, and the mechs do the minor */
+ if (status_type == GSS_C_GSS_CODE)
+ return (displayMajor(status_value, message_context,
+ status_string));
/*
- * select the approprate underlying mechanism routine and
+ * must be the minor status - let mechs do the work
+ * select the appropriate underlying mechanism routine and
* call it.
*/
mech = __gss_get_mechanism (mech_type);
- if (mech == NULL)
+ if (mech && mech->gss_display_status) {
+ if (mech_type == GSS_C_NULL_OID)
+ mech_type = &mech->mech_type;
+
+ return (mech->gss_display_status(mech->context, minor_status,
+ status_value, status_type, mech_type,
+ message_context, status_string));
+ }
+
+ if (!mech)
return (GSS_S_BAD_MECH);
- if (mech_type == GSS_C_NULL_OID)
- mech_type = &mech->mech_type;
-
- if (mech->gss_display_status)
- status = mech->gss_display_status(
- mech->context,
- minor_status,
- status_value,
- status_type,
- mech_type,
- message_context,
- status_string);
- else
- status = GSS_S_BAD_BINDINGS;
-
- return(status);
+ return (GSS_S_UNAVAILABLE);
}
+
+/*
+ * function to map the major error codes
+ * it uses case statements so that the strings could be wrapped by gettext
+ * msgCtxt is interpreted as:
+ * 0 - first call
+ * 1 - routine error
+ * >= 2 - the supplementary error code bit shifted by 1
+ */
+static OM_uint32
+displayMajor(status, msgCtxt, outStr)
+OM_uint32 status;
+OM_uint32 *msgCtxt;
+gss_buffer_t outStr;
+{
+ OM_uint32 oneVal, mask = 0x1, currErr;
+ char *errStr = NULL;
+ int i, haveErr = 0;
+
+ /* take care of the success value first */
+ if (status == GSS_S_COMPLETE)
+ errStr = "The routine completed successfully";
+ else if (*msgCtxt == 0 && (oneVal = GSS_CALLING_ERROR(status))) {
+ switch (oneVal) {
+ case GSS_S_CALL_INACCESSIBLE_READ:
+ errStr = "A required input parameter"
+ " could not be read";
+ break;
+
+ case GSS_S_CALL_INACCESSIBLE_WRITE:
+ errStr = "A required output parameter"
+ " could not be written";
+ break;
+
+ case GSS_S_CALL_BAD_STRUCTURE:
+ errStr = "A parameter was malformed";
+ break;
+
+ default:
+ errStr = "An invalid status code was supplied";
+ break;
+ }
+
+ /* we now need to determine new value of msgCtxt */
+ if (GSS_ROUTINE_ERROR(status))
+ *msgCtxt = 1;
+ else if ((oneVal = GSS_SUPPLEMENTARY_INFO(status)) != 0)
+ *msgCtxt = (OM_uint32)(oneVal << 1);
+ else
+ *msgCtxt = 0;
+
+ } else if ((*msgCtxt == 0 || *msgCtxt == 1) &&
+ (oneVal = GSS_ROUTINE_ERROR(status))) {
+ switch (oneVal) {
+ case GSS_S_BAD_MECH:
+ errStr = "An unsupported mechanism"
+ " was requested";
+ break;
+
+ case GSS_S_BAD_NAME:
+ errStr = "An invalid name was supplied";
+ break;
+
+ case GSS_S_BAD_NAMETYPE:
+ errStr = "A supplied name was of an"
+ " unsupported type";
+ break;
+
+ case GSS_S_BAD_BINDINGS:
+ errStr = "Incorrect channel bindings"
+ " were supplied";
+ break;
+
+ case GSS_S_BAD_SIG: /* same as GSS_S_BAD_MIC: */
+ errStr = "A token had an invalid Message"
+ " Integrity Check (MIC)";
+ break;
+
+ case GSS_S_NO_CRED:
+ errStr = "No credentials were supplied, or the"
+ " credentials were unavailable or"
+ " inaccessible";
+ break;
+
+ case GSS_S_NO_CONTEXT:
+ errStr = "No context has been established";
+ break;
+
+ case GSS_S_DEFECTIVE_TOKEN:
+ errStr = "Invalid token was supplied";
+ break;
+
+ case GSS_S_DEFECTIVE_CREDENTIAL:
+ errStr = "Invalid credential was supplied";
+ break;
+
+ case GSS_S_CREDENTIALS_EXPIRED:
+ errStr = "The referenced credential has"
+ " expired";
+ break;
+
+ case GSS_S_CONTEXT_EXPIRED:
+ errStr = "The referenced context has expired";
+ break;
+
+ case GSS_S_FAILURE:
+ errStr = "Unspecified GSS failure. Minor code"
+ " may provide more information";
+ break;
+
+ case GSS_S_BAD_QOP:
+ errStr = "The quality-of-protection (QOP) "
+ "requested could not be provided";
+ break;
+
+ case GSS_S_UNAUTHORIZED:
+ errStr = "The operation is forbidden by local"
+ " security policy";
+ break;
+
+ case GSS_S_UNAVAILABLE:
+ errStr = "The operation or option is not"
+ " available or unsupported";
+ break;
+
+ case GSS_S_DUPLICATE_ELEMENT:
+ errStr = "The requested credential element"
+ " already exists";
+ break;
+
+ case GSS_S_NAME_NOT_MN:
+ errStr = "The provided name was not mechanism"
+ " specific (MN)";
+ break;
+
+ case GSS_S_BAD_STATUS:
+ default:
+ errStr = "An invalid status code was supplied";
+ }
+
+ /* we must determine if the caller should call us again */
+ if ((oneVal = GSS_SUPPLEMENTARY_INFO(status)) != 0)
+ *msgCtxt = (OM_uint32)(oneVal << 1);
+ else
+ *msgCtxt = 0;
+
+ } else if ((*msgCtxt == 0 || *msgCtxt >= 2) &&
+ (oneVal = GSS_SUPPLEMENTARY_INFO(status))) {
+ /*
+ * if msgCtxt is not 0, then it should encode
+ * the supplementary error code we should be printing
+ */
+ if (*msgCtxt >= 2)
+ oneVal = (OM_uint32) (*msgCtxt) >> 1;
+ else
+ oneVal = GSS_SUPPLEMENTARY_INFO(status);
+
+ /* we display the errors LSB first */
+ for (i = 0; i < 16; i++) {
+ if (oneVal & mask) {
+ haveErr = 1;
+ break;
+ }
+ mask <<= 1;
+ }
+
+ /* isolate the bit or if not found set to illegal value */
+ if (haveErr)
+ currErr = oneVal & mask;
+ else
+ currErr = 1 << 17; /* illegal value */
+
+ switch (currErr) {
+ case GSS_S_CONTINUE_NEEDED:
+ errStr = "The routine must be called again to"
+ " complete its function";
+ break;
+
+ case GSS_S_DUPLICATE_TOKEN:
+ errStr = "The token was a duplicate of an"
+ " earlier token";
+ break;
+
+ case GSS_S_OLD_TOKEN:
+ errStr = "The token's validity period"
+ " has expired";
+ break;
+
+ case GSS_S_UNSEQ_TOKEN:
+ errStr = "A later token has already been"
+ " processed";
+ break;
+
+ case GSS_S_GAP_TOKEN:
+ errStr = "An expected per-message token was"
+ " not received";
+ break;
+
+ default:
+ errStr = "An invalid status code was supplied";
+ }
+
+ /*
+ * we must check if there is any other supplementary errors
+ * if found, then turn off current bit, and store next value
+ * in msgCtxt shifted by 1 bit
+ */
+ if (!haveErr)
+ *msgCtxt = 0;
+ else if (GSS_SUPPLEMENTARY_INFO(oneVal) ^ mask)
+ *msgCtxt = (OM_uint32)
+ ((GSS_SUPPLEMENTARY_INFO(oneVal) ^ mask) << 1);
+ else
+ *msgCtxt = 0;
+ }
+
+ if (errStr == NULL)
+ errStr = "An invalid status code was supplied";
+
+ /* now copy the status code and return to caller */
+ outStr->length = strlen(errStr);
+ outStr->value = malloc((size_t)outStr->length+1);
+ if (outStr->value == NULL) {
+ outStr->length = 0;
+ return (GSS_S_FAILURE);
+ }
+
+ (void) strcpy((char *)outStr->value, errStr);
+ return (GSS_S_COMPLETE);
+} /* displayMajor */
--- /dev/null
+/*
+ * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/* #pragma ident "@(#)g_dup_name.c 1.14 04/02/23 SMI" */
+
+/*
+ * routine gss_duplicate_name
+ *
+ * This routine does not rely on mechanism implementation of this
+ * name, but instead uses mechanism specific gss_import_name routine.
+ */
+
+#include <mglueP.h>
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#include <string.h>
+#include <errno.h>
+
+OM_uint32
+gss_duplicate_name(minor_status,
+ src_name,
+ dest_name)
+OM_uint32 *minor_status;
+const gss_name_t src_name;
+gss_name_t *dest_name;
+{
+ gss_union_name_t src_union, dest_union;
+ OM_uint32 major_status = GSS_S_FAILURE;
+
+
+ if (!minor_status)
+ return (GSS_S_CALL_INACCESSIBLE_WRITE);
+
+ *minor_status = 0;
+
+ /* if output_name is NULL, simply return */
+ if (dest_name == NULL)
+ return (GSS_S_CALL_INACCESSIBLE_WRITE | GSS_S_BAD_NAME);
+
+ *dest_name = 0;
+
+ if (src_name == NULL)
+ return (GSS_S_CALL_INACCESSIBLE_READ);
+
+ src_union = (gss_union_name_t)src_name;
+
+ /*
+ * First create the union name struct that will hold the external
+ * name and the name type.
+ */
+ dest_union = (gss_union_name_t)malloc(sizeof (gss_union_name_desc));
+ if (!dest_union)
+ goto allocation_failure;
+
+ dest_union->mech_type = 0;
+ dest_union->mech_name = 0;
+ dest_union->name_type = 0;
+ dest_union->external_name = 0;
+
+ /* Now copy the external representaion */
+ if (__gss_create_copy_buffer(src_union->external_name,
+ &dest_union->external_name, 0))
+ goto allocation_failure;
+
+ if (src_union->name_type != GSS_C_NULL_OID) {
+ major_status = generic_gss_copy_oid(minor_status,
+ src_union->name_type,
+ &dest_union->name_type);
+ if (major_status != GSS_S_COMPLETE)
+ goto allocation_failure;
+ }
+
+ /*
+ * See if source name is mechanim specific, if so then need to import it
+ */
+ if (src_union->mech_type) {
+ major_status = generic_gss_copy_oid(minor_status,
+ src_union->mech_type,
+ &dest_union->mech_type);
+ if (major_status != GSS_S_COMPLETE)
+ goto allocation_failure;
+
+ major_status = __gss_import_internal_name(minor_status,
+ dest_union->mech_type,
+ dest_union,
+ &dest_union->mech_name);
+ if (major_status != GSS_S_COMPLETE)
+ goto allocation_failure;
+ }
+
+
+ *dest_name = (gss_name_t)dest_union;
+ return (GSS_S_COMPLETE);
+
+allocation_failure:
+ if (dest_union) {
+ if (dest_union->external_name) {
+ if (dest_union->external_name->value)
+ free(dest_union->external_name->value);
+ free(dest_union->external_name);
+ }
+ if (dest_union->name_type)
+ (void) generic_gss_release_oid(minor_status,
+ &dest_union->name_type);
+ if (dest_union->mech_name)
+ (void) __gss_release_internal_name(minor_status,
+ dest_union->mech_type,
+ &dest_union->mech_name);
+ if (dest_union->mech_type)
+ (void) generic_gss_release_oid(minor_status,
+ &dest_union->mech_type);
+ free(dest_union);
+ }
+ return (major_status);
+} /* gss_duplicate_name */
-/* #ident "@(#)g_exp_sec_context.c 1.2 96/01/18 SMI" */
+/* #pragma ident "@(#)g_exp_sec_context.c 1.14 04/02/23 SMI" */
/*
* Copyright 1996 by Sun Microsystems, Inc.
{
OM_uint32 status;
- size_t length;
+ OM_uint32 length;
gss_union_ctx_id_t ctx;
gss_mechanism mech;
gss_buffer_desc token;
char *buf;
- gss_initialize();
+ if (minor_status == NULL)
+ return (GSS_S_CALL_INACCESSIBLE_WRITE);
+ *minor_status = 0;
if (context_handle == NULL || *context_handle == GSS_C_NO_CONTEXT)
- return GSS_S_NO_CONTEXT;
+ return (GSS_S_CALL_INACCESSIBLE_READ | GSS_S_NO_CONTEXT);
+
+ if (interprocess_token == NULL)
+ return (GSS_S_CALL_INACCESSIBLE_READ);
/*
* select the approprate underlying mechanism routine and
if (!mech)
return GSS_S_BAD_MECH;
if (!mech->gss_export_sec_context)
- return GSS_S_BAD_BINDINGS;
+ return (GSS_S_UNAVAILABLE);
status = mech->gss_export_sec_context(mech->context, minor_status,
&ctx->internal_ctx_id, &token);
interprocess_token->value = malloc(length);
if (interprocess_token->value == 0) {
(void) gss_release_buffer(minor_status, &token);
- *minor_status = ENOMEM;
return (GSS_S_FAILURE);
}
buf = interprocess_token->value;
--- /dev/null
+/*
+ * Copyright (c) 1996,1997, by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+/* #pragma ident "@(#)g_export_name.c 1.11 00/07/17 SMI" */
+
+/*
+ * glue routine gss_export_name
+ *
+ * Will either call the mechanism defined gss_export_name, or if one is
+ * not defined will call a generic_gss_export_name routine.
+ */
+
+#include <mglueP.h>
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#include <string.h>
+#include <errno.h>
+
+OM_uint32
+gss_export_name(minor_status,
+ input_name,
+ exported_name)
+OM_uint32 * minor_status;
+const gss_name_t input_name;
+gss_buffer_t exported_name;
+{
+ gss_union_name_t union_name;
+
+
+ if (minor_status)
+ *minor_status = 0;
+
+ /* check out parameter */
+ if (!exported_name)
+ return (GSS_S_CALL_INACCESSIBLE_WRITE);
+
+ exported_name->value = NULL;
+ exported_name->length = 0;
+
+ /* check input parameter */
+ if (!input_name)
+ return (GSS_S_CALL_INACCESSIBLE_READ | GSS_S_BAD_NAME);
+
+ union_name = (gss_union_name_t)input_name;
+
+ /* the name must be in mechanism specific format */
+ if (!union_name->mech_type)
+ return (GSS_S_NAME_NOT_MN);
+
+ return __gss_export_internal_name(minor_status, union_name->mech_type,
+ union_name->mech_name, exported_name);
+}
-/* #ident "@(#)g_glue.c 1.1 96/02/06 SMI" */
+/* #pragma ident "@(#)g_glue.c 1.25 04/02/23 SMI" */
/*
* Copyright 1996 by Sun Microsystems, Inc.
#include <string.h>
#include <errno.h>
-#define g_OID_equal(o1,o2) \
- (((o1)->length == (o2)->length) && \
- (memcmp((o1)->elements,(o2)->elements,(int) (o1)->length) == 0))
+#define MSO_BIT (8*(sizeof (int) - 1)) /* Most significant octet bit */
extern gss_mechanism *__gss_mechs_array;
*/
/*
- * given the mechs_array and a mechanism OID, return the
- * pointer to the mechanism, or NULL if that mechanism is
- * not supported. If the requested OID is NULL, then return
- * the first mechanism.
+ * get_der_length: Givin a pointer to a buffer that contains a DER encoded
+ * length, decode the length updating the buffer to point to the character
+ * after the DER encoding. The parameter bytes will point to the number of
+ * bytes that made up the DER encoding of the length originally pointed to
+ * by the buffer. Note we return -1 on error.
*/
+int
+get_der_length(unsigned char **buf, unsigned int buf_len, unsigned int *bytes)
+{
+ /* p points to the beginning of the buffer */
+ unsigned char *p = *buf;
+ int length, new_length;
+ int octets;
+
+ if (buf_len < 1)
+ return (-1);
+
+ /* We should have at least one byte */
+ *bytes = 1;
+
+ /*
+ * If the High order bit is not set then the length is just the value
+ * of *p.
+ */
+ if (*p < 128) {
+ *buf = p+1; /* Advance the buffer */
+ return (*p); /* return the length */
+ }
+
+ /*
+ * if the High order bit is set, then the low order bits represent
+ * the number of bytes that contain the DER encoding of the length.
+ */
+
+ octets = *p++ & 0x7f;
+ *bytes += octets;
-gss_mechanism __gss_get_mechanism (type)
- gss_OID type;
+ /* See if the supplied buffer contains enough bytes for the length. */
+ if (octets > buf_len - 1)
+ return (-1);
+
+ /*
+ * Calculate a multibyte length. The length is encoded as an
+ * unsigned integer base 256.
+ */
+ for (length = 0; octets; octets--) {
+ new_length = (length << 8) + *p++;
+ if (new_length < length) /* overflow */
+ return (-1);
+ length = new_length;
+ }
+
+ *buf = p; /* Advance the buffer */
+
+ return (length);
+}
+
+/*
+ * der_length_size: Return the number of bytes to encode a given length.
+ */
+unsigned int
+der_length_size(unsigned int len)
{
- int i;
+ int i;
- if (type == GSS_C_NULL_OID)
- return (__gss_mechs_array[0]);
+ if (len < 128)
+ return (1);
- for (i=0; __gss_mechs_array[i]->mech_type.length != 0; i++) {
- if ((__gss_mechs_array[i]->mech_type.length == type->length) &&
- (memcmp (__gss_mechs_array[i]->mech_type.elements, type->elements,
- type->length) == 0)) {
+ for (i = 0; len; i++) {
+ len >>= 8;
+ }
+
+ return (i+1);
+}
+
+/*
+ * put_der_length: Encode the supplied length into the buffer pointed to
+ * by buf. max_length represents the maximum length of the buffer pointed
+ * to by buff. We will advance buf to point to the character after the newly
+ * DER encoded length. We return 0 on success or -l it the length cannot
+ * be encoded in max_len characters.
+ */
+int
+put_der_length(unsigned int length, unsigned char **buf, unsigned int max_len)
+{
+ unsigned char *s = *buf, *p;
+ unsigned int buf_len = 0;
+ int i, first;
+
+ /* Oops */
+ if (buf == 0 || max_len < 1)
+ return (-1);
+
+ /* Single byte is the length */
+ if (length < 128) {
+ *s++ = length;
+ *buf = s;
+ return (0);
+ }
+
+ /* First byte contains the number of octets */
+ p = s + 1;
+
+ /* Running total of the DER encoding length */
+ buf_len = 0;
- return (__gss_mechs_array[i]);
+ /*
+ * Encode MSB first. We do the encoding by setting a shift
+ * factor to MSO_BIT (24 for 32 bit words) and then shifting the length
+ * by the factor. We then encode the resulting low order byte.
+ * We subtract 8 from the shift factor and repeat to ecnode the next
+ * byte. We stop when the shift factor is zero or we've run out of
+ * buffer to encode into.
+ */
+ first = 0;
+ for (i = MSO_BIT; i >= 0 && buf_len <= max_len; i -= 8) {
+ unsigned int v;
+ v = (length >> i) & 0xff;
+ if ((v) || first) {
+ buf_len += 1;
+ *p++ = v;
+ first = 1;
}
}
- return NULL;
+ if (i >= 0) /* buffer overflow */
+ return (-1);
+
+ /*
+ * We go back now and set the first byte to be the length with
+ * the high order bit set.
+ */
+ *s = buf_len | 0x80;
+ *buf = p;
+
+ return (0);
}
* The routine fills in the OID value and returns an error as necessary.
*/
- if (token == NULL)
+ if (OID == NULL)
+ return (GSS_S_CALL_INACCESSIBLE_WRITE);
+
+ if ((token == NULL) || (token->value == NULL))
return (GSS_S_DEFECTIVE_TOKEN);
/* Skip past the APP/Sequnce byte and the token length */
if (*(buffer_ptr++) != 0x60)
return (GSS_S_DEFECTIVE_TOKEN);
length = *buffer_ptr++;
+
+ /* check if token length is null */
+ if (length == 0)
+ return (GSS_S_DEFECTIVE_TOKEN);
+
if (length & 0x80) {
if ((length & 0x7f) > 4)
return (GSS_S_DEFECTIVE_TOKEN);
union_name->name_type,
internal_name);
else
- status = GSS_S_BAD_BINDINGS;
+ status = GSS_S_UNAVAILABLE;
return (status);
}
return (GSS_S_BAD_MECH);
}
+OM_uint32 __gss_export_internal_name(minor_status, mech_type,
+ internal_name, name_buf)
+ OM_uint32 *minor_status;
+ const gss_OID mech_type;
+ const gss_name_t internal_name;
+ gss_buffer_t name_buf;
+{
+ OM_uint32 status;
+ gss_mechanism mech;
+ gss_buffer_desc dispName;
+ gss_OID nameOid;
+ unsigned char *buf = NULL;
+ const unsigned char tokId[] = "\x04\x01";
+ const unsigned int tokIdLen = 2;
+ const int mechOidLenLen = 2, mechOidTagLen = 1, nameLenLen = 4;
+ int mechOidDERLen = 0;
+ int mechOidLen = 0;
+
+ mech = __gss_get_mechanism(mech_type);
+ if (!mech)
+ return (GSS_S_BAD_MECH);
+
+ if (mech->gss_export_name)
+ return (mech->gss_export_name(mech->context,
+ minor_status,
+ internal_name,
+ name_buf));
+
+ /*
+ * if we are here it is because the mechanism does not provide
+ * a gss_export_name so we will use our implementation. We
+ * do required that the mechanism define a gss_display_name.
+ */
+ if (!mech->gss_display_name)
+ return (GSS_S_UNAVAILABLE);
+
+ /*
+ * NOTE: RFC2743 (section 3.2) governs the format of the outer
+ * wrapper of exported names; the mechanisms' specs govern
+ * the format of the inner portion of the exported name
+ * and, for some (e.g., RFC1964, the Kerberos V mech), a
+ * generic default as implemented here will do.
+ *
+ * The outer wrapper of an exported MN is: 2-octet tok Id
+ * (0x0401) + 2-octet network-byte order mech OID length + mech
+ * oid (in DER format, including DER tag and DER length) +
+ * 4-octet network-byte order length of inner portion + inner
+ * portion.
+ *
+ * For the Kerberos V mechanism the inner portion of an exported
+ * MN is the display name string and ignores the name type OID
+ * altogether. And we hope this will be so for any future
+ * mechanisms also, so that factoring name export/import out of
+ * the mech and into libgss pays off.
+ */
+ if ((status = mech->gss_display_name(mech->context,
+ minor_status,
+ internal_name,
+ &dispName,
+ &nameOid))
+ != GSS_S_COMPLETE)
+ return (status);
+
+ /* determine the size of the buffer needed */
+ mechOidDERLen = der_length_size(mech_type->length);
+ name_buf->length = tokIdLen + mechOidLenLen +
+ mechOidTagLen + mechOidDERLen +
+ mech_type->length +
+ nameLenLen + dispName.length;
+ if ((name_buf->value = (void*)malloc(name_buf->length)) ==
+ (void*)NULL) {
+ name_buf->length = 0;
+ (void) gss_release_buffer(&status, &dispName);
+ return (GSS_S_FAILURE);
+ }
+
+ /* now create the name ..... */
+ buf = (unsigned char *)name_buf->value;
+ (void) memset(name_buf->value, 0, name_buf->length);
+ (void) memcpy(buf, tokId, tokIdLen);
+ buf += tokIdLen;
+
+ /* spec allows only 2 bytes for the mech oid length */
+ mechOidLen = mechOidDERLen + mechOidTagLen + mech_type->length;
+ *buf++ = (mechOidLen & 0xFF00) >> 8;
+ *buf++ = (mechOidLen & 0x00FF);
+
+ /*
+ * DER Encoding of mech OID contains OID Tag (0x06), length and
+ * mech OID value
+ */
+ *buf++ = 0x06;
+ if (put_der_length(mech_type->length, &buf,
+ (name_buf->length - tokIdLen -2)) != 0) {
+ name_buf->length = 0;
+ free(name_buf->value);
+ (void) gss_release_buffer(&status, &dispName);
+ return (GSS_S_FAILURE);
+ }
+
+ (void) memcpy(buf, mech_type->elements, mech_type->length);
+ buf += mech_type->length;
+
+ /* spec designates the next 4 bytes for the name length */
+ *buf++ = (dispName.length & 0xFF000000) >> 24;
+ *buf++ = (dispName.length & 0x00FF0000) >> 16;
+ *buf++ = (dispName.length & 0x0000FF00) >> 8;
+ *buf++ = (dispName.length & 0X000000FF);
+
+ /* for the final ingredient - add the name from gss_display_name */
+ (void) memcpy(buf, dispName.value, dispName.length);
+
+ /* release the buffer obtained from gss_display_name */
+ (void) gss_release_buffer(minor_status, &dispName);
+ return (GSS_S_COMPLETE);
+} /* __gss_export_internal_name */
+
OM_uint32 __gss_display_internal_name (minor_status, mech_type, internal_name,
external_name, name_type)
OM_uint32 *minor_status;
external_name,
name_type);
else
- status = GSS_S_BAD_BINDINGS;
+ status = GSS_S_UNAVAILABLE;
return (status);
}
minor_status,
internal_name);
else
- status = GSS_S_BAD_BINDINGS;
+ status = GSS_S_UNAVAILABLE;
return (status);
}
union_name = (gss_union_name_t) malloc (sizeof(gss_union_name_desc));
if (!union_name) {
- *minor_status = ENOMEM;
goto allocation_failure;
}
union_name->mech_type = 0;
union_name->external_name =
(gss_buffer_t) malloc(sizeof(gss_buffer_desc));
if (!union_name->external_name) {
- *minor_status = ENOMEM;
goto allocation_failure;
}
}
if (union_name->name_type)
gss_release_oid(&tmp, &union_name->name_type);
- if (union_name->mech_name)
- __gss_release_internal_name(minor_status, union_name->mech_type,
- &union_name->mech_name);
if (union_name->mech_type)
gss_release_oid(&tmp, &union_name->mech_type);
free(union_name);
}
+ /*
+ * do as the top comment says - since we are now owners of
+ * internal_name, we must clean it up
+ */
+ if (internal_name)
+ (void) __gss_release_internal_name(&tmp, &mech->mech_type,
+ &internal_name);
return (major_status);
}
return GSS_C_NO_CREDENTIAL;
}
-
+/*
+ * Routine to create and copy the gss_buffer_desc structure.
+ * Both space for the structure and the data is allocated.
+ */
+OM_uint32
+__gss_create_copy_buffer(srcBuf, destBuf, addNullChar)
+ const gss_buffer_t srcBuf;
+ gss_buffer_t *destBuf;
+ int addNullChar;
+{
+ gss_buffer_t aBuf;
+ unsigned int len;
+
+ if (destBuf == NULL)
+ return (GSS_S_CALL_INACCESSIBLE_WRITE);
+
+ *destBuf = 0;
+
+ aBuf = (gss_buffer_t)malloc(sizeof (gss_buffer_desc));
+ if (!aBuf)
+ return (GSS_S_FAILURE);
+
+ if (addNullChar)
+ len = srcBuf->length + 1;
+ else
+ len = srcBuf->length;
+
+ if (!(aBuf->value = (void*)malloc(len))) {
+ free(aBuf);
+ return (GSS_S_FAILURE);
+ }
+
+
+ (void) memcpy(aBuf->value, srcBuf->value, srcBuf->length);
+ aBuf->length = srcBuf->length;
+ *destBuf = aBuf;
+
+ /* optionally add a NULL character */
+ if (addNullChar)
+ ((char *)aBuf->value)[aBuf->length] = '\0';
+
+ return (GSS_S_COMPLETE);
+} /* ****** __gss_create_copy_buffer ****** */
-/* #ident "@(#)g_imp_name.c 1.2 96/02/06 SMI" */
+/* #pragma ident "@(#)g_imp_name.c 1.26 04/02/23 SMI" */
/*
* Copyright 1996 by Sun Microsystems, Inc.
#include <string.h>
#include <errno.h>
+/* local function to import GSS_C_EXPORT_NAME names */
+static OM_uint32 importExportName(OM_uint32 *, gss_union_name_t);
+
OM_uint32 KRB5_CALLCONV
gss_import_name(minor_status,
input_name_buffer,
{
gss_union_name_t union_name;
OM_uint32 tmp, major_status = GSS_S_FAILURE;
- gss_OID mech;
- gss_initialize();
+ /* check output parameters */
+ if (!minor_status)
+ return (GSS_S_CALL_INACCESSIBLE_WRITE);
- if (minor_status)
- *minor_status = 0;
+ *minor_status = 0;
- /* if output_name is NULL, simply return */
+ if (GSS_EMPTY_BUFFER(input_name_buffer))
+ return (GSS_S_CALL_INACCESSIBLE_READ);
- if(output_name == NULL)
- return (GSS_S_COMPLETE);
+ if (output_name == NULL)
+ return (GSS_S_CALL_INACCESSIBLE_WRITE);
*output_name = 0;
* First create the union name struct that will hold the external
* name and the name type.
*/
-
union_name = (gss_union_name_t) malloc (sizeof(gss_union_name_desc));
- if (!union_name) {
- *minor_status = ENOMEM;
- goto allocation_failure;
- }
+ if (!union_name)
+ return (GSS_S_FAILURE);
+
union_name->mech_type = 0;
union_name->mech_name = 0;
union_name->name_type = 0;
/*
* All we do here is record the external name and name_type.
* When the name is actually used, the underlying gss_import_name()
- * is called for the appropriate mechanism. Note that the name type
- * is assumed to be constant, so only a pointer to it is stored in
- * union_name
+ * is called for the appropriate mechanism. The exception to this
+ * rule is when the name of GSS_C_NT_EXPORT_NAME type. If that is
+ * the case, then we make it MN in this call.
*/
- union_name->external_name =
- (gss_buffer_t) malloc(sizeof(gss_buffer_desc));
- if (!union_name->external_name) {
- *minor_status = ENOMEM;
- goto allocation_failure;
- }
-
- union_name->external_name->length = input_name_buffer->length;
- /* we malloc length+1 to stick a NULL on the end, just in case */
- /* Note that this NULL is not included in ->length for a reason! */
- union_name->external_name->value =
- (void *) malloc(input_name_buffer->length+1);
- if (!union_name->external_name->value) {
- *minor_status = ENOMEM;
- goto allocation_failure;
+ major_status = __gss_create_copy_buffer(input_name_buffer,
+ &union_name->external_name, 0);
+ if (major_status != GSS_S_COMPLETE) {
+ free(union_name);
+ return (major_status);
}
-
- memcpy(union_name->external_name->value, input_name_buffer->value,
- input_name_buffer->length);
- /* add NULL to end of external_name->value, just in case... */
- ((char *)union_name->external_name->value)
- [input_name_buffer->length] = '\0';
-
- major_status = generic_gss_copy_oid(minor_status, input_name_type,
- &union_name->name_type);
- if (major_status != GSS_S_COMPLETE)
- goto allocation_failure;
+ if (input_name_type != GSS_C_NULL_OID) {
+ major_status = generic_gss_copy_oid(minor_status,
+ input_name_type,
+ &union_name->name_type);
+ if (major_status != GSS_S_COMPLETE)
+ goto allocation_failure;
+ }
/*
- * See if this is a mechanism-specific name. If so, let's import
- * it now so we can get any error messages, and to avoid trouble
- * later...
+ * In MIT Distribution the mechanism is determined from the nametype;
+ * This is not a good idea - first mechanism that supports a given
+ * name type is picked up; later on the caller can request a
+ * different mechanism. So we don't determine the mechanism here. Now
+ * the user level and kernel level import_name routine looks similar
+ * except the kernel routine makes a copy of the nametype structure. We
+ * do however make this an MN for names of GSS_C_NT_EXPORT_NAME type.
*/
- mech = gss_find_mechanism_from_name_type(input_name_type);
- if (mech) {
- major_status = generic_gss_copy_oid(minor_status, mech,
- &union_name->mech_type);
+ if (input_name_type != GSS_C_NULL_OID &&
+ g_OID_equal(input_name_type, GSS_C_NT_EXPORT_NAME)) {
+ major_status = importExportName(minor_status, union_name);
if (major_status != GSS_S_COMPLETE)
goto allocation_failure;
-
- major_status = __gss_import_internal_name(minor_status, mech,
- union_name,
- &union_name->mech_name);
- if (major_status)
- goto allocation_failure;
}
- *output_name = (gss_name_t) union_name;
-
- return(GSS_S_COMPLETE);
+ *output_name = (gss_name_t)union_name;
+ return (GSS_S_COMPLETE);
allocation_failure:
if (union_name) {
}
return (major_status);
}
+
+/*
+ * GSS export name constants
+ */
+static const char *expNameTokId = "\x04\x01";
+static const unsigned int expNameTokIdLen = 2;
+static const unsigned int mechOidLenLen = 2;
+static const unsigned int nameTypeLenLen = 2;
+
+static OM_uint32
+importExportName(minor, unionName)
+ OM_uint32 *minor;
+ gss_union_name_t unionName;
+{
+ gss_OID_desc mechOid;
+ gss_buffer_desc expName;
+ unsigned char *buf;
+ gss_mechanism mech;
+ OM_uint32 major, mechOidLen, nameLen, curLength;
+ unsigned int bytes;
+
+ expName.value = unionName->external_name->value;
+ expName.length = unionName->external_name->length;
+
+ curLength = expNameTokIdLen + mechOidLenLen;
+ if (expName.length < curLength)
+ return (GSS_S_DEFECTIVE_TOKEN);
+
+ buf = (unsigned char *)expName.value;
+ if (memcmp(expNameTokId, buf, expNameTokIdLen) != 0)
+ return (GSS_S_DEFECTIVE_TOKEN);
+
+ buf += expNameTokIdLen;
+
+ /* extract the mechanism oid length */
+ mechOidLen = (*buf++ << 8);
+ mechOidLen |= (*buf++);
+ curLength += mechOidLen;
+ if (expName.length < curLength)
+ return (GSS_S_DEFECTIVE_TOKEN);
+ /*
+ * The mechOid itself is encoded in DER format, OID Tag (0x06)
+ * length and the value of mech_OID
+ */
+ if (*buf++ != 0x06)
+ return (GSS_S_DEFECTIVE_TOKEN);
+
+ /*
+ * mechoid Length is encoded twice; once in 2 bytes as
+ * explained in RFC2743 (under mechanism independent exported
+ * name object format) and once using DER encoding
+ *
+ * We verify both lengths.
+ */
+
+ mechOid.length = get_der_length(&buf,
+ (expName.length - curLength), &bytes);
+ mechOid.elements = (void *)buf;
+
+ /*
+ * 'bytes' is the length of the DER length, '1' is for the DER
+ * tag for OID
+ */
+ if ((bytes + mechOid.length + 1) != mechOidLen)
+ return (GSS_S_DEFECTIVE_TOKEN);
+
+ buf += mechOid.length;
+ if ((mech = __gss_get_mechanism(&mechOid)) == NULL)
+ return (GSS_S_BAD_MECH);
+
+ if (mech->gss_import_name == NULL)
+ return (GSS_S_UNAVAILABLE);
+
+ /*
+ * we must now determine if we should unwrap the name ourselves
+ * or make the mechanism do it - we should only unwrap it
+ * if we create it; so if mech->gss_export_name == NULL, we must
+ * have created it.
+ */
+ if (mech->gss_export_name) {
+ if ((major = mech->gss_import_name(mech->context, minor,
+ &expName, (gss_OID)GSS_C_NT_EXPORT_NAME,
+ &unionName->mech_name)) != GSS_S_COMPLETE ||
+ (major = generic_gss_copy_oid(minor, &mechOid,
+ &unionName->mech_type)) !=
+ GSS_S_COMPLETE) {
+ return (major);
+ }
+ return (major);
+ }
+ /*
+ * we must have exported the name - so we now need to reconstruct it
+ * and call the mechanism to create it
+ *
+ * WARNING: Older versions of __gss_export_internal_name() did
+ * not export names correctly, but now it does. In
+ * order to stay compatible with existing exported
+ * names we must support names exported the broken
+ * way.
+ *
+ * Specifically, __gss_export_internal_name() used to include
+ * the name type OID in the encoding of the exported MN.
+ * Additionally, the Kerberos V mech used to make display names
+ * that included a null terminator which was counted in the
+ * display name gss_buffer_desc.
+ */
+ curLength += 4; /* 4 bytes for name len */
+ if (expName.length < curLength)
+ return (GSS_S_DEFECTIVE_TOKEN);
+
+ /* next 4 bytes in the name are the name length */
+ nameLen = (*buf++) << 24;
+ nameLen |= (*buf++ << 16);
+ nameLen |= (*buf++ << 8);
+ nameLen |= (*buf++);
+
+ /*
+ * we use < here because bad code in rpcsec_gss rounds up exported
+ * name token lengths and pads with nulls, otherwise != would be
+ * appropriate
+ */
+ curLength += nameLen; /* this is the total length */
+ if (expName.length < curLength)
+ return (GSS_S_DEFECTIVE_TOKEN);
+
+ /*
+ * We detect broken exported names here: they always start with
+ * a two-octet network-byte order OID length, which is always
+ * less than 256 bytes, so the first octet of the length is
+ * always '\0', which is not allowed in GSS-API display names
+ * (or never occurs in them anyways). Of course, the OID
+ * shouldn't be there, but it is. After the OID (sans DER tag
+ * and length) there's the name itself, though null-terminated;
+ * this null terminator should also not be there, but it is.
+ */
+ if (nameLen > 0 && *buf == '\0') {
+ OM_uint32 nameTypeLen;
+ /* next two bytes are the name oid */
+ if (nameLen < nameTypeLenLen)
+ return (GSS_S_DEFECTIVE_TOKEN);
+
+ nameLen -= nameTypeLenLen;
+
+ nameTypeLen = (*buf++) << 8;
+ nameTypeLen |= (*buf++);
+
+ if (nameLen < nameTypeLen)
+ return (GSS_S_DEFECTIVE_TOKEN);
+
+ buf += nameTypeLen;
+ nameLen -= nameTypeLen;
+
+ /*
+ * adjust for expected null terminator that should
+ * really not be there
+ */
+ if (nameLen > 0 && *(buf + nameLen - 1) == '\0')
+ nameLen--;
+ }
+
+ /*
+ * Can a name be null? Let the mech decide.
+ *
+ * NOTE: We use GSS_C_NULL_OID as the name type when importing
+ * the unwrapped name. Presumably the exported name had,
+ * prior to being exported been obtained in such a way
+ * that it has been properly perpared ("canonicalized," in
+ * GSS-API terms) accroding to some name type; we cannot
+ * tell what that name type was now, but the name should
+ * need no further preparation other than the lowest
+ * common denominator afforded by the mech to names
+ * imported with GSS_C_NULL_OID. For the Kerberos V mech
+ * this means doing less busywork too (particularly once
+ * IDN is thrown in with Kerberos V extensions).
+ */
+ expName.length = nameLen;
+ expName.value = nameLen ? (void *)buf : NULL;
+ major = mech->gss_import_name(mech->context, minor, &expName,
+ GSS_C_NULL_OID, &unionName->mech_name);
+ if (major != GSS_S_COMPLETE)
+ return (major);
+
+ return (generic_gss_copy_oid(minor, &mechOid, &unionName->mech_type));
+} /* importExportName */
-/* #ident "@(#)g_imp_sec_context.c 1.2 96/01/18 SMI" */
+/* #pragma ident "@(#)g_imp_sec_context.c 1.18 04/02/23 SMI" */
/*
* Copyright 1996 by Sun Microsystems, Inc.
gss_ctx_id_t * context_handle;
{
- size_t length;
+ OM_uint32 length = 0;
OM_uint32 status;
char *p;
gss_union_ctx_id_t ctx;
gss_buffer_desc token;
gss_mechanism mech;
- gss_initialize();
-
+ if (minor_status == NULL)
+ return (GSS_S_CALL_INACCESSIBLE_WRITE);
*minor_status = 0;
- if (interprocess_token->length == 0 || interprocess_token->value == 0)
- return (GSS_S_DEFECTIVE_TOKEN);
+ if (context_handle == NULL)
+ return (GSS_S_CALL_INACCESSIBLE_WRITE | GSS_S_NO_CONTEXT);
+ *context_handle = GSS_C_NO_CONTEXT;
+
+ if (GSS_EMPTY_BUFFER(interprocess_token))
+ return (GSS_S_CALL_INACCESSIBLE_READ | GSS_S_DEFECTIVE_TOKEN);
status = GSS_S_FAILURE;
ctx = (gss_union_ctx_id_t) malloc(sizeof(gss_union_ctx_id_desc));
- if (!ctx) {
- *minor_status = ENOMEM;
- goto error_out;
- }
+ if (!ctx)
+ return (GSS_S_FAILURE);
+
ctx->mech_type = (gss_OID) malloc(sizeof(gss_OID_desc));
if (!ctx->mech_type) {
- *minor_status = ENOMEM;
- goto error_out;
+ free(ctx);
+ return (GSS_S_FAILURE);
+ }
+
+ if (interprocess_token->length >= sizeof (OM_uint32)) {
+ p = interprocess_token->value;
+ length = (OM_uint32)*p++;
+ length = (OM_uint32)(length << 8) + *p++;
+ length = (OM_uint32)(length << 8) + *p++;
+ length = (OM_uint32)(length << 8) + *p++;
+ }
+
+ if (length == 0 ||
+ length > (interprocess_token->length - sizeof (OM_uint32))) {
+ free(ctx);
+ return (GSS_S_CALL_BAD_STRUCTURE | GSS_S_DEFECTIVE_TOKEN);
}
- p = interprocess_token->value;
- length = *p++;
- length = (length << 8) + *p++;
- length = (length << 8) + *p++;
- length = (length << 8) + *p++;
ctx->mech_type->length = length;
ctx->mech_type->elements = malloc(length);
if (!ctx->mech_type->elements) {
- *minor_status = ENOMEM;
goto error_out;
}
memcpy(ctx->mech_type->elements, p, length);
p += length;
- token.length = interprocess_token->length - 4 - length;
+ token.length = interprocess_token->length - sizeof (OM_uint32) - length;
token.value = p;
/*
goto error_out;
}
if (!mech->gss_import_sec_context) {
- status = GSS_S_BAD_BINDINGS;
+ status = GSS_S_UNAVAILABLE;
goto error_out;
}
-/* #ident "@(#)gss_init_sec_context.c 1.20 95/08/07 SMI" */
+/* #pragma ident "@(#)g_init_sec_context.c 1.20 03/10/24 SMI" */
/*
* Copyright 1996 by Sun Microsystems, Inc.
#endif
#include <string.h>
-#define g_OID_equal(o1,o2) \
- (((o1)->length == (o2)->length) && \
- (memcmp((o1)->elements,(o2)->elements,(int) (o1)->length) == 0))
-
OM_uint32 KRB5_CALLCONV
gss_init_sec_context (minor_status,
claimant_cred_handle,
OM_uint32 * time_rec;
{
- OM_uint32 status, temp_status, temp_minor_status;
+ OM_uint32 status, temp_minor_status;
gss_union_name_t union_name;
gss_union_cred_t union_cred;
gss_name_t internal_name;
gss_mechanism mech;
gss_cred_id_t input_cred_handle;
- gss_initialize();
+ if (minor_status == NULL)
+ return (GSS_S_CALL_INACCESSIBLE_WRITE);
+ *minor_status = 0;
+
+ /* clear output values */
+ if (actual_mech_type)
+ *actual_mech_type = NULL;
if (context_handle == NULL)
- return GSS_S_NO_CONTEXT;
+ return (GSS_S_CALL_INACCESSIBLE_WRITE | GSS_S_NO_CONTEXT);
union_name = (gss_union_name_t) target_name;
- /*
- * If mech_type is NULL, and the target_name is
- * mechanism-specific, then set it to the mech_type of
- * target_name.
- */
- if ((mech_type == GSS_C_NULL_OID) && union_name->mech_type)
- mech_type = union_name->mech_type;
+ if (target_name == NULL)
+ return (GSS_S_CALL_INACCESSIBLE_READ | GSS_S_BAD_NAME);
+
+ if (output_token == NULL)
+ return (GSS_S_CALL_INACCESSIBLE_WRITE);
+
+ output_token->value = NULL;
+ output_token->length = 0;
+
+
+ if (req_mech_type)
+ mech_type = (gss_OID)req_mech_type;
+
+ union_name = (gss_union_name_t)target_name;
/*
* obtain the gss mechanism information for the requested
if (mech == NULL)
return (GSS_S_BAD_MECH);
+ if (mech->gss_init_sec_context == NULL)
+ return (GSS_S_UNAVAILABLE);
+
if (mech_type == GSS_C_NULL_OID)
mech_type = &mech->mech_type;
* mech_type that we're about to use. Otherwise, do an import on
* the external_name form of the target name.
*/
- if (union_name->mech_type) {
- if (!g_OID_equal(union_name->mech_type, mech_type))
- return (GSS_S_BAD_MECH);
+ if (union_name->mech_type &&
+ g_OID_equal(union_name->mech_type, mech_type)) {
internal_name = union_name->mech_name;
} else {
- if ((temp_status = __gss_import_internal_name(minor_status, mech_type,
- union_name,
- &internal_name)))
- return (GSS_S_BAD_NAME);
+ if ((status = __gss_import_internal_name(minor_status, mech_type,
+ union_name,
+ &internal_name)) != GSS_S_COMPLETE)
+ return (status);
}
/*
*/
if(*context_handle == GSS_C_NO_CONTEXT) {
+ status = GSS_S_FAILURE;
union_ctx_id = (gss_union_ctx_id_t)
malloc(sizeof(gss_union_ctx_id_desc));
+ if (union_ctx_id == NULL)
+ goto end;
union_ctx_id->mech_type = (gss_OID)
malloc(sizeof(gss_OID_desc));
- /* copy in the mech type information */
-
- union_ctx_id->mech_type->elements = (void *)
- malloc(mech_type->length);
-
- union_ctx_id->mech_type->length = mech_type->length;
- memcpy(union_ctx_id->mech_type->elements, mech_type->elements,
- mech_type->length);
+ if (generic_gss_copy_oid(&temp_minor_status, mech_type,
+ &union_ctx_id->mech_type) != GSS_S_COMPLETE) {
+ free(union_ctx_id);
+ goto end;
+ }
/* copy the supplied context handle */
-
union_ctx_id->internal_ctx_id = *context_handle;
} else
union_ctx_id = *context_handle;
* now call the approprate underlying mechanism routine
*/
- if (mech->gss_init_sec_context) {
- status = mech->gss_init_sec_context(
- mech->context,
- minor_status,
- input_cred_handle,
- &union_ctx_id->internal_ctx_id,
- internal_name,
- mech_type,
- req_flags,
- time_req,
- input_chan_bindings,
- input_token,
- actual_mech_type,
- output_token,
- ret_flags,
- time_rec);
-
- if (*context_handle == GSS_C_NO_CONTEXT)
- *context_handle = (gss_ctx_id_t) union_ctx_id;
-
- } else
- status = GSS_S_BAD_BINDINGS;
-
- if (!union_name->mech_type) {
+ status = mech->gss_init_sec_context(
+ mech->context,
+ minor_status,
+ input_cred_handle,
+ &union_ctx_id->internal_ctx_id,
+ internal_name,
+ mech_type,
+ req_flags,
+ time_req,
+ input_chan_bindings,
+ input_token,
+ actual_mech_type,
+ output_token,
+ ret_flags,
+ time_rec);
+
+ if (status != GSS_S_COMPLETE && status != GSS_S_CONTINUE_NEEDED) {
+ /*
+ * the spec says (the preferred) method is to delete all
+ * context info on the first call to init, and on all
+ * subsequent calls make the caller responsible for
+ * calling gss_delete_sec_context
+ */
+ if (*context_handle == GSS_C_NO_CONTEXT) {
+ free(union_ctx_id->mech_type->elements);
+ free(union_ctx_id->mech_type);
+ free(union_ctx_id);
+ }
+ } else if (*context_handle == GSS_C_NO_CONTEXT)
+ *context_handle = (gss_ctx_id_t)union_ctx_id;
+
+end:
+ if (union_name->mech_name == NULL ||
+ union_name->mech_name != internal_name) {
(void) __gss_release_internal_name(&temp_minor_status,
mech_type, &internal_name);
}
-/* #ident "@(#)g_initialize.c 1.2 96/02/06 SMI" */
+/* #pragma ident "@(#)g_initialize.c 1.36 05/02/02 SMI" */
/*
* Copyright 1996 by Sun Microsystems, Inc.
#include <ctype.h>
#include <errno.h>
-#ifdef USE_SOLARIS_SHARED_LIBRARIES
#include <dlfcn.h>
-#define MECH_CONF "/etc/mech.conf"
+#define MECH_CONF "/etc/gss/mech"
+
+#define MECH_LIB_PREFIX1 "/usr/lib/"
+
+#define MECH_LIB_PREFIX2 ""
+
+#define MECH_LIB_DIR "gss/"
+
+#define MECH_LIB_PREFIX MECH_LIB_PREFIX1 MECH_LIB_PREFIX2 MECH_LIB_DIR
+
#define MECH_SYM "gss_mech_initialize"
-static void solaris_initialize (void);
-#endif /* USE_SOLARIS_SHARED_LIBRARIES */
+#define M_DEFAULT "default"
+
+#include <sys/stat.h>
-#define g_OID_equal(o1,o2) \
- (((o1)->length == (o2)->length) && \
- (memcmp((o1)->elements,(o2)->elements,(int) (o1)->length) == 0))
+#include "k5-thread.h"
extern gss_mechanism krb5_gss_initialize();
gss_mechanism *__gss_mechs_array = NULL;
+/* Local functions */
+static gss_mech_info searchMechList(const gss_OID);
+static void loadConfigFile(const char *);
+static void updateMechList(void);
+
+static void init_hardcoded(void);
+
/*
- * This function will add a new mechanism to the mechs_array
+ * list of mechanism libraries and their entry points.
+ * the list also maintains state of the mech libraries (loaded or not).
*/
+static gss_mech_info g_mechList = NULL;
+static gss_mech_info g_mechListTail = NULL;
+static k5_mutex_t g_mechListLock = K5_MUTEX_PARTIAL_INITIALIZER;
+static time_t g_confFileModTime = (time_t)0;
-static OM_uint32
-add_mechanism (mech, replace)
- gss_mechanism mech;
- int replace;
+int
+gssint_mechglue_init(void)
{
- gss_mechanism * temp_array;
- gss_OID_set mech_names;
- OM_uint32 minor_status, major_status;
- unsigned int i;
-
- if (mech == NULL)
- return GSS_S_COMPLETE;
-
- /* initialize the mechs_array if it hasn't already been initialized */
- if (__gss_mechs_array == NULL) {
- __gss_mechs_array = (gss_mechanism *) malloc (sizeof(gss_mechanism));
-
- if (__gss_mechs_array == NULL)
- return ENOMEM;
-
- __gss_mechs_array[0] = &null_mech;
- }
-
- /*
- * Find the length of __gss_mechs_array, and look for an existing
- * entry for this OID
- */
- for (i=0; __gss_mechs_array[i]->mech_type.length != 0; i++) {
- if (!g_OID_equal(&__gss_mechs_array[i]->mech_type,
- &mech->mech_type))
- continue;
+ return k5_mutex_finish_init(&g_mechListLock);
+}
+
+void
+gssint_mechglue_fini(void)
+{
+ k5_mutex_destroy(&g_mechListLock);
+}
+
- /* We found a match. Replace it? */
- if (!replace)
- return GSS_S_FAILURE;
+/*
+ * function used to reclaim the memory used by a gss_OID structure.
+ * This routine requires direct access to the mechList.
+ */
+OM_uint32
+gss_release_oid(minor_status, oid)
+OM_uint32 *minor_status;
+gss_OID *oid;
+{
+ OM_uint32 major;
+ gss_mech_info aMech = g_mechList;
+
+ if (minor_status == NULL)
+ return (GSS_S_CALL_INACCESSIBLE_WRITE);
+
+ *minor_status = 0;
+
+ while (aMech != NULL) {
+
+ /*
+ * look through the loaded mechanism libraries for
+ * gss_internal_release_oid until one returns success.
+ * gss_internal_release_oid will only return success when
+ * the OID was recognized as an internal mechanism OID. if no
+ * mechanisms recognize the OID, then call the generic version.
+ */
+
+ /*
+ * we can walk the mechanism list without a mutex, because we
+ * are only looking at fields which once read will never change.
+ * Mechanism entries are always added to the end, and as
+ * complete entries.
+ */
+ if (aMech->mech && aMech->mech->gss_internal_release_oid) {
+ major = aMech->mech->gss_internal_release_oid(
+ aMech->mech->context,
+ minor_status, oid);
+ if (major == GSS_S_COMPLETE)
+ return (GSS_S_COMPLETE);
+ }
+ aMech = aMech->next;
+ } /* while */
+
+ return (generic_gss_release_oid(minor_status, oid));
+} /* gss_release_oid */
- __gss_mechs_array[i] = mech;
- return GSS_S_COMPLETE;
- }
- /* we didn't find it -- add it to the end of the __gss_mechs_array */
- temp_array = (gss_mechanism *) realloc(__gss_mechs_array,
- (i+2)*sizeof(gss_mechanism));
+/*
+ * this function will return an oid set indicating available mechanisms.
+ * The set returned is based on configuration file entries and
+ * NOT on the loaded mechanisms. This function does not check if any
+ * of these can actually be loaded.
+ * This routine needs direct access to the mechanism list.
+ * To avoid reading the configuration file each call, we will save a
+ * a mech oid set, and only update it once the file has changed.
+ */
+static time_t g_mechSetTime = (time_t)0;
+static gss_OID_set_desc g_mechSet = { 0, NULL };
+static k5_mutex_t g_mechSetLock;
- if (temp_array == NULL)
- return ENOMEM;
- temp_array[i++] = mech;
- temp_array[i] = &null_mech;
+OM_uint32
+gss_indicate_mechs(minorStatus, mechSet)
+OM_uint32 *minorStatus;
+gss_OID_set *mechSet;
+{
+ gss_mech_info mList;
+ char *fileName;
+ struct stat fileInfo;
+ int count, i, j;
+ gss_OID curItem;
+
+ if (!minorStatus)
+ return (GSS_S_CALL_INACCESSIBLE_WRITE);
+
+ *minorStatus = 0;
+
+
+ /* check output parameter */
+ if (mechSet == NULL)
+ return (GSS_S_CALL_INACCESSIBLE_WRITE);
+
+ fileName = MECH_CONF;
+
+ /*
+ * If we have already computed the mechanisms supported and if it
+ * is still valid; make a copy and return to caller,
+ * otherwise build it first.
+ */
+ if ((stat(fileName, &fileInfo) == 0 &&
+ fileInfo.st_mtime > g_mechSetTime)) {
+ /*
+ * lock the mutex since we will be updating
+ * the mechList structure
+ * we need to keep the lock while we build the mechanism list
+ * since we are accessing parts of the mechList which could be
+ * modified.
+ */
+ (void) k5_mutex_lock(&g_mechListLock);
+
+ /*
+ * this checks for the case when we need to re-construct the
+ * g_mechSet structure, but the mechanism list is upto date
+ * (because it has been read by someone calling
+ * __gss_get_mechanism)
+ */
+ if (fileInfo.st_mtime > g_confFileModTime)
+ {
+ g_confFileModTime = fileInfo.st_mtime;
+ loadConfigFile(fileName);
+ }
+
+ /*
+ * we need to lock the mech set so that no one else will
+ * try to read it as we are re-creating it
+ */
+ (void) k5_mutex_lock(&g_mechSetLock);
+
+ /* if the oid list already exists we must free it first */
+ if (g_mechSet.count != 0) {
+ for (i = 0; i < g_mechSet.count; i++)
+ free(g_mechSet.elements[i].elements);
+ free(g_mechSet.elements);
+ g_mechSet.elements = NULL;
+ g_mechSet.count = 0;
+ }
+
+ /* determine how many elements to have in the list */
+ mList = g_mechList;
+ count = 0;
+ while (mList != NULL) {
+ count++;
+ mList = mList->next;
+ }
+
+ /* this should always be true, but.... */
+ if (count > 0) {
+ g_mechSet.elements =
+ (gss_OID) calloc(count, sizeof (gss_OID_desc));
+ if (g_mechSet.elements == NULL) {
+ (void) k5_mutex_unlock(&g_mechSetLock);
+ (void) k5_mutex_unlock(&g_mechListLock);
+ return (GSS_S_FAILURE);
+ }
+
+ (void) memset(g_mechSet.elements, 0,
+ count * sizeof (gss_OID_desc));
+
+ /* now copy each oid element */
+ g_mechSet.count = count;
+ count = 0;
+ mList = g_mechList;
+ while (mList != NULL) {
+ curItem = &(g_mechSet.elements[count]);
+ curItem->elements = (void*)
+ malloc(mList->mech_type->length);
+ if (curItem->elements == NULL) {
+ /*
+ * this is nasty - we must delete the
+ * part of the array already copied
+ */
+ for (i = 0; i < count; i++) {
+ free(g_mechSet.elements[i].
+ elements);
+ }
+ free(g_mechSet.elements);
+ g_mechSet.count = 0;
+ g_mechSet.elements = NULL;
+ (void) k5_mutex_unlock(&g_mechSetLock);
+ (void) k5_mutex_unlock(&g_mechListLock);
+ return (GSS_S_FAILURE);
+ }
+ g_OID_copy(curItem, mList->mech_type);
+ count++;
+ mList = mList->next;
+ }
+ }
+
+ g_mechSetTime = fileInfo.st_mtime;
+ (void) k5_mutex_unlock(&g_mechSetLock);
+ (void) k5_mutex_unlock(&g_mechListLock);
+ } /* if g_mechSet is out of date or not initialized */
+
+ /*
+ * the mech set is created and it is up to date
+ * so just copy it to caller
+ */
+ if ((*mechSet =
+ (gss_OID_set) malloc(sizeof (gss_OID_set_desc))) == NULL)
+ {
+ return (GSS_S_FAILURE);
+ }
- __gss_mechs_array = temp_array;
+ /*
+ * need to lock the g_mechSet in case someone tries to update it while
+ * I'm copying it.
+ */
+ (void) k5_mutex_lock(&g_mechSetLock);
+
+ /* allocate space for the oid structures */
+ if (((*mechSet)->elements =
+ (void*) calloc(g_mechSet.count, sizeof (gss_OID_desc)))
+ == NULL)
+ {
+ (void) k5_mutex_unlock(&g_mechSetLock);
+ free(*mechSet);
+ *mechSet = NULL;
+ return (GSS_S_FAILURE);
+ }
- /*
- * OK, now let's register all of the name types this mechanism
- * knows how to deal with.
- */
- major_status = gss_inquire_names_for_mech(&minor_status, &mech->mech_type,
- &mech_names);
- if (major_status != GSS_S_COMPLETE)
+ /* now copy the oid structures */
+ (void) memcpy((*mechSet)->elements, g_mechSet.elements,
+ g_mechSet.count * sizeof (gss_OID_desc));
+
+ (*mechSet)->count = g_mechSet.count;
+
+ /* still need to copy each of the oid elements arrays */
+ for (i = 0; i < (*mechSet)->count; i++) {
+ curItem = &((*mechSet)->elements[i]);
+ curItem->elements =
+ (void *) malloc(g_mechSet.elements[i].length);
+ if (curItem->elements == NULL) {
+ (void) k5_mutex_unlock(&g_mechSetLock);
+ /*
+ * must still free the allocated elements for
+ * each allocated gss_OID_desc
+ */
+ for (j = 0; j < i; j++) {
+ free((*mechSet)->elements[j].elements);
+ }
+ free((*mechSet)->elements);
+ free(mechSet);
+ *mechSet = NULL;
+ return (GSS_S_FAILURE);
+ }
+ g_OID_copy(curItem, &g_mechSet.elements[i]);
+ }
+ (void) k5_mutex_unlock(&g_mechSetLock);
return (GSS_S_COMPLETE);
- for (i=0; i < mech_names->count; i++) {
- gss_add_mech_name_type(&minor_status, &mech_names->elements[i],
- &mech->mech_type);
- }
- (void) gss_release_oid_set(&minor_status, &mech_names);
+} /* gss_indicate_mechs */
- return GSS_S_COMPLETE;
-}
+/*
+ * this function has been added for use by modules that need to
+ * know what (if any) optional parameters are supplied in the
+ * config file (MECH_CONF).
+ * It will return the option string for a specified mechanism.
+ * caller is responsible for freeing the memory
+ */
+char *
+__gss_get_modOptions(oid)
+const gss_OID oid;
+{
+ gss_mech_info aMech;
+ char *modOptions = NULL;
+
+ /* make sure we have fresh data */
+ (void) k5_mutex_lock(&g_mechListLock);
+ updateMechList();
+ (void) k5_mutex_unlock(&g_mechListLock);
+
+ /* searching the list does not require a lock */
+ if ((aMech = searchMechList(oid)) == NULL ||
+ aMech->optionStr == NULL) {
+ return (NULL);
+ }
+
+ /*
+ * need to obtain a lock on this structure in case someone else
+ * will try to update it during the copy
+ */
+ (void) k5_mutex_lock(&g_mechListLock);
+ if (aMech->optionStr)
+ modOptions = strdup(aMech->optionStr);
+ (void) k5_mutex_unlock(&g_mechListLock);
+
+ return (modOptions);
+} /* __gss_get_modOptions */
-void gss_initialize ()
+/*
+ * given a mechanism string return the mechanism oid
+ */
+OM_uint32
+__gss_mech_to_oid(const char *mechStr, gss_OID* oid)
{
- gss_mechanism mech;
+ gss_mech_info aMech;
- /* Make sure we've not run already */
- if (_gss_initialized)
- return;
- _gss_initialized = 1;
+ if (oid == NULL)
+ return (GSS_S_CALL_INACCESSIBLE_WRITE);
-#ifdef USE_SOLARIS_SHARED_LIBRARIES
- solaris_initialize();
+ *oid = GSS_C_NULL_OID;
-#else
- /*
- * Use hard-coded in mechanisms... I need to know what mechanisms
- * are supported... As more mechanisms become supported, they
- * should be added here, unless shared libraries are used.
- */
+ if ((mechStr == NULL) || (strlen(mechStr) == 0) ||
+ (strcasecmp(mechStr, M_DEFAULT) == 0))
+ return (GSS_S_COMPLETE);
- /* Initialize the krb5 mechanism */
- mech = (gss_mechanism)krb5_gss_initialize();
- if (mech)
- add_mechanism (mech, 1);
+ /* ensure we have fresh data */
+ (void) k5_mutex_lock(&g_mechListLock);
+ updateMechList();
+ (void) k5_mutex_unlock(&g_mechListLock);
-#endif /* USE_SOLARIS_SHARED_LIBRARIES */
+ aMech = g_mechList;
+
+ /* no lock required - only looking at fields that are not updated */
+ while (aMech != NULL) {
+ if ((aMech->mechNameStr) &&
+ strcmp(aMech->mechNameStr, mechStr) == 0) {
+ *oid = aMech->mech_type;
+ return (GSS_S_COMPLETE);
+ }
+ aMech = aMech->next;
+ }
+ return (GSS_S_FAILURE);
+} /* __gss_mech_to_oid */
- if (__gss_mechs_array == NULL) { /* this is very bad! */
- fprintf(stderr,"gss_initialize fatal error: no mechanisms loaded!\n");
- exit(-1);
- }
- return;
+/*
+ * Given the mechanism oid, return the readable mechanism name
+ * associated with that oid from the mech config file
+ * (/etc/gss/mech).
+ */
+const char *
+__gss_oid_to_mech(const gss_OID oid)
+{
+ gss_mech_info aMech;
+
+ if (oid == GSS_C_NULL_OID)
+ return (M_DEFAULT);
+
+ /* ensure we have fresh data */
+ (void) k5_mutex_lock(&g_mechListLock);
+ updateMechList();
+ (void) k5_mutex_unlock(&g_mechListLock);
+
+ if ((aMech = searchMechList(oid)) == NULL)
+ return (NULL);
+
+ return (aMech->mechNameStr);
+} /* __gss_oid_to_mech */
+
+
+/*
+ * return a list of mechanism strings supported
+ * upon return the array is terminated with a NULL entry
+ */
+OM_uint32
+__gss_get_mechanisms(char *mechArray[], int arrayLen)
+{
+ gss_mech_info aMech;
+ int i;
+
+ if (gssint_initialize_library())
+ return GSS_S_FAILURE;
+ if (mechArray == NULL || arrayLen < 1)
+ return (GSS_S_CALL_INACCESSIBLE_WRITE);
+
+ /* ensure we have fresh data */
+ (void) k5_mutex_lock(&g_mechListLock);
+ updateMechList();
+ (void) k5_mutex_unlock(&g_mechListLock);
+
+ aMech = g_mechList;
+
+ /* no lock required - only looking at fields that are not updated */
+ for (i = 1; i < arrayLen; i++) {
+ if (aMech != NULL) {
+ *mechArray = aMech->mechNameStr;
+ mechArray++;
+ aMech = aMech->next;
+ } else
+ break;
+ }
+ *mechArray = NULL;
+ return (GSS_S_COMPLETE);
+} /* gss_get_mechanisms */
+
+
+/*
+ * determines if the mechList needs to be updated from file
+ * and performs the update.
+ * this functions must be called with a lock of g_mechListLock
+ */
+static void
+updateMechList(void)
+{
+ char *fileName;
+ struct stat fileInfo;
+
+ init_hardcoded();
+ fileName = MECH_CONF;
+
+ /* check if mechList needs updating */
+ if (stat(fileName, &fileInfo) == 0 &&
+ (fileInfo.st_mtime > g_confFileModTime)) {
+ loadConfigFile(fileName);
+ g_confFileModTime = fileInfo.st_mtime;
+ }
+} /* updateMechList */
+
+
+static void
+init_hardcoded(void)
+{
+ extern struct gss_config krb5_mechanism;
+ gss_mech_info cf;
+
+ if (g_mechList != NULL)
+ return;
+ cf = malloc(sizeof(*cf));
+ if (cf == NULL)
+ return;
+ memset(cf, 0, sizeof(*cf));
+ cf->uLibName = strdup("<hardcoded internal>");
+ cf->mechNameStr = "kerberos_v5";
+ cf->mech_type = &krb5_mechanism.mech_type;
+ cf->mech = &krb5_mechanism;
+ cf->next = NULL;
+ g_mechList = cf;
}
+
+/*
+ * given the mechanism type, return the mechanism structure
+ * containing the mechanism library entry points.
+ * will return NULL if mech type is not found
+ * This function will also trigger the loading of the mechanism
+ * module if it has not been already loaded.
+ */
+gss_mechanism
+__gss_get_mechanism(oid)
+const gss_OID oid;
+{
+ gss_mech_info aMech;
+ gss_mechanism (*sym)(const gss_OID);
+ void *dl;
+
+ if (gssint_initialize_library())
+ return GSS_S_FAILURE;
+
+ /* check if the mechanism is already loaded */
+ if ((aMech = searchMechList(oid)) != NULL && aMech->mech) {
+ return (aMech->mech);
+ }
+
+ /*
+ * might need to re-read the configuration file before loading
+ * the mechanism to ensure we have the latest info.
+ */
+ (void) k5_mutex_lock(&g_mechListLock);
+ updateMechList();
+
+ aMech = searchMechList(oid);
+
+ /* is the mechanism present in the list ? */
+ if (aMech == NULL) {
+ (void) k5_mutex_unlock(&g_mechListLock);
+ return ((gss_mechanism)NULL);
+ }
+
+ /* has another thread loaded the mech */
+ if (aMech->mech) {
+ (void) k5_mutex_unlock(&g_mechListLock);
+ return (aMech->mech);
+ }
+
+ /* we found the mechanism, but it is not loaded */
+ if ((dl = dlopen(aMech->uLibName, RTLD_NOW)) == NULL) {
+#if 0
+ (void) syslog(LOG_INFO, "libgss dlopen(%s): %s\n",
+ aMech->uLibName, dlerror());
+#endif
+ (void) k5_mutex_unlock(&g_mechListLock);
+ return ((gss_mechanism)NULL);
+ }
+
+ if ((sym = (gss_mechanism (*)(const gss_OID))dlsym(dl, MECH_SYM))
+ == NULL) {
+ (void) dlclose(dl);
+#if 0
+ (void) syslog(LOG_INFO, "unable to initialize mechanism"
+ " library [%s]\n", aMech->uLibName);
+#endif
+ (void) k5_mutex_unlock(&g_mechListLock);
+ return ((gss_mechanism)NULL);
+ }
+
+ /* Call the symbol to get the mechanism table */
+ aMech->mech = (*sym)(aMech->mech_type);
+
+ if (aMech->mech == NULL) {
+ (void) dlclose(dl);
+#if 0
+ (void) syslog(LOG_INFO, "unable to initialize mechanism"
+ " library [%s]\n", aMech->uLibName);
+#endif
+ (void) k5_mutex_unlock(&g_mechListLock);
+ return ((gss_mechanism)NULL);
+ }
+
+ aMech->dl_handle = dl;
+
+ (void) k5_mutex_unlock(&g_mechListLock);
+ return (aMech->mech);
+} /* __gss_get_mechanism */
+
+gss_mechanism_ext
+__gss_get_mechanism_ext(oid)
+const gss_OID oid;
+{
+ gss_mech_info aMech;
+ gss_mechanism_ext mech_ext;
+
+ /* check if the mechanism is already loaded */
+ if ((aMech = searchMechList(oid)) != NULL && aMech->mech_ext != NULL)
+ return (aMech->mech_ext);
+
+ if (__gss_get_mechanism(oid) == NULL)
+ return (NULL);
+
+ if (aMech->dl_handle == NULL)
+ return (NULL);
+
+ /* Load the gss_config_ext struct for this mech */
+
+ mech_ext = (gss_mechanism_ext)malloc(sizeof (struct gss_config_ext));
+
+ if (mech_ext == NULL)
+ return (NULL);
+
+ /*
+ * dlsym() the mech's 'method' functions for the extended APIs
+ *
+ * NOTE: Until the void *context argument is removed from the
+ * SPI method functions' signatures it will be necessary to have
+ * different function pointer typedefs and function names for
+ * the SPI methods than for the API. When this argument is
+ * removed it will be possible to rename gss_*_sfct to gss_*_fct
+ * and and gssspi_* to gss_*.
+ */
+ mech_ext->gss_acquire_cred_with_password =
+ (gss_acquire_cred_with_password_sfct)dlsym(aMech->dl_handle,
+ "gssspi_acquire_cred_with_password");
+
+ /* Set aMech->mech_ext */
+ (void) k5_mutex_lock(&g_mechListLock);
+
+ if (aMech->mech_ext == NULL)
+ aMech->mech_ext = mech_ext;
+ else
+ free(mech_ext); /* we raced and lost; don't leak */
+
+ (void) k5_mutex_unlock(&g_mechListLock);
+
+ return (aMech->mech_ext);
+
+} /* __gss_get_mechanism_ext */
+
+
+/*
+ * this routine is used for searching the list of mechanism data.
+ * it needs not be mutex protected because we only add new structures
+ * from the end and they are fully initialized before being added.
+ */
+static gss_mech_info searchMechList(oid)
+const gss_OID oid;
+{
+ gss_mech_info aMech = g_mechList;
+
+ /* if oid is null -> then get default which is the first in the list */
+ if (oid == GSS_C_NULL_OID)
+ return (aMech);
+
+ while (aMech != NULL) {
+ if (g_OID_equal(aMech->mech_type, oid))
+ return (aMech);
+ aMech = aMech->next;
+ }
+
+ /* none found */
+ return ((gss_mech_info) NULL);
+} /* searchMechList */
+
+
+/*
+ * loads the configuration file
+ * this is called while having a mutex lock on the mechanism list
+ * entries for libraries that have been loaded can't be modified
+ * mechNameStr and mech_type fields are not updated during updates
+ */
+static void loadConfigFile(fileName)
+const char *fileName;
+{
+ char buffer[BUFSIZ], *oidStr, *oid, *sharedLib, *kernMod, *endp;
+ char *modOptions;
+ char sharedPath[sizeof (MECH_LIB_PREFIX) + BUFSIZ];
+ char *tmpStr;
+ FILE *confFile;
+ gss_OID mechOid;
+ gss_mech_info aMech, tmp;
+ OM_uint32 minor;
+ gss_buffer_desc oidBuf;
+
+ if ((confFile = fopen(fileName, "r")) == NULL) {
+ return;
+ }
+
+ (void) memset(buffer, 0, sizeof (buffer));
+ while (fgets(buffer, BUFSIZ, confFile) != NULL) {
+
+ /* ignore lines beginning with # */
+ if (*buffer == '#')
+ continue;
+
+ /*
+ * find the first white-space character after
+ * the mechanism name
+ */
+ oidStr = buffer;
+ for (oid = buffer; *oid && !isspace(*oid); oid++);
+
+ /* Now find the first non-white-space character */
+ if (*oid) {
+ *oid = '\0';
+ oid++;
+ while (*oid && isspace(*oid))
+ oid++;
+ }
+
+ /*
+ * If that's all, then this is a corrupt entry. Skip it.
+ */
+ if (! *oid)
+ continue;
+
+ /* Find the end of the oid and make sure it is NULL-ended */
+ for (endp = oid; *endp && !isspace(*endp); endp++)
+ ;
+
+ if (*endp) {
+ *endp = '\0';
+ }
+
+ /*
+ * check if an entry for this oid already exists
+ * if it does, and the library is already loaded then
+ * we can't modify it, so skip it
+ */
+ oidBuf.value = (void *)oid;
+ oidBuf.length = strlen(oid);
+ if (generic_gss_str_to_oid(&minor, &oidBuf, &mechOid)
+ != GSS_S_COMPLETE) {
+#if 0
+ (void) syslog(LOG_INFO, "invalid mechanism oid"
+ " [%s] in configuration file", oid);
+#endif
+ continue;
+ }
+
+ aMech = searchMechList(mechOid);
+ if (aMech && aMech->mech) {
+ free(mechOid->elements);
+ free(mechOid);
+ continue;
+ }
+
+ /* Find the start of the shared lib name */
+ for (sharedLib = endp+1; *sharedLib && isspace(*sharedLib);
+ sharedLib++)
+ ;
+
+ /*
+ * If that's all, then this is a corrupt entry. Skip it.
+ */
+ if (! *sharedLib) {
+ free(mechOid->elements);
+ free(mechOid);
+ continue;
+ }
+
+ /*
+ * Find the end of the shared lib name and make sure it is
+ * NULL-terminated.
+ */
+ for (endp = sharedLib; *endp && !isspace(*endp); endp++)
+ ;
+
+ if (*endp) {
+ *endp = '\0';
+ }
+
+ /* Find the start of the optional kernel module lib name */
+ for (kernMod = endp+1; *kernMod && isspace(*kernMod);
+ kernMod++)
+ ;
+
+ /*
+ * If this item starts with a bracket "[", then
+ * it is not a kernel module, but is a list of
+ * options for the user module to parse later.
+ */
+ if (*kernMod && *kernMod != '[') {
+ /*
+ * Find the end of the shared lib name and make sure
+ * it is NULL-terminated.
+ */
+ for (endp = kernMod; *endp && !isspace(*endp); endp++)
+ ;
+
+ if (*endp) {
+ *endp = '\0';
+ }
+ } else
+ kernMod = NULL;
+
+ /* Find the start of the optional module options list */
+ for (modOptions = endp+1; *modOptions && isspace(*modOptions);
+ modOptions++);
+
+ if (*modOptions == '[') {
+ /* move past the opening bracket */
+ for (modOptions = modOptions+1;
+ *modOptions && isspace(*modOptions);
+ modOptions++);
+
+ /* Find the closing bracket */
+ for (endp = modOptions;
+ *endp && *endp != ']'; endp++);
+
+ if (endp)
+ *endp = '\0';
+
+ } else {
+ modOptions = NULL;
+ }
+
+ (void) strcpy(sharedPath, MECH_LIB_PREFIX);
+ (void) strcat(sharedPath, sharedLib);
+
+ /*
+ * are we creating a new mechanism entry or
+ * just modifying existing (non loaded) mechanism entry
+ */
+ if (aMech) {
+ /*
+ * delete any old values and set new
+ * mechNameStr and mech_type are not modified
+ */
+ if (aMech->kmodName) {
+ free(aMech->kmodName);
+ aMech->kmodName = NULL;
+ }
+
+ if (aMech->optionStr) {
+ free(aMech->optionStr);
+ aMech->optionStr = NULL;
+ }
+
+ if ((tmpStr = strdup(sharedPath)) != NULL) {
+ if (aMech->uLibName)
+ free(aMech->uLibName);
+ aMech->uLibName = tmpStr;
+ }
+
+ if (kernMod) /* this is an optional parameter */
+ aMech->kmodName = strdup(kernMod);
+
+ if (modOptions) /* optional module options */
+ aMech->optionStr = strdup(modOptions);
+
+ /* the oid is already set */
+ free(mechOid->elements);
+ free(mechOid);
+ continue;
+ }
+
+ /* adding a new entry */
+ aMech = malloc(sizeof (struct gss_mech_config));
+ if (aMech == NULL) {
+ free(mechOid->elements);
+ free(mechOid);
+ continue;
+ }
+ (void) memset(aMech, 0, sizeof (struct gss_mech_config));
+ aMech->mech_type = mechOid;
+ aMech->uLibName = strdup(sharedPath);
+ aMech->mechNameStr = strdup(oidStr);
+
+ /* check if any memory allocations failed - bad news */
+ if (aMech->uLibName == NULL || aMech->mechNameStr == NULL) {
+ if (aMech->uLibName)
+ free(aMech->uLibName);
+ if (aMech->mechNameStr)
+ free(aMech->mechNameStr);
+ free(mechOid->elements);
+ free(mechOid);
+ free(aMech);
+ continue;
+ }
+ if (kernMod) /* this is an optional parameter */
+ aMech->kmodName = strdup(kernMod);
+
+ if (modOptions)
+ aMech->optionStr = strdup(modOptions);
+ /*
+ * add the new entry to the end of the list - make sure
+ * that only complete entries are added because other
+ * threads might currently be searching the list.
+ */
+ tmp = g_mechListTail;
+ g_mechListTail = aMech;
+
+ if (tmp != NULL)
+ tmp->next = aMech;
+
+ if (g_mechList == NULL)
+ g_mechList = aMech;
+ } /* while */
+ (void) fclose(confFile);
+} /* loadConfigFile */
+
+
#ifdef USE_SOLARIS_SHARED_LIBRARIES
/*
* read the configuration file to find out what mechanisms to
-/* #ident "@(#)g_inquire_context.c 1.2 96/01/18 SMI" */
+/* #pragma ident "@(#)g_inquire_context.c 1.15 04/02/23 SMI" */
/*
* Copyright 1996 by Sun Microsystems, Inc.
gss_union_ctx_id_t ctx;
gss_mechanism mech;
OM_uint32 status, temp_minor;
+ gss_name_t localTargName = NULL, localSourceName = NULL;
- gss_initialize();
+ if (!minor_status)
+ return (GSS_S_CALL_INACCESSIBLE_WRITE);
- /* if the context_handle is Null, return NO_CONTEXT error */
+ *minor_status = 0;
- if(context_handle == GSS_C_NO_CONTEXT)
- return(GSS_S_NO_CONTEXT);
+ /* if the context_handle is Null, return NO_CONTEXT error */
+ if (context_handle == GSS_C_NO_CONTEXT)
+ return (GSS_S_CALL_INACCESSIBLE_READ | GSS_S_NO_CONTEXT);
+
+ /* set all output value to NULL */
+ if (src_name)
+ *src_name = NULL;
+
+ if (targ_name)
+ *targ_name = NULL;
+
+ if (mech_type)
+ *mech_type = NULL;
/*
* select the approprate underlying mechanism routine and
ctx = (gss_union_ctx_id_t) context_handle;
mech = __gss_get_mechanism (ctx->mech_type);
- if (!mech || !mech->gss_inquire_context || !mech->gss_display_name) {
- return(GSS_S_NO_CONTEXT);
-
+ if (!mech || !mech->gss_inquire_context || !mech->gss_display_name ||
+ !mech->gss_release_name) {
+ return (GSS_S_UNAVAILABLE);
}
status = mech->gss_inquire_context(
mech->context,
minor_status,
ctx->internal_ctx_id,
- src_name,
- targ_name,
+ (src_name ? &localSourceName : NULL),
+ (targ_name ? &localTargName : NULL),
lifetime_rec,
- mech_type,
+ NULL,
ctx_flags,
locally_initiated,
open);
if (src_name) {
status = __gss_convert_name_to_union_name(minor_status, mech,
- *src_name, src_name);
+ localSourceName, src_name);
if (status != GSS_S_COMPLETE) {
- (void) mech->gss_release_name(mech->context,
- &temp_minor, src_name);
- (void) mech->gss_release_name(mech->context,
- &temp_minor, targ_name);
- if (mech_type) {
- gss_release_oid(&temp_minor, mech_type);
- }
- return (GSS_S_FAILURE);
+ if (localTargName)
+ mech->gss_release_name(mech->context,
+ &temp_minor, &localTargName);
+ return (status);
}
}
if (targ_name) {
status = __gss_convert_name_to_union_name(minor_status, mech,
- *targ_name, targ_name);
+ localTargName, targ_name);
if (status != GSS_S_COMPLETE) {
- if (mech_type) {
- gss_release_oid(&temp_minor, mech_type);
- }
- return (GSS_S_FAILURE);
+ if (src_name)
+ (void) gss_release_name(&temp_minor, src_name);
+
+ return (status);
}
}
+ /* spec says mech type must point to static storage */
+ if (mech_type)
+ *mech_type = &mech->mech_type;
return(GSS_S_COMPLETE);
}
-/* #ident "@(#)gss_inquire_cred.c 1.9 95/08/02 SMI" */
+/* #pragma ident "@(#)g_inquire_cred.c 1.16 04/02/23 SMI" */
/*
* Copyright 1996 by Sun Microsystems, Inc.
gss_name_t internal_name;
int i;
- gss_initialize();
+ /* check parms and set to defaults */
+ if (minor_status == NULL)
+ return (GSS_S_CALL_INACCESSIBLE_WRITE);
+ *minor_status = 0;
+
+ if (name)
+ *name = NULL;
+
+ if (mechanisms)
+ *mechanisms = NULL;
if (cred_handle == GSS_C_NO_CREDENTIAL) {
/*
*/
if ((mech = __gss_get_mechanism(GSS_C_NULL_OID)) == NULL)
- return(GSS_S_NO_CRED);
+ return (GSS_S_DEFECTIVE_CREDENTIAL);
if (!mech->gss_inquire_cred)
- return (GSS_S_FAILURE);
+ return (GSS_S_UNAVAILABLE);
status = mech->gss_inquire_cred(mech->context, minor_status,
GSS_C_NO_CREDENTIAL,
mech, internal_name,
name);
if (status != GSS_S_COMPLETE) {
- if (minor_status)
- *minor_status = temp_minor_status;
- __gss_release_internal_name(&temp_minor_status,
- &mech->mech_type, &internal_name);
+ *minor_status = temp_minor_status;
+ if (mechanisms && *mechanisms) {
+ (void) gss_release_oid_set(
+ &temp_minor_status,
+ mechanisms);
+ }
return (status);
}
}
* caller. If this call fails, return failure to our caller.
*/
- if(name != NULL)
- if(gss_import_name(&temp_minor_status,
- &union_cred->auxinfo.name,
- union_cred->auxinfo.name_type,
- name) != GSS_S_COMPLETE)
- return(GSS_S_DEFECTIVE_CREDENTIAL);
-
+ if(name != NULL) {
+ if ((gss_import_name(&temp_minor_status,
+ &union_cred->auxinfo.name,
+ union_cred->auxinfo.name_type,
+ name) != GSS_S_COMPLETE) ||
+ (gss_canonicalize_name(minor_status, *name,
+ &union_cred->mechs_array[0],
+ NULL) != GSS_S_COMPLETE)) {
+ status = GSS_S_DEFECTIVE_CREDENTIAL;
+ goto error;
+ }
+ }
+
/*
* copy the mechanism set in union_cred into an OID set and return in
* the mechanisms parameter.
*/
if(mechanisms != NULL) {
-
+ status = GSS_S_FAILURE;
*mechanisms = (gss_OID_set) malloc(sizeof(gss_OID_set_desc));
+ if (*mechanisms == NULL)
+ goto error;
- (*mechanisms)->count = union_cred->count;
+ (*mechanisms)->count = 0;
(*mechanisms)->elements =
(gss_OID) malloc(sizeof(gss_OID_desc) *
union_cred->count);
+ if ((*mechanisms)->elements == NULL) {
+ free(*mechanisms);
+ *mechanisms = NULL;
+ goto error;
+ }
+
for(i=0; i < union_cred->count; i++) {
- (*mechanisms)->elements[i].length =
- union_cred->mechs_array[i].length;
(*mechanisms)->elements[i].elements = (void *)
malloc(union_cred->mechs_array[i].length);
- memcpy((*mechanisms)->elements[i].elements,
- union_cred->mechs_array[i].elements,
- union_cred->mechs_array[i].length);
+ if ((*mechanisms)->elements[i].elements == NULL)
+ goto error;
+ g_OID_copy(&(*mechanisms)->elements[i],
+ &union_cred->mechs_array[i]);
+ (*mechanisms)->count++;
}
}
return(GSS_S_COMPLETE);
+
+error:
+ /*
+ * cleanup any allocated memory - we can just call
+ * gss_release_oid_set, because the set is constructed so that
+ * count always references the currently copied number of
+ * elements.
+ */
+ if (mechanisms && *mechanisms != NULL)
+ (void) gss_release_oid_set(&temp_minor_status, mechanisms);
+
+ if (name && *name != NULL)
+ (void) gss_release_name(&temp_minor_status, name);
+
+ return (status);
}
OM_uint32 KRB5_CALLCONV
gss_union_cred_t union_cred;
gss_cred_id_t mech_cred;
gss_mechanism mech;
+ OM_uint32 status, temp_minor_status;
+ gss_name_t internal_name;
+
mech = __gss_get_mechanism (mech_type);
if (!mech)
union_cred = (gss_union_cred_t) cred_handle;
mech_cred = __gss_get_mechanism_cred(union_cred, mech_type);
+ if (mech_cred == NULL)
+ return (GSS_S_DEFECTIVE_CREDENTIAL);
+
+ status = mech->gss_inquire_cred_by_mech(mech->context, minor_status,
+ mech_cred, mech_type,
+ name ? &internal_name : NULL,
+ initiator_lifetime,
+ acceptor_lifetime, cred_usage);
+
+ if (status != GSS_S_COMPLETE)
+ return (status);
+
+ if (name) {
+ /*
+ * Convert internal_name into a union_name equivalent.
+ */
+ status = __gss_convert_name_to_union_name(
+ &temp_minor_status, mech,
+ internal_name, name);
+ if (status != GSS_S_COMPLETE) {
+ *minor_status = temp_minor_status;
+ return (status);
+ }
+ }
- return (mech->gss_inquire_cred_by_mech(mech->context, minor_status,
- mech_cred, mech_type,
- name, initiator_lifetime,
- acceptor_lifetime, cred_usage));
+ return (GSS_S_COMPLETE);
}
-/* #ident "@(#)g_inquire_names.c 1.1 95/12/19 SMI" */
+/* #pragma ident "@(#)g_inquire_names.c 1.16 04/02/23 SMI" */
/*
* Copyright 1996 by Sun Microsystems, Inc.
#include "mglueP.h"
+#define MAX_MECH_OID_PAIRS 32
+
/* Last argument new for V2 */
OM_uint32 KRB5_CALLCONV
gss_inquire_names_for_mech(minor_status, mechanism, name_types)
OM_uint32 status;
gss_mechanism mech;
- gss_initialize();
-
+ if (minor_status == NULL)
+ return (GSS_S_CALL_INACCESSIBLE_WRITE);
+ *minor_status = 0;
+
+ if (name_types == NULL)
+ return (GSS_S_CALL_INACCESSIBLE_WRITE);
+
/*
* select the approprate underlying mechanism routine and
* call it.
mechanism,
name_types);
else
- status = GSS_S_BAD_BINDINGS;
+ status = GSS_S_UNAVAILABLE;
return(status);
}
- return(GSS_S_NO_CONTEXT);
+ return (GSS_S_BAD_MECH);
+}
+OM_uint32
+gss_inquire_mechs_for_name(minor_status, input_name, mech_set)
+
+ OM_uint32 * minor_status;
+ const gss_name_t input_name;
+ gss_OID_set * mech_set;
+
+{
+ OM_uint32 status;
+ static char *mech_list[MAX_MECH_OID_PAIRS+1];
+ gss_OID_set mech_name_types;
+ int present;
+ char *mechanism;
+ gss_OID mechOid;
+ gss_OID name_type;
+ gss_buffer_desc name_buffer;
+ int i;
+
+ if (minor_status == NULL)
+ return (GSS_S_CALL_INACCESSIBLE_WRITE);
+ *minor_status = 0;
+
+ if (input_name == NULL)
+ return (GSS_S_BAD_NAME);
+
+ status = gss_create_empty_oid_set(minor_status, mech_set);
+ if (status != GSS_S_COMPLETE)
+ return (status);
+ *mech_list = NULL;
+ status = __gss_get_mechanisms(mech_list, MAX_MECH_OID_PAIRS+1);
+ if (status != GSS_S_COMPLETE)
+ return (status);
+ for (i = 0; i < MAX_MECH_OID_PAIRS && mech_list[i] != NULL; i++) {
+ mechanism = mech_list[i];
+ if (__gss_mech_to_oid(mechanism, &mechOid) == GSS_S_COMPLETE) {
+ status = gss_inquire_names_for_mech(
+ minor_status,
+ mechOid,
+ &mech_name_types);
+ if (status == GSS_S_COMPLETE) {
+ status = gss_display_name(minor_status,
+ input_name,
+ &name_buffer,
+ &name_type);
+
+ (void) gss_release_buffer(NULL, &name_buffer);
+
+ if (status == GSS_S_COMPLETE && name_type) {
+ status = gss_test_oid_set_member(
+ minor_status,
+ name_type,
+ mech_name_types,
+ &present);
+ if (status == GSS_S_COMPLETE &&
+ present) {
+ status = gss_add_oid_set_member(
+ minor_status,
+ mechOid,
+ mech_set);
+ if (status != GSS_S_COMPLETE) {
+ (void) gss_release_oid_set(
+ minor_status,
+ &mech_name_types);
+ (void) gss_release_oid_set(
+ minor_status,
+ mech_set);
+ return (status);
+ }
+ }
+ }
+ (void) gss_release_oid_set(
+ minor_status,
+ &mech_name_types);
+ }
+ } else {
+ (void) gss_release_oid_set(
+ minor_status,
+ mech_set);
+ return (GSS_S_FAILURE);
+ }
+ }
+ return (GSS_S_COMPLETE);
}
#include <string.h>
#include <errno.h>
-#define g_OID_equal(o1,o2) \
- (((o1)->length == (o2)->length) && \
- (memcmp((o1)->elements,(o2)->elements,(int) (o1)->length) == 0))
-
static gss_mech_spec_name name_list = NULL;
/*
+/* #pragma ident "@(#)g_oid_ops.c 1.11 98/01/22 SMI" */
/*
* lib/gssapi/mechglue/g_oid_ops.c
*
extern gss_mechanism *__gss_mechs_array;
-OM_uint32 KRB5_CALLCONV
-gss_release_oid(minor_status, oid)
- OM_uint32 *minor_status;
- gss_OID *oid;
-{
- int i;
- OM_uint32 major_status;
-
- /* first call the gss_internal_release_oid for each mechanism
- * until one returns success. gss_internal_release_oid will only return
- * success when the OID was recognized as an internal mechanism OID.
- * if no mechanisms recognize the OID, then call the generic version.
- */
-
- for(i=0; __gss_mechs_array[i]->mech_type.length !=0; i++) {
- if (__gss_mechs_array[i]->gss_internal_release_oid) {
- major_status = __gss_mechs_array[i]->gss_internal_release_oid(
- __gss_mechs_array[i]->context,
- minor_status,
- oid);
- if (major_status == GSS_S_COMPLETE) {
- return (GSS_S_COMPLETE);
- }
- }
- }
-
- return generic_gss_release_oid(minor_status, oid);
-}
+/*
+ * gss_release_oid has been moved to g_initialize, becasue it requires access
+ * to the mechanism list. All functions requiring direct access to the
+ * mechanism list are now in g_initialize.c
+ */
OM_uint32 KRB5_CALLCONV
gss_create_empty_oid_set(minor_status, oid_set)
-/* #ident "@(#)gss_process_context.c 1.9 95/08/07 SMI" */
+/* #pragma ident "@(#)g_process_context.c 1.12 98/01/22 SMI" */
/*
* Copyright 1996 by Sun Microsystems, Inc.
gss_union_ctx_id_t ctx;
gss_mechanism mech;
- gss_initialize();
+ if (minor_status == NULL)
+ return (GSS_S_CALL_INACCESSIBLE_WRITE);
+ *minor_status = 0;
if (context_handle == GSS_C_NO_CONTEXT)
- return GSS_S_NO_CONTEXT;
+ return (GSS_S_CALL_INACCESSIBLE_READ | GSS_S_NO_CONTEXT);
+
+ if (GSS_EMPTY_BUFFER(token_buffer))
+ return (GSS_S_CALL_INACCESSIBLE_READ);
/*
* select the approprate underlying mechanism routine and
ctx->internal_ctx_id,
token_buffer);
else
- status = GSS_S_BAD_BINDINGS;
+ status = GSS_S_UNAVAILABLE;
return(status);
}
- return(GSS_S_NO_CONTEXT);
+ return (GSS_S_BAD_MECH);
}
-/* #ident "@(#)gss_release_cred.c 1.15 95/08/07 SMI" */
+/* #pragma ident "@(#)g_rel_cred.c 1.14 04/02/23 SMI" */
/*
* Copyright 1996 by Sun Microsystems, Inc.
gss_union_cred_t union_cred;
gss_mechanism mech;
- gss_initialize();
+ if (minor_status == NULL)
+ return (GSS_S_CALL_INACCESSIBLE_WRITE);
- if (minor_status)
- *minor_status = 0;
+ *minor_status = 0;
- /* if the cred_handle is null, return a NO_CRED error */
-
- if (cred_handle == GSS_C_NO_CREDENTIAL)
- return(GSS_S_NO_CRED);
+ if (cred_handle == NULL)
+ return (GSS_S_NO_CRED | GSS_S_CALL_INACCESSIBLE_READ);
/*
* Loop through the union_cred struct, selecting the approprate
union_cred = (gss_union_cred_t) *cred_handle;
*cred_handle = NULL;
- if (union_cred == NULL)
- return GSS_S_NO_CRED;
+ if (union_cred == (gss_union_cred_t)GSS_C_NO_CREDENTIAL)
+ return (GSS_S_COMPLETE);
status = GSS_S_COMPLETE;
status = GSS_S_NO_CRED;
} else
- status = GSS_S_NO_CRED;
+ status = GSS_S_UNAVAILABLE;
} else
- status = GSS_S_NO_CRED;
+ status = GSS_S_DEFECTIVE_CREDENTIAL;
}
gss_release_buffer(minor_status, &union_cred->auxinfo.name);
-/* #ident "@(#)gss_release_name.c 1.2 95/05/09 SMI" */
+/* #pragma ident "@(#)g_rel_name.c 1.11 04/02/23 SMI" */
/*
* Copyright 1996 by Sun Microsystems, Inc.
{
gss_union_name_t union_name;
- /* if input_name is NULL, return error */
+ if (minor_status == NULL)
+ return (GSS_S_CALL_INACCESSIBLE_WRITE);
+ *minor_status = 0;
+ /* if input_name is NULL, return error */
if (input_name == 0)
- return(GSS_S_BAD_NAME);
-
+ return (GSS_S_CALL_INACCESSIBLE_READ | GSS_S_BAD_NAME);
+
+ if (*input_name == GSS_C_NO_NAME)
+ return GSS_S_COMPLETE;
+
/*
* free up the space for the external_name and then
* free the union_name descriptor
union_name = (gss_union_name_t) *input_name;
*input_name = 0;
*minor_status = 0;
-
- if (union_name == NULL)
- return GSS_S_BAD_NAME;
if (union_name->name_type)
gss_release_oid(minor_status, &union_name->name_type);
-/* #ident "@(#)gss_release_oid_set.c 1.12 95/08/23 SMI" */
+/* #pragma ident "@(#)g_rel_oid_set.c 1.12 97/11/11 SMI" */
/*
* Copyright 1996 by Sun Microsystems, Inc.
OM_uint32 * minor_status;
gss_OID_set * set;
{
- size_t index;
- gss_OID oid;
+ OM_uint32 index;
+ gss_OID oid;
if (minor_status)
*minor_status = 0;
-/* #ident "@(#)gss_seal.c 1.10 95/08/07 SMI" */
+/* #pragma ident "@(#)g_seal.c 1.19 98/04/21 SMI" */
/*
* Copyright 1996 by Sun Microsystems, Inc.
#include "mglueP.h"
-OM_uint32 KRB5_CALLCONV
+OM_uint32
gss_seal (minor_status,
context_handle,
conf_req_flag,
gss_buffer_t input_message_buffer;
int * conf_state;
gss_buffer_t output_message_buffer;
-
{
+ /* EXPORT DELETE START */
+
OM_uint32 status;
gss_union_ctx_id_t ctx;
gss_mechanism mech;
- gss_initialize();
-
+ if (minor_status == NULL)
+ return (GSS_S_CALL_INACCESSIBLE_WRITE);
+ *minor_status = 0;
+
if (context_handle == GSS_C_NO_CONTEXT)
- return GSS_S_NO_CONTEXT;
+ return (GSS_S_CALL_INACCESSIBLE_READ | GSS_S_NO_CONTEXT);
+
+ if (input_message_buffer == NULL)
+ return (GSS_S_CALL_INACCESSIBLE_READ);
+
+ if (output_message_buffer == NULL)
+ return (GSS_S_CALL_INACCESSIBLE_WRITE);
/*
* select the approprate underlying mechanism routine and
conf_state,
output_message_buffer);
else
- status = GSS_S_BAD_BINDINGS;
+ status = GSS_S_UNAVAILABLE;
return(status);
}
-
- return(GSS_S_NO_CONTEXT);
+ /* EXPORT DELETE END */
+
+ return (GSS_S_BAD_MECH);
}
-OM_uint32 KRB5_CALLCONV
+OM_uint32
gss_wrap (minor_status,
context_handle,
conf_req_flag,
gss_buffer_t output_message_buffer;
{
- return gss_seal(minor_status, context_handle, conf_req_flag,
- (int) qop_req, input_message_buffer, conf_state,
- output_message_buffer);
+ return gss_seal(minor_status, (gss_ctx_id_t)context_handle,
+ conf_req_flag, (int) qop_req,
+ (gss_buffer_t)input_message_buffer, conf_state,
+ output_message_buffer);
}
/*
* New for V2
*/
-OM_uint32 KRB5_CALLCONV
+OM_uint32
gss_wrap_size_limit(minor_status, context_handle, conf_req_flag,
qop_req, req_output_size, max_input_size)
OM_uint32 *minor_status;
OM_uint32 req_output_size;
OM_uint32 *max_input_size;
{
- OM_uint32 status;
gss_union_ctx_id_t ctx;
gss_mechanism mech;
- gss_initialize();
+ if (minor_status == NULL)
+ return (GSS_S_CALL_INACCESSIBLE_WRITE);
+ *minor_status = 0;
if (context_handle == GSS_C_NO_CONTEXT)
- return GSS_S_NO_CONTEXT;
+ return (GSS_S_CALL_INACCESSIBLE_READ | GSS_S_NO_CONTEXT);
+
+ if (max_input_size == NULL)
+ return (GSS_S_CALL_INACCESSIBLE_WRITE);
/*
* select the approprate underlying mechanism routine and
mech = __gss_get_mechanism (ctx->mech_type);
if (!mech)
- return (GSS_S_NO_CONTEXT);
+ return (GSS_S_BAD_MECH);
if (!mech->gss_wrap_size_limit)
- return (GSS_S_BAD_BINDINGS);
+ return (GSS_S_UNAVAILABLE);
- status = mech->gss_wrap_size_limit(mech->context, minor_status,
- context_handle, conf_req_flag, qop_req,
- req_output_size, max_input_size);
- return(status);
+ return (mech->gss_wrap_size_limit(mech->context, minor_status,
+ ctx->internal_ctx_id, conf_req_flag, qop_req,
+ req_output_size, max_input_size));
}
-/* #ident "@(#)gss_sign.c 1.10 95/08/07 SMI" */
+/* #pragma ident "@(#)g_sign.c 1.14 98/04/23 SMI" */
/*
* Copyright 1996 by Sun Microsystems, Inc.
gss_union_ctx_id_t ctx;
gss_mechanism mech;
- gss_initialize();
+ if (minor_status == NULL)
+ return (GSS_S_CALL_INACCESSIBLE_WRITE);
+ *minor_status = 0;
if (context_handle == GSS_C_NO_CONTEXT)
- return GSS_S_NO_CONTEXT;
+ return (GSS_S_CALL_INACCESSIBLE_READ | GSS_S_NO_CONTEXT);
+ if (message_buffer == NULL)
+ return (GSS_S_CALL_INACCESSIBLE_READ);
+
+ if (msg_token == NULL)
+ return (GSS_S_CALL_INACCESSIBLE_WRITE);
+
+ msg_token->value = NULL;
+ msg_token->length = 0;
/*
* select the approprate underlying mechanism routine and
* call it.
message_buffer,
msg_token);
else
- status = GSS_S_BAD_BINDINGS;
+ status = GSS_S_UNAVAILABLE;
return(status);
}
- return(GSS_S_NO_CONTEXT);
+ return (GSS_S_BAD_MECH);
}
OM_uint32 KRB5_CALLCONV
--- /dev/null
+/*
+ * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/* #pragma ident "@(#)g_store_cred.c 1.2 04/04/05 SMI" */
+
+/*
+ * glue routine for gss_store_cred
+ */
+
+#include <mglueP.h>
+
+OM_uint32 gss_store_cred(minor_status,
+ input_cred_handle,
+ cred_usage,
+ desired_mech,
+ overwrite_cred,
+ default_cred,
+ elements_stored,
+ cred_usage_stored)
+
+OM_uint32 *minor_status;
+const gss_cred_id_t input_cred_handle;
+gss_cred_usage_t cred_usage;
+const gss_OID desired_mech;
+OM_uint32 overwrite_cred;
+OM_uint32 default_cred;
+gss_OID_set *elements_stored;
+gss_cred_usage_t *cred_usage_stored;
+
+{
+ OM_uint32 major_status = GSS_S_FAILURE;
+ gss_union_cred_t union_cred;
+ gss_cred_id_t mech_cred;
+ gss_mechanism mech;
+ gss_OID dmech;
+ int i;
+
+ /* Start by checking parameters */
+ if (minor_status == NULL)
+ return (GSS_S_CALL_INACCESSIBLE_WRITE|GSS_S_NO_CRED);
+ *minor_status = 0;
+
+ if (input_cred_handle == GSS_C_NO_CREDENTIAL)
+ return (GSS_S_CALL_INACCESSIBLE_READ);
+
+ if (elements_stored != NULL)
+ *elements_stored = GSS_C_NULL_OID_SET;
+
+ if (cred_usage_stored != NULL)
+ *cred_usage_stored = GSS_C_BOTH; /* there's no GSS_C_NEITHER */
+
+ union_cred = (gss_union_cred_t)input_cred_handle;
+
+ /* desired_mech != GSS_C_NULL_OID -> store one element */
+ if (desired_mech != GSS_C_NULL_OID) {
+ mech = __gss_get_mechanism(desired_mech);
+ if (mech == NULL)
+ return (GSS_S_BAD_MECH);
+
+ if (mech->gss_store_cred == NULL)
+ return (major_status);
+
+ mech_cred = __gss_get_mechanism_cred(union_cred, desired_mech);
+ if (mech_cred == GSS_C_NO_CREDENTIAL)
+ return (GSS_S_NO_CRED);
+
+ return (mech->gss_store_cred(mech->context,
+ minor_status,
+ (gss_cred_id_t)mech_cred,
+ cred_usage,
+ desired_mech,
+ overwrite_cred,
+ default_cred,
+ elements_stored,
+ cred_usage_stored));
+ }
+
+ /* desired_mech == GSS_C_NULL_OID -> store all elements */
+
+ *minor_status = 0;
+
+ for (i = 0; i < union_cred->count; i++) {
+ /* Get mech and cred element */
+ dmech = &union_cred->mechs_array[i];
+ mech = __gss_get_mechanism(dmech);
+ if (mech == NULL)
+ continue;
+
+ if (mech->gss_store_cred == NULL)
+ continue;
+
+ mech_cred = __gss_get_mechanism_cred(union_cred, dmech);
+ if (mech_cred == GSS_C_NO_CREDENTIAL)
+ continue; /* can't happen, but safe to ignore */
+
+ major_status = mech->gss_store_cred(mech->context,
+ minor_status,
+ (gss_cred_id_t)mech_cred,
+ cred_usage,
+ dmech,
+ overwrite_cred,
+ default_cred,
+ NULL,
+ cred_usage_stored);
+ if (major_status != GSS_S_COMPLETE)
+ continue;
+
+ /* Succeeded for at least one mech */
+
+ if (elements_stored == NULL)
+ continue;
+
+ if (*elements_stored == GSS_C_NULL_OID_SET) {
+ major_status = gss_create_empty_oid_set(minor_status,
+ elements_stored);
+
+ if (GSS_ERROR(major_status))
+ return (major_status);
+ }
+
+ major_status = gss_add_oid_set_member(minor_status, dmech,
+ elements_stored);
+
+ /* The caller should clean up elements_stored */
+ if (GSS_ERROR(major_status))
+ return (major_status);
+ }
+
+ /*
+ * Success with some mechs may mask failure with others, but
+ * that's what elements_stored is for.
+ */
+ return (major_status);
+}
-/* #ident "@(#)gss_unseal.c 1.10 95/08/07 SMI" */
+/* #pragma ident "@(#)g_unseal.c 1.13 98/01/22 SMI" */
/*
* Copyright 1996 by Sun Microsystems, Inc.
int * qop_state;
{
+/* EXPORT DELETE START */
OM_uint32 status;
gss_union_ctx_id_t ctx;
gss_mechanism mech;
- gss_initialize();
+ if (minor_status == NULL)
+ return (GSS_S_CALL_INACCESSIBLE_WRITE);
+ *minor_status = 0;
if (context_handle == GSS_C_NO_CONTEXT)
- return GSS_S_NO_CONTEXT;
+ return (GSS_S_CALL_INACCESSIBLE_READ | GSS_S_NO_CONTEXT);
+
+ if (GSS_EMPTY_BUFFER(input_message_buffer))
+ return (GSS_S_CALL_INACCESSIBLE_READ);
+
+ if (output_message_buffer == NULL)
+ return (GSS_S_CALL_INACCESSIBLE_WRITE);
+
+ output_message_buffer->length = 0;
+ output_message_buffer->value = NULL;
/*
* select the approprate underlying mechanism routine and
conf_state,
qop_state);
else
- status = GSS_S_BAD_BINDINGS;
+ status = GSS_S_UNAVAILABLE;
return(status);
}
- return(GSS_S_NO_CONTEXT);
+/* EXPORT DELETE END */
+
+ return (GSS_S_BAD_MECH);
}
OM_uint32 KRB5_CALLCONV
qop_state)
OM_uint32 * minor_status;
-gss_ctx_id_t context_handle;
-gss_buffer_t input_message_buffer;
+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;
{
- return (gss_unseal(minor_status, context_handle,
- input_message_buffer,
- output_message_buffer,
- conf_state, (int *) qop_state));
+ return (gss_unseal(minor_status, (gss_ctx_id_t)context_handle,
+ (gss_buffer_t)input_message_buffer,
+ output_message_buffer, conf_state, (int *) qop_state));
}
--- /dev/null
+/*
+ * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/* #pragma ident "@(#)g_userok.c 1.1 04/03/25 SMI" */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <deflt.h>
+#include <mglueP.h>
+#include <gssapi/gssapi.h>
+#include <gssapi/gssapi_ext.h>
+
+
+static OM_uint32
+compare_names(OM_uint32 *minor,
+ const gss_OID mech_type,
+ const gss_name_t name,
+ const char *user,
+ int *user_ok)
+{
+
+ OM_uint32 status, tmpMinor;
+ gss_name_t imported_name;
+ gss_name_t canon_name;
+ gss_buffer_desc gss_user;
+ int match = 0;
+
+ *user_ok = 0;
+
+ gss_user.value = (void *)user;
+ if (!gss_user.value || !name || !mech_type)
+ return (GSS_S_BAD_NAME);
+ gss_user.length = strlen(gss_user.value);
+
+ status = gss_import_name(minor,
+ &gss_user,
+ GSS_C_NT_USER_NAME,
+ &imported_name);
+ if (status != GSS_S_COMPLETE) {
+ goto out;
+ }
+
+ status = gss_canonicalize_name(minor,
+ imported_name,
+ mech_type,
+ &canon_name);
+ if (status != GSS_S_COMPLETE) {
+ (void) gss_release_name(&tmpMinor, &imported_name);
+ goto out;
+ }
+
+ status = gss_compare_name(minor,
+ canon_name,
+ name,
+ &match);
+ (void) gss_release_name(&tmpMinor, &canon_name);
+ (void) gss_release_name(&tmpMinor, &imported_name);
+ if (status == GSS_S_COMPLETE) {
+ if (match)
+ *user_ok = 1; /* remote user is a-ok */
+ }
+
+out:
+ return (status);
+}
+
+
+OM_uint32
+__gss_userok(OM_uint32 *minor,
+ const gss_name_t name,
+ const char *user,
+ int *user_ok)
+
+{
+ gss_mechanism mech;
+ gss_union_name_t intName;
+ gss_name_t mechName = NULL;
+ OM_uint32 major;
+
+ if (minor == NULL || user_ok == NULL)
+ return (GSS_S_CALL_INACCESSIBLE_WRITE);
+
+ if (name == NULL || user == NULL)
+ return (GSS_S_CALL_INACCESSIBLE_READ);
+
+ *user_ok = 0;
+ *minor = GSS_S_COMPLETE;
+
+ intName = (gss_union_name_t)name;
+
+ mech = __gss_get_mechanism(intName->mech_type);
+ if (mech == NULL)
+ return (GSS_S_UNAVAILABLE);
+
+ /* may need to import the name if this is not MN */
+ if (intName->mech_type == NULL) {
+ return (GSS_S_FAILURE);
+ } else
+ mechName = intName->mech_name;
+
+ if (mech->__gss_userok)
+ major = mech->__gss_userok(mech->context, minor, mechName,
+ user, user_ok);
+ else
+ major = compare_names(minor, intName->mech_type,
+ name, user, user_ok);
+
+ return (major);
+} /* gss_userok */
--- /dev/null
+/*
+ * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/* #pragma ident "@(#)g_utils.c 1.8 04/02/23 SMI" */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <strings.h>
+#include <ctype.h>
+#include <errno.h>
+#include <gssapi/gssapi.h>
+#include <gssapi/gssapi_ext.h>
+#include <synch.h>
+
+#define Q_DEFAULT "default"
+#define BUFLEN 256
+
+static int qop_num_pair_cnt;
+static const char QOP_NUM_FILE[] = "/etc/gss/qop";
+static qop_num qop_num_pairs[MAX_QOP_NUM_PAIRS+1];
+static mutex_t qopfile_lock = DEFAULTMUTEX;
+
+static OM_uint32 __gss_read_qop_file(void);
+
+/*
+ * This routine fetches qop and num from "/etc/gss/qop".
+ * There is a memory leak associated with rereading this file,
+ * because we can't free the qop_num_pairs array when we reread
+ * the file (some callers may have been given these pointers).
+ * In general, this memory leak should be a small one, because
+ * we don't expect the qop file to be changed and reread often.
+ */
+static OM_uint32
+__gss_read_qop_file(void)
+{
+ char buf[BUFLEN]; /* one line from the file */
+ char *name, *next;
+ char *qopname, *num_str;
+ char *line;
+ FILE *fp;
+ static int last = 0;
+ struct stat stbuf;
+ OM_uint32 major = GSS_S_COMPLETE;
+
+ (void) mutex_lock(&qopfile_lock);
+ if (stat(QOP_NUM_FILE, &stbuf) != 0 || stbuf.st_mtime < last) {
+ if (!qop_num_pairs[0].qop) {
+ major = GSS_S_FAILURE;
+ }
+ goto done;
+ }
+ last = stbuf.st_mtime;
+
+ fp = fopen(QOP_NUM_FILE, "r");
+ if (fp == (FILE *)0) {
+ major = GSS_S_FAILURE;
+ goto done;
+ }
+
+ /*
+ * For each line in the file parse it appropriately.
+ * File format : qopname num(int)
+ * Note that we silently ignore corrupt entries.
+ */
+ qop_num_pair_cnt = 0;
+ while (!feof(fp)) {
+ line = fgets(buf, BUFLEN, fp);
+ if (line == NULL)
+ break;
+
+ /* Skip comments and blank lines */
+ if ((*line == '#') || (*line == '\n'))
+ continue;
+
+ /* Skip trailing comments */
+ next = strchr(line, '#');
+ if (next)
+ *next = '\0';
+
+ name = &(buf[0]);
+ while (isspace(*name))
+ name++;
+ if (*name == '\0') /* blank line */
+ continue;
+
+ qopname = name; /* will contain qop name */
+ while (!isspace(*qopname))
+ qopname++;
+ if (*qopname == '\0') {
+ continue;
+ }
+ next = qopname+1;
+ *qopname = '\0'; /* null terminate qopname */
+ qop_num_pairs[qop_num_pair_cnt].qop = strdup(name);
+ if (qop_num_pairs[qop_num_pair_cnt].qop == NULL)
+ continue;
+
+ name = next;
+ while (isspace(*name))
+ name++;
+ if (*name == '\0') { /* end of line, no num */
+ free(qop_num_pairs[qop_num_pair_cnt].qop);
+ continue;
+ }
+ num_str = name; /* will contain num (n) */
+ while (!isspace(*num_str))
+ num_str++;
+ next = num_str+1;
+ *num_str++ = '\0'; /* null terminate num_str */
+
+ qop_num_pairs[qop_num_pair_cnt].num = (OM_uint32)atoi(name);
+ name = next;
+ while (isspace(*name))
+ name++;
+ if (*name == '\0') { /* end of line, no mechanism */
+ free(qop_num_pairs[qop_num_pair_cnt].qop);
+ continue;
+ }
+ num_str = name; /* will contain mech */
+ while (!isspace(*num_str))
+ num_str++;
+ *num_str = '\0';
+
+ qop_num_pairs[qop_num_pair_cnt].mech = strdup(name);
+ if (qop_num_pairs[qop_num_pair_cnt].mech == NULL) {
+ free(qop_num_pairs[qop_num_pair_cnt].qop);
+ continue;
+ }
+
+ if (qop_num_pair_cnt++ >= MAX_QOP_NUM_PAIRS)
+ break;
+ }
+ (void) fclose(fp);
+done:
+ (void) mutex_unlock(&qopfile_lock);
+ return (major);
+}
+
+OM_uint32
+__gss_qop_to_num(
+ char *qop,
+ char *mech,
+ OM_uint32 *num
+)
+{
+ int i;
+ OM_uint32 major = GSS_S_FAILURE;
+
+ if (!num)
+ return (GSS_S_CALL_INACCESSIBLE_WRITE);
+
+ if (qop == NULL || strlen(qop) == 0 ||
+ strcasecmp(qop, Q_DEFAULT) == 0) {
+ *num = GSS_C_QOP_DEFAULT;
+ return (GSS_S_COMPLETE);
+ }
+
+ if ((major = __gss_read_qop_file()) != GSS_S_COMPLETE)
+ return (major);
+
+ for (i = 0; i < qop_num_pair_cnt; i++) {
+ if ((strcasecmp(mech, qop_num_pairs[i].mech) == 0) &&
+ (strcasecmp(qop, qop_num_pairs[i].qop) == 0)) {
+ *num = qop_num_pairs[i].num;
+ return (GSS_S_COMPLETE);
+ }
+ }
+
+ return (GSS_S_FAILURE);
+}
+
+OM_uint32
+__gss_num_to_qop(
+ char *mech,
+ OM_uint32 num,
+ char **qop
+)
+{
+ int i;
+ OM_uint32 major;
+
+ if (!qop)
+ return (GSS_S_CALL_INACCESSIBLE_WRITE);
+ *qop = NULL;
+
+ if (num == GSS_C_QOP_DEFAULT) {
+ *qop = Q_DEFAULT;
+ return (GSS_S_COMPLETE);
+ }
+
+ if (mech == NULL)
+ return (GSS_S_CALL_INACCESSIBLE_READ);
+
+ if ((major = __gss_read_qop_file()) != GSS_S_COMPLETE)
+ return (major);
+
+ for (i = 0; i < qop_num_pair_cnt; i++) {
+ if ((strcasecmp(mech, qop_num_pairs[i].mech) == 0) &&
+ (num == qop_num_pairs[i].num)) {
+ *qop = qop_num_pairs[i].qop;
+ return (GSS_S_COMPLETE);
+ }
+ }
+ return (GSS_S_FAILURE);
+}
+
+/*
+ * For a given mechanism pass back qop information about it in a buffer
+ * of size MAX_QOPS_PER_MECH+1.
+ */
+OM_uint32
+__gss_get_mech_info(
+ char *mech,
+ char **qops
+)
+{
+ int i, cnt = 0;
+ OM_uint32 major = GSS_S_COMPLETE;
+
+ if (!qops)
+ return (GSS_S_CALL_INACCESSIBLE_WRITE);
+ *qops = NULL;
+
+ if (!mech)
+ return (GSS_S_CALL_INACCESSIBLE_READ);
+
+ if ((major = __gss_read_qop_file()) != GSS_S_COMPLETE)
+ return (major);
+
+ for (i = 0; i < qop_num_pair_cnt; i++) {
+ if (strcmp(mech, qop_num_pairs[i].mech) == 0) {
+ if (cnt >= MAX_QOPS_PER_MECH) {
+ return (GSS_S_FAILURE);
+ }
+ qops[cnt++] = qop_num_pairs[i].qop;
+ }
+ }
+ qops[cnt] = NULL;
+ return (GSS_S_COMPLETE);
+}
+
+/*
+ * Copy the qop values and names for the mechanism back in a qop_num
+ * buffer of size MAX_QOPS_PER_MECH provided by the caller.
+ */
+OM_uint32
+__gss_mech_qops(
+ char *mech,
+ qop_num *mechqops,
+ int *numqop
+)
+{
+ int i;
+ OM_uint32 major;
+ int cnt = 0;
+
+ if (!mechqops || !numqop)
+ return (GSS_S_CALL_INACCESSIBLE_WRITE);
+ *numqop = 0;
+
+ if (!mech)
+ return (GSS_S_CALL_INACCESSIBLE_READ);
+
+ if ((major = __gss_read_qop_file()) != GSS_S_COMPLETE)
+ return (major);
+
+ for (i = 0; i < qop_num_pair_cnt; i++) {
+ if (strcasecmp(mech, qop_num_pairs[i].mech) == 0) {
+ if (cnt >= MAX_QOPS_PER_MECH) {
+ return (GSS_S_FAILURE);
+ }
+ mechqops[cnt++] = qop_num_pairs[i];
+ }
+ }
+ *numqop = cnt;
+ return (GSS_S_COMPLETE);
+}
-/* #ident "@(#)gss_verify.c 1.9 95/08/07 SMI" */
+/* #pragma ident "@(#)g_verify.c 1.13 98/04/23 SMI" */
/*
* Copyright 1996 by Sun Microsystems, Inc.
gss_union_ctx_id_t ctx;
gss_mechanism mech;
- gss_initialize();
+
+ if (minor_status == NULL)
+ return (GSS_S_CALL_INACCESSIBLE_WRITE);
+ *minor_status = 0;
if (context_handle == GSS_C_NO_CONTEXT)
- return GSS_S_NO_CONTEXT;
+ return (GSS_S_CALL_INACCESSIBLE_READ | GSS_S_NO_CONTEXT);
+
+ if ((message_buffer == NULL) || GSS_EMPTY_BUFFER(token_buffer))
+ return (GSS_S_CALL_INACCESSIBLE_READ);
/*
* select the approprate underlying mechanism routine and
token_buffer,
qop_state);
else
- status = GSS_S_BAD_BINDINGS;
+ status = GSS_S_UNAVAILABLE;
return(status);
}
- return(GSS_S_NO_CONTEXT);
+ return (GSS_S_BAD_MECH);
}
OM_uint32 KRB5_CALLCONV
-/* #ident "@(#)gssd_pname_to_uid.c 1.5 95/08/02 SMI" */
+/* #pragma ident "@(#)gssd_pname_to_uid.c 1.18 04/02/23 SMI" */
/*
* Copyright 1996 by Sun Microsystems, Inc.
int status;
gss_mechanism mech;
- gss_initialize();
-
/*
* find the appropriate mechanism specific pname_to_uid procedure and
* call it.
#include "mechglue.h"
+#define g_OID_equal(o1, o2) \
+ (((o1)->length == (o2)->length) && \
+ (memcmp((o1)->elements, (o2)->elements, (o1)->length) == 0))
+
+#define g_OID_copy(o1, o2) \
+do { \
+ memcpy((o1)->elements, (o2)->elements, (o2)->length); \
+ (o1)->length = (o2)->length; \
+} while (0)
+
+#define GSS_EMPTY_BUFFER(buf) ((buf) == NULL ||\
+ (buf)->value == NULL || (buf)->length == 0)
+
/*
* Array of context IDs typed by mechanism OID
*/
typedef struct gss_union_cred_auxinfo {
gss_buffer_desc name;
gss_OID name_type;
- time_t creation_time;
+ OM_uint32 creation_time;
OM_uint32 time_rec;
int cred_usage;
} gss_union_cred_auxinfo;
typedef struct gss_union_cred_t {
int count;
gss_OID mechs_array;
- gss_cred_id_t * cred_array;
+ gss_cred_id_t *cred_array;
gss_union_cred_auxinfo auxinfo;
} gss_union_cred_desc, *gss_union_cred_t;
+typedef OM_uint32 (*gss_acquire_cred_with_password_sfct)(
+ void *, /* context */
+ OM_uint32 *, /* minor_status */
+ const gss_name_t, /* desired_name */
+ const gss_buffer_t, /* password */
+ OM_uint32, /* time_req */
+ const gss_OID_set, /* desired_mechs */
+ int, /* cred_usage */
+ gss_cred_id_t *, /* output_cred_handle */
+ gss_OID_set *, /* actual_mechs */
+ OM_uint32 * /* time_rec */
+ /* */);
+
/********************************************************/
/* The Mechanism Dispatch Table -- a mechanism needs to */
/* define one of these and provide a function to return */
gss_OID, /* mech type */
uid_t * /* uid */
);
-
+ OM_uint32 (*__gss_userok)
+ (
+ void *, /* context */
+ OM_uint32 *, /* minor_status */
+ const gss_name_t, /* pname */
+ const char *, /* local user */
+ int * /* user ok? */
+ /* */);
+ OM_uint32 (*gss_export_name)
+ (
+ void *, /* context */
+ OM_uint32 *, /* minor_status */
+ const gss_name_t, /* input_name */
+ gss_buffer_t /* exported_name */
+ /* */);
+ OM_uint32 (*gss_store_cred)
+ (
+ void *, /* context */
+ OM_uint32 *, /* minor_status */
+ const gss_cred_id_t, /* input_cred */
+ gss_cred_usage_t, /* cred_usage */
+ const gss_OID, /* desired_mech */
+ OM_uint32, /* overwrite_cred */
+ OM_uint32, /* default_cred */
+ gss_OID_set *, /* elements_stored */
+ gss_cred_usage_t * /* cred_usage_stored */
+ /* */);
} *gss_mechanism;
+/* This structure MUST NOT be used by any code outside libgss */
+typedef struct gss_config_ext {
+ gss_acquire_cred_with_password_sfct gss_acquire_cred_with_password;
+} *gss_mechanism_ext;
+
+/*
+ * In the user space we use a wrapper structure to encompass the
+ * mechanism entry points. The wrapper contain the mechanism
+ * entry points and other data which is only relevant to the gss-api
+ * layer. In the kernel we use only the gss_config strucutre because
+ * the kernal does not cantain any of the extra gss-api specific data.
+ */
+typedef struct gss_mech_config {
+ char *kmodName; /* kernel module name */
+ char *uLibName; /* user library name */
+ char *mechNameStr; /* mechanism string name */
+ char *optionStr; /* optional mech parameters */
+ void *dl_handle; /* RTLD object handle for the mech */
+ gss_OID mech_type; /* mechanism oid */
+ gss_mechanism mech; /* mechanism initialization struct */
+ gss_mechanism_ext mech_ext; /* extensions */
+ struct gss_mech_config *next; /* next element in the list */
+} *gss_mech_info;
+
/********************************************************/
/* Internal mechglue routines */
+int gssint_mechglue_init(void);
+void gssint_mechglue_fini(void);
+
gss_mechanism __gss_get_mechanism (gss_OID);
+gss_mechanism_ext __gss_get_mechanism_ext(const gss_OID);
OM_uint32 __gss_get_mech_type (gss_OID, gss_buffer_t);
+char *__gss_get_kmodName(const gss_OID);
+char *__gss_get_modOptions(const gss_OID);
OM_uint32 __gss_import_internal_name (OM_uint32 *, gss_OID, gss_union_name_t,
gss_name_t *);
+OM_uint32 __gss_export_internal_name(OM_uint32 *, const gss_OID,
+ const gss_name_t, gss_buffer_t);
OM_uint32 __gss_display_internal_name (OM_uint32 *, gss_OID, gss_name_t,
gss_buffer_t, gss_OID *);
OM_uint32 __gss_release_internal_name (OM_uint32 *, gss_OID, gss_name_t *);
gss_OID /* mech_type */
);
+OM_uint32 __gss_create_copy_buffer(
+ const gss_buffer_t, /* src buffer */
+ gss_buffer_t *, /* destination buffer */
+ int /* NULL terminate buffer ? */
+);
+
OM_uint32 generic_gss_release_oid
(OM_uint32 *, /* minor_status */
gss_OID * /* oid */
gss_OID * /* oid */
);
+OM_uint32 gss_copy_oid_set(
+ OM_uint32 *, /* minor_status */
+ const gss_OID_set_desc *, /* oid set */
+ gss_OID_set * /* new oid set */
+);
gss_OID gss_find_mechanism_from_name_type (gss_OID); /* name_type */
gss_OID /* mech */
);
+/*
+ * Sun extensions to GSS-API v2
+ */
+
+OM_uint32
+__gss_mech_to_oid(
+ const char *mech, /* mechanism string name */
+ gss_OID *oid /* mechanism oid */
+);
+
+const char *
+__gss_oid_to_mech(
+ const gss_OID oid /* mechanism oid */
+);
+
+OM_uint32
+__gss_get_mechanisms(
+ char *mechArray[], /* array to populate with mechs */
+ int arrayLen /* length of passed in array */
+);
+
+OM_uint32
+__gss_userok(
+ OM_uint32 *, /* minor */
+ const gss_name_t, /* name */
+ const char *, /* user */
+ int * /* user_ok */
+);
+
+OM_uint32
+gss_store_cred(
+ OM_uint32 *, /* minor_status */
+ const gss_cred_id_t, /* input_cred_handle */
+ gss_cred_usage_t, /* cred_usage */
+ const gss_OID, /* desired_mech */
+ OM_uint32, /* overwrite_cred */
+ OM_uint32, /* default_cred */
+ gss_OID_set *, /* elements_stored */
+ gss_cred_usage_t * /* cred_usage_stored */
+);
+
+int
+get_der_length(
+ unsigned char **, /* buf */
+ unsigned int, /* buf_len */
+ unsigned int * /* bytes */
+);
+
+unsigned int
+der_length_size(unsigned int /* len */);
+
+int
+put_der_length(
+ unsigned int, /* length */
+ unsigned char **, /* buf */
+ unsigned int /* max_len */
+);
+
#endif /* _GSS_MECHGLUEP_H */
+/* #pragma ident "@(#)oid_ops.c 1.19 04/02/23 SMI" */
/*
* lib/gssapi/generic/oid_ops.c
*
OM_uint32 *minor_status;
gss_OID *oid;
{
- *minor_status = 0;
+ if (minor_status)
+ *minor_status = 0;
if (*oid == GSS_C_NO_OID)
return(GSS_S_COMPLETE);
* descriptor. This allows applications to freely mix their own heap-
* allocated OID values with OIDs returned by GSS-API.
*/
- if ((*oid != gss_nt_user_name) &&
- (*oid != gss_nt_machine_uid_name) &&
- (*oid != gss_nt_string_uid_name) &&
+
+ /*
+ * We use the official OID definitions instead of the unofficial OID
+ * defintions. But we continue to support the unofficial OID
+ * gss_nt_service_name just in case if some gss applications use
+ * the old OID.
+ */
+
+ if ((*oid != GSS_C_NT_USER_NAME) &&
+ (*oid != GSS_C_NT_MACHINE_UID_NAME) &&
+ (*oid != GSS_C_NT_STRING_UID_NAME) &&
+ (*oid != GSS_C_NT_HOSTBASED_SERVICE) &&
+ (*oid != GSS_C_NT_ANONYMOUS) &&
+ (*oid != GSS_C_NT_EXPORT_NAME) &&
(*oid != gss_nt_service_name)) {
free((*oid)->elements);
free(*oid);
{
gss_OID p;
+ *minor_status = 0;
+
p = (gss_OID) malloc(sizeof(gss_OID_desc));
if (!p) {
*minor_status = ENOMEM;
p->elements = malloc(p->length);
if (!p->elements) {
free(p);
- *minor_status = ENOMEM;
return GSS_S_FAILURE;
}
memcpy(p->elements, oid->elements, p->length);
OM_uint32 *minor_status;
gss_OID_set *oid_set;
{
+ *minor_status = 0;
+
if ((*oid_set = (gss_OID_set) malloc(sizeof(gss_OID_set_desc)))) {
memset(*oid_set, 0, sizeof(gss_OID_set_desc));
- *minor_status = 0;
return(GSS_S_COMPLETE);
}
else {
gss_OID elist;
gss_OID lastel;
+ *minor_status = 0;
+
+ if (member_oid == NULL || member_oid->length == 0 ||
+ member_oid->elements == NULL)
+ return (GSS_S_CALL_INACCESSIBLE_READ);
+
elist = (*oid_set)->elements;
/* Get an enlarged copy of the array */
if (((*oid_set)->elements = (gss_OID) malloc(((*oid_set)->count+1) *
gss_OID_set set;
int *present;
{
- size_t i;
+ OM_uint32 i;
int result;
+ *minor_status = 0;
+
+ if (member == NULL || set == NULL)
+ return (GSS_S_CALL_INACCESSIBLE_READ);
+
+ if (present == NULL)
+ return (GSS_S_CALL_INACCESSIBLE_WRITE);
+
result = 0;
for (i=0; i<set->count; i++) {
if ((set->elements[i].length == member->length) &&
}
}
*present = result;
- *minor_status = 0;
return(GSS_S_COMPLETE);
}
gss_buffer_t oid_str;
{
char numstr[128];
- unsigned long number;
+ OM_uint32 number;
int numshift;
- size_t string_length;
- size_t i;
+ OM_uint32 string_length;
+ OM_uint32 i;
unsigned char *cp;
char *bp;
+ *minor_status = 0;
+
+ if (oid == NULL || oid->length == 0 || oid->elements == NULL)
+ return (GSS_S_CALL_INACCESSIBLE_READ);
+
+ if (oid_str == NULL)
+ return (GSS_S_CALL_INACCESSIBLE_WRITE);
+
/* Decoded according to krb5/gssapi_krb5.c */
/* First determine the size of the string */
sprintf(numstr, "%ld ", number%40);
string_length += strlen(numstr);
for (i=1; i<oid->length; i++) {
- if ( (size_t) (numshift+7) < (sizeof(unsigned long)*8)) {
+ if ((OM_uint32) (numshift+7) < (sizeof (OM_uint32)*8)) {/* XXX */
number = (number << 7) | (cp[i] & 0x7f);
numshift += 7;
}
else {
- *minor_status = EINVAL;
return(GSS_S_FAILURE);
}
if ((cp[i] & 0x80) == 0) {
string_length += 4;
if ((bp = (char *) malloc(string_length))) {
strcpy(bp, "{ ");
- number = (unsigned long) cp[0];
+ number = (OM_uint32) cp[0];
sprintf(numstr, "%ld ", number/40);
strcat(bp, numstr);
sprintf(numstr, "%ld ", number%40);
strcat(bp, "}");
oid_str->length = strlen(bp)+1;
oid_str->value = (void *) bp;
- *minor_status = 0;
return(GSS_S_COMPLETE);
}
*minor_status = ENOMEM;
int index;
unsigned char *op;
+ *minor_status = 0;
+
+ if (GSS_EMPTY_BUFFER(oid_str))
+ return (GSS_S_CALL_INACCESSIBLE_READ);
+
+ if (oid == NULL)
+ return (GSS_S_CALL_INACCESSIBLE_WRITE);
+
brace = 0;
bp = (char *) oid_str->value;
cp = bp;
}
while ((bp < &cp[oid_str->length]) && isdigit(*bp))
bp++;
- while ((bp < &cp[oid_str->length]) && isspace(*bp))
+ while ((bp < &cp[oid_str->length]) &&
+ (isspace(*bp) || *bp == '.'))
bp++;
nbytes++;
while (isdigit(*bp)) {
- if (sscanf(bp, "%ld", &numbuf) != 1) {
- *minor_status = EINVAL;
+ if (sscanf(bp, "%d", &numbuf) != 1) {
return(GSS_S_FAILURE);
}
while (numbuf) {
}
while ((bp < &cp[oid_str->length]) && isdigit(*bp))
bp++;
- while ((bp < &cp[oid_str->length]) && isspace(*bp))
+ while ((bp < &cp[oid_str->length]) &&
+ (isspace(*bp) || *bp == '.'))
bp++;
}
if (brace && (*bp != '}')) {
- *minor_status = EINVAL;
return(GSS_S_FAILURE);
}
* Phew! We've come this far, so the syntax is good.
*/
if ((*oid = (gss_OID) malloc(sizeof(gss_OID_desc)))) {
- if (((*oid)->elements = (void *) malloc((size_t) nbytes))) {
+ if (((*oid)->elements = (void *) malloc(nbytes))) {
(*oid)->length = nbytes;
op = (unsigned char *) (*oid)->elements;
bp = startp;
- sscanf(bp, "%ld", &numbuf);
+ (void) sscanf(bp, "%d", &numbuf);
while (isdigit(*bp))
bp++;
- while (isspace(*bp))
+ while (isspace(*bp) || *bp == '.')
bp++;
onumbuf = 40*numbuf;
- sscanf(bp, "%ld", &numbuf);
+ (void) sscanf(bp, "%d", &numbuf);
onumbuf += numbuf;
*op = (unsigned char) onumbuf;
op++;
while (isdigit(*bp))
bp++;
- while (isspace(*bp))
+ while (isspace(*bp) || *bp == '.')
bp++;
while (isdigit(*bp)) {
- sscanf(bp, "%ld", &numbuf);
+ (void) sscanf(bp, "%d", &numbuf);
nbytes = 0;
/* Have to fill in the bytes msb-first */
onumbuf = numbuf;
}
while (isdigit(*bp))
bp++;
- while (isspace(*bp))
+ while (isspace(*bp) || *bp == '.')
bp++;
}
- *minor_status = 0;
return(GSS_S_COMPLETE);
}
else {
*oid = GSS_C_NO_OID;
}
}
- *minor_status = ENOMEM;
return(GSS_S_FAILURE);
}
+/*
+ * Copyright 1993 by OpenVision Technologies, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appears in all copies and
+ * that both that copyright notice and this permission notice appear in
+ * supporting documentation, and that the name of OpenVision not be used
+ * in advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission. OpenVision makes no
+ * representations about the suitability of this software for any
+ * purpose. It is provided "as is" without express or implied warranty.
+ *
+ * OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+ * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+OM_uint32
+gss_copy_oid_set(
+ OM_uint32 *minor_status,
+ const gss_OID_set_desc * const oidset,
+ gss_OID_set *new_oidset
+ )
+{
+ gss_OID_set_desc *copy;
+ OM_uint32 minor = 0;
+ OM_uint32 major = GSS_S_COMPLETE;
+ OM_uint32 index;
+
+ if (minor_status)
+ *minor_status = 0;
+
+ if (oidset == NULL)
+ return (GSS_S_CALL_INACCESSIBLE_READ);
+
+ if (new_oidset == NULL)
+ return (GSS_S_CALL_INACCESSIBLE_WRITE);
+
+ *new_oidset = NULL;
+
+ if ((copy = (gss_OID_set_desc *) calloc(1, sizeof (*copy))) == NULL) {
+ major = GSS_S_FAILURE;
+ goto done;
+ }
+
+ if ((copy->elements = (gss_OID_desc *)
+ calloc(oidset->count, sizeof (*copy->elements))) == NULL) {
+ major = GSS_S_FAILURE;
+ goto done;
+ }
+ copy->count = oidset->count;
+
+ for (index = 0; index < copy->count; index++) {
+ gss_OID_desc *out = ©->elements[index];
+ gss_OID_desc *in = &oidset->elements[index];
+
+ if ((out->elements = (void *) malloc(in->length)) == NULL) {
+ major = GSS_S_FAILURE;
+ goto done;
+ }
+ (void) memcpy(out->elements, in->elements, in->length);
+ out->length = in->length;
+ }
+
+ *new_oidset = copy;
+done:
+ if (major != GSS_S_COMPLETE) {
+ (void) gss_release_oid_set(&minor, ©);
+ }
+
+ return (major);
+}