diff options
author | dfr <dfr@FreeBSD.org> | 2008-05-07 13:53:12 +0000 |
---|---|---|
committer | dfr <dfr@FreeBSD.org> | 2008-05-07 13:53:12 +0000 |
commit | be0348cb75cae58cd1683f6fdbff884cb9bc405b (patch) | |
tree | 1338a6c0e5d3e7c3b0da720ac15cd79fc72c6b5a /lib/libgssapi | |
parent | 52bf09d8197dd1ec84e1ab72684f2058f0eae9e1 (diff) | |
download | FreeBSD-src-be0348cb75cae58cd1683f6fdbff884cb9bc405b.zip FreeBSD-src-be0348cb75cae58cd1683f6fdbff884cb9bc405b.tar.gz |
Fix conflicts after heimdal-1.1 import and add build infrastructure. Import
all non-style changes made by heimdal to our own libgssapi.
Diffstat (limited to 'lib/libgssapi')
54 files changed, 1930 insertions, 332 deletions
diff --git a/lib/libgssapi/Makefile b/lib/libgssapi/Makefile index cedc424..5d4fef3 100644 --- a/lib/libgssapi/Makefile +++ b/lib/libgssapi/Makefile @@ -1,51 +1,64 @@ # $FreeBSD$ LIB= gssapi -SHLIB_MAJOR= 9 +SHLIB_MAJOR= 10 +WARNS= 6 +VERSION_DEF= ${.CURDIR}/../libc/Versions.def +SYMBOL_MAPS= ${.CURDIR}/Symbol.map SRCS= -SRCS+= gss_utils.c -SRCS+= gss_mech_switch.c -SRCS+= gss_names.c -SRCS+= gss_acquire_cred.c -SRCS+= gss_release_cred.c -SRCS+= gss_init_sec_context.c SRCS+= gss_accept_sec_context.c -SRCS+= gss_process_context_token.c -SRCS+= gss_delete_sec_context.c -SRCS+= gss_context_time.c -SRCS+= gss_get_mic.c -SRCS+= gss_verify_mic.c -SRCS+= gss_wrap.c -SRCS+= gss_unwrap.c -SRCS+= gss_display_status.c -SRCS+= gss_indicate_mechs.c +SRCS+= gss_acquire_cred.c +SRCS+= gss_add_cred.c +SRCS+= gss_add_oid_set_member.c +SRCS+= gss_buffer_set.c +SRCS+= gss_canonicalize_name.c SRCS+= gss_compare_name.c +SRCS+= gss_context_time.c +SRCS+= gss_create_empty_oid_set.c +SRCS+= gss_decapsulate_token.c +SRCS+= gss_delete_sec_context.c SRCS+= gss_display_name.c -SRCS+= gss_import_name.c +SRCS+= gss_display_status.c +SRCS+= gss_duplicate_name.c +SRCS+= gss_duplicate_oid.c +SRCS+= gss_encapsulate_token.c SRCS+= gss_export_name.c -SRCS+= gss_release_name.c -SRCS+= gss_inquire_cred.c -SRCS+= gss_inquire_context.c -SRCS+= gss_wrap_size_limit.c -SRCS+= gss_add_cred.c -SRCS+= gss_inquire_cred_by_mech.c SRCS+= gss_export_sec_context.c +SRCS+= gss_get_mic.c +SRCS+= gss_import_name.c SRCS+= gss_import_sec_context.c -SRCS+= gss_inquire_names_for_mech.c +SRCS+= gss_indicate_mechs.c +SRCS+= gss_init_sec_context.c +SRCS+= gss_inquire_context.c +SRCS+= gss_inquire_cred.c +SRCS+= gss_inquire_cred_by_mech.c +SRCS+= gss_inquire_cred_by_oid.c SRCS+= gss_inquire_mechs_for_name.c -SRCS+= gss_canonicalize_name.c -SRCS+= gss_duplicate_name.c -SRCS+= gss_sign.c -SRCS+= gss_verify.c +SRCS+= gss_inquire_names_for_mech.c +SRCS+= gss_inquire_sec_context_by_oid.c +SRCS+= gss_mech_switch.c +SRCS+= gss_names.c +SRCS+= gss_oid_to_str.c +SRCS+= gss_process_context_token.c +SRCS+= gss_pseudo_random.c +SRCS+= gss_release_buffer.c +SRCS+= gss_release_cred.c +SRCS+= gss_release_name.c +SRCS+= gss_release_oid.c +SRCS+= gss_release_oid_set.c SRCS+= gss_seal.c -SRCS+= gss_unseal.c -SRCS+= gss_krb5.c -SRCS+= gss_create_empty_oid_set.c -SRCS+= gss_add_oid_set_member.c +SRCS+= gss_set_cred_option.c +SRCS+= gss_set_sec_context_option.c +SRCS+= gss_sign.c SRCS+= gss_test_oid_set_member.c -SRCS+= gss_release_oid_set.c -SRCS+= gss_release_buffer.c +SRCS+= gss_unseal.c +SRCS+= gss_unwrap.c +SRCS+= gss_utils.c +SRCS+= gss_verify.c +SRCS+= gss_verify_mic.c +SRCS+= gss_wrap.c +SRCS+= gss_wrap_size_limit.c MAN= MAN+= gssapi.3 diff --git a/lib/libgssapi/Symbol.map b/lib/libgssapi/Symbol.map new file mode 100644 index 0000000..d2746da --- /dev/null +++ b/lib/libgssapi/Symbol.map @@ -0,0 +1,69 @@ +/* + * $FreeBSD$ + */ + +FBSD_1.1 { + GSS_C_NT_ANONYMOUS; + GSS_C_NT_EXPORT_NAME; + GSS_C_NT_HOSTBASED_SERVICE; + GSS_C_NT_HOSTBASED_SERVICE_X; + GSS_C_NT_MACHINE_UID_NAME; + GSS_C_NT_STRING_UID_NAME; + GSS_C_NT_USER_NAME; + GSS_KRB5_NT_MACHINE_UID_NAME; + GSS_KRB5_NT_PRINCIPAL_NAME; + GSS_KRB5_NT_STRING_UID_NAME; + GSS_KRB5_NT_USER_NAME; + gss_accept_sec_context; + gss_acquire_cred; + gss_add_buffer_set_member; + gss_add_cred; + gss_add_oid_set_member; + gss_canonicalize_name; + gss_compare_name; + gss_context_time; + gss_create_empty_buffer_set; + gss_create_empty_oid_set; + gss_decapsulate_token; + gss_delete_sec_context; + gss_display_name; + gss_display_status; + gss_duplicate_name; + gss_duplicate_oid; + gss_encapsulate_token; + gss_export_name; + gss_export_sec_context; + gss_get_mic; + gss_import_name; + gss_import_sec_context; + gss_indicate_mechs; + gss_init_sec_context; + gss_inquire_context; + gss_inquire_cred; + gss_inquire_cred_by_mech; + gss_inquire_cred_by_oid; + gss_inquire_mechs_for_name; + gss_inquire_names_for_mech; + gss_inquire_sec_context_by_oid; + gss_oid_equal; + gss_oid_to_str; + gss_process_context_token; + gss_pseudo_random; + gss_release_buffer; + gss_release_buffer_set; + gss_release_cred; + gss_release_name; + gss_release_oid; + gss_release_oid_set; + gss_seal; + gss_set_cred_option; + gss_set_sec_context_option; + gss_sign; + gss_test_oid_set_member; + gss_unseal; + gss_unwrap; + gss_verify; + gss_verify_mic; + gss_wrap; + gss_wrap_size_limit; +}; diff --git a/lib/libgssapi/context.h b/lib/libgssapi/context.h index 403b390..ac162aa 100644 --- a/lib/libgssapi/context.h +++ b/lib/libgssapi/context.h @@ -30,3 +30,4 @@ struct _gss_context { struct _gss_mech_switch *gc_mech; gss_ctx_id_t gc_ctx; }; + diff --git a/lib/libgssapi/cred.h b/lib/libgssapi/cred.h index 6301b89..e6fed6f 100644 --- a/lib/libgssapi/cred.h +++ b/lib/libgssapi/cred.h @@ -37,7 +37,6 @@ struct _gss_mechanism_cred { SLIST_HEAD(_gss_mechanism_cred_list, _gss_mechanism_cred); struct _gss_cred { - gss_cred_usage_t gc_usage; struct _gss_mechanism_cred_list gc_mc; }; diff --git a/lib/libgssapi/gss_accept_sec_context.c b/lib/libgssapi/gss_accept_sec_context.c index 62a3bda..b424092 100644 --- a/lib/libgssapi/gss_accept_sec_context.c +++ b/lib/libgssapi/gss_accept_sec_context.c @@ -35,6 +35,116 @@ #include "context.h" #include "cred.h" #include "name.h" +#include "utils.h" + +static OM_uint32 +parse_header(const gss_buffer_t input_token, gss_OID mech_oid) +{ + unsigned char *p = input_token->value; + size_t len = input_token->length; + size_t a, b; + + /* + * Token must start with [APPLICATION 0] SEQUENCE. + * But if it doesn't assume it is DCE-STYLE Kerberos! + */ + if (len == 0) + return (GSS_S_DEFECTIVE_TOKEN); + + p++; + len--; + + /* + * Decode the length and make sure it agrees with the + * token length. + */ + if (len == 0) + return (GSS_S_DEFECTIVE_TOKEN); + if ((*p & 0x80) == 0) { + a = *p; + p++; + len--; + } else { + b = *p & 0x7f; + p++; + len--; + if (len < b) + return (GSS_S_DEFECTIVE_TOKEN); + a = 0; + while (b) { + a = (a << 8) | *p; + p++; + len--; + b--; + } + } + if (a != len) + return (GSS_S_DEFECTIVE_TOKEN); + + /* + * Decode the OID for the mechanism. Simplify life by + * assuming that the OID length is less than 128 bytes. + */ + if (len < 2 || *p != 0x06) + return (GSS_S_DEFECTIVE_TOKEN); + if ((p[1] & 0x80) || p[1] > (len - 2)) + return (GSS_S_DEFECTIVE_TOKEN); + mech_oid->length = p[1]; + p += 2; + len -= 2; + mech_oid->elements = p; + + return (GSS_S_COMPLETE); +} + +static gss_OID_desc krb5_mechanism = +{9, (void *)(uintptr_t) "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02"}; +static gss_OID_desc ntlm_mechanism = +{10, (void *)(uintptr_t) "\x2b\x06\x01\x04\x01\x82\x37\x02\x02\x0a"}; +static gss_OID_desc spnego_mechanism = +{6, (void *)(uintptr_t) "\x2b\x06\x01\x05\x05\x02"}; + +static OM_uint32 +choose_mech(const gss_buffer_t input, gss_OID mech_oid) +{ + OM_uint32 status; + + /* + * First try to parse the gssapi token header and see if it's a + * correct header, use that in the first hand. + */ + + status = parse_header(input, mech_oid); + if (status == GSS_S_COMPLETE) + return (GSS_S_COMPLETE); + + /* + * Lets guess what mech is really is, callback function to mech ?? + */ + + if (input->length > 8 && + memcmp((const char *)input->value, "NTLMSSP\x00", 8) == 0) + { + *mech_oid = ntlm_mechanism; + return (GSS_S_COMPLETE); + } else if (input->length != 0 && + ((const char *)input->value)[0] == 0x6E) + { + /* Could be a raw AP-REQ (check for APPLICATION tag) */ + *mech_oid = krb5_mechanism; + return (GSS_S_COMPLETE); + } else if (input->length == 0) { + /* + * There is the a wierd mode of SPNEGO (in CIFS and + * SASL GSS-SPENGO where the first token is zero + * length and the acceptor returns a mech_list, lets + * hope that is what is happening now. + */ + *mech_oid = spnego_mechanism; + return (GSS_S_COMPLETE); + } + return (status); +} OM_uint32 gss_accept_sec_context(OM_uint32 *minor_status, gss_ctx_id_t *context_handle, @@ -58,71 +168,28 @@ OM_uint32 gss_accept_sec_context(OM_uint32 *minor_status, int allocated_ctx; *minor_status = 0; - if (src_name) *src_name = 0; - if (mech_type) *mech_type = 0; - if (ret_flags) *ret_flags = 0; - if (time_rec) *time_rec = 0; - if (delegated_cred_handle) *delegated_cred_handle = 0; - output_token->length = 0; - output_token->value = 0; + if (src_name) + *src_name = GSS_C_NO_NAME; + if (mech_type) + *mech_type = GSS_C_NO_OID; + if (ret_flags) + *ret_flags = 0; + if (time_rec) + *time_rec = 0; + if (delegated_cred_handle) + *delegated_cred_handle = GSS_C_NO_CREDENTIAL; + _gss_buffer_zero(output_token); /* * If this is the first call (*context_handle is NULL), we must * parse the input token to figure out the mechanism to use. */ if (*context_handle == GSS_C_NO_CONTEXT) { - unsigned char *p = input_token->value; - size_t len = input_token->length; - size_t a, b; gss_OID_desc mech_oid; - /* - * Token must start with [APPLICATION 0] SEQUENCE. - */ - if (len == 0 || *p != 0x60) - return (GSS_S_DEFECTIVE_TOKEN); - p++; - len--; - - /* - * Decode the length and make sure it agrees with the - * token length. - */ - if (len == 0) - return (GSS_S_DEFECTIVE_TOKEN); - if ((*p & 0x80) == 0) { - a = *p; - p++; - len--; - } else { - b = *p & 0x7f; - p++; - len--; - if (len < b) - return (GSS_S_DEFECTIVE_TOKEN); - a = 0; - while (b) { - a = (a << 8) | *p; - p++; - len--; - b--; - } - } - if (a != len) - return (GSS_S_DEFECTIVE_TOKEN); - - /* - * Decode the OID for the mechanism. Simplify life by - * assuming that the OID length is less than 128 bytes. - */ - if (len < 2 || *p != 0x06) - return (GSS_S_DEFECTIVE_TOKEN); - if ((p[1] & 0x80) || p[1] > (len - 2)) - return (GSS_S_DEFECTIVE_TOKEN); - mech_oid.length = p[1]; - p += 2; - len -= 2; - mech_oid.elements = p; + major_status = choose_mech(input_token, &mech_oid); + if (major_status != GSS_S_COMPLETE) + return (major_status); /* * Now that we have a mechanism, we can find the @@ -157,6 +224,7 @@ OM_uint32 gss_accept_sec_context(OM_uint32 *minor_status, } delegated_mc = GSS_C_NO_CREDENTIAL; + mech_ret_flags = 0; major_status = m->gm_accept_sec_context(minor_status, &ctx->gc_ctx, acceptor_mc, @@ -169,12 +237,12 @@ OM_uint32 gss_accept_sec_context(OM_uint32 *minor_status, time_rec, &delegated_mc); if (major_status != GSS_S_COMPLETE && - major_status != GSS_S_CONTINUE_NEEDED) + major_status != GSS_S_CONTINUE_NEEDED) { + _gss_mg_error(m, major_status, *minor_status); return (major_status); + } - if (!src_name) { - m->gm_release_name(minor_status, &src_mn); - } else { + if (src_name && src_mn) { /* * Make a new name and mark it as an MN. */ @@ -185,6 +253,8 @@ OM_uint32 gss_accept_sec_context(OM_uint32 *minor_status, return (GSS_S_FAILURE); } *src_name = (gss_name_t) name; + } else if (src_mn) { + m->gm_release_name(minor_status, &src_mn); } if (delegated_mc == GSS_C_NO_CREDENTIAL) @@ -195,29 +265,27 @@ OM_uint32 gss_accept_sec_context(OM_uint32 *minor_status, m->gm_release_cred(minor_status, &delegated_mc); mech_ret_flags &= ~GSS_C_DELEG_FLAG; } else { - struct _gss_cred *cred; - struct _gss_mechanism_cred *mc; + struct _gss_cred *dcred; + struct _gss_mechanism_cred *dmc; - cred = malloc(sizeof(struct _gss_cred)); - if (!cred) { + dcred = malloc(sizeof(struct _gss_cred)); + if (!dcred) { *minor_status = ENOMEM; return (GSS_S_FAILURE); } - SLIST_INIT(&cred->gc_mc); - mc = malloc(sizeof(struct _gss_mechanism_cred)); - if (!mc) { - free(cred); + SLIST_INIT(&dcred->gc_mc); + dmc = malloc(sizeof(struct _gss_mechanism_cred)); + if (!dmc) { + free(dcred); *minor_status = ENOMEM; return (GSS_S_FAILURE); } - m->gm_inquire_cred(minor_status, delegated_mc, - 0, 0, &cred->gc_usage, 0); - mc->gmc_mech = m; - mc->gmc_mech_oid = &m->gm_mech_oid; - mc->gmc_cred = delegated_mc; - SLIST_INSERT_HEAD(&cred->gc_mc, mc, gmc_link); - - *delegated_cred_handle = (gss_cred_id_t) cred; + dmc->gmc_mech = m; + dmc->gmc_mech_oid = &m->gm_mech_oid; + dmc->gmc_cred = delegated_mc; + SLIST_INSERT_HEAD(&dcred->gc_mc, dmc, gmc_link); + + *delegated_cred_handle = (gss_cred_id_t) dcred; } } diff --git a/lib/libgssapi/gss_acquire_cred.c b/lib/libgssapi/gss_acquire_cred.c index ba8b8b1..f6ae4d1 100644 --- a/lib/libgssapi/gss_acquire_cred.c +++ b/lib/libgssapi/gss_acquire_cred.c @@ -52,14 +52,23 @@ gss_acquire_cred(OM_uint32 *minor_status, struct _gss_cred *cred; struct _gss_mechanism_cred *mc; struct _gss_mechanism_name *mn; - OM_uint32 min_time, time; - int i; + OM_uint32 min_time, cred_time; + size_t i; + + *minor_status = 0; + if (output_cred_handle) + *output_cred_handle = GSS_C_NO_CREDENTIAL; + if (actual_mechs) + *actual_mechs = GSS_C_NO_OID_SET; + if (time_rec) + *time_rec = 0; + + _gss_load_mech(); /* * First make sure that at least one of the requested * mechanisms is one that we support. */ - _gss_load_mech(); if (mechs) { for (i = 0; i < mechs->count; i++) { int t; @@ -69,7 +78,6 @@ gss_acquire_cred(OM_uint32 *minor_status, break; } if (i == mechs->count) { - *output_cred_handle = 0; *minor_status = 0; return (GSS_S_BAD_MECH); } @@ -91,7 +99,6 @@ gss_acquire_cred(OM_uint32 *minor_status, *minor_status = ENOMEM; return (GSS_S_FAILURE); } - cred->gc_usage = cred_usage; SLIST_INIT(&cred->gc_mc); set.count = 1; @@ -102,8 +109,9 @@ gss_acquire_cred(OM_uint32 *minor_status, continue; if (desired_name != GSS_C_NO_NAME) { - mn = _gss_find_mn(name, &mechs->elements[i]); - if (!mn) + major_status = _gss_find_mn(minor_status, name, + &mechs->elements[i], &mn); + if (major_status != GSS_S_COMPLETE) continue; } @@ -122,13 +130,13 @@ gss_acquire_cred(OM_uint32 *minor_status, (desired_name != GSS_C_NO_NAME ? mn->gmn_name : GSS_C_NO_NAME), time_req, &set, cred_usage, - &mc->gmc_cred, NULL, &time); + &mc->gmc_cred, NULL, &cred_time); if (major_status) { free(mc); continue; } - if (time < min_time) - min_time = time; + if (cred_time < min_time) + min_time = cred_time; if (actual_mechs) { major_status = gss_add_oid_set_member(minor_status, @@ -152,7 +160,6 @@ gss_acquire_cred(OM_uint32 *minor_status, free(cred); if (actual_mechs) gss_release_oid_set(minor_status, actual_mechs); - *output_cred_handle = 0; *minor_status = 0; return (GSS_S_NO_CRED); } diff --git a/lib/libgssapi/gss_add_cred.c b/lib/libgssapi/gss_add_cred.c index 6175607..4dcca18 100644 --- a/lib/libgssapi/gss_add_cred.c +++ b/lib/libgssapi/gss_add_cred.c @@ -33,6 +33,7 @@ #include "mech_switch.h" #include "cred.h" #include "name.h" +#include "utils.h" static struct _gss_mechanism_cred * _gss_copy_cred(struct _gss_mechanism_cred *mc) @@ -48,8 +49,10 @@ _gss_copy_cred(struct _gss_mechanism_cred *mc) major_status = m->gm_inquire_cred_by_mech(&minor_status, mc->gmc_cred, mc->gmc_mech_oid, &name, &initiator_lifetime, &acceptor_lifetime, &cred_usage); - if (major_status) + if (major_status) { + _gss_mg_error(m, major_status, minor_status); return (0); + } major_status = m->gm_add_cred(&minor_status, GSS_C_NO_CREDENTIAL, name, mc->gmc_mech_oid, @@ -57,8 +60,10 @@ _gss_copy_cred(struct _gss_mechanism_cred *mc) &cred, 0, 0, 0); m->gm_release_name(&minor_status, &name); - if (major_status) + if (major_status) { + _gss_mg_error(m, major_status, minor_status); return (0); + } new_mc = malloc(sizeof(struct _gss_mechanism_cred)); if (!new_mc) { @@ -87,24 +92,27 @@ gss_add_cred(OM_uint32 *minor_status, { OM_uint32 major_status; struct _gss_mech_switch *m; - gss_OID_set_desc set; - struct _gss_name *name = (struct _gss_name *) desired_name; struct _gss_cred *cred = (struct _gss_cred *) input_cred_handle; struct _gss_cred *new_cred; + gss_cred_id_t release_cred; struct _gss_mechanism_cred *mc, *target_mc, *copy_mc; struct _gss_mechanism_name *mn; - OM_uint32 min_time, time, junk; - int i; + OM_uint32 junk; - *output_cred_handle = 0; *minor_status = 0; + *output_cred_handle = GSS_C_NO_CREDENTIAL; + if (initiator_time_rec) + *initiator_time_rec = 0; + if (acceptor_time_rec) + *acceptor_time_rec = 0; + if (actual_mechs) + *actual_mechs = GSS_C_NO_OID_SET; new_cred = malloc(sizeof(struct _gss_cred)); if (!new_cred) { *minor_status = ENOMEM; return (GSS_S_FAILURE); } - new_cred->gc_usage = cred_usage; SLIST_INIT(&new_cred->gc_mc); /* @@ -116,12 +124,13 @@ gss_add_cred(OM_uint32 *minor_status, target_mc = 0; if (cred) { SLIST_FOREACH(mc, &cred->gc_mc, gmc_link) { - if (_gss_oid_equal(mc->gmc_mech, desired_mech)) { + if (gss_oid_equal(mc->gmc_mech_oid, desired_mech)) { target_mc = mc; } copy_mc = _gss_copy_cred(mc); if (!copy_mc) { - gss_release_cred(&junk, (gss_cred_id_t*) &new_cred); + release_cred = (gss_cred_id_t) new_cred; + gss_release_cred(&junk, &release_cred); *minor_status = ENOMEM; return (GSS_S_FAILURE); } @@ -133,11 +142,13 @@ gss_add_cred(OM_uint32 *minor_status, * Figure out a suitable mn, if any. */ if (desired_name) { - mn = _gss_find_mn((struct _gss_name *) desired_name, - desired_mech); - if (!mn) { + major_status = _gss_find_mn(minor_status, + (struct _gss_name *) desired_name, + desired_mech, + &mn); + if (major_status != GSS_S_COMPLETE) { free(new_cred); - return (GSS_S_BAD_NAME); + return (major_status); } } else { mn = 0; @@ -147,7 +158,8 @@ gss_add_cred(OM_uint32 *minor_status, mc = malloc(sizeof(struct _gss_mechanism_cred)); if (!mc) { - gss_release_cred(&junk, (gss_cred_id_t*) &new_cred); + release_cred = (gss_cred_id_t) new_cred; + gss_release_cred(&junk, &release_cred); *minor_status = ENOMEM; return (GSS_S_FAILURE); } @@ -167,7 +179,9 @@ gss_add_cred(OM_uint32 *minor_status, acceptor_time_rec); if (major_status) { - gss_release_cred(&junk, (gss_cred_id_t*) &new_cred); + _gss_mg_error(m, major_status, *minor_status); + release_cred = (gss_cred_id_t) new_cred; + gss_release_cred(&junk, &release_cred); free(mc); return (major_status); } diff --git a/lib/libgssapi/gss_buffer_set.c b/lib/libgssapi/gss_buffer_set.c new file mode 100644 index 0000000..af62e5c --- /dev/null +++ b/lib/libgssapi/gss_buffer_set.c @@ -0,0 +1,126 @@ +/* + * Copyright (c) 2004, PADL Software Pty Ltd. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of PADL Software nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY PADL SOFTWARE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL PADL SOFTWARE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +/* $FreeBSD$ */ + +#include <gssapi/gssapi.h> +#include <errno.h> +#include <stdlib.h> +#include <string.h> + +/* RCSID("$Id: gss_buffer_set.c 18885 2006-10-24 21:53:02Z lha $"); */ + +OM_uint32 +gss_create_empty_buffer_set(OM_uint32 * minor_status, + gss_buffer_set_t *buffer_set) +{ + gss_buffer_set_t set; + + set = (gss_buffer_set_desc *) malloc(sizeof(*set)); + if (set == GSS_C_NO_BUFFER_SET) { + *minor_status = ENOMEM; + return (GSS_S_FAILURE); + } + + set->count = 0; + set->elements = NULL; + + *buffer_set = set; + + *minor_status = 0; + return (GSS_S_COMPLETE); +} + +OM_uint32 +gss_add_buffer_set_member(OM_uint32 * minor_status, + const gss_buffer_t member_buffer, gss_buffer_set_t *buffer_set) +{ + gss_buffer_set_t set; + gss_buffer_t p; + OM_uint32 ret; + + if (*buffer_set == GSS_C_NO_BUFFER_SET) { + ret = gss_create_empty_buffer_set(minor_status, + buffer_set); + if (ret) { + return (ret); + } + } + + set = *buffer_set; + set->elements = realloc(set->elements, + (set->count + 1) * sizeof(set->elements[0])); + if (set->elements == NULL) { + *minor_status = ENOMEM; + return (GSS_S_FAILURE); + } + + p = &set->elements[set->count]; + + p->value = malloc(member_buffer->length); + if (p->value == NULL) { + *minor_status = ENOMEM; + return (GSS_S_FAILURE); + } + memcpy(p->value, member_buffer->value, member_buffer->length); + p->length = member_buffer->length; + + set->count++; + + *minor_status = 0; + return (GSS_S_COMPLETE); +} + +OM_uint32 +gss_release_buffer_set(OM_uint32 * minor_status, gss_buffer_set_t *buffer_set) +{ + size_t i; + OM_uint32 minor; + + *minor_status = 0; + + if (*buffer_set == GSS_C_NO_BUFFER_SET) + return (GSS_S_COMPLETE); + + for (i = 0; i < (*buffer_set)->count; i++) + gss_release_buffer(&minor, &((*buffer_set)->elements[i])); + + free((*buffer_set)->elements); + + (*buffer_set)->elements = NULL; + (*buffer_set)->count = 0; + + free(*buffer_set); + *buffer_set = GSS_C_NO_BUFFER_SET; + + return (GSS_S_COMPLETE); +} + diff --git a/lib/libgssapi/gss_canonicalize_name.c b/lib/libgssapi/gss_canonicalize_name.c index 0983622..28940b9 100644 --- a/lib/libgssapi/gss_canonicalize_name.c +++ b/lib/libgssapi/gss_canonicalize_name.c @@ -49,16 +49,17 @@ gss_canonicalize_name(OM_uint32 *minor_status, *minor_status = 0; *output_name = 0; - mn = _gss_find_mn(name, mech_type); - if (!mn) { - return (GSS_S_BAD_MECH); - } + major_status = _gss_find_mn(minor_status, name, mech_type, &mn); + if (major_status) + return (major_status); m = mn->gmn_mech; major_status = m->gm_canonicalize_name(minor_status, mn->gmn_name, mech_type, &new_canonical_name); - if (major_status) + if (major_status) { + _gss_mg_error(m, major_status, *minor_status); return (major_status); + } /* * Now we make a new name and mark it as an MN. diff --git a/lib/libgssapi/gss_compare_name.c b/lib/libgssapi/gss_compare_name.c index 644b4a6..05b28f6 100644 --- a/lib/libgssapi/gss_compare_name.c +++ b/lib/libgssapi/gss_compare_name.c @@ -27,9 +27,11 @@ */ #include <gssapi/gssapi.h> +#include <string.h> #include "mech_switch.h" #include "name.h" +#include "utils.h" OM_uint32 gss_compare_name(OM_uint32 *minor_status, @@ -47,7 +49,7 @@ gss_compare_name(OM_uint32 *minor_status, */ if (name1->gn_value.value && name2->gn_value.value) { *name_equal = 1; - if (!_gss_oid_equal(name1->gn_type, name2->gn_type)) { + if (!gss_oid_equal(&name1->gn_type, &name2->gn_type)) { *name_equal = 0; } else if (name1->gn_value.length != name2->gn_value.length || memcmp(name1->gn_value.value, name1->gn_value.value, @@ -59,8 +61,11 @@ gss_compare_name(OM_uint32 *minor_status, struct _gss_mechanism_name *mn2; SLIST_FOREACH(mn1, &name1->gn_mn, gmn_link) { - mn2 = _gss_find_mn(name2, mn1->gmn_mech_oid); - if (mn2) { + OM_uint32 major_status; + + major_status = _gss_find_mn(minor_status, name2, + mn1->gmn_mech_oid, &mn2); + if (major_status == GSS_S_COMPLETE) { return (mn1->gmn_mech->gm_compare_name( minor_status, mn1->gmn_name, diff --git a/lib/libgssapi/gss_create_empty_oid_set.c b/lib/libgssapi/gss_create_empty_oid_set.c index 0412817..c35f99f 100644 --- a/lib/libgssapi/gss_create_empty_oid_set.c +++ b/lib/libgssapi/gss_create_empty_oid_set.c @@ -37,7 +37,7 @@ gss_create_empty_oid_set(OM_uint32 *minor_status, gss_OID_set set; *minor_status = 0; - *oid_set = 0; + *oid_set = GSS_C_NO_OID_SET; set = malloc(sizeof(gss_OID_set_desc)); if (!set) { diff --git a/lib/libgssapi/gss_decapsulate_token.c b/lib/libgssapi/gss_decapsulate_token.c new file mode 100644 index 0000000..65ff46a --- /dev/null +++ b/lib/libgssapi/gss_decapsulate_token.c @@ -0,0 +1,107 @@ +/*- + * Copyright (c) 2008 Doug Rabson + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#include <gssapi/gssapi.h> +#include <stdlib.h> +#include <string.h> + +#include "utils.h" + +OM_uint32 +gss_decapsulate_token(const gss_buffer_t input_token, gss_OID oid, + gss_buffer_t output_token) +{ + unsigned char *p = input_token->value; + size_t len = input_token->length; + size_t a, b; + gss_OID_desc mech_oid; + + _gss_buffer_zero(output_token); + + /* + * Token must start with [APPLICATION 0] SEQUENCE. + */ + if (len == 0 || *p != 0x60) + return (GSS_S_DEFECTIVE_TOKEN); + p++; + len--; + + /* + * Decode the length and make sure it agrees with the + * token length. + */ + if (len == 0) + return (GSS_S_DEFECTIVE_TOKEN); + if ((*p & 0x80) == 0) { + a = *p; + p++; + len--; + } else { + b = *p & 0x7f; + p++; + len--; + if (len < b) + return (GSS_S_DEFECTIVE_TOKEN); + a = 0; + while (b) { + a = (a << 8) | *p; + p++; + len--; + b--; + } + } + if (a != len) + return (GSS_S_DEFECTIVE_TOKEN); + + /* + * Decode the OID for the mechanism. Simplify life by + * assuming that the OID length is less than 128 bytes. + */ + if (len < 2 || *p != 0x06) + return (GSS_S_DEFECTIVE_TOKEN); + if ((p[1] & 0x80) || p[1] > (len - 2)) + return (GSS_S_DEFECTIVE_TOKEN); + mech_oid.length = p[1]; + p += 2; + len -= 2; + mech_oid.elements = p; + + if (!gss_oid_equal(&mech_oid, oid)) + return (GSS_S_FAILURE); + + p += mech_oid.length; + len -= mech_oid.length; + + output_token->length = len; + output_token->value = malloc(len); + if (!output_token->value) + return (GSS_S_DEFECTIVE_TOKEN); + memcpy(output_token->value, p, len); + + return (GSS_S_COMPLETE); +} diff --git a/lib/libgssapi/gss_delete_sec_context.c b/lib/libgssapi/gss_delete_sec_context.c index b1f39c2..b4b087f 100644 --- a/lib/libgssapi/gss_delete_sec_context.c +++ b/lib/libgssapi/gss_delete_sec_context.c @@ -32,6 +32,7 @@ #include "mech_switch.h" #include "context.h" +#include "utils.h" OM_uint32 gss_delete_sec_context(OM_uint32 *minor_status, @@ -41,6 +42,9 @@ gss_delete_sec_context(OM_uint32 *minor_status, OM_uint32 major_status; struct _gss_context *ctx = (struct _gss_context *) *context_handle; + if (output_token) + _gss_buffer_zero(output_token); + *minor_status = 0; if (ctx) { /* @@ -50,12 +54,9 @@ gss_delete_sec_context(OM_uint32 *minor_status, if (ctx->gc_ctx) { major_status = ctx->gc_mech->gm_delete_sec_context( minor_status, &ctx->gc_ctx, output_token); - } else if (output_token != GSS_C_NO_BUFFER) { - output_token->length = 0; - output_token->value = 0; } free(ctx); - *context_handle = 0; + *context_handle = GSS_C_NO_CONTEXT; } return (GSS_S_COMPLETE); diff --git a/lib/libgssapi/gss_display_name.c b/lib/libgssapi/gss_display_name.c index 5fe4f1d..61faaba 100644 --- a/lib/libgssapi/gss_display_name.c +++ b/lib/libgssapi/gss_display_name.c @@ -33,6 +33,7 @@ #include "mech_switch.h" #include "name.h" +#include "utils.h" OM_uint32 gss_display_name(OM_uint32 *minor_status, @@ -44,6 +45,15 @@ gss_display_name(OM_uint32 *minor_status, struct _gss_name *name = (struct _gss_name *) input_name; struct _gss_mechanism_name *mn; + _gss_buffer_zero(output_name_buffer); + if (output_name_type) + *output_name_type = GSS_C_NO_OID; + + if (name == NULL) { + *minor_status = 0; + return (GSS_S_BAD_NAME); + } + /* * If we know it, copy the buffer used to import the name in * the first place. Otherwise, ask all the MNs in turn if diff --git a/lib/libgssapi/gss_display_status.c b/lib/libgssapi/gss_display_status.c index f87cc9e..0374fbd 100644 --- a/lib/libgssapi/gss_display_status.c +++ b/lib/libgssapi/gss_display_status.c @@ -57,12 +57,47 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ +/* + * Copyright (c) 1998 - 2005 Kungliga Tekniska H�gskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ #include <gssapi/gssapi.h> +#include <stdio.h> #include <string.h> +#include <stdlib.h> #include <errno.h> #include "mech_switch.h" +#include "utils.h" static const char * calling_error(OM_uint32 v) @@ -88,7 +123,7 @@ static const char * routine_error(OM_uint32 v) { static const char *msgs[] = { - NULL, /* 0 */ + "Function completed successfully", /* 0 */ "An unsupported mechanism was requested", "An invalid name was supplied", "A supplied name was of an unsupported type", @@ -112,9 +147,7 @@ routine_error(OM_uint32 v) v >>= GSS_C_ROUTINE_ERROR_OFFSET; - if (v == 0) - return ""; - else if (v >= sizeof(msgs)/sizeof(*msgs)) + if (v >= sizeof(msgs)/sizeof(*msgs)) return "unknown routine error"; else return msgs[v]; @@ -140,23 +173,119 @@ supplementary_error(OM_uint32 v) return msgs[v]; } +#if defined(__sparc64__) || defined(__arm__) || defined(__mips__) + +/* + * These platforms don't support TLS on FreeBSD - threads will just + * have to step on each other's error values for now. + */ +#define __thread + +#endif + +struct mg_thread_ctx { + gss_OID mech; + OM_uint32 maj_stat; + OM_uint32 min_stat; + gss_buffer_desc maj_error; + gss_buffer_desc min_error; +}; +static __thread struct mg_thread_ctx last_error_context; + +static OM_uint32 +_gss_mg_get_error(const gss_OID mech, OM_uint32 type, + OM_uint32 value, gss_buffer_t string) +{ + struct mg_thread_ctx *mg; + + mg = &last_error_context; + + if (mech != NULL && gss_oid_equal(mg->mech, mech) == 0) + return (GSS_S_BAD_STATUS); + + switch (type) { + case GSS_C_GSS_CODE: { + if (value != mg->maj_stat || mg->maj_error.length == 0) + break; + string->value = malloc(mg->maj_error.length); + string->length = mg->maj_error.length; + memcpy(string->value, mg->maj_error.value, + mg->maj_error.length); + return (GSS_S_COMPLETE); + } + case GSS_C_MECH_CODE: { + if (value != mg->min_stat || mg->min_error.length == 0) + break; + string->value = malloc(mg->min_error.length); + string->length = mg->min_error.length; + memcpy(string->value, mg->min_error.value, + mg->min_error.length); + return (GSS_S_COMPLETE); + } + } + string->value = NULL; + string->length = 0; + return (GSS_S_BAD_STATUS); +} + +void +_gss_mg_error(struct _gss_mech_switch *m, OM_uint32 maj, OM_uint32 min) +{ + OM_uint32 major_status, minor_status; + OM_uint32 message_content; + struct mg_thread_ctx *mg; + + mg = &last_error_context; + + gss_release_buffer(&minor_status, &mg->maj_error); + gss_release_buffer(&minor_status, &mg->min_error); + + mg->mech = &m->gm_mech_oid; + mg->maj_stat = maj; + mg->min_stat = min; + + major_status = m->gm_display_status(&minor_status, + maj, + GSS_C_GSS_CODE, + &m->gm_mech_oid, + &message_content, + &mg->maj_error); + if (GSS_ERROR(major_status)) { + mg->maj_error.value = NULL; + mg->maj_error.length = 0; + } + major_status = m->gm_display_status(&minor_status, + min, + GSS_C_MECH_CODE, + &m->gm_mech_oid, + &message_content, + &mg->min_error); + if (GSS_ERROR(major_status)) { + mg->min_error.value = NULL; + mg->min_error.length = 0; + } +} + OM_uint32 gss_display_status(OM_uint32 *minor_status, OM_uint32 status_value, int status_type, - const gss_OID input_mech_type, + const gss_OID mech_type, OM_uint32 *message_content, gss_buffer_t status_string) { OM_uint32 major_status; - gss_OID mech_type; - - mech_type = input_mech_type; - if (mech_type == GSS_C_NO_OID) { - _gss_load_mech(); - mech_type = &SLIST_FIRST(&_gss_mechs)->gm_mech_oid; - if (mech_type == NULL) - return (GSS_S_BAD_MECH); + + _gss_buffer_zero(status_string); + *message_content = 0; + + major_status = _gss_mg_get_error(mech_type, status_type, + status_value, status_string); + if (major_status == GSS_S_COMPLETE) { + + *message_content = 0; + *minor_status = 0; + return (GSS_S_COMPLETE); } *minor_status = 0; @@ -172,24 +301,40 @@ gss_display_status(OM_uint32 *minor_status, calling_error(GSS_CALLING_ERROR(status_value)), routine_error(GSS_ROUTINE_ERROR(status_value))); + if (buf == NULL) + break; + status_string->length = strlen(buf); status_string->value = buf; - return GSS_S_COMPLETE; + return (GSS_S_COMPLETE); } case GSS_C_MECH_CODE: { - struct _gss_mech_switch *m; - m = _gss_find_mech_switch(mech_type); - if (m) { - major_status = m->gm_display_status(minor_status, - status_value, status_type, mech_type, - message_content, status_string); - if (major_status == GSS_S_COMPLETE) - return (GSS_S_COMPLETE); + OM_uint32 maj_junk, min_junk; + gss_buffer_desc oid; + char *buf; + + maj_junk = gss_oid_to_str(&min_junk, mech_type, &oid); + if (maj_junk != GSS_S_COMPLETE) { + oid.value = strdup("unknown"); + oid.length = 7; } + + asprintf (&buf, "unknown mech-code %lu for mech %.*s", + (unsigned long)status_value, + (int)oid.length, (char *)oid.value); + if (maj_junk == GSS_S_COMPLETE) + gss_release_buffer(&min_junk, &oid); + + if (buf == NULL) + break; + + status_string->length = strlen(buf); + status_string->value = buf; + + return (GSS_S_COMPLETE); } } - status_string->value = NULL; - status_string->length = 0; + _gss_buffer_zero(status_string); return (GSS_S_BAD_STATUS); } diff --git a/lib/libgssapi/gss_duplicate_name.c b/lib/libgssapi/gss_duplicate_name.c index f0ce417..c6d07ac 100644 --- a/lib/libgssapi/gss_duplicate_name.c +++ b/lib/libgssapi/gss_duplicate_name.c @@ -44,11 +44,12 @@ OM_uint32 gss_duplicate_name(OM_uint32 *minor_status, struct _gss_mechanism_name *mn; *minor_status = 0; + *dest_name = GSS_C_NO_NAME; /* * If this name has a value (i.e. it didn't come from * gss_canonicalize_name(), we re-import the thing. Otherwise, - * we make an empty name to hold the MN copy. + * we make a copy of the mechanism names. */ if (name->gn_value.value) { major_status = gss_import_name(minor_status, @@ -56,6 +57,12 @@ OM_uint32 gss_duplicate_name(OM_uint32 *minor_status, if (major_status != GSS_S_COMPLETE) return (major_status); new_name = (struct _gss_name *) *dest_name; + + SLIST_FOREACH(mn, &name->gn_mn, gmn_link) { + struct _gss_mechanism_name *mn2; + _gss_find_mn(minor_status, new_name, + mn->gmn_mech_oid, &mn2); + } } else { new_name = malloc(sizeof(struct _gss_name)); if (!new_name) { @@ -63,17 +70,30 @@ OM_uint32 gss_duplicate_name(OM_uint32 *minor_status, return (GSS_S_FAILURE); } memset(new_name, 0, sizeof(struct _gss_name)); - SLIST_INIT(&name->gn_mn); + SLIST_INIT(&new_name->gn_mn); *dest_name = (gss_name_t) new_name; - } - /* - * Import the new name into any mechanisms listed in the - * original name. We could probably get away with only doing - * this if the original was canonical. - */ - SLIST_FOREACH(mn, &name->gn_mn, gmn_link) { - _gss_find_mn(new_name, mn->gmn_mech_oid); + SLIST_FOREACH(mn, &name->gn_mn, gmn_link) { + struct _gss_mechanism_name *new_mn; + + new_mn = malloc(sizeof(*new_mn)); + if (!new_mn) { + *minor_status = ENOMEM; + return (GSS_S_FAILURE); + } + new_mn->gmn_mech = mn->gmn_mech; + new_mn->gmn_mech_oid = mn->gmn_mech_oid; + + major_status = + mn->gmn_mech->gm_duplicate_name(minor_status, + mn->gmn_name, &new_mn->gmn_name); + if (major_status != GSS_S_COMPLETE) { + free(new_mn); + continue; + } + SLIST_INSERT_HEAD(&new_name->gn_mn, new_mn, gmn_link); + } + } return (GSS_S_COMPLETE); diff --git a/lib/libgssapi/gss_duplicate_oid.c b/lib/libgssapi/gss_duplicate_oid.c new file mode 100644 index 0000000..591508d --- /dev/null +++ b/lib/libgssapi/gss_duplicate_oid.c @@ -0,0 +1,65 @@ +/*- + * Copyright (c) 2008 Doug Rabson + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#include <gssapi/gssapi.h> +#include <stdlib.h> +#include <string.h> +#include <errno.h> + +OM_uint32 gss_duplicate_oid(OM_uint32 *minor_status, + const gss_OID src_oid, + gss_OID *dest_oid_p) +{ + gss_OID dest_oid; + + *minor_status = 0; + *dest_oid_p = GSS_C_NO_OID; + + if (src_oid == GSS_C_NO_OID) + return (GSS_S_COMPLETE); + + dest_oid = malloc(sizeof(gss_OID_desc)); + if (!dest_oid) { + *minor_status = ENOMEM; + return (GSS_S_FAILURE); + } + + dest_oid->elements = malloc(src_oid->length); + if (!dest_oid->elements) { + free(dest_oid); + *minor_status = ENOMEM; + return (GSS_S_FAILURE); + } + + memcpy(dest_oid->elements, src_oid->elements, src_oid->length); + dest_oid->length = src_oid->length; + + *dest_oid_p = dest_oid; + + return (GSS_S_COMPLETE); +} diff --git a/lib/libgssapi/gss_encapsulate_token.c b/lib/libgssapi/gss_encapsulate_token.c new file mode 100644 index 0000000..ed0e217 --- /dev/null +++ b/lib/libgssapi/gss_encapsulate_token.c @@ -0,0 +1,131 @@ +/*- + * Copyright (c) 2008 Doug Rabson + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#include <gssapi/gssapi.h> +#include <stdlib.h> +#include <string.h> + +#include "utils.h" + +OM_uint32 +gss_encapsulate_token(const gss_buffer_t input_token, gss_OID oid, + gss_buffer_t output_token) +{ + unsigned char *p; + size_t len, inside_len; + size_t a, b; + int i; + + _gss_buffer_zero(output_token); + + /* + * First time around, we calculate the size, second time, we + * encode the token. + */ + p = 0; + for (i = 0; i < 2; i++) { + len = 0; + + /* + * Token starts with [APPLICATION 0] SEQUENCE. + */ + if (p) + *p++ = 0x60; + len++; + + /* + * The length embedded in the token is the space + * needed for the encapsulated oid plus the length of + * the inner token. + */ + if (oid->length > 127) + return (GSS_S_DEFECTIVE_TOKEN); + + inside_len = 2 + oid->length + input_token->length; + + /* + * Figure out how to encode the length + */ + if (inside_len < 128) { + if (p) + *p++ = inside_len; + len++; + } else { + b = 1; + if (inside_len >= 0x100) + b++; + if (inside_len >= 0x10000) + b++; + if (inside_len >= 0x1000000) + b++; + if (p) + *p++ = b | 0x80; + len++; + a = inside_len << 8*(4 - b); + while (b) { + if (p) + *p++ = (a >> 24); + a <<= 8; + len++; + b--; + } + } + + /* + * Encode the OID for the mechanism. Simplify life by + * assuming that the OID length is less than 128 bytes. + */ + if (p) + *p++ = 0x06; + len++; + if (p) + *p++ = oid->length; + len++; + if (p) { + memcpy(p, oid->elements, oid->length); + p += oid->length; + } + len += oid->length; + + if (p) { + memcpy(p, input_token->value, input_token->length); + p += input_token->length; + } + len += input_token->length; + + if (i == 0) { + output_token->length = len; + output_token->value = malloc(len); + if (!output_token->value) + return (GSS_S_DEFECTIVE_TOKEN); + p = output_token->value; + } + } + + return (GSS_S_COMPLETE); +} diff --git a/lib/libgssapi/gss_export_name.c b/lib/libgssapi/gss_export_name.c index 6cba2f8..49174bb 100644 --- a/lib/libgssapi/gss_export_name.c +++ b/lib/libgssapi/gss_export_name.c @@ -30,6 +30,7 @@ #include "mech_switch.h" #include "name.h" +#include "utils.h" OM_uint32 gss_export_name(OM_uint32 *minor_status, @@ -39,8 +40,7 @@ gss_export_name(OM_uint32 *minor_status, struct _gss_name *name = (struct _gss_name *) input_name; struct _gss_mechanism_name *mn; - exported_name->value = NULL; - exported_name->length = 0; + _gss_buffer_zero(exported_name); /* * If this name already has any attached MNs, export the first @@ -48,12 +48,9 @@ gss_export_name(OM_uint32 *minor_status, * list. */ mn = SLIST_FIRST(&name->gn_mn); - if (!mn) - mn = _gss_find_mn(name, - &SLIST_FIRST(&_gss_mechs)->gm_mech_oid); if (!mn) { *minor_status = 0; - return (GSS_S_BAD_MECH); + return (GSS_S_NAME_NOT_MN); } return mn->gmn_mech->gm_export_name(minor_status, diff --git a/lib/libgssapi/gss_export_sec_context.c b/lib/libgssapi/gss_export_sec_context.c index 71c6874..a600f28 100644 --- a/lib/libgssapi/gss_export_sec_context.c +++ b/lib/libgssapi/gss_export_sec_context.c @@ -33,6 +33,7 @@ #include "mech_switch.h" #include "context.h" +#include "utils.h" OM_uint32 gss_export_sec_context(OM_uint32 *minor_status, @@ -44,6 +45,8 @@ gss_export_sec_context(OM_uint32 *minor_status, struct _gss_mech_switch *m = ctx->gc_mech; gss_buffer_desc buf; + _gss_buffer_zero(interprocess_token); + major_status = m->gm_export_sec_context(minor_status, &ctx->gc_ctx, &buf); @@ -63,6 +66,7 @@ gss_export_sec_context(OM_uint32 *minor_status, * GSS_C_NO_CONTEXT, which we did above. * Return GSS_S_FAILURE. */ + _gss_buffer_zero(interprocess_token); *minor_status = ENOMEM; return (GSS_S_FAILURE); } @@ -72,6 +76,8 @@ gss_export_sec_context(OM_uint32 *minor_status, memcpy(p + 2, m->gm_mech_oid.elements, m->gm_mech_oid.length); memcpy(p + 2 + m->gm_mech_oid.length, buf.value, buf.length); gss_release_buffer(minor_status, &buf); + } else { + _gss_mg_error(m, major_status, *minor_status); } return (major_status); diff --git a/lib/libgssapi/gss_get_mic.c b/lib/libgssapi/gss_get_mic.c index a3495ec..dff3b54 100644 --- a/lib/libgssapi/gss_get_mic.c +++ b/lib/libgssapi/gss_get_mic.c @@ -30,6 +30,7 @@ #include "mech_switch.h" #include "context.h" +#include "utils.h" OM_uint32 gss_get_mic(OM_uint32 *minor_status, @@ -41,6 +42,12 @@ gss_get_mic(OM_uint32 *minor_status, struct _gss_context *ctx = (struct _gss_context *) context_handle; struct _gss_mech_switch *m = ctx->gc_mech; + _gss_buffer_zero(message_token); + if (ctx == NULL) { + *minor_status = 0; + return (GSS_S_NO_CONTEXT); + } + return (m->gm_get_mic(minor_status, ctx->gc_ctx, qop_req, message_buffer, message_token)); } diff --git a/lib/libgssapi/gss_import_name.c b/lib/libgssapi/gss_import_name.c index 65820b1..3d8079d 100644 --- a/lib/libgssapi/gss_import_name.c +++ b/lib/libgssapi/gss_import_name.c @@ -47,7 +47,6 @@ _gss_import_export_name(OM_uint32 *minor_status, gss_OID_desc mech_oid; struct _gss_mech_switch *m; struct _gss_name *name; - struct _gss_mechanism_name *mn; gss_name_t new_canonical_name; *minor_status = 0; @@ -126,6 +125,10 @@ _gss_import_export_name(OM_uint32 *minor_status, */ major_status = m->gm_import_name(minor_status, input_name_buffer, GSS_C_NT_EXPORT_NAME, &new_canonical_name); + if (major_status != GSS_S_COMPLETE) { + _gss_mg_error(m, major_status, *minor_status); + return (major_status); + } /* * Now we make a new name and mark it as an MN. @@ -152,9 +155,10 @@ gss_import_name(OM_uint32 *minor_status, OM_uint32 major_status; struct _gss_name *name; + *output_name = GSS_C_NO_NAME; + if (input_name_buffer->length == 0) { *minor_status = 0; - *output_name = 0; return (GSS_S_BAD_NAME); } @@ -169,7 +173,7 @@ gss_import_name(OM_uint32 *minor_status, * the mechanism and then import it as an MN. See RFC 2743 * section 3.2 for a description of the format. */ - if (_gss_oid_equal(name_type, GSS_C_NT_EXPORT_NAME)) { + if (gss_oid_equal(name_type, GSS_C_NT_EXPORT_NAME)) { return _gss_import_export_name(minor_status, input_name_buffer, output_name); } @@ -179,15 +183,14 @@ gss_import_name(OM_uint32 *minor_status, * should figure out the list of supported name types using * gss_inquire_names_for_mech. */ - if (!_gss_oid_equal(name_type, GSS_C_NT_USER_NAME) - && !_gss_oid_equal(name_type, GSS_C_NT_MACHINE_UID_NAME) - && !_gss_oid_equal(name_type, GSS_C_NT_STRING_UID_NAME) - && !_gss_oid_equal(name_type, GSS_C_NT_HOSTBASED_SERVICE_X) - && !_gss_oid_equal(name_type, GSS_C_NT_HOSTBASED_SERVICE) - && !_gss_oid_equal(name_type, GSS_C_NT_ANONYMOUS) - && !_gss_oid_equal(name_type, GSS_KRB5_NT_PRINCIPAL_NAME)) { + if (!gss_oid_equal(name_type, GSS_C_NT_USER_NAME) + && !gss_oid_equal(name_type, GSS_C_NT_MACHINE_UID_NAME) + && !gss_oid_equal(name_type, GSS_C_NT_STRING_UID_NAME) + && !gss_oid_equal(name_type, GSS_C_NT_HOSTBASED_SERVICE_X) + && !gss_oid_equal(name_type, GSS_C_NT_HOSTBASED_SERVICE) + && !gss_oid_equal(name_type, GSS_C_NT_ANONYMOUS) + && !gss_oid_equal(name_type, GSS_KRB5_NT_PRINCIPAL_NAME)) { *minor_status = 0; - *output_name = 0; return (GSS_S_BAD_NAMETYPE); } @@ -209,7 +212,8 @@ gss_import_name(OM_uint32 *minor_status, major_status = _gss_copy_buffer(minor_status, input_name_buffer, &name->gn_value); if (major_status) { - gss_release_name(minor_status, (gss_name_t*) &name); + gss_name_t rname = (gss_name_t)name; + gss_release_name(minor_status, &rname); return (GSS_S_FAILURE); } diff --git a/lib/libgssapi/gss_import_sec_context.c b/lib/libgssapi/gss_import_sec_context.c index ce3ddd1..0ab138e 100644 --- a/lib/libgssapi/gss_import_sec_context.c +++ b/lib/libgssapi/gss_import_sec_context.c @@ -47,7 +47,7 @@ gss_import_sec_context(OM_uint32 *minor_status, size_t len; *minor_status = 0; - *context_handle = 0; + *context_handle = GSS_C_NO_CONTEXT; /* * We added an oid to the front of the token in @@ -77,6 +77,7 @@ gss_import_sec_context(OM_uint32 *minor_status, major_status = m->gm_import_sec_context(minor_status, &buf, &ctx->gc_ctx); if (major_status != GSS_S_COMPLETE) { + _gss_mg_error(m, major_status, *minor_status); free(ctx); } else { *context_handle = (gss_ctx_id_t) ctx; diff --git a/lib/libgssapi/gss_indicate_mechs.c b/lib/libgssapi/gss_indicate_mechs.c index 87a34f4..ec4350f 100644 --- a/lib/libgssapi/gss_indicate_mechs.c +++ b/lib/libgssapi/gss_indicate_mechs.c @@ -37,7 +37,7 @@ gss_indicate_mechs(OM_uint32 *minor_status, struct _gss_mech_switch *m; OM_uint32 major_status; gss_OID_set set; - int i; + size_t i; _gss_load_mech(); @@ -50,6 +50,12 @@ gss_indicate_mechs(OM_uint32 *minor_status, major_status = m->gm_indicate_mechs(minor_status, &set); if (major_status) continue; + if (set == GSS_C_NO_OID_SET) { + major_status = gss_add_oid_set_member( + minor_status, + &m->gm_mech_oid, mech_set); + continue; + } for (i = 0; i < set->count; i++) major_status = gss_add_oid_set_member(minor_status, &set->elements[i], mech_set); diff --git a/lib/libgssapi/gss_init_sec_context.c b/lib/libgssapi/gss_init_sec_context.c index 8b596f3..d8f06ab 100644 --- a/lib/libgssapi/gss_init_sec_context.c +++ b/lib/libgssapi/gss_init_sec_context.c @@ -35,13 +35,30 @@ #include "name.h" #include "cred.h" #include "context.h" +#include "utils.h" + +static gss_cred_id_t +_gss_mech_cred_find(gss_cred_id_t cred_handle, gss_OID mech_type) +{ + struct _gss_cred *cred = (struct _gss_cred *)cred_handle; + struct _gss_mechanism_cred *mc; + + if (cred == NULL) + return GSS_C_NO_CREDENTIAL; + + SLIST_FOREACH(mc, &cred->gc_mc, gmc_link) { + if (gss_oid_equal(mech_type, mc->gmc_mech_oid)) + return mc->gmc_cred; + } + return GSS_C_NO_CREDENTIAL; +} OM_uint32 gss_init_sec_context(OM_uint32 * minor_status, const gss_cred_id_t initiator_cred_handle, gss_ctx_id_t * context_handle, const gss_name_t target_name, - const gss_OID imech_type, + const gss_OID input_mech_type, OM_uint32 req_flags, OM_uint32 time_req, const gss_channel_bindings_t input_chan_bindings, @@ -52,24 +69,23 @@ gss_init_sec_context(OM_uint32 * minor_status, OM_uint32 * time_rec) { OM_uint32 major_status; - gss_OID mech_type; struct _gss_mech_switch *m; struct _gss_name *name = (struct _gss_name *) target_name; struct _gss_mechanism_name *mn; struct _gss_context *ctx = (struct _gss_context *) *context_handle; - struct _gss_cred *cred = (struct _gss_cred *) initiator_cred_handle; - struct _gss_mechanism_cred *mc; gss_cred_id_t cred_handle; int allocated_ctx; + gss_OID mech_type = input_mech_type; *minor_status = 0; - if ((mech_type = imech_type) == GSS_C_NO_OID) { - _gss_load_mech(); - mech_type = &SLIST_FIRST(&_gss_mechs)->gm_mech_oid; - if (mech_type == NULL) - return (GSS_S_BAD_MECH); - } + _gss_buffer_zero(output_token); + if (actual_mech_type) + *actual_mech_type = GSS_C_NO_OID; + if (ret_flags) + *ret_flags = 0; + if (time_rec) + *time_rec = 0; /* * If we haven't allocated a context yet, do so now and lookup @@ -77,6 +93,14 @@ gss_init_sec_context(OM_uint32 * minor_status, * sure we use the same mechanism switch as before. */ if (!ctx) { + if (mech_type == GSS_C_NO_OID) { + _gss_load_mech(); + if (_gss_mech_oids == GSS_C_NO_OID_SET + || _gss_mech_oids->count == 0) + return (GSS_S_BAD_MECH); + mech_type = &_gss_mech_oids->elements[0]; + } + ctx = malloc(sizeof(struct _gss_context)); if (!ctx) { *minor_status = ENOMEM; @@ -91,31 +115,24 @@ gss_init_sec_context(OM_uint32 * minor_status, allocated_ctx = 1; } else { m = ctx->gc_mech; + mech_type = &ctx->gc_mech->gm_mech_oid; allocated_ctx = 0; } /* * Find the MN for this mechanism. */ - mn = _gss_find_mn(name, mech_type); - if (mn == NULL) { + major_status = _gss_find_mn(minor_status, name, mech_type, &mn); + if (major_status != GSS_S_COMPLETE) { if (allocated_ctx) free(ctx); - return GSS_S_BAD_NAME; + return (major_status); } /* * If we have a cred, find the cred for this mechanism. */ - cred_handle = GSS_C_NO_CREDENTIAL; - if (cred) { - SLIST_FOREACH(mc, &cred->gc_mc, gmc_link) { - if (_gss_oid_equal(mech_type, mc->gmc_mech_oid)) { - cred_handle = mc->gmc_cred; - break; - } - } - } + cred_handle = _gss_mech_cred_find(initiator_cred_handle, mech_type); major_status = m->gm_init_sec_context(minor_status, cred_handle, @@ -135,6 +152,8 @@ gss_init_sec_context(OM_uint32 * minor_status, && major_status != GSS_S_CONTINUE_NEEDED) { if (allocated_ctx) free(ctx); + _gss_buffer_zero(output_token); + _gss_mg_error(m, major_status, *minor_status); } else { *context_handle = (gss_ctx_id_t) ctx; } diff --git a/lib/libgssapi/gss_inquire_context.c b/lib/libgssapi/gss_inquire_context.c index 3f4531d..c9f2a0c 100644 --- a/lib/libgssapi/gss_inquire_context.c +++ b/lib/libgssapi/gss_inquire_context.c @@ -49,27 +49,43 @@ gss_inquire_context(OM_uint32 *minor_status, struct _gss_name *name; gss_name_t src_mn, targ_mn; + if (locally_initiated) + *locally_initiated = 0; + if (open) + *open = 0; + if (lifetime_rec) + *lifetime_rec = 0; + + if (src_name) + *src_name = GSS_C_NO_NAME; + if (targ_name) + *targ_name = GSS_C_NO_NAME; + if (mech_type) + *mech_type = GSS_C_NO_OID; + src_mn = targ_mn = GSS_C_NO_NAME; + major_status = m->gm_inquire_context(minor_status, ctx->gc_ctx, - src_name ? &src_mn : 0, - targ_name ? &targ_mn : 0, + src_name ? &src_mn : NULL, + targ_name ? &targ_mn : NULL, lifetime_rec, mech_type, ctx_flags, locally_initiated, open); - if (src_name) *src_name = 0; - if (targ_name) *targ_name = 0; - if (major_status != GSS_S_COMPLETE) { + _gss_mg_error(m, major_status, *minor_status); return (major_status); } if (src_name) { name = _gss_make_name(m, src_mn); if (!name) { - minor_status = 0; + if (mech_type) + *mech_type = GSS_C_NO_OID; + m->gm_release_name(minor_status, &src_mn); + *minor_status = 0; return (GSS_S_FAILURE); } *src_name = (gss_name_t) name; @@ -78,6 +94,11 @@ gss_inquire_context(OM_uint32 *minor_status, if (targ_name) { name = _gss_make_name(m, targ_mn); if (!name) { + if (mech_type) + *mech_type = GSS_C_NO_OID; + if (src_name) + gss_release_name(minor_status, src_name); + m->gm_release_name(minor_status, &src_mn); minor_status = 0; return (GSS_S_FAILURE); } diff --git a/lib/libgssapi/gss_inquire_cred.c b/lib/libgssapi/gss_inquire_cred.c index 60b746f..c51f07e 100644 --- a/lib/libgssapi/gss_inquire_cred.c +++ b/lib/libgssapi/gss_inquire_cred.c @@ -35,6 +35,20 @@ #include "name.h" #include "cred.h" +#define AUSAGE 1 +#define IUSAGE 2 + +static void +updateusage(gss_cred_usage_t usage, int *usagemask) +{ + if (usage == GSS_C_BOTH) + *usagemask |= AUSAGE | IUSAGE; + else if (usage == GSS_C_ACCEPT) + *usagemask |= AUSAGE; + else if (usage == GSS_C_INITIATE) + *usagemask |= IUSAGE; +} + OM_uint32 gss_inquire_cred(OM_uint32 *minor_status, const gss_cred_id_t cred_handle, @@ -46,29 +60,35 @@ gss_inquire_cred(OM_uint32 *minor_status, OM_uint32 major_status; struct _gss_mech_switch *m; struct _gss_cred *cred = (struct _gss_cred *) cred_handle; - struct _gss_mechanism_cred *mc; struct _gss_name *name; struct _gss_mechanism_name *mn; OM_uint32 min_lifetime; + int found = 0; + int usagemask = 0; + gss_cred_usage_t usage; + + _gss_load_mech(); *minor_status = 0; if (name_ret) - *name_ret = 0; + *name_ret = GSS_C_NO_NAME; if (lifetime) *lifetime = 0; if (cred_usage) *cred_usage = 0; + if (mechanisms) + *mechanisms = GSS_C_NO_OID_SET; if (name_ret) { name = malloc(sizeof(struct _gss_name)); - if (!name) { + if (name == NULL) { *minor_status = ENOMEM; return (GSS_S_FAILURE); } memset(name, 0, sizeof(struct _gss_name)); SLIST_INIT(&name->gn_mn); } else { - name = 0; + name = NULL; } if (mechanisms) { @@ -82,16 +102,19 @@ gss_inquire_cred(OM_uint32 *minor_status, min_lifetime = GSS_C_INDEFINITE; if (cred) { + struct _gss_mechanism_cred *mc; + SLIST_FOREACH(mc, &cred->gc_mc, gmc_link) { gss_name_t mc_name; OM_uint32 mc_lifetime; major_status = mc->gmc_mech->gm_inquire_cred(minor_status, - mc->gmc_cred, &mc_name, &mc_lifetime, NULL, NULL); + mc->gmc_cred, &mc_name, &mc_lifetime, &usage, NULL); if (major_status) continue; - if (name) { + updateusage(usage, &usagemask); + if (name && mc_name) { mn = malloc(sizeof(struct _gss_mechanism_name)); if (!mn) { mc->gmc_mech->gm_release_name(minor_status, @@ -102,7 +125,7 @@ gss_inquire_cred(OM_uint32 *minor_status, mn->gmn_mech_oid = mc->gmc_mech_oid; mn->gmn_name = mc_name; SLIST_INSERT_HEAD(&name->gn_mn, mn, gmn_link); - } else { + } else if (mc_name) { mc->gmc_mech->gm_release_name(minor_status, &mc_name); } @@ -113,6 +136,7 @@ gss_inquire_cred(OM_uint32 *minor_status, if (mechanisms) gss_add_oid_set_member(minor_status, mc->gmc_mech_oid, mechanisms); + found++; } } else { SLIST_FOREACH(m, &_gss_mechs, gm_link) { @@ -121,24 +145,25 @@ gss_inquire_cred(OM_uint32 *minor_status, major_status = m->gm_inquire_cred(minor_status, GSS_C_NO_CREDENTIAL, &mc_name, &mc_lifetime, - cred_usage, NULL); + &usage, NULL); if (major_status) continue; + updateusage(usage, &usagemask); if (name && mc_name) { mn = malloc( sizeof(struct _gss_mechanism_name)); if (!mn) { - mc->gmc_mech->gm_release_name( + m->gm_release_name( minor_status, &mc_name); continue; } - mn->gmn_mech = mc->gmc_mech; - mn->gmn_mech_oid = mc->gmc_mech_oid; + mn->gmn_mech = m; + mn->gmn_mech_oid = &m->gm_mech_oid; mn->gmn_name = mc_name; SLIST_INSERT_HEAD(&name->gn_mn, mn, gmn_link); } else if (mc_name) { - mc->gmc_mech->gm_release_name(minor_status, + m->gm_release_name(minor_status, &mc_name); } @@ -148,13 +173,17 @@ gss_inquire_cred(OM_uint32 *minor_status, if (mechanisms) gss_add_oid_set_member(minor_status, &m->gm_mech_oid, mechanisms); + found++; } + } - if ((*mechanisms)->count == 0) { - gss_release_oid_set(minor_status, mechanisms); - *minor_status = 0; - return (GSS_S_NO_CRED); - } + if (found == 0) { + gss_name_t n = (gss_name_t)name; + if (n) + gss_release_name(minor_status, &n); + gss_release_oid_set(minor_status, mechanisms); + *minor_status = 0; + return (GSS_S_NO_CRED); } *minor_status = 0; @@ -162,7 +191,13 @@ gss_inquire_cred(OM_uint32 *minor_status, *name_ret = (gss_name_t) name; if (lifetime) *lifetime = min_lifetime; - if (cred && cred_usage) - *cred_usage = cred->gc_usage; + if (cred_usage) { + if ((usagemask & (AUSAGE|IUSAGE)) == (AUSAGE|IUSAGE)) + *cred_usage = GSS_C_BOTH; + else if (usagemask & IUSAGE) + *cred_usage = GSS_C_INITIATE; + else if (usagemask & AUSAGE) + *cred_usage = GSS_C_ACCEPT; + } return (GSS_S_COMPLETE); } diff --git a/lib/libgssapi/gss_inquire_cred_by_mech.c b/lib/libgssapi/gss_inquire_cred_by_mech.c index 2896f77..d9c21ba 100644 --- a/lib/libgssapi/gss_inquire_cred_by_mech.c +++ b/lib/libgssapi/gss_inquire_cred_by_mech.c @@ -49,6 +49,14 @@ gss_inquire_cred_by_mech(OM_uint32 *minor_status, struct _gss_name *name; *minor_status = 0; + if (cred_name) + *cred_name = GSS_C_NO_NAME; + if (initiator_lifetime) + *initiator_lifetime = 0; + if (acceptor_lifetime) + *acceptor_lifetime = 0; + if (cred_usage) + *cred_usage = 0; m = _gss_find_mech_switch(mech_type); if (!m) @@ -68,15 +76,21 @@ gss_inquire_cred_by_mech(OM_uint32 *minor_status, major_status = m->gm_inquire_cred_by_mech(minor_status, mc, mech_type, &mn, initiator_lifetime, acceptor_lifetime, cred_usage); - if (major_status != GSS_S_COMPLETE) + if (major_status != GSS_S_COMPLETE) { + _gss_mg_error(m, major_status, *minor_status); return (major_status); + } - name = _gss_make_name(m, mn); - if (!name) { + if (cred_name) { + name = _gss_make_name(m, mn); + if (!name) { + m->gm_release_name(minor_status, &mn); + return (GSS_S_NO_CRED); + } + *cred_name = (gss_name_t) name; + } else { m->gm_release_name(minor_status, &mn); - return (GSS_S_NO_CRED); } - *cred_name = (gss_name_t) name; return (GSS_S_COMPLETE); } diff --git a/lib/libgssapi/gss_inquire_cred_by_oid.c b/lib/libgssapi/gss_inquire_cred_by_oid.c new file mode 100644 index 0000000..fcb54a1 --- /dev/null +++ b/lib/libgssapi/gss_inquire_cred_by_oid.c @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2004, PADL Software Pty Ltd. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of PADL Software nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY PADL SOFTWARE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL PADL SOFTWARE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +/* $FreeBSD$ */ + +#include <gssapi/gssapi.h> + +#include "mech_switch.h" +#include "cred.h" +#include "name.h" + +/* RCSID("$Id: gss_inquire_cred_by_oid.c 19960 2007-01-17 15:09:24Z lha $"); */ + +OM_uint32 +gss_inquire_cred_by_oid (OM_uint32 *minor_status, + const gss_cred_id_t cred_handle, + const gss_OID desired_object, + gss_buffer_set_t *data_set) +{ + struct _gss_cred *cred = (struct _gss_cred *) cred_handle; + OM_uint32 status = GSS_S_COMPLETE; + struct _gss_mechanism_cred *mc; + struct _gss_mech_switch *m; + gss_buffer_set_t set = GSS_C_NO_BUFFER_SET; + + *minor_status = 0; + *data_set = GSS_C_NO_BUFFER_SET; + + if (cred == NULL) + return GSS_S_NO_CRED; + + SLIST_FOREACH(mc, &cred->gc_mc, gmc_link) { + gss_buffer_set_t rset = GSS_C_NO_BUFFER_SET; + size_t i; + + m = mc->gmc_mech; + if (m == NULL) { + gss_release_buffer_set(minor_status, &set); + *minor_status = 0; + return GSS_S_BAD_MECH; + } + + if (m->gm_inquire_cred_by_oid == NULL) + continue; + + status = m->gm_inquire_cred_by_oid(minor_status, + mc->gmc_cred, desired_object, &rset); + if (status != GSS_S_COMPLETE) + continue; + + for (i = 0; i < rset->count; i++) { + status = gss_add_buffer_set_member(minor_status, + &rset->elements[i], &set); + if (status != GSS_S_COMPLETE) + break; + } + gss_release_buffer_set(minor_status, &rset); + } + if (set == GSS_C_NO_BUFFER_SET) + status = GSS_S_FAILURE; + *data_set = set; + *minor_status = 0; + return status; +} + diff --git a/lib/libgssapi/gss_inquire_mechs_for_name.c b/lib/libgssapi/gss_inquire_mechs_for_name.c index 10bdd7f..68918df 100644 --- a/lib/libgssapi/gss_inquire_mechs_for_name.c +++ b/lib/libgssapi/gss_inquire_mechs_for_name.c @@ -44,6 +44,8 @@ gss_inquire_mechs_for_name(OM_uint32 *minor_status, *minor_status = 0; + _gss_load_mech(); + major_status = gss_create_empty_oid_set(minor_status, mech_types); if (major_status) return (major_status); diff --git a/lib/libgssapi/gss_inquire_names_for_mech.c b/lib/libgssapi/gss_inquire_names_for_mech.c index 3ebb632..21f03af 100644 --- a/lib/libgssapi/gss_inquire_names_for_mech.c +++ b/lib/libgssapi/gss_inquire_names_for_mech.c @@ -39,6 +39,7 @@ gss_inquire_names_for_mech(OM_uint32 *minor_status, struct _gss_mech_switch *m = _gss_find_mech_switch(mechanism); *minor_status = 0; + *name_types = GSS_C_NO_OID_SET; if (!m) return (GSS_S_BAD_MECH); @@ -57,15 +58,15 @@ gss_inquire_names_for_mech(OM_uint32 *minor_status, major_status = gss_add_oid_set_member(minor_status, GSS_C_NT_HOSTBASED_SERVICE, name_types); if (major_status) { - OM_uint32 ms; - gss_release_oid_set(&ms, name_types); + OM_uint32 junk; + gss_release_oid_set(&junk, name_types); return (major_status); } major_status = gss_add_oid_set_member(minor_status, GSS_C_NT_USER_NAME, name_types); if (major_status) { - OM_uint32 ms; - gss_release_oid_set(&ms, name_types); + OM_uint32 junk; + gss_release_oid_set(&junk, name_types); return (major_status); } } diff --git a/lib/libgssapi/gss_inquire_sec_context_by_oid.c b/lib/libgssapi/gss_inquire_sec_context_by_oid.c new file mode 100644 index 0000000..5a90142 --- /dev/null +++ b/lib/libgssapi/gss_inquire_sec_context_by_oid.c @@ -0,0 +1,60 @@ +/*- + * Copyright (c) 2008 Doug Rabson + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#include <gssapi/gssapi.h> + +#include "mech_switch.h" +#include "context.h" + +OM_uint32 +gss_inquire_sec_context_by_oid(OM_uint32 *minor_status, + const gss_ctx_id_t context_handle, + const gss_OID desired_object, + gss_buffer_set_t *result) +{ + OM_uint32 major_status; + struct _gss_context *ctx = (struct _gss_context *) context_handle; + struct _gss_mech_switch *m; + + *minor_status = 0; + *result = GSS_C_NO_BUFFER_SET; + if (!ctx) + return (GSS_S_NO_CONTEXT); + + m = ctx->gc_mech; + if (m->gm_inquire_sec_context_by_oid) { + major_status = m->gm_inquire_sec_context_by_oid( + minor_status, ctx->gc_ctx, desired_object, result); + if (major_status != GSS_S_COMPLETE) + _gss_mg_error(m, major_status, *minor_status); + } else { + major_status = GSS_S_BAD_MECH; + } + + return (major_status); +} diff --git a/lib/libgssapi/gss_mech_switch.c b/lib/libgssapi/gss_mech_switch.c index a7528a4..f5808c5 100644 --- a/lib/libgssapi/gss_mech_switch.c +++ b/lib/libgssapi/gss_mech_switch.c @@ -27,6 +27,7 @@ */ #include <gssapi/gssapi.h> +#include <ctype.h> #include <dlfcn.h> #include <errno.h> #include <stdio.h> @@ -56,6 +57,9 @@ _gss_string_to_oid(const char* s, gss_OID oid) const char *p, *q; char *res; + oid->length = 0; + oid->elements = NULL; + /* * First figure out how many numbers in the oid, then * calculate the compiled oid size. @@ -153,23 +157,23 @@ _gss_string_to_oid(const char* s, gss_OID oid) return (0); } -#define SYM(name) \ -do { \ - m->gm_ ## name = dlsym(so, "gss_" #name); \ - if (!m->gm_ ## name) { \ - fprintf(stderr, "can't find symbol gss_" #name "\n"); \ - goto bad; \ - } \ -} while (0) -#define OPTSYM(name) \ -do { \ - m->gm_ ## name = dlsym(so, "gss_" #name); \ +#define SYM(name) \ +do { \ + snprintf(buf, sizeof(buf), "%s_%s", \ + m->gm_name_prefix, #name); \ + m->gm_ ## name = dlsym(so, buf); \ + if (!m->gm_ ## name) { \ + fprintf(stderr, "can't find symbol %s\n", buf); \ + goto bad; \ + } \ } while (0) -#define OPTSYM2(symname, ourname) \ -do { \ - m->ourname = dlsym(so, #symname); \ +#define OPTSYM(name) \ +do { \ + snprintf(buf, sizeof(buf), "%s_%s", \ + m->gm_name_prefix, #name); \ + m->gm_ ## name = dlsym(so, buf); \ } while (0) /* @@ -185,8 +189,8 @@ _gss_load_mech(void) char *name, *oid, *lib, *kobj; struct _gss_mech_switch *m; int count; - char **pp; void *so; + const char *(*prefix_fn)(void); if (SLIST_FIRST(&_gss_mechs)) return; @@ -232,6 +236,13 @@ _gss_load_mech(void) continue; } + prefix_fn = (const char *(*)(void)) + dlsym(so, "_gss_name_prefix"); + if (prefix_fn) + m->gm_name_prefix = prefix_fn(); + else + m->gm_name_prefix = "gss"; + major_status = gss_add_oid_set_member(&minor_status, &m->gm_mech_oid, &_gss_mech_oids); if (major_status) { @@ -252,7 +263,7 @@ _gss_load_mech(void) SYM(wrap); SYM(unwrap); SYM(display_status); - SYM(indicate_mechs); + OPTSYM(indicate_mechs); SYM(compare_name); SYM(display_name); SYM(import_name); @@ -269,10 +280,11 @@ _gss_load_mech(void) SYM(inquire_mechs_for_name); SYM(canonicalize_name); SYM(duplicate_name); - OPTSYM2(gsskrb5_register_acceptor_identity, - gm_krb5_register_acceptor_identity); - OPTSYM(krb5_copy_ccache); - OPTSYM(krb5_compat_des3_mic); + OPTSYM(inquire_sec_context_by_oid); + OPTSYM(inquire_cred_by_oid); + OPTSYM(set_sec_context_option); + OPTSYM(set_cred_option); + OPTSYM(pseudo_random); SLIST_INSERT_HEAD(&_gss_mechs, m, gm_link); count++; @@ -294,7 +306,7 @@ _gss_find_mech_switch(gss_OID mech) _gss_load_mech(); SLIST_FOREACH(m, &_gss_mechs, gm_link) { - if (_gss_oid_equal(&m->gm_mech_oid, mech)) + if (gss_oid_equal(&m->gm_mech_oid, mech)) return m; } return (0); diff --git a/lib/libgssapi/gss_names.c b/lib/libgssapi/gss_names.c index d10350a..02775ec 100644 --- a/lib/libgssapi/gss_names.c +++ b/lib/libgssapi/gss_names.c @@ -33,6 +33,7 @@ #include "mech_switch.h" #include "name.h" +#include "utils.h" /* * The implementation must reserve static storage for a @@ -46,7 +47,7 @@ * to that gss_OID_desc. */ static gss_OID_desc GSS_C_NT_USER_NAME_storage = - {10, (void *)"\x2a\x86\x48\x86\xf7\x12\x01\x02\x01\x01"}; + {10, (void *)(uintptr_t)"\x2a\x86\x48\x86\xf7\x12\x01\x02\x01\x01"}; gss_OID GSS_C_NT_USER_NAME = &GSS_C_NT_USER_NAME_storage; /* @@ -61,7 +62,7 @@ gss_OID GSS_C_NT_USER_NAME = &GSS_C_NT_USER_NAME_storage; * initialized to point to that gss_OID_desc. */ static gss_OID_desc GSS_C_NT_MACHINE_UID_NAME_storage = - {10, (void *)"\x2a\x86\x48\x86\xf7\x12\x01\x02\x01\x02"}; + {10, (void *)(uintptr_t)"\x2a\x86\x48\x86\xf7\x12\x01\x02\x01\x02"}; gss_OID GSS_C_NT_MACHINE_UID_NAME = &GSS_C_NT_MACHINE_UID_NAME_storage; /* @@ -76,7 +77,7 @@ gss_OID GSS_C_NT_MACHINE_UID_NAME = &GSS_C_NT_MACHINE_UID_NAME_storage; * initialized to point to that gss_OID_desc. */ static gss_OID_desc GSS_C_NT_STRING_UID_NAME_storage = - {10, (void *)"\x2a\x86\x48\x86\xf7\x12\x01\x02\x01\x03"}; + {10, (void *)(uintptr_t)"\x2a\x86\x48\x86\xf7\x12\x01\x02\x01\x03"}; gss_OID GSS_C_NT_STRING_UID_NAME = &GSS_C_NT_STRING_UID_NAME_storage; /* @@ -97,7 +98,7 @@ gss_OID GSS_C_NT_STRING_UID_NAME = &GSS_C_NT_STRING_UID_NAME_storage; * implementations */ static gss_OID_desc GSS_C_NT_HOSTBASED_SERVICE_X_storage = - {6, (void *)"\x2b\x06\x01\x05\x06\x02"}; + {6, (void *)(uintptr_t)"\x2b\x06\x01\x05\x06\x02"}; gss_OID GSS_C_NT_HOSTBASED_SERVICE_X = &GSS_C_NT_HOSTBASED_SERVICE_X_storage; /* @@ -112,7 +113,7 @@ gss_OID GSS_C_NT_HOSTBASED_SERVICE_X = &GSS_C_NT_HOSTBASED_SERVICE_X_storage; * to point to that gss_OID_desc. */ static gss_OID_desc GSS_C_NT_HOSTBASED_SERVICE_storage = - {10, (void *)"\x2a\x86\x48\x86\xf7\x12\x01\x02\x01\x04"}; + {10, (void *)(uintptr_t)"\x2a\x86\x48\x86\xf7\x12\x01\x02\x01\x04"}; gss_OID GSS_C_NT_HOSTBASED_SERVICE = &GSS_C_NT_HOSTBASED_SERVICE_storage; /* @@ -126,7 +127,7 @@ gss_OID GSS_C_NT_HOSTBASED_SERVICE = &GSS_C_NT_HOSTBASED_SERVICE_storage; * to that gss_OID_desc. */ static gss_OID_desc GSS_C_NT_ANONYMOUS_storage = - {6, (void *)"\x2b\x06\01\x05\x06\x03"}; + {6, (void *)(uintptr_t)"\x2b\x06\01\x05\x06\x03"}; gss_OID GSS_C_NT_ANONYMOUS = &GSS_C_NT_ANONYMOUS_storage; /* @@ -140,7 +141,7 @@ gss_OID GSS_C_NT_ANONYMOUS = &GSS_C_NT_ANONYMOUS_storage; * to that gss_OID_desc. */ static gss_OID_desc GSS_C_NT_EXPORT_NAME_storage = - {6, (void *)"\x2b\x06\x01\x05\x06\x04"}; + {6, (void *)(uintptr_t)"\x2b\x06\x01\x05\x06\x04"}; gss_OID GSS_C_NT_EXPORT_NAME = &GSS_C_NT_EXPORT_NAME_storage; /* @@ -150,7 +151,7 @@ gss_OID GSS_C_NT_EXPORT_NAME = &GSS_C_NT_EXPORT_NAME_storage; * is "GSS_KRB5_NT_PRINCIPAL_NAME". */ static gss_OID_desc GSS_KRB5_NT_PRINCIPAL_NAME_storage = - {10, (void *)"\x2a\x86\x48\x86\xf7\x12\x01\x02\x02\x01"}; + {10, (void *)(uintptr_t)"\x2a\x86\x48\x86\xf7\x12\x01\x02\x02\x01"}; gss_OID GSS_KRB5_NT_PRINCIPAL_NAME = &GSS_KRB5_NT_PRINCIPAL_NAME_storage; /* @@ -177,15 +178,18 @@ gss_OID GSS_KRB5_NT_MACHINE_UID_NAME = &GSS_C_NT_MACHINE_UID_NAME_storage; */ gss_OID GSS_KRB5_NT_STRING_UID_NAME = &GSS_C_NT_STRING_UID_NAME_storage; -struct _gss_mechanism_name * -_gss_find_mn(struct _gss_name *name, gss_OID mech) +OM_uint32 +_gss_find_mn(OM_uint32 *minor_status, struct _gss_name *name, gss_OID mech, + struct _gss_mechanism_name **output_mn) { - OM_uint32 major_status, minor_status; + OM_uint32 major_status; struct _gss_mech_switch *m; struct _gss_mechanism_name *mn; + *output_mn = NULL; + SLIST_FOREACH(mn, &name->gn_mn, gmn_link) { - if (_gss_oid_equal(mech, mn->gmn_mech_oid)) + if (gss_oid_equal(mech, mn->gmn_mech_oid)) break; } @@ -195,40 +199,42 @@ _gss_find_mn(struct _gss_name *name, gss_OID mech) * MN but it is from a different mech), give up now. */ if (!name->gn_value.value) - return (0); + return (GSS_S_BAD_NAME); m = _gss_find_mech_switch(mech); if (!m) - return (0); + return (GSS_S_BAD_MECH); mn = malloc(sizeof(struct _gss_mechanism_name)); if (!mn) - return (0); + return (GSS_S_FAILURE); - major_status = m->gm_import_name(&minor_status, + major_status = m->gm_import_name(minor_status, &name->gn_value, (name->gn_type.elements ? &name->gn_type : GSS_C_NO_OID), &mn->gmn_name); - if (major_status) { + if (major_status != GSS_S_COMPLETE) { + _gss_mg_error(m, major_status, *minor_status); free(mn); - return (0); + return (major_status); } mn->gmn_mech = m; mn->gmn_mech_oid = &m->gm_mech_oid; SLIST_INSERT_HEAD(&name->gn_mn, mn, gmn_link); } - return (mn); + *output_mn = mn; + return (GSS_S_COMPLETE); } + /* * Make a name from an MN. */ struct _gss_name * _gss_make_name(struct _gss_mech_switch *m, gss_name_t new_mn) { - OM_uint32 minor_status; struct _gss_name *name; struct _gss_mechanism_name *mn; diff --git a/lib/libgssapi/gss_oid_to_str.c b/lib/libgssapi/gss_oid_to_str.c new file mode 100644 index 0000000..05e0d73 --- /dev/null +++ b/lib/libgssapi/gss_oid_to_str.c @@ -0,0 +1,118 @@ +/*- + * Copyright (c) 2000 The Regents of the University of Michigan. + * All rights reserved. + * + * Copyright (c) 2000 Dug Song <dugsong@UMICH.EDU>. + * All rights reserved, all wrongs reversed. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/* $FreeBSD$ */ + +#include <gssapi/gssapi.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <errno.h> + +#include "utils.h" + +OM_uint32 +gss_oid_to_str(OM_uint32 *minor_status, gss_OID oid, gss_buffer_t oid_str) +{ + char numstr[128]; + unsigned long number; + int numshift; + size_t string_length; + size_t i; + unsigned char *cp; + char *bp; + + *minor_status = 0; + _gss_buffer_zero(oid_str); + + if (oid == GSS_C_NULL_OID) + return (GSS_S_FAILURE); + + /* Decoded according to krb5/gssapi_krb5.c */ + + /* First determine the size of the string */ + string_length = 0; + number = 0; + numshift = 0; + cp = (unsigned char *) oid->elements; + number = (unsigned long) cp[0]; + sprintf(numstr, "%ld ", number/40); + string_length += strlen(numstr); + sprintf(numstr, "%ld ", number%40); + string_length += strlen(numstr); + for (i=1; i<oid->length; i++) { + if ( (size_t) (numshift+7) < (sizeof(unsigned long)*8)) { + number = (number << 7) | (cp[i] & 0x7f); + numshift += 7; + } + else { + *minor_status = 0; + return(GSS_S_FAILURE); + } + if ((cp[i] & 0x80) == 0) { + sprintf(numstr, "%ld ", number); + string_length += strlen(numstr); + number = 0; + numshift = 0; + } + } + /* + * If we get here, we've calculated the length of "n n n ... n ". + * Add 4 here for "{ " and "}\0". + */ + string_length += 4; + if ((bp = (char *) malloc(string_length))) { + strcpy(bp, "{ "); + number = (unsigned long) cp[0]; + sprintf(numstr, "%ld ", number/40); + strcat(bp, numstr); + sprintf(numstr, "%ld ", number%40); + strcat(bp, numstr); + number = 0; + cp = (unsigned char *) oid->elements; + for (i=1; i<oid->length; i++) { + number = (number << 7) | (cp[i] & 0x7f); + if ((cp[i] & 0x80) == 0) { + sprintf(numstr, "%ld ", number); + strcat(bp, numstr); + number = 0; + } + } + strcat(bp, "}"); + oid_str->length = strlen(bp)+1; + oid_str->value = (void *) bp; + *minor_status = 0; + return(GSS_S_COMPLETE); + } + *minor_status = ENOMEM; + return(GSS_S_FAILURE); +} diff --git a/lib/libgssapi/gss_pseudo_random.c b/lib/libgssapi/gss_pseudo_random.c new file mode 100644 index 0000000..7216609 --- /dev/null +++ b/lib/libgssapi/gss_pseudo_random.c @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2007 Kungliga Tekniska H�gskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +/* $FreeBSD$ */ +/* $Id: gss_pseudo_random.c 20053 2007-01-24 01:31:35Z lha $ */ + +#include <gssapi/gssapi.h> + +#include "mech_switch.h" +#include "context.h" +#include "utils.h" + +OM_uint32 +gss_pseudo_random(OM_uint32 *minor_status, + gss_ctx_id_t context, + int prf_key, + const gss_buffer_t prf_in, + ssize_t desired_output_len, + gss_buffer_t prf_out) +{ + struct _gss_context *ctx = (struct _gss_context *) context; + struct _gss_mech_switch *m = ctx->gc_mech; + OM_uint32 major_status; + + _gss_buffer_zero(prf_out); + *minor_status = 0; + + if (ctx == NULL) { + *minor_status = 0; + return GSS_S_NO_CONTEXT; + } + + if (m->gm_pseudo_random == NULL) + return GSS_S_UNAVAILABLE; + + major_status = (*m->gm_pseudo_random)(minor_status, ctx->gc_ctx, + prf_key, prf_in, desired_output_len, + prf_out); + if (major_status != GSS_S_COMPLETE) + _gss_mg_error(m, major_status, *minor_status); + + return major_status; +} diff --git a/lib/libgssapi/gss_release_buffer.c b/lib/libgssapi/gss_release_buffer.c index 8e7fa60..7a85745 100644 --- a/lib/libgssapi/gss_release_buffer.c +++ b/lib/libgssapi/gss_release_buffer.c @@ -27,6 +27,9 @@ */ #include <gssapi/gssapi.h> +#include <stdlib.h> + +#include "utils.h" OM_uint32 gss_release_buffer(OM_uint32 *minor_status, @@ -36,8 +39,7 @@ gss_release_buffer(OM_uint32 *minor_status, *minor_status = 0; if (buffer->value) free(buffer->value); - buffer->length = 0; - buffer->value = 0; + _gss_buffer_zero(buffer); return (GSS_S_COMPLETE); } diff --git a/lib/libgssapi/gss_release_cred.c b/lib/libgssapi/gss_release_cred.c index cec814c..6093acd 100644 --- a/lib/libgssapi/gss_release_cred.c +++ b/lib/libgssapi/gss_release_cred.c @@ -51,6 +51,6 @@ gss_release_cred(OM_uint32 *minor_status, gss_cred_id_t *cred_handle) free(cred); *minor_status = 0; - *cred_handle = 0; + *cred_handle = GSS_C_NO_CREDENTIAL; return (GSS_S_COMPLETE); } diff --git a/lib/libgssapi/gss_release_name.c b/lib/libgssapi/gss_release_name.c index 4294ad7..08ae10a 100644 --- a/lib/libgssapi/gss_release_name.c +++ b/lib/libgssapi/gss_release_name.c @@ -38,7 +38,6 @@ gss_release_name(OM_uint32 *minor_status, gss_name_t *input_name) { struct _gss_name *name = (struct _gss_name *) *input_name; - struct _gss_mech_switch *m; *minor_status = 0; if (name) { @@ -53,7 +52,8 @@ gss_release_name(OM_uint32 *minor_status, free(mn); } gss_release_buffer(minor_status, &name->gn_value); - *input_name = 0; + free(name); + *input_name = GSS_C_NO_NAME; } return (GSS_S_COMPLETE); } diff --git a/lib/libgssapi/gss_release_oid.c b/lib/libgssapi/gss_release_oid.c new file mode 100644 index 0000000..a2e7a61 --- /dev/null +++ b/lib/libgssapi/gss_release_oid.c @@ -0,0 +1,61 @@ +/*- + * Copyright (c) 2006 Kungliga Tekniska H�gskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +/* $FreeBSD$ */ + +#include <gssapi/gssapi.h> +#include <stdlib.h> + +/* RCSID("$Id: gss_release_oid.c 17747 2006-06-30 09:34:54Z lha $"); */ + +OM_uint32 +gss_release_oid(OM_uint32 *minor_status, gss_OID *oid) +{ + gss_OID o = *oid; + + *oid = GSS_C_NO_OID; + + if (minor_status != NULL) + *minor_status = 0; + + if (o == GSS_C_NO_OID) + return (GSS_S_COMPLETE); + + if (o->elements != NULL) { + free(o->elements); + o->elements = NULL; + } + o->length = 0; + free(o); + + return (GSS_S_COMPLETE); +} diff --git a/lib/libgssapi/gss_release_oid_set.c b/lib/libgssapi/gss_release_oid_set.c index 49c17ab..bedb90b 100644 --- a/lib/libgssapi/gss_release_oid_set.c +++ b/lib/libgssapi/gss_release_oid_set.c @@ -36,11 +36,11 @@ gss_release_oid_set(OM_uint32 *minor_status, { *minor_status = 0; - if (*set) { + if (set && *set) { if ((*set)->elements) free((*set)->elements); free(*set); - *set = 0; + *set = GSS_C_NO_OID_SET; } return (GSS_S_COMPLETE); } diff --git a/lib/libgssapi/gss_set_cred_option.c b/lib/libgssapi/gss_set_cred_option.c new file mode 100644 index 0000000..93b2212 --- /dev/null +++ b/lib/libgssapi/gss_set_cred_option.c @@ -0,0 +1,125 @@ +/* + * Copyright (c) 2004, PADL Software Pty Ltd. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of PADL Software nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY PADL SOFTWARE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL PADL SOFTWARE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +/* $FreeBSD$ */ +/* RCSID("$Id: gss_set_cred_option.c 21126 2007-06-18 20:19:59Z lha $"); */ + +#include <gssapi/gssapi.h> +#include <stdlib.h> +#include <errno.h> + +#include "mech_switch.h" +#include "cred.h" + +OM_uint32 +gss_set_cred_option (OM_uint32 *minor_status, + gss_cred_id_t *cred_handle, + const gss_OID object, + const gss_buffer_t value) +{ + struct _gss_cred *cred = (struct _gss_cred *) *cred_handle; + OM_uint32 major_status = GSS_S_COMPLETE; + struct _gss_mechanism_cred *mc; + int one_ok = 0; + + *minor_status = 0; + + _gss_load_mech(); + + if (cred == NULL) { + struct _gss_mech_switch *m; + + cred = malloc(sizeof(*cred)); + if (cred == NULL) + return GSS_S_FAILURE; + + SLIST_INIT(&cred->gc_mc); + + SLIST_FOREACH(m, &_gss_mechs, gm_link) { + + if (m->gm_set_cred_option == NULL) + continue; + + mc = malloc(sizeof(*mc)); + if (mc == NULL) { + *cred_handle = (gss_cred_id_t)cred; + gss_release_cred(minor_status, cred_handle); + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + + mc->gmc_mech = m; + mc->gmc_mech_oid = &m->gm_mech_oid; + mc->gmc_cred = GSS_C_NO_CREDENTIAL; + + major_status = m->gm_set_cred_option( + minor_status, &mc->gmc_cred, object, value); + + if (major_status) { + free(mc); + continue; + } + one_ok = 1; + SLIST_INSERT_HEAD(&cred->gc_mc, mc, gmc_link); + } + *cred_handle = (gss_cred_id_t)cred; + if (!one_ok) { + OM_uint32 junk; + gss_release_cred(&junk, cred_handle); + } + } else { + struct _gss_mech_switch *m; + + SLIST_FOREACH(mc, &cred->gc_mc, gmc_link) { + m = mc->gmc_mech; + + if (m == NULL) + return GSS_S_BAD_MECH; + + if (m->gm_set_cred_option == NULL) + continue; + + major_status = m->gm_set_cred_option(minor_status, + &mc->gmc_cred, object, value); + if (major_status == GSS_S_COMPLETE) + one_ok = 1; + else + _gss_mg_error(m, major_status, *minor_status); + + } + } + if (one_ok) { + *minor_status = 0; + return (GSS_S_COMPLETE); + } + return (major_status); +} + diff --git a/lib/libgssapi/gss_set_sec_context_option.c b/lib/libgssapi/gss_set_sec_context_option.c new file mode 100644 index 0000000..4b6bf1b --- /dev/null +++ b/lib/libgssapi/gss_set_sec_context_option.c @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2004, PADL Software Pty Ltd. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of PADL Software nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY PADL SOFTWARE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL PADL SOFTWARE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +/* $FreeBSD$ */ +/* RCSID("$Id: gss_set_sec_context_option.c 19928 2007-01-16 10:37:54Z lha $"); */ + +#include <gssapi/gssapi.h> + +#include "mech_switch.h" +#include "context.h" + +OM_uint32 +gss_set_sec_context_option (OM_uint32 *minor_status, + gss_ctx_id_t *context_handle, + const gss_OID object, + const gss_buffer_t value) +{ + struct _gss_context *ctx; + OM_uint32 major_status; + struct _gss_mech_switch *m; + int one_ok = 0; + + *minor_status = 0; + + if (context_handle == NULL) { + _gss_load_mech(); + major_status = GSS_S_BAD_MECH; + SLIST_FOREACH(m, &_gss_mechs, gm_link) { + if (!m->gm_set_sec_context_option) + continue; + major_status = m->gm_set_sec_context_option( + minor_status, + NULL, object, value); + if (major_status == GSS_S_COMPLETE) + one_ok = 1; + } + if (one_ok) { + *minor_status = 0; + return (GSS_S_COMPLETE); + } + return (major_status); + } + + ctx = (struct _gss_context *) *context_handle; + + if (ctx == NULL) + return (GSS_S_NO_CONTEXT); + + m = ctx->gc_mech; + + if (m == NULL) + return (GSS_S_BAD_MECH); + + if (m->gm_set_sec_context_option != NULL) { + major_status = m->gm_set_sec_context_option(minor_status, + &ctx->gc_ctx, object, value); + if (major_status != GSS_S_COMPLETE) + _gss_mg_error(m, major_status, *minor_status); + } else + major_status = (GSS_S_BAD_MECH); + + return (major_status); +} + diff --git a/lib/libgssapi/gss_test_oid_set_member.c b/lib/libgssapi/gss_test_oid_set_member.c index 62175ca..0421319 100644 --- a/lib/libgssapi/gss_test_oid_set_member.c +++ b/lib/libgssapi/gss_test_oid_set_member.c @@ -36,11 +36,11 @@ gss_test_oid_set_member(OM_uint32 *minor_status, const gss_OID_set set, int *present) { - int i; + size_t i; *present = 0; for (i = 0; i < set->count; i++) - if (_gss_oid_equal(member, &set->elements[i])) + if (gss_oid_equal(member, &set->elements[i])) *present = 1; *minor_status = 0; diff --git a/lib/libgssapi/gss_unseal.c b/lib/libgssapi/gss_unseal.c index bc7dc26..c377510 100644 --- a/lib/libgssapi/gss_unseal.c +++ b/lib/libgssapi/gss_unseal.c @@ -39,5 +39,5 @@ gss_unseal(OM_uint32 *minor_status, return (gss_unwrap(minor_status, context_handle, input_message_buffer, - output_message_buffer, conf_state, qop_state)); + output_message_buffer, conf_state, (gss_qop_t *)qop_state)); } diff --git a/lib/libgssapi/gss_utils.c b/lib/libgssapi/gss_utils.c index 1f8dfab..ec582a9 100644 --- a/lib/libgssapi/gss_utils.c +++ b/lib/libgssapi/gss_utils.c @@ -34,7 +34,7 @@ #include "utils.h" int -_gss_oid_equal(const gss_OID oid1, const gss_OID oid2) +gss_oid_equal(const gss_OID oid1, const gss_OID oid2) { if (oid1 == oid2) @@ -57,6 +57,7 @@ _gss_copy_oid(OM_uint32 *minor_status, *minor_status = 0; to_oid->elements = malloc(len); if (!to_oid->elements) { + to_oid->length = 0; *minor_status = ENOMEM; return GSS_S_FAILURE; } @@ -76,6 +77,7 @@ _gss_copy_buffer(OM_uint32 *minor_status, to_buf->value = malloc(len); if (!to_buf->value) { *minor_status = ENOMEM; + to_buf->length = 0; return GSS_S_FAILURE; } to_buf->length = len; diff --git a/lib/libgssapi/gss_verify.c b/lib/libgssapi/gss_verify.c index 3110875..0aa3fd6 100644 --- a/lib/libgssapi/gss_verify.c +++ b/lib/libgssapi/gss_verify.c @@ -37,5 +37,6 @@ gss_verify(OM_uint32 *minor_status, { return (gss_verify_mic(minor_status, - context_handle, message_buffer, token_buffer, qop_state)); + context_handle, message_buffer, token_buffer, + (gss_qop_t *)qop_state)); } diff --git a/lib/libgssapi/gss_verify_mic.c b/lib/libgssapi/gss_verify_mic.c index 4e11ab1..fa3d68d 100644 --- a/lib/libgssapi/gss_verify_mic.c +++ b/lib/libgssapi/gss_verify_mic.c @@ -41,6 +41,13 @@ gss_verify_mic(OM_uint32 *minor_status, struct _gss_context *ctx = (struct _gss_context *) context_handle; struct _gss_mech_switch *m = ctx->gc_mech; + if (qop_state) + *qop_state = 0; + if (ctx == NULL) { + *minor_status = 0; + return (GSS_S_NO_CONTEXT); + } + return (m->gm_verify_mic(minor_status, ctx->gc_ctx, message_buffer, token_buffer, qop_state)); } diff --git a/lib/libgssapi/gss_wrap.c b/lib/libgssapi/gss_wrap.c index 0d7c749..2f94316 100644 --- a/lib/libgssapi/gss_wrap.c +++ b/lib/libgssapi/gss_wrap.c @@ -30,6 +30,7 @@ #include "mech_switch.h" #include "context.h" +#include "utils.h" OM_uint32 gss_wrap(OM_uint32 *minor_status, @@ -43,6 +44,14 @@ gss_wrap(OM_uint32 *minor_status, struct _gss_context *ctx = (struct _gss_context *) context_handle; struct _gss_mech_switch *m = ctx->gc_mech; + if (conf_state) + *conf_state = 0; + _gss_buffer_zero(output_message_buffer); + if (ctx == NULL) { + *minor_status = 0; + return (GSS_S_NO_CONTEXT); + } + return (m->gm_wrap(minor_status, ctx->gc_ctx, conf_req_flag, qop_req, input_message_buffer, conf_state, output_message_buffer)); diff --git a/lib/libgssapi/gss_wrap_size_limit.c b/lib/libgssapi/gss_wrap_size_limit.c index 8abd52a..15a8706 100644 --- a/lib/libgssapi/gss_wrap_size_limit.c +++ b/lib/libgssapi/gss_wrap_size_limit.c @@ -42,6 +42,12 @@ gss_wrap_size_limit(OM_uint32 *minor_status, struct _gss_context *ctx = (struct _gss_context *) context_handle; struct _gss_mech_switch *m = ctx->gc_mech; + *max_input_size = 0; + if (ctx == NULL) { + *minor_status = 0; + return (GSS_S_NO_CONTEXT); + } + return (m->gm_wrap_size_limit(minor_status, ctx->gc_ctx, conf_req_flag, qop_req, req_output_size, max_input_size)); } diff --git a/lib/libgssapi/mech.5 b/lib/libgssapi/mech.5 index 1edcc1a..fd17e3a 100644 --- a/lib/libgssapi/mech.5 +++ b/lib/libgssapi/mech.5 @@ -50,11 +50,18 @@ A shared library containing the implementation of this mechanism. A kernel module containing the implementation of this mechanism (not yet supported in FreeBSD). .It Library options (optional) -Optionsal parameters interpreted by the mechanism. Library options +Optional parameters interpreted by the mechanism. Library options must be enclosed in brackets ([ ]) to differentiate them from the optional kernel module entry. .El .Pp +The first mechanism listed in +.Pa "/etc/gss/mech" +is the default mechanism. +This mechanism will be used by +.Xr gss_init_sec_context 3 +if the user doesn't specify a specific mechanism. +.Pp The .Pa "/etc/gss/qop" file contains a list of Quality of Protection values for use with diff --git a/lib/libgssapi/mech_switch.h b/lib/libgssapi/mech_switch.h index 4add12d..876adcd 100644 --- a/lib/libgssapi/mech_switch.h +++ b/lib/libgssapi/mech_switch.h @@ -26,6 +26,7 @@ * $FreeBSD$ */ +#include <unistd.h> #include <sys/queue.h> typedef OM_uint32 _gss_acquire_cred_t @@ -266,24 +267,46 @@ typedef OM_uint32 _gss_duplicate_name_t ( gss_name_t * /* dest_name */ ); -typedef OM_uint32 _gsskrb5_register_acceptor_identity ( - const char * /* identity */ +typedef OM_uint32 _gss_inquire_sec_context_by_oid + (OM_uint32 *, /* minor_status */ + const gss_ctx_id_t, /* context_handle */ + const gss_OID, /* desired_object */ + gss_buffer_set_t * /* result */ ); -typedef OM_uint32 _gss_krb5_copy_ccache ( - OM_uint32 *, /* minor_status */ - gss_cred_id_t, /* cred_handle */ - struct krb5_ccache_data * /* out */ +typedef OM_uint32 _gss_inquire_cred_by_oid + (OM_uint32 *, /* bminor_status */ + const gss_cred_id_t, /* cred_handle, */ + const gss_OID, /* desired_object */ + gss_buffer_set_t * /* data_set */ ); -typedef OM_uint32 _gss_krb5_compat_des3_mic ( - OM_uint32 *, /* minor_status */ - gss_ctx_id_t, /* context_handle */ - int /* flag */ +typedef OM_uint32 _gss_set_sec_context_option + (OM_uint32 *, /* minor status */ + gss_ctx_id_t *, /* context */ + const gss_OID, /* option to set */ + const gss_buffer_t /* option value */ + ); + +typedef OM_uint32 _gss_set_cred_option + (OM_uint32 *, /* minor status */ + gss_cred_id_t *, /* cred */ + const gss_OID, /* option to set */ + const gss_buffer_t /* option value */ + ); + +typedef OM_uint32 _gss_pseudo_random + (OM_uint32 *, /* minor status */ + gss_ctx_id_t, /* context */ + int, /* PRF key */ + const gss_buffer_t, /* PRF input */ + ssize_t, /* desired output length */ + gss_buffer_t /* PRF output */ ); struct _gss_mech_switch { SLIST_ENTRY(_gss_mech_switch) gm_link; + const char *gm_name_prefix; gss_OID_desc gm_mech_oid; void *gm_so; _gss_acquire_cred_t *gm_acquire_cred; @@ -315,9 +338,11 @@ struct _gss_mech_switch { _gss_inquire_mechs_for_name_t *gm_inquire_mechs_for_name; _gss_canonicalize_name_t *gm_canonicalize_name; _gss_duplicate_name_t *gm_duplicate_name; - _gsskrb5_register_acceptor_identity *gm_krb5_register_acceptor_identity; - _gss_krb5_copy_ccache *gm_krb5_copy_ccache; - _gss_krb5_compat_des3_mic *gm_krb5_compat_des3_mic; + _gss_inquire_sec_context_by_oid *gm_inquire_sec_context_by_oid; + _gss_inquire_cred_by_oid *gm_inquire_cred_by_oid; + _gss_set_sec_context_option *gm_set_sec_context_option; + _gss_set_cred_option *gm_set_cred_option; + _gss_pseudo_random *gm_pseudo_random; }; SLIST_HEAD(_gss_mech_switch_list, _gss_mech_switch); extern struct _gss_mech_switch_list _gss_mechs; @@ -325,3 +350,5 @@ extern gss_OID_set _gss_mech_oids; extern void _gss_load_mech(void); extern struct _gss_mech_switch *_gss_find_mech_switch(gss_OID); +extern void _gss_mg_error(struct _gss_mech_switch *m, OM_uint32 maj, + OM_uint32 min); diff --git a/lib/libgssapi/name.h b/lib/libgssapi/name.h index a64d5d9..7f54359 100644 --- a/lib/libgssapi/name.h +++ b/lib/libgssapi/name.h @@ -42,7 +42,8 @@ struct _gss_name { struct _gss_mechanism_name_list gn_mn; /* list of MNs */ }; -extern struct _gss_mechanism_name * - _gss_find_mn(struct _gss_name *name, gss_OID mech); -struct _gss_name * +extern OM_uint32 + _gss_find_mn(OM_uint32 *, struct _gss_name *, gss_OID, + struct _gss_mechanism_name **); +extern struct _gss_name * _gss_make_name(struct _gss_mech_switch *m, gss_name_t new_mn); diff --git a/lib/libgssapi/utils.h b/lib/libgssapi/utils.h index 46edb9d..a54cb50 100644 --- a/lib/libgssapi/utils.h +++ b/lib/libgssapi/utils.h @@ -26,6 +26,8 @@ * $FreeBSD$ */ +#define _gss_buffer_zero(buffer) \ + do { (buffer)->value = NULL; (buffer)->length = 0; } while(0) extern int _gss_oid_equal(const gss_OID, const gss_OID); extern OM_uint32 _gss_copy_oid(OM_uint32 *, const gss_OID, gss_OID); extern OM_uint32 _gss_copy_buffer(OM_uint32 *minor_status, |