/* Unprivileged */ void ssh_gssapi_supported_oids(gss_OID_set *oidset) { int i = 0; OM_uint32 min_status; int present; gss_OID_set supported; gss_create_empty_oid_set(&min_status, oidset); if (GSS_ERROR(gss_indicate_mechs(&min_status, &supported))) return; while (supported_mechs[i]->name != NULL) { if (GSS_ERROR(gss_test_oid_set_member(&min_status, &supported_mechs[i]->oid, supported, &present))) present = 0; if (present) gss_add_oid_set_member(&min_status, &supported_mechs[i]->oid, oidset); i++; } gss_release_oid_set(&min_status, &supported); }
OM_uint32 ssh_gssapi_test_oid_supported(OM_uint32 *ms, gss_OID member, int *present) { if (supported_oids == NULL) ssh_gssapi_prepare_supported_oids(); return gss_test_oid_set_member(ms, member, supported_oids, present); }
OM_uint32 gss_add_oid_set_member (OM_uint32 * minor_status, const gss_OID member_oid, gss_OID_set * oid_set) { gss_OID tmp; size_t n; OM_uint32 res; int present; res = gss_test_oid_set_member(minor_status, member_oid, *oid_set, &present); if (res != GSS_S_COMPLETE) return res; if (present) { *minor_status = 0; return GSS_S_COMPLETE; } n = (*oid_set)->count + 1; tmp = realloc ((*oid_set)->elements, n * sizeof(gss_OID_desc)); if (tmp == NULL) { *minor_status = ENOMEM; return GSS_S_FAILURE; } (*oid_set)->elements = tmp; (*oid_set)->count = n; (*oid_set)->elements[n-1] = *member_oid; *minor_status = 0; return GSS_S_COMPLETE; }
/** * Initialize a previously allocated error of type * GLOBUS_ERROR_TYPE_GSSAPI * @ingroup globus_gssapi_error_object * * @param error * The previously allocated error object. * @param base_source * Pointer to the originating module. * @param base_cause * The error object causing the error. If this is the original * error this paramater may be NULL. * @param major_status * The GSSAPI major status * @param minor_status * The GSSAPI minor status * @return * The resulting error object. You may have to call * globus_error_put() on this object before passing it on. */ globus_object_t * globus_error_initialize_gssapi_error( globus_object_t * error, globus_module_descriptor_t * base_source, globus_object_t * base_cause, const OM_uint32 major_status, const OM_uint32 minor_status) { globus_l_gssapi_error_data_t * instance_data; globus_object_t * minor_obj; gss_OID_set actual_mechs; OM_uint32 local_minor_status; extern gss_OID gss_mech_globus_gssapi_openssl; instance_data = (globus_l_gssapi_error_data_t *) malloc(sizeof(globus_l_gssapi_error_data_t)); instance_data->major_status = major_status; instance_data->minor_status = minor_status; instance_data->is_globus_gsi = GLOBUS_FALSE; if(gss_indicate_mechs( &local_minor_status, &actual_mechs) == GSS_S_COMPLETE) { int boolean; if(gss_test_oid_set_member( &local_minor_status, gss_mech_globus_gssapi_openssl, actual_mechs, &boolean) == GSS_S_COMPLETE && boolean) { instance_data->is_globus_gsi = GLOBUS_TRUE; } gss_release_oid_set(&local_minor_status, &actual_mechs); } if(instance_data->is_globus_gsi) { minor_obj = globus_error_get((globus_result_t) minor_status); if(!base_cause) { base_cause = minor_obj; } else if(minor_obj) { base_cause = globus_error_initialize_base( minor_obj, globus_error_get_source(base_cause), base_cause); } } globus_object_set_local_instance_data(error, instance_data); return globus_error_initialize_base(error, base_source, base_cause); }/* globus_error_initialize_gssapi_error() */
/* * Return TRUE if cred available for mechanism. Caller need no acquire * lock because mechanisms list is immutable. */ int gssEapCredAvailable(gss_cred_id_t cred, gss_OID mech) { OM_uint32 minor; int present = 0; GSSEAP_ASSERT(mech != GSS_C_NO_OID); if (cred == GSS_C_NO_CREDENTIAL || cred->mechanisms == GSS_C_NO_OID_SET) return 1; gss_test_oid_set_member(&minor, mech, cred->mechanisms, &present); return present; }
OM_uint32 GSSAPI_CALLCONV _gsskrb5_acquire_cred (OM_uint32 * minor_status, gss_const_name_t desired_name, OM_uint32 time_req, const gss_OID_set desired_mechs, gss_cred_usage_t cred_usage, gss_cred_id_t * output_cred_handle, gss_OID_set * actual_mechs, OM_uint32 * time_rec ) { OM_uint32 ret; if (desired_mechs) { int present = 0; ret = gss_test_oid_set_member(minor_status, GSS_KRB5_MECHANISM, desired_mechs, &present); if (ret) return ret; if (!present) { *minor_status = 0; return GSS_S_BAD_MECH; } } ret = _gsskrb5_acquire_cred_ext(minor_status, desired_name, GSS_C_NO_OID, NULL, time_req, GSS_KRB5_MECHANISM, cred_usage, output_cred_handle); if (ret) return ret; ret = _gsskrb5_inquire_cred(minor_status, *output_cred_handle, NULL, time_rec, NULL, actual_mechs); if (ret) { OM_uint32 tmp; _gsskrb5_release_cred(&tmp, output_cred_handle); } return ret; }
static OM_uint32 acceptor_approved(void *userptr, gss_name_t target_name, const gss_cred_id_t cred_handle, gss_OID mech) { OM_uint32 junk, ret; gss_OID_set oidset; if (cred_handle) { int present = 0; ret = gss_inquire_cred(&junk, cred_handle, NULL, NULL, NULL, &oidset); if (ret != GSS_S_COMPLETE) return ret; ret = gss_test_oid_set_member(&junk, mech, oidset, &present); gss_release_oid_set(&junk, &oidset); if (ret != GSS_S_COMPLETE || present == 0) return GSS_S_FAILURE; } else { gss_cred_id_t cred = GSS_C_NO_CREDENTIAL; if (target_name == GSS_C_NO_NAME) return GSS_S_COMPLETE; gss_create_empty_oid_set(&junk, &oidset); gss_add_oid_set_member(&junk, mech, &oidset); ret = gss_acquire_cred(&junk, target_name, GSS_C_INDEFINITE, oidset, GSS_C_ACCEPT, &cred, NULL, NULL); gss_release_oid_set(&junk, &oidset); if (ret != GSS_S_COMPLETE) return ret; gss_release_cred(&junk, &cred); } return GSS_S_COMPLETE; }
gss_OID_set mag_filter_unwanted_mechs(gss_OID_set src) { gss_const_OID unwanted_mechs[] = { &gss_mech_spnego, gss_mech_krb5_old, gss_mech_krb5_wrong, gss_mech_iakerb, GSS_C_NO_OID }; gss_OID_set dst; uint32_t maj, min; int present = 0; if (src == GSS_C_NO_OID_SET) return GSS_C_NO_OID_SET; for (int i = 0; unwanted_mechs[i] != GSS_C_NO_OID; i++) { maj = gss_test_oid_set_member(&min, discard_const(unwanted_mechs[i]), src, &present); if (present) break; } if (present) { maj = gss_create_empty_oid_set(&min, &dst); if (maj != GSS_S_COMPLETE) { return GSS_C_NO_OID_SET; } for (int i = 0; i < src->count; i++) { present = 0; for (int j = 0; unwanted_mechs[j] != GSS_C_NO_OID; j++) { if (gss_oid_equal(&src->elements[i], unwanted_mechs[j])) { present = 1; break; } } if (present) continue; maj = gss_add_oid_set_member(&min, &src->elements[i], &dst); if (maj != GSS_S_COMPLETE) { gss_release_oid_set(&min, &dst); return GSS_C_NO_OID_SET; } } return dst; } return src; }
OM_uint32 gss_add_oid_set_member(OM_uint32 *minor_status, const gss_OID member_oid, gss_OID_set *oid_set) { OM_uint32 major_status; gss_OID_set set = *oid_set; gss_OID new_elements; gss_OID new_oid; int t; *minor_status = 0; major_status = gss_test_oid_set_member(minor_status, member_oid, *oid_set, &t); if (major_status) return (major_status); if (t) return (GSS_S_COMPLETE); new_elements = malloc((set->count + 1) * sizeof(gss_OID_desc)); if (!new_elements) { *minor_status = ENOMEM; return (GSS_S_FAILURE); } new_oid = &new_elements[set->count]; new_oid->elements = malloc(member_oid->length); if (!new_oid->elements) { free(new_elements); return (GSS_S_FAILURE); } new_oid->length = member_oid->length; memcpy(new_oid->elements, member_oid->elements, member_oid->length); if (set->elements) { memcpy(new_elements, set->elements, set->count * sizeof(gss_OID_desc)); free(set->elements); } set->elements = new_elements; set->count++; return (GSS_S_COMPLETE); }
static RD_BOOL cssp_gss_mech_available(gss_OID mech) { int mech_found; OM_uint32 major_status, minor_status; gss_OID_set mech_set; mech_found = 0; if (mech == GSS_C_NO_OID) return True; major_status = gss_indicate_mechs(&minor_status, &mech_set); if (!mech_set) return False; if (GSS_ERROR(major_status)) { cssp_gss_report_error(GSS_C_GSS_CODE, "Failed to get available mechs on system", major_status, minor_status); return False; } gss_test_oid_set_member(&minor_status, mech, mech_set, &mech_found); if (GSS_ERROR(major_status)) { cssp_gss_report_error(GSS_C_GSS_CODE, "Failed to match mechanism in set", major_status, minor_status); return False; } if (!mech_found) return False; return True; }
/* * We only support those mechanisms that we know about (ie ones that we know * how to check local user kuserok and the like) */ static int userauth_gssapi(struct ssh *ssh) { Authctxt *authctxt = ssh->authctxt; gss_OID_desc goid = {0, NULL}; Gssctxt *ctxt = NULL; int r, mechs, present; gss_OID_set supported; OM_uint32 ms; size_t len; u_char *doid = NULL; if (!authctxt->valid || authctxt->user == NULL) return (0); if ((r = sshpkt_get_u32(ssh, &mechs)) != 0) fatal("%s: %s", __func__, ssh_err(r)); if (mechs == 0) { debug("Mechanism negotiation is not supported"); return (0); } ssh_gssapi_supported_oids(&supported); do { mechs--; if (doid) xfree(doid); present = 0; if ((r = sshpkt_get_string(ssh, &doid, &len)) != 0) fatal("%s: %s", __func__, ssh_err(r)); if (len > 2 && doid[0] == SSH_GSS_OIDTYPE && doid[1] == len - 2) { goid.elements = doid + 2; goid.length = len - 2; gss_test_oid_set_member(&ms, &goid, supported, &present); } else { logit("Badly formed OID received"); } } while (mechs > 0 && !present); gss_release_oid_set(&ms, &supported); if (!present) { xfree(doid); authctxt->server_caused_failure = 1; return (0); } if (GSS_ERROR(PRIVSEP(ssh_gssapi_server_ctx(&ctxt, &goid)))) { if (ctxt != NULL) ssh_gssapi_delete_ctx(&ctxt); xfree(doid); authctxt->server_caused_failure = 1; return (0); } authctxt->methoddata = (void *)ctxt; /* Return the OID that we received */ if ((r = sshpkt_start(ssh, SSH2_MSG_USERAUTH_GSSAPI_RESPONSE)) != 0 || (r = sshpkt_put_string(ssh, doid, len)) != 0 || (r = sshpkt_send(ssh)) != 0) fatal("%s: %s", __func__, ssh_err(r)); xfree(doid); ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_GSSAPI_TOKEN, &input_gssapi_token); ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_GSSAPI_ERRTOK, &input_gssapi_errtok); authctxt->postponed = 1; return (0); }
OM_uint32 gss_acquire_cred(OM_uint32 *minor_status, const gss_name_t desired_name, OM_uint32 time_req, const gss_OID_set desired_mechs, gss_cred_usage_t cred_usage, gss_cred_id_t *output_cred_handle, gss_OID_set *actual_mechs, OM_uint32 *time_rec) { OM_uint32 major_status; gss_OID_set mechs = desired_mechs; gss_OID_set_desc set; struct _gss_name *name = (struct _gss_name *) desired_name; gssapi_mech_interface m; struct _gss_cred *cred; struct _gss_mechanism_cred *mc; OM_uint32 min_time, cred_time; int i; _gss_load_mech(); /* * First make sure that at least one of the requested * mechanisms is one that we support. */ if (mechs) { for (i = 0; i < mechs->count; i++) { int t; gss_test_oid_set_member(minor_status, &mechs->elements[i], _gss_mech_oids, &t); if (t) break; } if (i == mechs->count) { *output_cred_handle = 0; *minor_status = 0; return (GSS_S_BAD_MECH); } } if (actual_mechs) { major_status = gss_create_empty_oid_set(minor_status, actual_mechs); if (major_status) return (major_status); } cred = malloc(sizeof(struct _gss_cred)); if (!cred) { if (actual_mechs) gss_release_oid_set(minor_status, actual_mechs); *minor_status = ENOMEM; return (GSS_S_FAILURE); } cred->gc_usage = cred_usage; SLIST_INIT(&cred->gc_mc); if (mechs == GSS_C_NO_OID_SET) mechs = _gss_mech_oids; set.count = 1; min_time = GSS_C_INDEFINITE; for (i = 0; i < mechs->count; i++) { struct _gss_mechanism_name *mn = NULL; m = __gss_get_mechanism(&mechs->elements[i]); if (!m) continue; if (desired_name != GSS_C_NO_NAME) { mn = _gss_find_mn(name, &mechs->elements[i]); if (!mn) continue; } mc = malloc(sizeof(struct _gss_mechanism_cred)); if (!mc) { continue; } SLIST_INIT(&cred->gc_mc); mc->gmc_mech = m; mc->gmc_mech_oid = &m->gm_mech_oid; /* * XXX Probably need to do something with actual_mechs. */ set.elements = &mechs->elements[i]; major_status = m->gm_acquire_cred(minor_status, (desired_name != GSS_C_NO_NAME ? mn->gmn_name : GSS_C_NO_NAME), time_req, &set, cred_usage, &mc->gmc_cred, NULL, &cred_time); if (major_status) { free(mc); continue; } if (cred_time < min_time) min_time = cred_time; if (actual_mechs) { major_status = gss_add_oid_set_member(minor_status, mc->gmc_mech_oid, actual_mechs); if (major_status) { m->gm_release_cred(minor_status, &mc->gmc_cred); free(mc); continue; } } SLIST_INSERT_HEAD(&cred->gc_mc, mc, gmc_link); } /* * If we didn't manage to create a single credential, return * an error. */ if (!SLIST_FIRST(&cred->gc_mc)) { 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); } if (time_rec) *time_rec = min_time; *output_cred_handle = (gss_cred_id_t) cred; *minor_status = 0; return (GSS_S_COMPLETE); }
OM_uint32 GSSAPI_LIB_FUNCTION gss_acquire_cred_ex_f(gss_status_id_t status, gss_name_t desired_name, OM_uint32 flags, OM_uint32 time_req, gss_const_OID desired_mech, gss_cred_usage_t cred_usage, gss_auth_identity_t identity, void * userctx, void (*usercomplete)(void *, OM_uint32, gss_status_id_t, gss_cred_id_t, gss_OID_set, OM_uint32)) { OM_uint32 major_status, minor_status; gss_name_t name = GSS_C_NO_NAME; gss_cred_id_t cred; OM_uint32 junk; gss_buffer_desc buffer; if (usercomplete == NULL) return GSS_S_CALL_INACCESSIBLE_READ; /* * If no desired_name, make one up from the identity */ if (desired_name == GSS_C_NO_NAME) { char *str; if (identity->username == NULL) return GSS_S_FAILURE; if (identity->realm) asprintf(&str, "%s@%s", identity->username, identity->realm); else str = strdup(identity->username); buffer.value = str; buffer.length = strlen(str); major_status = gss_import_name(&minor_status, &buffer, GSS_C_NT_USER_NAME, &name); free(str); if (major_status) return major_status; desired_name = name; } /* * First make sure that at least one of the requested * mechanisms is one that we support. */ if (desired_mech) { int t; gss_test_oid_set_member(&junk, desired_mech, _gss_mech_oids, &t); if (!t) { if (name) gss_release_name(&junk, &name); return (GSS_S_BAD_MECH); } } buffer.value = identity->password; buffer.length = strlen(identity->password); cred = GSS_C_NO_CREDENTIAL; major_status = gss_acquire_cred_ext(&minor_status, desired_name, GSS_C_CRED_PASSWORD, &buffer, time_req, desired_mech, cred_usage, &cred); if (name) gss_release_name(&junk, &name); if (major_status) return major_status; usercomplete(userctx, major_status, status, cred, GSS_C_NO_OID_SET, GSS_C_INDEFINITE); return GSS_S_COMPLETE; }
OM_uint32 GSSAPI_CALLCONV _gss_spnego_indicate_mechtypelist (OM_uint32 *minor_status, gss_name_t target_name, OM_uint32 (*func)(void *, gss_name_t, const gss_cred_id_t, gss_OID), void *userctx, int includeMSCompatOID, const gss_cred_id_t cred_handle, MechTypeList *mechtypelist, gss_OID *preferred_mech) { gss_OID_set supported_mechs = GSS_C_NO_OID_SET; gss_OID first_mech = GSS_C_NO_OID; OM_uint32 ret, junk; int present = 0; size_t i; mechtypelist->len = 0; mechtypelist->val = NULL; if (cred_handle) { ret = gss_inquire_cred(minor_status, cred_handle, NULL, NULL, NULL, &supported_mechs); } else { ret = gss_indicate_mechs(minor_status, &supported_mechs); } if (ret != GSS_S_COMPLETE) { return ret; } if (supported_mechs->count == 0) { *minor_status = ENOENT; gss_release_oid_set(minor_status, &supported_mechs); return GSS_S_FAILURE; } /* * Propose Kerberos mech first if we have Kerberos credentials/supported mechs */ ret = gss_test_oid_set_member(&junk, GSS_KRB5_MECHANISM, supported_mechs, &present); if (ret == GSS_S_COMPLETE && present) { ret = (*func)(userctx, target_name, cred_handle, GSS_KRB5_MECHANISM); if (ret == GSS_S_COMPLETE) { ret = add_mech_type(GSS_KRB5_MECHANISM, includeMSCompatOID, mechtypelist); if (!GSS_ERROR(ret)) { if (includeMSCompatOID) first_mech = &_gss_spnego_mskrb_mechanism_oid_desc; else first_mech = GSS_KRB5_MECHANISM; } #ifdef __APPLE_PRIVATE__ (void)add_mech_type(GSS_APPL_LKDC_SUPPORTED, 0, mechtypelist); #endif } } ret = GSS_S_COMPLETE; /* * Now lets, check all other mechs */ for (i = 0; i < supported_mechs->count; i++) { OM_uint32 subret; if (gss_oid_equal(&supported_mechs->elements[i], GSS_SPNEGO_MECHANISM)) continue; if (gss_oid_equal(&supported_mechs->elements[i], GSS_KRB5_MECHANISM)) continue; if (gss_oid_equal(&supported_mechs->elements[i], GSS_NETLOGON_MECHANISM)) continue; subret = (*func)(userctx, target_name, cred_handle, &supported_mechs->elements[i]); if (subret != GSS_S_COMPLETE) continue; ret = add_mech_type(&supported_mechs->elements[i], includeMSCompatOID, mechtypelist); if (ret != 0) { *minor_status = ret; ret = GSS_S_FAILURE; break; } if (first_mech == GSS_C_NO_OID) first_mech = &supported_mechs->elements[i]; } if (mechtypelist->len == 0) { gss_release_oid_set(minor_status, &supported_mechs); *minor_status = 0; return GSS_S_BAD_MECH; } if (preferred_mech != NULL) { ret = gss_duplicate_oid(minor_status, first_mech, preferred_mech); if (ret != GSS_S_COMPLETE) free_MechTypeList(mechtypelist); } gss_release_oid_set(minor_status, &supported_mechs); return ret; }
static bool mag_auth_basic(request_rec *req, struct mag_config *cfg, gss_buffer_desc ba_user, gss_buffer_desc ba_pwd, gss_name_t *client, gss_OID *mech_type, gss_cred_id_t *delegated_cred, uint32_t *vtime) { #ifdef HAVE_GSS_KRB5_CCACHE_NAME const char *user_ccache = NULL; const char *orig_ccache = NULL; long long unsigned int rndname; apr_status_t rs; #endif gss_name_t user = GSS_C_NO_NAME; gss_cred_id_t user_cred = GSS_C_NO_CREDENTIAL; gss_ctx_id_t user_ctx = GSS_C_NO_CONTEXT; gss_name_t server = GSS_C_NO_NAME; gss_cred_id_t server_cred = GSS_C_NO_CREDENTIAL; gss_ctx_id_t server_ctx = GSS_C_NO_CONTEXT; gss_buffer_desc input = GSS_C_EMPTY_BUFFER; gss_buffer_desc output = GSS_C_EMPTY_BUFFER; gss_OID_set allowed_mechs; gss_OID_set filtered_mechs; gss_OID_set actual_mechs = GSS_C_NO_OID_SET; uint32_t init_flags = 0; uint32_t maj, min; int present = 0; bool ret = false; maj = gss_import_name(&min, &ba_user, GSS_C_NT_USER_NAME, &user); if (GSS_ERROR(maj)) { ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, req, "In Basic Auth, %s", mag_error(req, "gss_import_name() failed", maj, min)); goto done; } if (cfg->basic_mechs) { allowed_mechs = cfg->basic_mechs; } else if (cfg->allowed_mechs) { allowed_mechs = cfg->allowed_mechs; } else { struct mag_server_config *scfg; /* Try to fetch the default set if not explicitly configured, * We need to do this because gss_acquire_cred_with_password() * is currently limited to acquire creds for a single "default" * mechanism if no desired mechanisms are passed in. This causes * authentication to fail for secondary mechanisms as no user * credentials are generated for those. */ scfg = ap_get_module_config(req->server->module_config, &auth_gssapi_module); /* In the worst case scenario default_mechs equals to GSS_C_NO_OID_SET. * This generally causes only the krb5 mechanism to be tried due * to implementation constraints, but may change in future. */ allowed_mechs = scfg->default_mechs; } /* Remove Spnego if present, or we'd repeat failed authentiations * multiple times, one within Spnego and then again with an explicit * mechanism. We would normally just force Spnego and use * gss_set_neg_mechs, but due to the way we source the server name * and the fact MIT up to 1.14 at least does no handle union names, * we can't provide spnego with a server name that can be used by * multiple mechanisms, causing any but the first mechanism to fail. * Also remove unwanted krb mechs, or AS requests will be repeated * multiple times uselessly. */ filtered_mechs = mag_filter_unwanted_mechs(allowed_mechs); if (filtered_mechs == allowed_mechs) { /* in case filtered_mechs was not allocated here don't free it */ filtered_mechs = GSS_C_NO_OID_SET; } else if (filtered_mechs == GSS_C_NO_OID_SET) { ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, req, "Fatal " "failure while filtering mechs, aborting"); goto done; } else { /* use the filtered list */ allowed_mechs = filtered_mechs; } #ifdef HAVE_GSS_KRB5_CCACHE_NAME /* If we are using the krb5 mechanism make sure to set a per thread * memory ccache so that there can't be interferences between threads. * Also make sure we have new cache so no cached results end up being * used. Some implementations of gss_acquire_cred_with_password() do * not reacquire creds if cached ones are around, failing to check * again for the password. */ maj = gss_test_oid_set_member(&min, discard_const(gss_mech_krb5), allowed_mechs, &present); if (GSS_ERROR(maj)) { ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, req, "In Basic Auth, %s", mag_error(req, "gss_test_oid_set_member() failed", maj, min)); goto done; } if (present) { rs = apr_generate_random_bytes((unsigned char *)(&rndname), sizeof(long long unsigned int)); if (rs != APR_SUCCESS) { ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, req, "Failed to generate random ccache name"); goto done; } user_ccache = apr_psprintf(req->pool, "MEMORY:user_%qu", rndname); maj = gss_krb5_ccache_name(&min, user_ccache, &orig_ccache); if (GSS_ERROR(maj)) { ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, req, "In Basic Auth, %s", mag_error(req, "gss_krb5_ccache_name() " "failed", maj, min)); goto done; } } #endif maj = gss_acquire_cred_with_password(&min, user, &ba_pwd, GSS_C_INDEFINITE, allowed_mechs, GSS_C_INITIATE, &user_cred, &actual_mechs, NULL); if (GSS_ERROR(maj)) { ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, req, "In Basic Auth, %s", mag_error(req, "gss_acquire_cred_with_password() " "failed", maj, min)); goto done; } /* must acquire creds based on the actual mechs we want to try */ if (!mag_acquire_creds(req, cfg, actual_mechs, GSS_C_ACCEPT, &server_cred, NULL)) { goto done; } #ifdef HAVE_CRED_STORE if (cfg->deleg_ccache_dir) { /* delegate ourselves credentials so we store them as requested */ init_flags |= GSS_C_DELEG_FLAG; } #endif for (int i = 0; i < actual_mechs->count; i++) { /* free these if looping */ gss_release_buffer(&min, &output); gss_release_buffer(&min, &input); gss_release_name(&min, &server); maj = gss_inquire_cred_by_mech(&min, server_cred, &actual_mechs->elements[i], &server, NULL, NULL, NULL); if (GSS_ERROR(maj)) { ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, req, "%s", mag_error(req, "gss_inquired_cred_by_mech() " "failed", maj, min)); continue; } do { /* output and input are inverted here, this is intentional */ maj = gss_init_sec_context(&min, user_cred, &user_ctx, server, &actual_mechs->elements[i], init_flags, 300, GSS_C_NO_CHANNEL_BINDINGS, &output, NULL, &input, NULL, NULL); if (GSS_ERROR(maj)) { ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, req, "%s", mag_error(req, "gss_init_sec_context() " "failed", maj, min)); break; } gss_release_buffer(&min, &output); maj = gss_accept_sec_context(&min, &server_ctx, server_cred, &input, GSS_C_NO_CHANNEL_BINDINGS, client, mech_type, &output, NULL, vtime, delegated_cred); if (GSS_ERROR(maj)) { ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, req, "%s", mag_error(req, "gss_accept_sec_context()" " failed", maj, min)); break; } gss_release_buffer(&min, &input); } while (maj == GSS_S_CONTINUE_NEEDED); if (maj == GSS_S_COMPLETE) { ret = true; break; } } done: gss_release_buffer(&min, &output); gss_release_buffer(&min, &input); gss_release_name(&min, &server); gss_delete_sec_context(&min, &server_ctx, GSS_C_NO_BUFFER); gss_release_cred(&min, &server_cred); gss_release_name(&min, &user); gss_release_cred(&min, &user_cred); gss_delete_sec_context(&min, &user_ctx, GSS_C_NO_BUFFER); gss_release_oid_set(&min, &actual_mechs); gss_release_oid_set(&min, &filtered_mechs); #ifdef HAVE_GSS_KRB5_CCACHE_NAME if (user_ccache != NULL) { maj = gss_krb5_ccache_name(&min, orig_ccache, NULL); if (maj != GSS_S_COMPLETE) { ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, req, "Failed to restore per-thread ccache, %s", mag_error(req, "gss_krb5_ccache_name() " "failed", maj, min)); } } #endif return ret; }
OM_uint32 gss_acquire_cred (OM_uint32 * minor_status, const gss_name_t desired_name, OM_uint32 time_req, const gss_OID_set desired_mechs, gss_cred_usage_t cred_usage, gss_cred_id_t * output_cred_handle, gss_OID_set * actual_mechs, OM_uint32 * time_rec ) { gss_cred_id_t handle; OM_uint32 ret; if (cred_usage != GSS_C_ACCEPT && cred_usage != GSS_C_INITIATE && cred_usage != GSS_C_BOTH) { *minor_status = GSS_KRB5_S_G_BAD_USAGE; return GSS_S_FAILURE; } GSSAPI_KRB5_INIT (); *output_cred_handle = NULL; if (time_rec) *time_rec = 0; if (actual_mechs) *actual_mechs = GSS_C_NO_OID_SET; if (desired_mechs) { int present = 0; ret = gss_test_oid_set_member(minor_status, GSS_KRB5_MECHANISM, desired_mechs, &present); if (ret) return ret; if (!present) { *minor_status = 0; return GSS_S_BAD_MECH; } } handle = (gss_cred_id_t)malloc(sizeof(*handle)); if (handle == GSS_C_NO_CREDENTIAL) { *minor_status = ENOMEM; return (GSS_S_FAILURE); } memset(handle, 0, sizeof (*handle)); HEIMDAL_MUTEX_init(&handle->cred_id_mutex); if (desired_name != GSS_C_NO_NAME) { ret = gss_duplicate_name(minor_status, desired_name, &handle->principal); if (ret != GSS_S_COMPLETE) { HEIMDAL_MUTEX_destroy(&handle->cred_id_mutex); free(handle); return (ret); } } if (cred_usage == GSS_C_INITIATE || cred_usage == GSS_C_BOTH) { ret = acquire_initiator_cred(minor_status, desired_name, time_req, desired_mechs, cred_usage, handle, actual_mechs, time_rec); if (ret != GSS_S_COMPLETE) { HEIMDAL_MUTEX_destroy(&handle->cred_id_mutex); krb5_free_principal(gssapi_krb5_context, handle->principal); free(handle); return (ret); } } if (cred_usage == GSS_C_ACCEPT || cred_usage == GSS_C_BOTH) { ret = acquire_acceptor_cred(minor_status, desired_name, time_req, desired_mechs, cred_usage, handle, actual_mechs, time_rec); if (ret != GSS_S_COMPLETE) { HEIMDAL_MUTEX_destroy(&handle->cred_id_mutex); krb5_free_principal(gssapi_krb5_context, handle->principal); free(handle); return (ret); } } ret = gss_create_empty_oid_set(minor_status, &handle->mechanisms); if (ret == GSS_S_COMPLETE) ret = gss_add_oid_set_member(minor_status, GSS_KRB5_MECHANISM, &handle->mechanisms); if (ret == GSS_S_COMPLETE) ret = gss_inquire_cred(minor_status, handle, NULL, time_rec, NULL, actual_mechs); if (ret != GSS_S_COMPLETE) { if (handle->mechanisms != NULL) gss_release_oid_set(NULL, &handle->mechanisms); HEIMDAL_MUTEX_destroy(&handle->cred_id_mutex); krb5_free_principal(gssapi_krb5_context, handle->principal); free(handle); return (ret); } *minor_status = 0; if (time_rec) { ret = gssapi_lifetime_left(minor_status, handle->lifetime, time_rec); if (ret) return ret; } handle->usage = cred_usage; *output_cred_handle = handle; return (GSS_S_COMPLETE); }
/* * We only support those mechanisms that we know about (ie ones that we know * how to check local user kuserok and the like) */ static int userauth_gssapi(Authctxt *authctxt) { gss_OID_desc goid = {0, NULL}; Gssctxt *ctxt = NULL; int mechs; gss_OID_set supported; int present; OM_uint32 ms; u_int len; u_char *doid = NULL; /* authctxt->valid may be 0 if we haven't yet determined username from gssapi context. */ if (authctxt->user == NULL) return (0); mechs = packet_get_int(); if (mechs == 0) { debug("Mechanism negotiation is not supported"); return (0); } ssh_gssapi_supported_oids(&supported); do { mechs--; if (doid) xfree(doid); present = 0; doid = packet_get_string(&len); if (len > 2 && doid[0] == SSH_GSS_OIDTYPE && doid[1] == len - 2) { goid.elements = doid + 2; goid.length = len - 2; gss_test_oid_set_member(&ms, &goid, supported, &present); } else { logit("Badly formed OID received"); } } while (mechs > 0 && !present); gss_release_oid_set(&ms, &supported); if (!present) { xfree(doid); authctxt->server_caused_failure = 1; return (0); } if (GSS_ERROR(PRIVSEP(ssh_gssapi_server_ctx(&ctxt, &goid)))) { if (ctxt != NULL) ssh_gssapi_delete_ctx(&ctxt); xfree(doid); authctxt->server_caused_failure = 1; return (0); } authctxt->methoddata = (void *)ctxt; packet_start(SSH2_MSG_USERAUTH_GSSAPI_RESPONSE); /* Return the OID that we received */ packet_put_string(doid, len); packet_send(); xfree(doid); dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, &input_gssapi_token); dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_ERRTOK, &input_gssapi_errtok); authctxt->postponed = 1; return (0); }
/** @internal * @brief handles an user authentication using GSSAPI */ int ssh_gssapi_handle_userauth(ssh_session session, const char *user, uint32_t n_oid, ssh_string *oids){ char service_name[]="host"; gss_buffer_desc name_buf; gss_name_t server_name; /* local server fqdn */ OM_uint32 maj_stat, min_stat; unsigned int i; char *ptr; gss_OID_set supported; /* oids supported by server */ gss_OID_set both_supported; /* oids supported by both client and server */ gss_OID_set selected; /* oid selected for authentication */ int present=0; int oid_count=0; struct gss_OID_desc_struct oid; int rc; if (ssh_callbacks_exists(session->server_callbacks, gssapi_select_oid_function)){ ssh_string oid_s = session->server_callbacks->gssapi_select_oid_function(session, user, n_oid, oids, session->server_callbacks->userdata); if (oid_s != NULL){ if (ssh_gssapi_init(session) == SSH_ERROR) return SSH_ERROR; session->gssapi->state = SSH_GSSAPI_STATE_RCV_TOKEN; rc = ssh_gssapi_send_response(session, oid_s); ssh_string_free(oid_s); return rc; } else { return ssh_auth_reply_default(session,0); } } gss_create_empty_oid_set(&min_stat, &both_supported); maj_stat = gss_indicate_mechs(&min_stat, &supported); for (i=0; i < supported->count; ++i){ ptr = ssh_get_hexa(supported->elements[i].elements, supported->elements[i].length); SSH_LOG(SSH_LOG_DEBUG, "Supported mech %d: %s\n", i, ptr); free(ptr); } for (i=0 ; i< n_oid ; ++i){ unsigned char *oid_s = (unsigned char *) ssh_string_data(oids[i]); size_t len = ssh_string_len(oids[i]); if(len < 2 || oid_s[0] != SSH_OID_TAG || ((size_t)oid_s[1]) != len - 2){ SSH_LOG(SSH_LOG_WARNING,"GSSAPI: received invalid OID"); continue; } oid.elements = &oid_s[2]; oid.length = len - 2; gss_test_oid_set_member(&min_stat,&oid,supported,&present); if(present){ gss_add_oid_set_member(&min_stat,&oid,&both_supported); oid_count++; } } gss_release_oid_set(&min_stat, &supported); if (oid_count == 0){ SSH_LOG(SSH_LOG_PROTOCOL,"GSSAPI: no OID match"); ssh_auth_reply_default(session, 0); gss_release_oid_set(&min_stat, &both_supported); return SSH_OK; } /* from now we have room for context */ if (ssh_gssapi_init(session) == SSH_ERROR) return SSH_ERROR; name_buf.value = service_name; name_buf.length = strlen(name_buf.value) + 1; maj_stat = gss_import_name(&min_stat, &name_buf, (gss_OID) GSS_C_NT_HOSTBASED_SERVICE, &server_name); if (maj_stat != GSS_S_COMPLETE) { SSH_LOG(SSH_LOG_WARNING, "importing name %d, %d", maj_stat, min_stat); ssh_gssapi_log_error(SSH_LOG_WARNING, "importing name", maj_stat); return -1; } maj_stat = gss_acquire_cred(&min_stat, server_name, 0, both_supported, GSS_C_ACCEPT, &session->gssapi->server_creds, &selected, NULL); gss_release_name(&min_stat, &server_name); gss_release_oid_set(&min_stat, &both_supported); if (maj_stat != GSS_S_COMPLETE) { SSH_LOG(SSH_LOG_WARNING, "error acquiring credentials %d, %d", maj_stat, min_stat); ssh_gssapi_log_error(SSH_LOG_WARNING, "acquiring creds", maj_stat); ssh_auth_reply_default(session,0); return SSH_ERROR; } SSH_LOG(SSH_LOG_PROTOCOL, "acquiring credentials %d, %d", maj_stat, min_stat); /* finding which OID from client we selected */ for (i=0 ; i< n_oid ; ++i){ unsigned char *oid_s = (unsigned char *) ssh_string_data(oids[i]); size_t len = ssh_string_len(oids[i]); if(len < 2 || oid_s[0] != SSH_OID_TAG || ((size_t)oid_s[1]) != len - 2){ SSH_LOG(SSH_LOG_WARNING,"GSSAPI: received invalid OID"); continue; } oid.elements = &oid_s[2]; oid.length = len - 2; gss_test_oid_set_member(&min_stat,&oid,selected,&present); if(present){ SSH_LOG(SSH_LOG_PACKET, "Selected oid %d", i); break; } } session->gssapi->mech.length = oid.length; session->gssapi->mech.elements = malloc(oid.length); if (session->gssapi->mech.elements == NULL){ ssh_set_error_oom(session); return SSH_ERROR; } memcpy(session->gssapi->mech.elements, oid.elements, oid.length); gss_release_oid_set(&min_stat, &selected); session->gssapi->user = strdup(user); session->gssapi->service = service_name; session->gssapi->state = SSH_GSSAPI_STATE_RCV_TOKEN; return ssh_gssapi_send_response(session, oids[i]); }
/* * We only support those mechanisms that we know about (ie ones that we know * how to check local user kuserok and the like */ static int userauth_gssapi(Authctxt *authctxt) { gss_OID_desc oid = {0, NULL}; Gssctxt *ctxt = NULL; int mechs; gss_OID_set supported; int present; OM_uint32 ms; u_int len; char *doid = NULL; if (!authctxt->valid || authctxt->user == NULL) return (0); mechs = packet_get_int(); if (mechs == 0) { debug("Mechanism negotiation is not supported"); return (0); } ssh_gssapi_supported_oids(&supported); do { mechs--; if (doid) xfree(doid); doid = packet_get_string(&len); if (doid[0] != SSH_GSS_OIDTYPE || doid[1] != len-2) { logit("Mechanism OID received using the old encoding form"); oid.elements = doid; oid.length = len; } else { oid.elements = doid + 2; oid.length = len - 2; } gss_test_oid_set_member(&ms, &oid, supported, &present); } while (mechs > 0 && !present); gss_release_oid_set(&ms, &supported); if (!present) { xfree(doid); return (0); } if (GSS_ERROR(PRIVSEP(ssh_gssapi_server_ctx(&ctxt, &oid)))) { xfree(doid); return (0); } authctxt->methoddata=(void *)ctxt; packet_start(SSH2_MSG_USERAUTH_GSSAPI_RESPONSE); /* Return OID in same format as we received it*/ packet_put_string(doid, len); packet_send(); xfree(doid); dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, &input_gssapi_token); dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_ERRTOK, &input_gssapi_errtok); authctxt->postponed = 1; return (0); }
/** * This function is not a public interface and is deprecated anyways, do * not use. Use gss_acquire_cred_with_password() instead for now. * * @deprecated */ OM_uint32 _gss_acquire_cred_ext(OM_uint32 *minor_status, gss_const_name_t desired_name, gss_const_OID credential_type, const void *credential_data, OM_uint32 time_req, gss_const_OID desired_mech, gss_cred_usage_t cred_usage, gss_cred_id_t *output_cred_handle) { OM_uint32 major_status; struct _gss_name *name = (struct _gss_name *) desired_name; gssapi_mech_interface m; struct _gss_cred *cred; gss_OID_set_desc set, *mechs; size_t i; *minor_status = 0; if (output_cred_handle == NULL) return GSS_S_CALL_INACCESSIBLE_READ; _gss_load_mech(); if (desired_mech != GSS_C_NO_OID) { int match = 0; gss_test_oid_set_member(minor_status, (gss_OID)desired_mech, _gss_mech_oids, &match); if (!match) return GSS_S_BAD_MECH; set.count = 1; set.elements = (gss_OID)desired_mech; mechs = &set; } else mechs = _gss_mech_oids; cred = calloc(1, sizeof(*cred)); if (cred == NULL) { *minor_status = ENOMEM; return GSS_S_FAILURE; } HEIM_SLIST_INIT(&cred->gc_mc); for (i = 0; i < mechs->count; i++) { struct _gss_mechanism_name *mn = NULL; struct _gss_mechanism_cred *mc = NULL; m = __gss_get_mechanism(&mechs->elements[i]); if (!m) continue; if (desired_name != GSS_C_NO_NAME) { major_status = _gss_find_mn(minor_status, name, &mechs->elements[i], &mn); if (major_status != GSS_S_COMPLETE) continue; } major_status = _gss_acquire_mech_cred(minor_status, m, mn, credential_type, credential_data, time_req, desired_mech, cred_usage, &mc); if (GSS_ERROR(major_status)) { if (mechs->count == 1) _gss_mg_error(m, major_status, *minor_status); continue; } HEIM_SLIST_INSERT_HEAD(&cred->gc_mc, mc, gmc_link); } /* * If we didn't manage to create a single credential, return * an error. */ if (!HEIM_SLIST_FIRST(&cred->gc_mc)) { free(cred); if (mechs->count > 1) *minor_status = 0; return GSS_S_NO_CRED; } *output_cred_handle = (gss_cred_id_t) cred; *minor_status = 0; return GSS_S_COMPLETE; }
static void import_names() { OM_uint32 major_status, minor_status; globus_gsi_cred_handle_t handle; gss_buffer_desc buffer; X509 * cert; gss_OID_set name_types; globus_result_t result; globus_list_t *i, *j; compare_name_test_case_t * test_case; int present; major_status = gss_inquire_names_for_mech( &minor_status, (gss_OID) globus_i_gss_mech_globus_gssapi_openssl, &name_types); if (major_status == GSS_S_COMPLETE) { major_status = gss_test_oid_set_member( &minor_status, GLOBUS_GSS_C_NT_X509, name_types, &present); if (major_status == GSS_S_COMPLETE && present) { gss_l_x509_support = GLOBUS_TRUE; } major_status = gss_test_oid_set_member( &minor_status, GLOBUS_GSS_C_NT_HOST_IP, name_types, &present); if (major_status == GSS_S_COMPLETE && present) { gss_l_host_ip_support = GLOBUS_TRUE; } major_status = gss_release_oid_set(&minor_status, &name_types); } for (i = test_cases; !globus_list_empty(i); i = globus_list_rest(i)) { test_case = globus_list_first(i); if (test_case->name1 == GSS_C_NO_NAME) { switch (test_case->name_type1) { case GSS_L_ANONYMOUS: major_status = gss_import_name(&minor_status, &buffer, GSS_C_NT_ANONYMOUS, &test_case->name1); if (major_status != GSS_S_COMPLETE) { fprintf(stderr, "Error importing <anonymous>\n"); globus_gsi_gssapi_test_print_error(stderr, major_status, minor_status); exit(-1); } break; case GSS_L_NO_OID: buffer.value = test_case->name_token1; buffer.length = strlen(buffer.value); major_status = gss_import_name(&minor_status, &buffer, GSS_C_NO_OID, &test_case->name1); if (major_status != GSS_S_COMPLETE) { fprintf(stderr, "Error importing %s\n", test_case->name_token1); globus_gsi_gssapi_test_print_error(stderr, major_status, minor_status); exit(-1); } break; case GSS_L_HOSTBASED_SERVICE: buffer.value = test_case->name_token1; buffer.length = strlen(buffer.value); major_status = gss_import_name(&minor_status, &buffer, GSS_C_NT_HOSTBASED_SERVICE, &test_case->name1); if (major_status != GSS_S_COMPLETE) { fprintf(stderr, "Error importing %s\n", test_case->name_token1); globus_gsi_gssapi_test_print_error(stderr, major_status, minor_status); exit(-1); } break; case GSS_L_HOST_IP: if (gss_l_host_ip_support) { buffer.value = test_case->name_token1; buffer.length = strlen(buffer.value); major_status = gss_import_name(&minor_status, &buffer, GLOBUS_GSS_C_NT_HOST_IP, &test_case->name1); if (major_status != GSS_S_COMPLETE) { fprintf(stderr, "Error importing %s\n", test_case->name_token1); globus_gsi_gssapi_test_print_error(stderr, major_status, minor_status); exit(-1); } } break; case GSS_L_X509: if (gss_l_x509_support) { result = globus_gsi_cred_handle_init(&handle, NULL); if (result != GLOBUS_SUCCESS) { globus_gsi_gssapi_test_print_result(stderr, result); exit(-1); } result = globus_gsi_cred_read_cert(handle, test_case->name_token1); if (result != GLOBUS_SUCCESS) { globus_gsi_gssapi_test_print_result(stderr, result); exit(-2); } result = globus_gsi_cred_get_cert(handle, &cert); buffer.value = cert; buffer.length = sizeof(X509); major_status = gss_import_name(&minor_status, &buffer, GLOBUS_GSS_C_NT_X509, &test_case->name1); if (major_status != GSS_S_COMPLETE) { fprintf(stderr, "Error importing %s\n", test_case->name_token1); globus_gsi_gssapi_test_print_error(stderr, major_status, minor_status); exit(-1); } X509_free(cert); globus_gsi_cred_handle_destroy(handle); } break; } for (j = i; !globus_list_empty(j); j = globus_list_rest(j)) { compare_name_test_case_t *test_case2 = globus_list_first(j); if (test_case->name_type1 == test_case2->name_type1 && test_case->name_token1 && test_case2->name_token1 && strcmp(test_case->name_token1, test_case2->name_token1) == 0 && test_case2->name1 == GSS_C_NO_NAME) { test_case2->name1 = test_case->name1; } if (test_case->name_type1 == test_case2->name_type2 && test_case->name_token1 && test_case2->name_token2 && strcmp(test_case->name_token1, test_case2->name_token2) == 0 && test_case2->name2 == GSS_C_NO_NAME) { test_case2->name2 = test_case->name1; } } } if (test_case->name2 == GSS_C_NO_NAME) { switch (test_case->name_type2) { case GSS_L_ANONYMOUS: major_status = gss_import_name(&minor_status, &buffer, GSS_C_NT_ANONYMOUS, &test_case->name2); if (major_status != GSS_S_COMPLETE) { fprintf(stderr, "Error importing <anonymous>\n"); globus_gsi_gssapi_test_print_error(stderr, major_status, minor_status); exit(-1); } break; case GSS_L_NO_OID: buffer.value = test_case->name_token2; buffer.length = strlen(buffer.value); major_status = gss_import_name(&minor_status, &buffer, GSS_C_NO_OID, &test_case->name2); if (major_status != GSS_S_COMPLETE) { fprintf(stderr, "Error importing %s\n", test_case->name_token2); globus_gsi_gssapi_test_print_error(stderr, major_status, minor_status); exit(-1); } break; case GSS_L_HOSTBASED_SERVICE: buffer.value = test_case->name_token2; buffer.length = strlen(buffer.value); major_status = gss_import_name(&minor_status, &buffer, GSS_C_NT_HOSTBASED_SERVICE, &test_case->name2); if (major_status != GSS_S_COMPLETE) { fprintf(stderr, "Error importing %s\n", test_case->name_token2); globus_gsi_gssapi_test_print_error(stderr, major_status, minor_status); exit(-1); } break; case GSS_L_HOST_IP: if (gss_l_host_ip_support) { buffer.value = test_case->name_token2; buffer.length = strlen(buffer.value); major_status = gss_import_name(&minor_status, &buffer, GLOBUS_GSS_C_NT_HOST_IP, &test_case->name2); if (major_status != GSS_S_COMPLETE) { fprintf(stderr, "Error importing %s\n", test_case->name_token2); globus_gsi_gssapi_test_print_error(stderr, major_status, minor_status); exit(-1); } } break; case GSS_L_X509: if (gss_l_x509_support) { result = globus_gsi_cred_handle_init(&handle, NULL); if (result != GLOBUS_SUCCESS) { globus_gsi_gssapi_test_print_result(stderr, result); exit(-1); } result = globus_gsi_cred_read_cert(handle, test_case->name_token2); if (result != GLOBUS_SUCCESS) { globus_gsi_gssapi_test_print_result(stderr, result); exit(-2); } result = globus_gsi_cred_get_cert(handle, &cert); buffer.value = cert; buffer.length = sizeof(X509); major_status = gss_import_name(&minor_status, &buffer, GLOBUS_GSS_C_NT_X509, &test_case->name2); if (major_status != GSS_S_COMPLETE) { fprintf(stderr, "Error importing %s\n", test_case->name_token2); globus_gsi_gssapi_test_print_error(stderr, major_status, minor_status); exit(-1); } X509_free(cert); globus_gsi_cred_handle_destroy(handle); } break; } for (j = i; !globus_list_empty(j); j = globus_list_rest(j)) { compare_name_test_case_t *test_case2 = globus_list_first(j); if (test_case->name_type2 == test_case2->name_type1 && test_case->name_token2 && test_case2->name_token1 && strcmp(test_case->name_token2, test_case2->name_token1) == 0 && test_case2->name1 == GSS_C_NO_NAME) { test_case2->name1 = test_case->name2; } if (test_case->name_type2 == test_case2->name_type2 && test_case->name_token2 && test_case2->name_token2 && strcmp(test_case->name_token2, test_case2->name_token2) == 0 && test_case2->name2 == GSS_C_NO_NAME) { test_case2->name2 = test_case->name2; } } } } }