From 34f4d58d9956768d835fe58e5c7454a456e4997e Mon Sep 17 00:00:00 2001 From: Tom Yu Date: Thu, 26 Jan 2006 22:05:08 +0000 Subject: [PATCH] interim commit git-svn-id: svn://anonsvn.mit.edu/krb5/users/tlyu/branches/mechglue@17628 dc483132-0cff-0310-8789-dd5450dbe970 --- src/lib/gssapi/Makefile.in | 8 +- src/lib/gssapi/configure.in | 2 +- src/lib/gssapi/generic/Makefile.in | 3 - src/lib/gssapi/generic/gssapi.hin | 7 + src/lib/gssapi/generic/gssapi_err_generic.et | 3 + src/lib/gssapi/gss_libinit.c | 6 + src/lib/gssapi/krb5/Makefile.in | 2 +- src/lib/gssapi/krb5/copy_ccache.c | 2 +- src/lib/gssapi/krb5/get_tkt_flags.c | 2 +- src/lib/gssapi/krb5/gssapiP_krb5.h | 30 + src/lib/gssapi/krb5/gssapi_krb5.c | 2 +- src/lib/gssapi/krb5/krb5_gss_glue.c | 641 ++++++++++-- src/lib/gssapi/krb5/lucid_context.c | 2 +- src/lib/gssapi/krb5/set_allowable_enctypes.c | 8 +- src/lib/gssapi/mechglue/Makefile.in | 183 ++-- .../gssapi/mechglue/g_accept_sec_context.c | 199 +++- src/lib/gssapi/mechglue/g_acquire_cred.c | 560 +++++------ src/lib/gssapi/mechglue/g_canon_name.c | 155 +++ src/lib/gssapi/mechglue/g_compare_name.c | 54 +- src/lib/gssapi/mechglue/g_context_time.c | 17 +- .../gssapi/mechglue/g_delete_sec_context.c | 22 +- src/lib/gssapi/mechglue/g_dsp_name.c | 44 +- src/lib/gssapi/mechglue/g_dsp_status.c | 287 +++++- src/lib/gssapi/mechglue/g_dup_name.c | 118 +++ src/lib/gssapi/mechglue/g_exp_sec_context.c | 16 +- src/lib/gssapi/mechglue/g_export_name.c | 55 ++ src/lib/gssapi/mechglue/g_glue.c | 337 ++++++- src/lib/gssapi/mechglue/g_imp_name.c | 284 ++++-- src/lib/gssapi/mechglue/g_imp_sec_context.c | 51 +- src/lib/gssapi/mechglue/g_init_sec_context.c | 130 +-- src/lib/gssapi/mechglue/g_initialize.c | 931 ++++++++++++++++-- src/lib/gssapi/mechglue/g_inq_context.c | 62 +- src/lib/gssapi/mechglue/g_inq_cred.c | 116 ++- src/lib/gssapi/mechglue/g_inq_names.c | 100 +- src/lib/gssapi/mechglue/g_mechname.c | 4 - src/lib/gssapi/mechglue/g_oid_ops.c | 34 +- src/lib/gssapi/mechglue/g_process_context.c | 15 +- src/lib/gssapi/mechglue/g_rel_cred.c | 22 +- src/lib/gssapi/mechglue/g_rel_name.c | 17 +- src/lib/gssapi/mechglue/g_rel_oid_set.c | 6 +- src/lib/gssapi/mechglue/g_seal.c | 60 +- src/lib/gssapi/mechglue/g_sign.c | 20 +- src/lib/gssapi/mechglue/g_store_cred.c | 136 +++ src/lib/gssapi/mechglue/g_unseal.c | 35 +- src/lib/gssapi/mechglue/g_userok.c | 112 +++ src/lib/gssapi/mechglue/g_utils.c | 281 ++++++ src/lib/gssapi/mechglue/g_verify.c | 16 +- src/lib/gssapi/mechglue/gssd_pname_to_uid.c | 4 +- src/lib/gssapi/mechglue/mglueP.h | 159 ++- src/lib/gssapi/mechglue/oid_ops.c | 174 +++- 50 files changed, 4442 insertions(+), 1092 deletions(-) create mode 100644 src/lib/gssapi/mechglue/g_canon_name.c create mode 100644 src/lib/gssapi/mechglue/g_dup_name.c create mode 100644 src/lib/gssapi/mechglue/g_export_name.c create mode 100644 src/lib/gssapi/mechglue/g_store_cred.c create mode 100644 src/lib/gssapi/mechglue/g_userok.c create mode 100644 src/lib/gssapi/mechglue/g_utils.c diff --git a/src/lib/gssapi/Makefile.in b/src/lib/gssapi/Makefile.in index c3d0be67c..2f7ed757a 100644 --- a/src/lib/gssapi/Makefile.in +++ b/src/lib/gssapi/Makefile.in @@ -2,7 +2,7 @@ thisconfigdir=. 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 @@ -13,7 +13,7 @@ LOCAL_SUBDIRS= generic krb5 ##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 @@ -28,8 +28,8 @@ LIBMAJOR=2 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) diff --git a/src/lib/gssapi/configure.in b/src/lib/gssapi/configure.in index eccc62815..8c9786843 100644 --- a/src/lib/gssapi/configure.in +++ b/src/lib/gssapi/configure.in @@ -16,4 +16,4 @@ AC_CHECK_HEADER(xom.h,[ 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) diff --git a/src/lib/gssapi/generic/Makefile.in b/src/lib/gssapi/generic/Makefile.in index 1306b7db4..d80163a08 100644 --- a/src/lib/gssapi/generic/Makefile.in +++ b/src/lib/gssapi/generic/Makefile.in @@ -62,7 +62,6 @@ SRCS = \ $(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 \ @@ -77,7 +76,6 @@ OBJS = \ $(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) \ @@ -92,7 +90,6 @@ STLIBOBJS = \ 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 \ diff --git a/src/lib/gssapi/generic/gssapi.hin b/src/lib/gssapi/generic/gssapi.hin index 83fe62bb1..d3b93548e 100644 --- a/src/lib/gssapi/generic/gssapi.hin +++ b/src/lib/gssapi/generic/gssapi.hin @@ -702,6 +702,13 @@ OM_uint32 KRB5_CALLCONV gss_inquire_names_for_mech 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 diff --git a/src/lib/gssapi/generic/gssapi_err_generic.et b/src/lib/gssapi/generic/gssapi_err_generic.et index 99ba45fe3..3e976e3db 100644 --- a/src/lib/gssapi/generic/gssapi_err_generic.et +++ b/src/lib/gssapi/generic/gssapi_err_generic.et @@ -43,4 +43,7 @@ error_code G_BAD_DIRECTION, "Packet was replayed in wrong direction" 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 diff --git a/src/lib/gssapi/gss_libinit.c b/src/lib/gssapi/gss_libinit.c index 5561b5398..1d9a2397a 100644 --- a/src/lib/gssapi/gss_libinit.c +++ b/src/lib/gssapi/gss_libinit.c @@ -7,6 +7,8 @@ #include "gss_libinit.h" #include "k5-platform.h" +#include "mglueP.h" + /* * Initialize the GSSAPI library. */ @@ -26,6 +28,9 @@ int gssint_lib_init(void) 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; @@ -57,6 +62,7 @@ void gssint_lib_fini(void) 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) diff --git a/src/lib/gssapi/krb5/Makefile.in b/src/lib/gssapi/krb5/Makefile.in index 3ef9b5b84..a410d55f2 100644 --- a/src/lib/gssapi/krb5/Makefile.in +++ b/src/lib/gssapi/krb5/Makefile.in @@ -2,7 +2,7 @@ thisconfigdir=./.. 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 diff --git a/src/lib/gssapi/krb5/copy_ccache.c b/src/lib/gssapi/krb5/copy_ccache.c index fd408d7fb..38f109054 100644 --- a/src/lib/gssapi/krb5/copy_ccache.c +++ b/src/lib/gssapi/krb5/copy_ccache.c @@ -1,7 +1,7 @@ #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; diff --git a/src/lib/gssapi/krb5/get_tkt_flags.c b/src/lib/gssapi/krb5/get_tkt_flags.c index 74f1532ae..19841a086 100644 --- a/src/lib/gssapi/krb5/get_tkt_flags.c +++ b/src/lib/gssapi/krb5/get_tkt_flags.c @@ -27,7 +27,7 @@ */ 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; diff --git a/src/lib/gssapi/krb5/gssapiP_krb5.h b/src/lib/gssapi/krb5/gssapiP_krb5.h index 7d7599c61..c942c1868 100644 --- a/src/lib/gssapi/krb5/gssapiP_krb5.h +++ b/src/lib/gssapi/krb5/gssapiP_krb5.h @@ -74,6 +74,9 @@ /** 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 @@ -631,4 +634,31 @@ OM_uint32 gss_krb5int_unseal_token_v3(krb5_context *contextptr, 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_ */ diff --git a/src/lib/gssapi/krb5/gssapi_krb5.c b/src/lib/gssapi/krb5/gssapi_krb5.c index c188e6e5a..feb8499b2 100644 --- a/src/lib/gssapi/krb5/gssapi_krb5.c +++ b/src/lib/gssapi/krb5/gssapi_krb5.c @@ -87,7 +87,7 @@ 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 */ diff --git a/src/lib/gssapi/krb5/krb5_gss_glue.c b/src/lib/gssapi/krb5/krb5_gss_glue.c index 583881d8e..e4a9618ba 100644 --- a/src/lib/gssapi/krb5/krb5_gss_glue.c +++ b/src/lib/gssapi/krb5/krb5_gss_glue.c @@ -25,11 +25,366 @@ */ #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; @@ -55,9 +410,10 @@ gss_accept_sec_context(minor_status, context_handle, 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; @@ -78,11 +434,12 @@ gss_acquire_cred(minor_status, desired_name, time_req, desired_mechs, } /* 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; @@ -102,18 +459,22 @@ gss_add_cred(minor_status, input_cred_handle, desired_name, desired_mech, 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; @@ -123,8 +484,9 @@ gss_compare_name(minor_status, name1, name2, name_equal) 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; @@ -133,17 +495,21 @@ gss_context_time(minor_status, context_handle, 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; @@ -152,8 +518,9 @@ gss_delete_sec_context(minor_status, context_handle, 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; @@ -163,9 +530,10 @@ gss_display_name(minor_status, input_name, output_name_buffer, output_name_type) 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; @@ -179,8 +547,9 @@ gss_display_status(minor_status, status_value, 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; @@ -190,10 +559,12 @@ gss_export_sec_context(minor_status, context_handle, 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; @@ -203,27 +574,32 @@ gss_get_mic(minor_status, context_handle, 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; @@ -233,19 +609,21 @@ gss_import_sec_context(minor_status, interprocess_token, 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; @@ -268,10 +646,11 @@ gss_init_sec_context(minor_status, claimant_cred_handle, 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; @@ -288,9 +667,10 @@ gss_inquire_context(minor_status, context_handle, initiator_name, acceptor_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; @@ -303,9 +683,10 @@ gss_inquire_cred(minor_status, cred_handle, name, lifetime_ret, } /* 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; @@ -320,8 +701,9 @@ gss_inquire_cred_by_mech(minor_status, cred_handle, mech_type, name, } /* 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; @@ -331,18 +713,22 @@ gss_inquire_names_for_mech(minor_status, mechanism, 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; @@ -351,52 +737,62 @@ gss_process_context_token(minor_status, context_handle, 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; @@ -410,10 +806,11 @@ gss_seal(minor_status, context_handle, conf_req_flag, qop_req, 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; @@ -424,10 +821,12 @@ gss_sign(minor_status, context_handle, 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; @@ -439,9 +838,10 @@ gss_verify_mic(minor_status, context_handle, } /* 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; @@ -456,8 +856,9 @@ gss_wrap(minor_status, context_handle, conf_req_flag, qop_req, } /* 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; @@ -466,8 +867,9 @@ gss_str_to_oid(minor_status, oid_str, 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; @@ -476,11 +878,13 @@ gss_test_oid_set_member(minor_status, member, set, present) 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; @@ -493,10 +897,12 @@ gss_unseal(minor_status, context_handle, 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; @@ -507,11 +913,13 @@ gss_unwrap(minor_status, context_handle, 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; @@ -526,9 +934,10 @@ gss_verify(minor_status, context_handle, 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; @@ -541,9 +950,11 @@ gss_wrap_size_limit(minor_status, context_handle, 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; @@ -552,11 +963,12 @@ gss_canonicalize_name(minor_status, input_name, mech_type, output_name) 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; @@ -564,15 +976,82 @@ gss_export_name(minor_status, input_name, 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); +} diff --git a/src/lib/gssapi/krb5/lucid_context.c b/src/lib/gssapi/krb5/lucid_context.c index ac81fff60..a1679a93d 100644 --- a/src/lib/gssapi/krb5/lucid_context.c +++ b/src/lib/gssapi/krb5/lucid_context.c @@ -60,7 +60,7 @@ make_external_lucid_ctx_v1( */ 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, diff --git a/src/lib/gssapi/krb5/set_allowable_enctypes.c b/src/lib/gssapi/krb5/set_allowable_enctypes.c index 88cae714a..1ce6c4b9e 100644 --- a/src/lib/gssapi/krb5/set_allowable_enctypes.c +++ b/src/lib/gssapi/krb5/set_allowable_enctypes.c @@ -59,10 +59,10 @@ #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; diff --git a/src/lib/gssapi/mechglue/Makefile.in b/src/lib/gssapi/mechglue/Makefile.in index 313e6715a..f7988b7e7 100644 --- a/src/lib/gssapi/mechglue/Makefile.in +++ b/src/lib/gssapi/mechglue/Makefile.in @@ -1,119 +1,94 @@ -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:: @@ -123,3 +98,5 @@ install:: done includes:: + +# @libobj_frag@ diff --git a/src/lib/gssapi/mechglue/g_accept_sec_context.c b/src/lib/gssapi/mechglue/g_accept_sec_context.c index 8cc752fe7..b2a21e6de 100644 --- a/src/lib/gssapi/mechglue/g_accept_sec_context.c +++ b/src/lib/gssapi/mechglue/g_accept_sec_context.c @@ -1,4 +1,4 @@ -/* #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. @@ -44,7 +44,7 @@ gss_accept_sec_context (minor_status, output_token, ret_flags, time_rec, - delegated_cred_handle) + d_cred) OM_uint32 * minor_status; gss_ctx_id_t * context_handle; @@ -56,23 +56,39 @@ gss_OID * mech_type; 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 @@ -82,6 +98,9 @@ gss_cred_id_t * delegated_cred_handle; 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) @@ -90,34 +109,22 @@ gss_cred_id_t * delegated_cred_handle; 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; } @@ -149,7 +156,7 @@ gss_cred_id_t * delegated_cred_handle; 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) @@ -166,36 +173,140 @@ gss_cred_id_t * delegated_cred_handle; * 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); } diff --git a/src/lib/gssapi/mechglue/g_acquire_cred.c b/src/lib/gssapi/mechglue/g_acquire_cred.c index 8ecf55f31..c0bfd3f5a 100644 --- a/src/lib/gssapi/mechglue/g_acquire_cred.c +++ b/src/lib/gssapi/mechglue/g_acquire_cred.c @@ -1,4 +1,4 @@ -/* #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. @@ -35,36 +35,37 @@ #include #include -#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; @@ -91,291 +92,118 @@ gss_OID_set * 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; icount; 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 */ @@ -401,36 +229,73 @@ gss_add_cred(minor_status, input_cred_handle, 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) @@ -443,22 +308,51 @@ gss_add_cred(minor_status, input_cred_handle, 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; @@ -467,57 +361,77 @@ gss_add_cred(minor_status, input_cred_handle, *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); } diff --git a/src/lib/gssapi/mechglue/g_canon_name.c b/src/lib/gssapi/mechglue/g_canon_name.c new file mode 100644 index 000000000..c786d4d04 --- /dev/null +++ b/src/lib/gssapi/mechglue/g_canon_name.c @@ -0,0 +1,155 @@ +/* + * 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 +#ifdef HAVE_STDLIB_H +#include +#endif +#include +#include + +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 ********/ diff --git a/src/lib/gssapi/mechglue/g_compare_name.c b/src/lib/gssapi/mechglue/g_compare_name.c index 851be4a85..9cd50d9de 100644 --- a/src/lib/gssapi/mechglue/g_compare_name.c +++ b/src/lib/gssapi/mechglue/g_compare_name.c @@ -1,4 +1,4 @@ -/* #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. @@ -33,10 +33,6 @@ #endif #include -#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, @@ -54,13 +50,15 @@ int * name_equal; 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; @@ -82,12 +80,9 @@ int * name_equal; 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.... */ /* @@ -116,8 +111,32 @@ int * name_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, @@ -146,7 +165,8 @@ int * name_equal; 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); diff --git a/src/lib/gssapi/mechglue/g_context_time.c b/src/lib/gssapi/mechglue/g_context_time.c index 6f08c9224..82262a06e 100644 --- a/src/lib/gssapi/mechglue/g_context_time.c +++ b/src/lib/gssapi/mechglue/g_context_time.c @@ -1,4 +1,4 @@ -/* #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. @@ -42,11 +42,16 @@ OM_uint32 * time_rec; 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. @@ -64,10 +69,10 @@ OM_uint32 * time_rec; 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); } diff --git a/src/lib/gssapi/mechglue/g_delete_sec_context.c b/src/lib/gssapi/mechglue/g_delete_sec_context.c index fae0b0ac3..9678bd083 100644 --- a/src/lib/gssapi/mechglue/g_delete_sec_context.c +++ b/src/lib/gssapi/mechglue/g_delete_sec_context.c @@ -1,4 +1,4 @@ -/* #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. @@ -46,13 +46,18 @@ gss_buffer_t output_token; 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. @@ -70,10 +75,9 @@ gss_buffer_t output_token; &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); @@ -81,6 +85,6 @@ gss_buffer_t output_token; return(status); } - - return(GSS_S_NO_CONTEXT); + + return (GSS_S_BAD_MECH); } diff --git a/src/lib/gssapi/mechglue/g_dsp_name.c b/src/lib/gssapi/mechglue/g_dsp_name.c index 8bd0426c3..f90c87669 100644 --- a/src/lib/gssapi/mechglue/g_dsp_name.c +++ b/src/lib/gssapi/mechglue/g_dsp_name.c @@ -1,4 +1,4 @@ -/* #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. @@ -49,8 +49,18 @@ gss_OID * output_name_type; 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; @@ -70,27 +80,29 @@ gss_OID * output_name_type; * 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); } diff --git a/src/lib/gssapi/mechglue/g_dsp_status.c b/src/lib/gssapi/mechglue/g_dsp_status.c index 4b58c38f7..51d552e56 100644 --- a/src/lib/gssapi/mechglue/g_dsp_status.c +++ b/src/lib/gssapi/mechglue/g_dsp_status.c @@ -1,4 +1,4 @@ -/* #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. @@ -29,9 +29,11 @@ #include "mglueP.h" #include -#ifdef HAVE_STDLIB_H #include -#endif +#include + +/* local function */ +static OM_uint32 displayMajor(OM_uint32, OM_uint32 *, gss_buffer_t); OM_uint32 KRB5_CALLCONV gss_display_status (minor_status, @@ -49,36 +51,275 @@ OM_uint32 * message_context; 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 */ diff --git a/src/lib/gssapi/mechglue/g_dup_name.c b/src/lib/gssapi/mechglue/g_dup_name.c new file mode 100644 index 000000000..d8508202c --- /dev/null +++ b/src/lib/gssapi/mechglue/g_dup_name.c @@ -0,0 +1,118 @@ +/* + * 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 +#ifdef HAVE_STDLIB_H +#include +#endif +#include +#include + +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 */ diff --git a/src/lib/gssapi/mechglue/g_exp_sec_context.c b/src/lib/gssapi/mechglue/g_exp_sec_context.c index 958553b49..a9a244366 100644 --- a/src/lib/gssapi/mechglue/g_exp_sec_context.c +++ b/src/lib/gssapi/mechglue/g_exp_sec_context.c @@ -1,4 +1,4 @@ -/* #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. @@ -45,16 +45,21 @@ gss_buffer_t interprocess_token; { 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 @@ -66,7 +71,7 @@ gss_buffer_t interprocess_token; 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); @@ -78,7 +83,6 @@ gss_buffer_t interprocess_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; diff --git a/src/lib/gssapi/mechglue/g_export_name.c b/src/lib/gssapi/mechglue/g_export_name.c new file mode 100644 index 000000000..6b5780c2a --- /dev/null +++ b/src/lib/gssapi/mechglue/g_export_name.c @@ -0,0 +1,55 @@ +/* + * 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 +#ifdef HAVE_STDLIB_H +#include +#endif +#include +#include + +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); +} diff --git a/src/lib/gssapi/mechglue/g_glue.c b/src/lib/gssapi/mechglue/g_glue.c index 6aecab7fb..d807ff070 100644 --- a/src/lib/gssapi/mechglue/g_glue.c +++ b/src/lib/gssapi/mechglue/g_glue.c @@ -1,4 +1,4 @@ -/* #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. @@ -30,9 +30,7 @@ #include #include -#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; @@ -41,29 +39,141 @@ 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); } @@ -102,7 +212,10 @@ OM_uint32 __gss_get_mech_type(OID, token) * 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 */ @@ -112,6 +225,11 @@ OM_uint32 __gss_get_mech_type(OID, token) 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); @@ -153,7 +271,7 @@ gss_name_t *internal_name; union_name->name_type, internal_name); else - status = GSS_S_BAD_BINDINGS; + status = GSS_S_UNAVAILABLE; return (status); } @@ -161,6 +279,123 @@ gss_name_t *internal_name; 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; @@ -182,7 +417,7 @@ gss_OID *name_type; external_name, name_type); else - status = GSS_S_BAD_BINDINGS; + status = GSS_S_UNAVAILABLE; return (status); } @@ -206,7 +441,7 @@ gss_name_t *internal_name; minor_status, internal_name); else - status = GSS_S_BAD_BINDINGS; + status = GSS_S_UNAVAILABLE; return (status); } @@ -232,7 +467,6 @@ OM_uint32 __gss_convert_name_to_union_name(minor_status, mech, 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; @@ -248,7 +482,6 @@ OM_uint32 __gss_convert_name_to_union_name(minor_status, mech, union_name->external_name = (gss_buffer_t) malloc(sizeof(gss_buffer_desc)); if (!union_name->external_name) { - *minor_status = ENOMEM; goto allocation_failure; } @@ -271,13 +504,17 @@ 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); } @@ -302,4 +539,46 @@ __gss_get_mechanism_cred(union_cred, mech_type) 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 ****** */ diff --git a/src/lib/gssapi/mechglue/g_imp_name.c b/src/lib/gssapi/mechglue/g_imp_name.c index e93b4c9ac..e68b3e24e 100644 --- a/src/lib/gssapi/mechglue/g_imp_name.c +++ b/src/lib/gssapi/mechglue/g_imp_name.c @@ -1,4 +1,4 @@ -/* #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. @@ -35,6 +35,9 @@ #include #include +/* 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, @@ -49,17 +52,18 @@ gss_name_t * output_name; { 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; @@ -70,12 +74,10 @@ gss_name_t * output_name; * 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; @@ -84,61 +86,43 @@ gss_name_t * output_name; /* * 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) { @@ -158,3 +142,187 @@ allocation_failure: } 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 */ diff --git a/src/lib/gssapi/mechglue/g_imp_sec_context.c b/src/lib/gssapi/mechglue/g_imp_sec_context.c index eed9bbeda..fd3a3af43 100644 --- a/src/lib/gssapi/mechglue/g_imp_sec_context.c +++ b/src/lib/gssapi/mechglue/g_imp_sec_context.c @@ -1,4 +1,4 @@ -/* #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. @@ -44,48 +44,59 @@ gss_buffer_t interprocess_token; 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; /* @@ -99,7 +110,7 @@ gss_ctx_id_t * context_handle; goto error_out; } if (!mech->gss_import_sec_context) { - status = GSS_S_BAD_BINDINGS; + status = GSS_S_UNAVAILABLE; goto error_out; } diff --git a/src/lib/gssapi/mechglue/g_init_sec_context.c b/src/lib/gssapi/mechglue/g_init_sec_context.c index 4ff47f899..78e0553d8 100644 --- a/src/lib/gssapi/mechglue/g_init_sec_context.c +++ b/src/lib/gssapi/mechglue/g_init_sec_context.c @@ -1,4 +1,4 @@ -/* #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. @@ -33,10 +33,6 @@ #endif #include -#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, @@ -67,7 +63,7 @@ OM_uint32 * ret_flags; 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; @@ -76,20 +72,33 @@ OM_uint32 * time_rec; 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 @@ -100,6 +109,9 @@ OM_uint32 * time_rec; 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; @@ -108,15 +120,14 @@ OM_uint32 * time_rec; * 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); } /* @@ -127,23 +138,22 @@ OM_uint32 * time_rec; */ 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; @@ -160,30 +170,40 @@ OM_uint32 * time_rec; * 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); } diff --git a/src/lib/gssapi/mechglue/g_initialize.c b/src/lib/gssapi/mechglue/g_initialize.c index 09e14deed..41bbb78ac 100644 --- a/src/lib/gssapi/mechglue/g_initialize.c +++ b/src/lib/gssapi/mechglue/g_initialize.c @@ -1,4 +1,4 @@ -/* #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. @@ -36,18 +36,25 @@ #include #include -#ifdef USE_SOLARIS_SHARED_LIBRARIES #include -#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 -#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(); @@ -58,113 +65,855 @@ static struct gss_config null_mech = { 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(""); + 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 diff --git a/src/lib/gssapi/mechglue/g_inq_context.c b/src/lib/gssapi/mechglue/g_inq_context.c index 3f28c484f..ec1ace62b 100644 --- a/src/lib/gssapi/mechglue/g_inq_context.c +++ b/src/lib/gssapi/mechglue/g_inq_context.c @@ -1,4 +1,4 @@ -/* #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. @@ -59,13 +59,26 @@ int * open; 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 @@ -75,19 +88,19 @@ int * open; 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); @@ -100,33 +113,32 @@ int * 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); } diff --git a/src/lib/gssapi/mechglue/g_inq_cred.c b/src/lib/gssapi/mechglue/g_inq_cred.c index e0a2bc4a8..812fd9dab 100644 --- a/src/lib/gssapi/mechglue/g_inq_cred.c +++ b/src/lib/gssapi/mechglue/g_inq_cred.c @@ -1,4 +1,4 @@ -/* #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. @@ -56,7 +56,16 @@ gss_OID_set * mechanisms; 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) { /* @@ -68,10 +77,10 @@ gss_OID_set * mechanisms; */ 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, @@ -89,10 +98,12 @@ gss_OID_set * mechanisms; 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); } } @@ -124,39 +135,68 @@ gss_OID_set * mechanisms; * 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 @@ -173,6 +213,9 @@ gss_inquire_cred_by_mech(minor_status, cred_handle, mech_type, name, 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) @@ -182,10 +225,31 @@ gss_inquire_cred_by_mech(minor_status, cred_handle, mech_type, name, 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); } diff --git a/src/lib/gssapi/mechglue/g_inq_names.c b/src/lib/gssapi/mechglue/g_inq_names.c index 7c07f44ed..b1592bd44 100644 --- a/src/lib/gssapi/mechglue/g_inq_names.c +++ b/src/lib/gssapi/mechglue/g_inq_names.c @@ -1,4 +1,4 @@ -/* #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. @@ -28,6 +28,8 @@ #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) @@ -40,8 +42,13 @@ gss_OID_set * 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. @@ -58,10 +65,93 @@ gss_OID_set * name_types; 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); } diff --git a/src/lib/gssapi/mechglue/g_mechname.c b/src/lib/gssapi/mechglue/g_mechname.c index c013bdc15..0607c38f1 100644 --- a/src/lib/gssapi/mechglue/g_mechname.c +++ b/src/lib/gssapi/mechglue/g_mechname.c @@ -15,10 +15,6 @@ #include #include -#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; /* diff --git a/src/lib/gssapi/mechglue/g_oid_ops.c b/src/lib/gssapi/mechglue/g_oid_ops.c index 4a9d765f2..a036d8763 100644 --- a/src/lib/gssapi/mechglue/g_oid_ops.c +++ b/src/lib/gssapi/mechglue/g_oid_ops.c @@ -1,3 +1,4 @@ +/* #pragma ident "@(#)g_oid_ops.c 1.11 98/01/22 SMI" */ /* * lib/gssapi/mechglue/g_oid_ops.c * @@ -34,34 +35,11 @@ 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) diff --git a/src/lib/gssapi/mechglue/g_process_context.c b/src/lib/gssapi/mechglue/g_process_context.c index dcb4716bc..83687df3e 100644 --- a/src/lib/gssapi/mechglue/g_process_context.c +++ b/src/lib/gssapi/mechglue/g_process_context.c @@ -1,4 +1,4 @@ -/* #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. @@ -42,10 +42,15 @@ gss_buffer_t token_buffer; 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 @@ -64,10 +69,10 @@ gss_buffer_t token_buffer; 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); } diff --git a/src/lib/gssapi/mechglue/g_rel_cred.c b/src/lib/gssapi/mechglue/g_rel_cred.c index 44d82709e..e289f591c 100644 --- a/src/lib/gssapi/mechglue/g_rel_cred.c +++ b/src/lib/gssapi/mechglue/g_rel_cred.c @@ -1,4 +1,4 @@ -/* #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. @@ -45,15 +45,13 @@ gss_cred_id_t * cred_handle; 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 @@ -64,8 +62,8 @@ gss_cred_id_t * cred_handle; 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; @@ -86,9 +84,9 @@ gss_cred_id_t * cred_handle; 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); diff --git a/src/lib/gssapi/mechglue/g_rel_name.c b/src/lib/gssapi/mechglue/g_rel_name.c index 29c3f9819..ffa678c26 100644 --- a/src/lib/gssapi/mechglue/g_rel_name.c +++ b/src/lib/gssapi/mechglue/g_rel_name.c @@ -1,4 +1,4 @@ -/* #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. @@ -43,11 +43,17 @@ gss_name_t * input_name; { 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 @@ -56,9 +62,6 @@ gss_name_t * input_name; 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); diff --git a/src/lib/gssapi/mechglue/g_rel_oid_set.c b/src/lib/gssapi/mechglue/g_rel_oid_set.c index 357c00e67..f712a891a 100644 --- a/src/lib/gssapi/mechglue/g_rel_oid_set.c +++ b/src/lib/gssapi/mechglue/g_rel_oid_set.c @@ -1,4 +1,4 @@ -/* #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. @@ -39,8 +39,8 @@ gss_release_oid_set (minor_status, 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; diff --git a/src/lib/gssapi/mechglue/g_seal.c b/src/lib/gssapi/mechglue/g_seal.c index 7d66e469a..c68a6b031 100644 --- a/src/lib/gssapi/mechglue/g_seal.c +++ b/src/lib/gssapi/mechglue/g_seal.c @@ -1,4 +1,4 @@ -/* #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. @@ -28,7 +28,7 @@ #include "mglueP.h" -OM_uint32 KRB5_CALLCONV +OM_uint32 gss_seal (minor_status, context_handle, conf_req_flag, @@ -44,16 +44,25 @@ int qop_req; 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 @@ -75,15 +84,16 @@ gss_buffer_t output_message_buffer; 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, @@ -101,15 +111,16 @@ int * conf_state; 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; @@ -119,14 +130,18 @@ gss_wrap_size_limit(minor_status, context_handle, conf_req_flag, 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 @@ -137,13 +152,12 @@ gss_wrap_size_limit(minor_status, context_handle, conf_req_flag, 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)); } diff --git a/src/lib/gssapi/mechglue/g_sign.c b/src/lib/gssapi/mechglue/g_sign.c index 4dfd3ec71..f1f883f52 100644 --- a/src/lib/gssapi/mechglue/g_sign.c +++ b/src/lib/gssapi/mechglue/g_sign.c @@ -1,4 +1,4 @@ -/* #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. @@ -46,11 +46,21 @@ gss_buffer_t msg_token; 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. @@ -69,12 +79,12 @@ gss_buffer_t msg_token; 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 diff --git a/src/lib/gssapi/mechglue/g_store_cred.c b/src/lib/gssapi/mechglue/g_store_cred.c new file mode 100644 index 000000000..7ccbfcd7e --- /dev/null +++ b/src/lib/gssapi/mechglue/g_store_cred.c @@ -0,0 +1,136 @@ +/* + * 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 + +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); +} diff --git a/src/lib/gssapi/mechglue/g_unseal.c b/src/lib/gssapi/mechglue/g_unseal.c index 9ca1c1512..8e975827f 100644 --- a/src/lib/gssapi/mechglue/g_unseal.c +++ b/src/lib/gssapi/mechglue/g_unseal.c @@ -1,4 +1,4 @@ -/* #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. @@ -44,14 +44,26 @@ int * conf_state; 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 @@ -72,12 +84,14 @@ int * qop_state; 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 @@ -89,15 +103,14 @@ gss_unwrap (minor_status, 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)); } diff --git a/src/lib/gssapi/mechglue/g_userok.c b/src/lib/gssapi/mechglue/g_userok.c new file mode 100644 index 000000000..eaf376ea8 --- /dev/null +++ b/src/lib/gssapi/mechglue/g_userok.c @@ -0,0 +1,112 @@ +/* + * 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 +#include +#include +#include +#include +#include +#include + + +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 */ diff --git a/src/lib/gssapi/mechglue/g_utils.c b/src/lib/gssapi/mechglue/g_utils.c new file mode 100644 index 000000000..875e159f7 --- /dev/null +++ b/src/lib/gssapi/mechglue/g_utils.c @@ -0,0 +1,281 @@ +/* + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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); +} diff --git a/src/lib/gssapi/mechglue/g_verify.c b/src/lib/gssapi/mechglue/g_verify.c index 7fc86b448..4f2415566 100644 --- a/src/lib/gssapi/mechglue/g_verify.c +++ b/src/lib/gssapi/mechglue/g_verify.c @@ -1,4 +1,4 @@ -/* #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. @@ -46,10 +46,16 @@ int * qop_state; 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 @@ -69,12 +75,12 @@ int * qop_state; 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 diff --git a/src/lib/gssapi/mechglue/gssd_pname_to_uid.c b/src/lib/gssapi/mechglue/gssd_pname_to_uid.c index eb7c051ac..036ae904f 100644 --- a/src/lib/gssapi/mechglue/gssd_pname_to_uid.c +++ b/src/lib/gssapi/mechglue/gssd_pname_to_uid.c @@ -1,4 +1,4 @@ -/* #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. @@ -42,8 +42,6 @@ uid_t * uid; int status; gss_mechanism mech; - gss_initialize(); - /* * find the appropriate mechanism specific pname_to_uid procedure and * call it. diff --git a/src/lib/gssapi/mechglue/mglueP.h b/src/lib/gssapi/mechglue/mglueP.h index c9a7d4ee3..20f5ea655 100644 --- a/src/lib/gssapi/mechglue/mglueP.h +++ b/src/lib/gssapi/mechglue/mglueP.h @@ -12,6 +12,19 @@ #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 */ @@ -50,7 +63,7 @@ typedef struct gss_mech_spec_name_t { 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; @@ -61,10 +74,23 @@ typedef struct 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 */ @@ -334,16 +360,74 @@ typedef struct gss_config { 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 *); @@ -359,6 +443,12 @@ gss_cred_id_t __gss_get_mechanism_cred 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 */ @@ -400,6 +490,11 @@ OM_uint32 generic_gss_str_to_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 */ @@ -409,4 +504,62 @@ OM_uint32 gss_add_mech_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 */ diff --git a/src/lib/gssapi/mechglue/oid_ops.c b/src/lib/gssapi/mechglue/oid_ops.c index 8e9da8852..e13e6a4f5 100644 --- a/src/lib/gssapi/mechglue/oid_ops.c +++ b/src/lib/gssapi/mechglue/oid_ops.c @@ -1,3 +1,4 @@ +/* #pragma ident "@(#)oid_ops.c 1.19 04/02/23 SMI" */ /* * lib/gssapi/generic/oid_ops.c * @@ -45,7 +46,8 @@ generic_gss_release_oid(minor_status, oid) 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); @@ -59,9 +61,20 @@ generic_gss_release_oid(minor_status, oid) * 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); @@ -77,6 +90,8 @@ generic_gss_copy_oid(minor_status, oid, new_oid) { gss_OID p; + *minor_status = 0; + p = (gss_OID) malloc(sizeof(gss_OID_desc)); if (!p) { *minor_status = ENOMEM; @@ -86,7 +101,6 @@ generic_gss_copy_oid(minor_status, oid, new_oid) p->elements = malloc(p->length); if (!p->elements) { free(p); - *minor_status = ENOMEM; return GSS_S_FAILURE; } memcpy(p->elements, oid->elements, p->length); @@ -100,9 +114,10 @@ generic_gss_create_empty_oid_set(minor_status, oid_set) 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 { @@ -120,6 +135,12 @@ generic_gss_add_oid_set_member(minor_status, member_oid, oid_set) 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) * @@ -163,9 +184,17 @@ generic_gss_test_oid_set_member(minor_status, member, set, present) 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; icount; i++) { if ((set->elements[i].length == member->length) && @@ -177,7 +206,6 @@ generic_gss_test_oid_set_member(minor_status, member, set, present) } } *present = result; - *minor_status = 0; return(GSS_S_COMPLETE); } @@ -191,13 +219,21 @@ generic_gss_oid_to_str(minor_status, oid, oid_str) 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 */ @@ -211,12 +247,11 @@ generic_gss_oid_to_str(minor_status, oid, oid_str) sprintf(numstr, "%ld ", number%40); string_length += strlen(numstr); for (i=1; ilength; 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) { @@ -233,7 +268,7 @@ generic_gss_oid_to_str(minor_status, oid, oid_str) 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); @@ -251,7 +286,6 @@ generic_gss_oid_to_str(minor_status, oid, oid_str) strcat(bp, "}"); oid_str->length = strlen(bp)+1; oid_str->value = (void *) bp; - *minor_status = 0; return(GSS_S_COMPLETE); } *minor_status = ENOMEM; @@ -272,6 +306,14 @@ generic_gss_str_to_oid(minor_status, oid_str, oid) 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; @@ -304,12 +346,12 @@ generic_gss_str_to_oid(minor_status, oid_str, oid) } 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) { @@ -318,11 +360,11 @@ generic_gss_str_to_oid(minor_status, oid_str, oid) } 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); } @@ -330,26 +372,26 @@ generic_gss_str_to_oid(minor_status, oid_str, oid) * 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; @@ -369,10 +411,9 @@ generic_gss_str_to_oid(minor_status, oid_str, oid) } while (isdigit(*bp)) bp++; - while (isspace(*bp)) + while (isspace(*bp) || *bp == '.') bp++; } - *minor_status = 0; return(GSS_S_COMPLETE); } else { @@ -380,7 +421,82 @@ generic_gss_str_to_oid(minor_status, oid_str, oid) *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); +} -- 2.26.2