/* * Free a SPNEGO context handle. The caller must have acquired * the lock before this is called. */ OM_uint32 GSSAPI_CALLCONV _gss_spnego_internal_delete_sec_context (OM_uint32 *minor_status, gss_ctx_id_t *context_handle, gss_buffer_t output_token ) { gssspnego_ctx ctx; OM_uint32 ret, minor; *minor_status = 0; if (context_handle == NULL) { return GSS_S_NO_CONTEXT; } if (output_token != GSS_C_NO_BUFFER) { output_token->length = 0; output_token->value = NULL; } ctx = (gssspnego_ctx)*context_handle; *context_handle = GSS_C_NO_CONTEXT; if (ctx == NULL) { return GSS_S_NO_CONTEXT; } if (ctx->NegTokenInit_mech_types.value) free(ctx->NegTokenInit_mech_types.value); gss_release_oid(&minor, &ctx->preferred_mech_type); ctx->negotiated_mech_type = GSS_C_NO_OID; gss_release_oid(&minor, &ctx->selected_mech_type); ctx->selected_mech_type = GSS_C_NO_OID; gss_release_name(&minor, &ctx->target_name); gss_release_name(&minor, &ctx->mech_src_name); if (ctx->negotiated_ctx_id != GSS_C_NO_CONTEXT) { ret = gss_delete_sec_context(minor_status, &ctx->negotiated_ctx_id, NULL); ctx->negotiated_ctx_id = GSS_C_NO_CONTEXT; } else { ret = GSS_S_COMPLETE; } HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); HEIMDAL_MUTEX_destroy(&ctx->ctx_id_mutex); free(ctx); return ret; }
static void pamGssCleanupMech(pam_handle_t *pamh, void *data, int error_status) { #ifndef HAVE_HEIMDAL_VERSION OM_uint32 minor; gss_release_oid(&minor, (gss_OID *)&data); #endif }
OM_uint32 ntlm_gss_delete_sec_context( OM_uint32 *minor_status, gss_ctx_id_t *context_handle, gss_buffer_t output_token) { ntlm_gss_ctx_id_t ntlm_ctx = NULL; OM_uint32 ret = GSS_S_COMPLETE; if (context_handle == NULL) { return (GSS_S_FAILURE); } ntlm_ctx = (ntlm_gss_ctx_id_t) *context_handle; if (ntlm_ctx->upn_name) { free(ntlm_ctx->upn_name); } if (ntlm_ctx->ntlm_session_key) { free(ntlm_ctx->ntlm_session_key); } if (ntlm_ctx->ntlm_usr) { srp_user_delete(ntlm_ctx->ntlm_usr); ntlm_ctx->ntlm_usr = NULL; } if (ntlm_ctx->ntlm_ver) { srp_verifier_delete(ntlm_ctx->ntlm_ver); ntlm_ctx->ntlm_ver = NULL; } if (ntlm_ctx->mech) { OM_uint32 min_tmp = GSS_S_COMPLETE; gss_release_oid(&min_tmp, &ntlm_ctx->mech); } krb5_free_keyblock(ntlm_ctx->krb5_ctx, ntlm_ctx->keyblock); ntlm_ctx->keyblock = NULL; krb5_free_context(ntlm_ctx->krb5_ctx); ntlm_ctx->krb5_ctx = NULL; free(*context_handle); *context_handle = NULL; return (ret); }
uint32_t gp_conv_gssx_to_name(uint32_t *min, gssx_name *in, gss_name_t *out) { gss_buffer_t input_name = GSS_C_NO_BUFFER; gss_OID name_type = GSS_C_NO_OID; gss_buffer_desc name_buffer; uint32_t ret_maj; uint32_t ret_min; int ret; if (in->display_name.octet_string_len != 0) { /* ok we have a display name. * In this case always import and canonicalize it so we can * safely export the name using the original form, even if we * already have exported_name */ ret = gp_conv_gssx_to_buffer_alloc(&in->display_name, &input_name); if (ret) { ret_maj = GSS_S_FAILURE; ret_min = ret; goto done; } ret = gp_conv_gssx_to_oid_alloc(&in->name_type, &name_type); if (ret) { ret_maj = GSS_S_FAILURE; ret_min = ret; goto done; } ret_maj = gss_import_name(&ret_min, input_name, name_type, out); if (ret_maj) { goto done; } } else { gp_conv_gssx_to_buffer(&in->exported_name, &name_buffer); ret_maj = gss_import_name(&ret_min, &name_buffer, GSS_C_NT_EXPORT_NAME, out); if (ret_maj) { goto done; } } done: *min = ret_min; gss_release_buffer(&ret_min, input_name); gss_release_oid(&ret_min, &name_type); return ret_maj; }
OM_uint32 KRB5_CALLCONV gss_inquire_name(OM_uint32 *minor_status, gss_name_t name, int *name_is_MN, gss_OID *MN_mech, gss_buffer_set_t *attrs) { OM_uint32 status, tmp; gss_union_name_t union_name; gss_mechanism mech; if (minor_status == NULL) return GSS_S_CALL_INACCESSIBLE_WRITE; if (name == GSS_C_NO_NAME) return GSS_S_CALL_INACCESSIBLE_READ | GSS_S_BAD_NAME; if (MN_mech != NULL) *MN_mech = GSS_C_NO_OID; if (attrs != NULL) *attrs = GSS_C_NO_BUFFER_SET; *minor_status = 0; union_name = (gss_union_name_t)name; if (union_name->mech_type == GSS_C_NO_OID) { /* We don't yet support non-mechanism attributes */ if (name_is_MN != NULL) name_is_MN = 0; *minor_status = 0; return GSS_S_COMPLETE; } if (name_is_MN != NULL) *name_is_MN = 1; if (MN_mech != NULL) { status = generic_gss_copy_oid(minor_status, union_name->mech_type, MN_mech); if (GSS_ERROR(status)) return status; } mech = gssint_get_mechanism(name->mech_type); if (mech == NULL) { gss_release_oid(&tmp, MN_mech); return GSS_S_BAD_NAME; } if (mech->gss_inquire_name == NULL) { gss_release_oid(&tmp, MN_mech); return GSS_S_UNAVAILABLE; } status = (*mech->gss_inquire_name)(minor_status, union_name->mech_name, NULL, NULL, attrs); if (status != GSS_S_COMPLETE) { generic_gss_release_oid(&tmp, MN_mech); map_error(minor_status, mech); } return status; }
int pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc, const char **argv) { int status, confFlags = 0; char hostNameBufBuf[5 + MAXHOSTNAMELEN + 1] = "host@"; int isConvPasswordBuf = 0; OM_uint32 major, minor; gss_buffer_desc userNameBuf = GSS_C_EMPTY_BUFFER; gss_buffer_desc hostNameBuf = GSS_C_EMPTY_BUFFER; gss_buffer_desc passwordBuf = GSS_C_EMPTY_BUFFER; gss_name_t userName = GSS_C_NO_NAME; gss_name_t hostName = GSS_C_NO_NAME; gss_cred_id_t initiatorCred = GSS_C_NO_CREDENTIAL; gss_cred_id_t acceptorCred = GSS_C_NO_CREDENTIAL; gss_OID mech = &gss_spnego_mechanism_oid_desc; gss_OID_set_desc mechOids; confFlags = readConfFlags(argc, argv); status = readConfMechOid(argc, argv, &mech); BAIL_ON_PAM_ERROR(status); if (flags & PAM_DISALLOW_NULL_AUTHTOK) confFlags &= ~(FLAG_NULLOK); status = pam_get_user(pamh, (void *)&userNameBuf.value, NULL); BAIL_ON_PAM_ERROR(status); userNameBuf.length = strlen((char *)userNameBuf.value); major = gss_import_name(&minor, &userNameBuf, GSS_C_NT_USER_NAME, &userName); BAIL_ON_GSS_ERROR(major, minor); if (gethostname(&hostNameBufBuf[5], MAXHOSTNAMELEN) != 0) { status = PAM_SYSTEM_ERR; goto cleanup; } hostNameBuf.length = strlen(hostNameBufBuf); hostNameBuf.value = hostNameBufBuf; major = gss_import_name(&minor, &hostNameBuf, GSS_C_NT_HOSTBASED_SERVICE, &hostName); BAIL_ON_GSS_ERROR(major, minor); mechOids.count = 1; mechOids.elements = mech; major = gss_acquire_cred(&minor, hostName, GSS_C_INDEFINITE, &mechOids, GSS_C_ACCEPT, &acceptorCred, NULL, NULL); BAIL_ON_GSS_ERROR(major, minor); status = PAM_AUTHINFO_UNAVAIL; if (confFlags & (FLAG_USE_FIRST_PASS | FLAG_TRY_FIRST_PASS)) { status = pam_get_item(pamh, PAM_AUTHTOK, (void *)&passwordBuf.value); BAIL_ON_PAM_ERROR(status); if (passwordBuf.value != NULL) passwordBuf.length = strlen((char *)passwordBuf.value); status = pamGssAcquireCred(pamh, confFlags, userName, &passwordBuf, mech, &initiatorCred); if (status == PAM_SUCCESS) status = pamGssInitAcceptSecContext(pamh, confFlags, initiatorCred, acceptorCred, hostName, mech); if (confFlags & FLAG_USE_FIRST_PASS) BAIL_ON_PAM_ERROR(status); } if (status != PAM_SUCCESS) { isConvPasswordBuf = 1; if (flags & PAM_SILENT) goto cleanup; status = pamGssGetAuthTok(pamh, confFlags, &passwordBuf); BAIL_ON_PAM_ERROR(status); gss_release_cred(&minor, &initiatorCred); status = pamGssAcquireCred(pamh, confFlags, userName, &passwordBuf, mech, &initiatorCred); if (status == PAM_SUCCESS) status = pamGssInitAcceptSecContext(pamh, confFlags, initiatorCred, acceptorCred, hostName, mech); BAIL_ON_PAM_ERROR(status); } status = pam_set_data(pamh, GSS_CRED_DATA, initiatorCred, pamGssCleanupCred); BAIL_ON_PAM_ERROR(status); initiatorCred = GSS_C_NO_CREDENTIAL; cleanup: gss_release_name(&minor, &userName); gss_release_name(&minor, &hostName); gss_release_cred(&minor, &initiatorCred); gss_release_cred(&minor, &acceptorCred); #ifdef __APPLE__ if (mech != &gss_spnego_mechanism_oid_desc) gss_release_oid(&minor, &mech); #endif if (isConvPasswordBuf) { memset((char *)passwordBuf.value, 0, passwordBuf.length); free(passwordBuf.value); } return status; }
int gp_import_and_canon_name(struct gp_call_ctx *gpcall, union gp_rpc_arg *arg, union gp_rpc_res *res) { struct gssx_arg_import_and_canon_name *icna; struct gssx_res_import_and_canon_name *icnr; gss_OID mech = GSS_C_NO_OID; gss_name_t import_name = GSS_C_NO_NAME; gss_name_t output_name = GSS_C_NO_NAME; uint32_t ret_maj = 0; uint32_t ret_min = 0; int ret; icna = &arg->import_and_canon_name; icnr = &res->import_and_canon_name; if (icna->input_name.display_name.octet_string_len == 0 && icna->input_name.exported_name.octet_string_len == 0) { ret = EINVAL; goto done; } ret_maj = gp_conv_gssx_to_name(&ret_min, &icna->input_name, &import_name); if (ret_maj) { goto done; } if (icna->mech.octet_string_len != 0) { ret = gp_conv_gssx_to_oid_alloc(&icna->mech, &mech); if (ret) { ret_maj = GSS_S_FAILURE; ret_min = ret; goto done; } ret_maj = gss_canonicalize_name(&ret_min, import_name, mech, &output_name); if (ret_maj) { goto done; } ret_maj = gp_conv_name_to_gssx_alloc(&ret_min, output_name, &icnr->output_name); } else { ret_maj = gp_conv_name_to_gssx_alloc(&ret_min, import_name, &icnr->output_name); } /* TODO: check also icna->input_name.exported_composite_name */ /* TODO: icna->name_attributes */ done: ret = gp_conv_status_to_gssx(&icna->call_ctx, ret_maj, ret_min, mech, &icnr->status); gss_release_oid(&ret_min, &mech); gss_release_name(&ret_min, &import_name); gss_release_name(&ret_min, &output_name); return ret; }
OM_uint32 gssi_inquire_context(OM_uint32 *minor_status, gss_ctx_id_t context_handle, gss_name_t *src_name, gss_name_t *targ_name, OM_uint32 *lifetime_rec, gss_OID *mech_type, OM_uint32 *ctx_flags, int *locally_initiated, int *open) { struct gpp_context_handle *ctx_handle; struct gpp_name_handle *s_name = NULL; struct gpp_name_handle *t_name = NULL; gss_OID mech_oid; OM_uint32 maj, min; GSSI_TRACE(); if (!context_handle) { return GSS_S_CALL_INACCESSIBLE_READ; } ctx_handle = (struct gpp_context_handle *)context_handle; if (!ctx_handle->local && !ctx_handle->remote) { return GSS_S_CALL_INACCESSIBLE_READ; } if (src_name) { s_name = calloc(1, sizeof(struct gpp_name_handle)); if (!s_name) { min = ENOMEM; maj = GSS_S_FAILURE; goto done; } } if (targ_name) { t_name = calloc(1, sizeof(struct gpp_name_handle)); if (!t_name) { min = ENOMEM; maj = GSS_S_FAILURE; goto done; } } if (ctx_handle->local) { maj = gss_inquire_context(&min, ctx_handle->local, s_name ? &s_name->local : NULL, t_name ? &t_name->local : NULL, lifetime_rec, &mech_oid, ctx_flags, locally_initiated, open); } else { maj = gpm_inquire_context(&min, ctx_handle->remote, s_name ? &s_name->remote : NULL, t_name ? &t_name->remote : NULL, lifetime_rec, &mech_oid, ctx_flags, locally_initiated, open); } if (maj != GSS_S_COMPLETE) { goto done; } if (s_name) { maj = gpp_copy_oid(&min, mech_oid, &s_name->mech_type); if (maj != GSS_S_COMPLETE) { goto done; } } if (t_name) { maj = gpp_copy_oid(&min, mech_oid, &t_name->mech_type); if (maj != GSS_S_COMPLETE) { goto done; } } done: *minor_status = gpp_map_error(min); if (maj == GSS_S_COMPLETE) { if (mech_type) { *mech_type = mech_oid; } else { (void)gss_release_oid(&min, &mech_oid); } if (src_name) { *src_name = (gss_name_t)s_name; } if (targ_name) { *targ_name = (gss_name_t)t_name; } } else { (void)gss_release_oid(&min, &mech_oid); (void)gssi_release_name(&min, (gss_name_t *)&s_name); (void)gssi_release_name(&min, (gss_name_t *)&t_name); } return maj; }
void *server_thread(void *pvt) { const char **argv; struct athread *data; char buffer[MAX_RPC_SIZE]; uint32_t buflen; gss_buffer_desc in_token = GSS_C_EMPTY_BUFFER; uint32_t ret_maj; uint32_t ret_min; struct gssx_ctx *context_handle = NULL; struct gssx_cred *cred_handle = NULL; struct gssx_name *src_name = NULL; gss_buffer_desc out_token = GSS_C_EMPTY_BUFFER; struct gssx_cred *deleg_cred = NULL; gss_OID_set mech_set = GSS_C_NO_OID_SET; gss_OID_set mech_names = GSS_C_NO_OID_SET; gss_OID_set mech_types = GSS_C_NO_OID_SET; gss_OID_set mech_attrs = GSS_C_NO_OID_SET; gss_OID_set known_mech_attrs = GSS_C_NO_OID_SET; gss_buffer_desc sasl_mech_name = GSS_C_EMPTY_BUFFER; gss_buffer_desc mech_name = GSS_C_EMPTY_BUFFER; gss_buffer_desc mech_description = GSS_C_EMPTY_BUFFER; gss_buffer_desc name = GSS_C_EMPTY_BUFFER; gss_buffer_desc short_desc = GSS_C_EMPTY_BUFFER; gss_buffer_desc long_desc = GSS_C_EMPTY_BUFFER; gss_OID_set mechs = GSS_C_NO_OID_SET; gss_buffer_desc target_buf; struct gssx_name *target_name = NULL; struct gssx_name *canon_name = NULL; gss_buffer_desc out_name_buf = GSS_C_EMPTY_BUFFER; gss_OID out_name_type = GSS_C_NO_OID; gss_buffer_desc msg_token = GSS_C_EMPTY_BUFFER; int ret; gss_buffer_desc input_message_buffer = GSS_C_EMPTY_BUFFER; gss_buffer_desc output_message_buffer = GSS_C_EMPTY_BUFFER; gss_qop_t qop_state; int conf_state; data = (struct athread *)pvt; argv = data->argv; target_buf.value = (void *)data->target; target_buf.length = strlen(data->target) + 1; /* import name family functions tests */ ret_maj = gpm_import_name(&ret_min, &target_buf, GSS_C_NT_HOSTBASED_SERVICE, &target_name); if (ret_maj) { DEBUG("gssproxy returned an error: %d\n", ret_maj); gp_log_failure(GSS_C_NO_OID, ret_maj, ret_min); goto done; } ret_maj = gpm_canonicalize_name(&ret_min, target_name, discard_const(gss_mech_krb5), &canon_name); if (ret_maj) { DEBUG("gssproxy returned an error: %d\n", ret_maj); gp_log_failure(GSS_C_NO_OID, ret_maj, ret_min); goto done; } ret_maj = gpm_display_name(&ret_min, canon_name, &out_name_buf, &out_name_type); if (ret_maj) { DEBUG("gssproxy returned an error: %d\n", ret_maj); gp_log_failure(GSS_C_NO_OID, ret_maj, ret_min); goto done; } DEBUG("Acquiring for: %s\n", (char *)out_name_buf.value); /* indicate mechs family functions tests */ ret_maj = gpm_indicate_mechs(&ret_min, &mech_set); if (ret_maj) { DEBUG("gssproxy returned an error: %d\n", ret_maj); gp_log_failure(GSS_C_NO_OID, ret_maj, ret_min); goto done; } ret_maj = gpm_inquire_names_for_mech(&ret_min, &mech_set->elements[0], &mech_names); if (ret_maj) { DEBUG("gssproxy returned an error: %d\n", ret_maj); gp_log_failure(&mech_set->elements[0], ret_maj, ret_min); goto done; } ret_maj = gpm_inquire_attrs_for_mech(&ret_min, &mech_set->elements[0], &mech_attrs, &known_mech_attrs); if (ret_maj) { DEBUG("gssproxy returned an error: %d\n", ret_maj); gp_log_failure(&mech_set->elements[0], ret_maj, ret_min); goto done; } ret_maj = gpm_inquire_saslname_for_mech(&ret_min, &mech_set->elements[0], &sasl_mech_name, &mech_name, &mech_description); if (ret_maj) { DEBUG("gssproxy returned an error: %d\n", ret_maj); gp_log_failure(&mech_set->elements[0], ret_maj, ret_min); goto done; } ret_maj = gpm_display_mech_attr(&ret_min, &mech_attrs->elements[0], &name, &short_desc, &long_desc); if (ret_maj) { DEBUG("gssproxy returned an error: %d\n", ret_maj); gp_log_failure(GSS_C_NO_OID, ret_maj, ret_min); goto done; } ret_maj = gpm_indicate_mechs_by_attrs(&ret_min, GSS_C_NO_OID_SET, GSS_C_NO_OID_SET, GSS_C_NO_OID_SET, &mechs); if (ret_maj) { DEBUG("gssproxy returned an error: %d\n", ret_maj); gp_log_failure(GSS_C_NO_OID, ret_maj, ret_min); goto done; } ret_maj = gpm_inquire_mechs_for_name(&ret_min, target_name, &mech_types); if (ret_maj) { DEBUG("gssproxy returned an error: %d\n", ret_maj); gp_log_failure(GSS_C_NO_OID, ret_maj, ret_min); goto done; } ret_maj = gpm_acquire_cred(&ret_min, NULL, NULL, GSS_C_INDEFINITE, mech_set, GSS_C_ACCEPT, false, &cred_handle, NULL, NULL); if (ret_maj) { DEBUG("gssproxy returned an error: %d\n", ret_maj); gp_log_failure(GSS_C_NO_OID, ret_maj, ret_min); goto done; } ret = t_recv_buffer(data->srv_pipe[0], buffer, &buflen); if (ret) { DEBUG("Failed to get data from client!\n"); goto done; } in_token.value = buffer; in_token.length = buflen; ret_maj = gpm_accept_sec_context(&ret_min, &context_handle, cred_handle, &in_token, GSS_C_NO_CHANNEL_BINDINGS, &src_name, NULL, &out_token, NULL, NULL, &deleg_cred); if (ret_maj) { DEBUG("gssproxy returned an error: %d\n", ret_maj); gp_log_failure(GSS_C_NO_OID, ret_maj, ret_min); goto done; } if (out_token.length) { ret = t_send_buffer(data->cli_pipe[1], out_token.value, out_token.length); if (ret) { DEBUG("Failed to send data to client!\n"); goto done; } } /* receive message from client */ ret = t_recv_buffer(data->srv_pipe[0], buffer, &buflen); if (ret) { DEBUG("Failed to get data from client!\n"); goto done; } in_token.value = buffer; in_token.length = buflen; /* receive signature from client */ ret = t_recv_buffer(data->srv_pipe[0], &buffer[in_token.length], &buflen); if (ret) { DEBUG("Failed to get data from client!\n"); goto done; } msg_token.value = &buffer[in_token.length]; msg_token.length = buflen; ret_maj = gpm_verify_mic(&ret_min, context_handle, &in_token, &msg_token, NULL); if (ret_maj) { DEBUG("gpm_verify_mic failed: %d\n", ret_maj); gp_log_failure(GSS_C_NO_OID, ret_maj, ret_min); goto done; } DEBUG("Received valid msg from client: [%s]\n", buffer); ret = t_recv_buffer(data->srv_pipe[0], buffer, &buflen); if (ret) { DEBUG("Failed to get data from client!\n"); goto done; } input_message_buffer.value = buffer; input_message_buffer.length = buflen; ret_maj = gpm_unwrap(&ret_min, context_handle, &input_message_buffer, &output_message_buffer, &conf_state, &qop_state); if (ret_maj) { DEBUG("gpm_unwrap failed: %d\n", ret_maj); gp_log_failure(GSS_C_NO_OID, ret_maj, ret_min); goto done; } DEBUG("Received valid msg from client: [%s]\n", (char *)output_message_buffer.value); done: gpm_release_name(&ret_min, &src_name); gpm_release_buffer(&ret_min, &out_token); gpm_release_buffer(&ret_min, &output_message_buffer); gpm_release_cred(&ret_min, &deleg_cred); gpm_delete_sec_context(&ret_min, &context_handle, GSS_C_NO_BUFFER); gss_release_oid_set(&ret_min, &mech_set); gss_release_oid_set(&ret_min, &mech_names); gss_release_oid_set(&ret_min, &mech_types); gss_release_oid_set(&ret_min, &mech_attrs); gss_release_oid_set(&ret_min, &known_mech_attrs); gss_release_buffer(&ret_min, &sasl_mech_name); gss_release_buffer(&ret_min, &mech_name); gss_release_buffer(&ret_min, &mech_description); gss_release_buffer(&ret_min, &name); gss_release_buffer(&ret_min, &short_desc); gss_release_buffer(&ret_min, &long_desc); gss_release_oid_set(&ret_min, &mechs); gpm_release_name(&ret_min, &target_name); gpm_release_name(&ret_min, &canon_name); gss_release_buffer(&ret_min, &out_name_buf); gss_release_oid(&ret_min, &out_name_type); close(data->srv_pipe[0]); close(data->cli_pipe[1]); pthread_exit(NULL); }
static bool mag_list_of_mechs(cmd_parms *parms, gss_OID_set *oidset, bool add_spnego, const char *w) { gss_buffer_desc buf = { 0 }; uint32_t maj, min; gss_OID_set set; gss_OID oid; bool release_oid = false; if (NULL == *oidset) { maj = gss_create_empty_oid_set(&min, &set); if (maj != GSS_S_COMPLETE) { ap_log_error(APLOG_MARK, APLOG_ERR, 0, parms->server, "gss_create_empty_oid_set() failed."); *oidset = GSS_C_NO_OID_SET; return false; } if (add_spnego) { oid = discard_const(&gss_mech_spnego); maj = gss_add_oid_set_member(&min, oid, &set); if (maj != GSS_S_COMPLETE) { ap_log_error(APLOG_MARK, APLOG_ERR, 0, parms->server, "gss_add_oid_set_member() failed."); (void)gss_release_oid_set(&min, &set); *oidset = GSS_C_NO_OID_SET; return false; } } /* register in the pool so it can be released once the server * winds down */ apr_pool_cleanup_register(parms->pool, (void *)set, mag_oid_set_destroy, apr_pool_cleanup_null); *oidset = set; } else { set = *oidset; } if (strcmp(w, "krb5") == 0) { oid = discard_const(gss_mech_krb5); } else if (strcmp(w, "iakerb") == 0) { oid = discard_const(gss_mech_iakerb); } else if (strcmp(w, "ntlmssp") == 0) { oid = discard_const(gss_mech_ntlmssp); } else { buf.value = discard_const(w); buf.length = strlen(w); maj = gss_str_to_oid(&min, &buf, &oid); if (maj != GSS_S_COMPLETE) { ap_log_error(APLOG_MARK, APLOG_ERR, 0, parms->server, "Unrecognized GSSAPI Mechanism: [%s]", w); return false; } release_oid = true; } maj = gss_add_oid_set_member(&min, oid, &set); if (maj != GSS_S_COMPLETE) { ap_log_error(APLOG_MARK, APLOG_ERR, 0, parms->server, "gss_add_oid_set_member() failed for [%s].", w); } if (release_oid) { (void)gss_release_oid(&min, &oid); } return true; }
static OM_uint32 initAcceptSecContext(OM_uint32 *minor, gss_cred_id_t claimant_cred_handle, gss_cred_id_t verifier_cred_handle, gss_cred_id_t *deleg_cred_handle) { OM_uint32 major, tmp_minor; gss_buffer_desc token, tmp; gss_ctx_id_t initiator_context = GSS_C_NO_CONTEXT; gss_ctx_id_t acceptor_context = GSS_C_NO_CONTEXT; gss_name_t source_name = GSS_C_NO_NAME; gss_name_t target_name = GSS_C_NO_NAME; OM_uint32 time_rec; gss_OID mech = GSS_C_NO_OID; token.value = NULL; token.length = 0; tmp.value = NULL; tmp.length = 0; *deleg_cred_handle = GSS_C_NO_CREDENTIAL; major = gss_inquire_cred(minor, verifier_cred_handle, &target_name, NULL, NULL, NULL); if (GSS_ERROR(major)) { displayStatus("gss_inquire_cred", major, *minor); return major; } displayCanonName(minor, target_name, "Target name"); mech = use_spnego ? (gss_OID)&spnego_mech : (gss_OID)gss_mech_krb5; displayOID(minor, mech, "Target mech"); major = gss_init_sec_context(minor, claimant_cred_handle, &initiator_context, target_name, mech, GSS_C_REPLAY_FLAG | GSS_C_SEQUENCE_FLAG, GSS_C_INDEFINITE, GSS_C_NO_CHANNEL_BINDINGS, GSS_C_NO_BUFFER, NULL, &token, NULL, &time_rec); if (target_name != GSS_C_NO_NAME) (void) gss_release_name(&tmp_minor, &target_name); if (GSS_ERROR(major)) { displayStatus("gss_init_sec_context", major, *minor); return major; } mech = GSS_C_NO_OID; major = gss_accept_sec_context(minor, &acceptor_context, verifier_cred_handle, &token, GSS_C_NO_CHANNEL_BINDINGS, &source_name, &mech, &tmp, NULL, &time_rec, deleg_cred_handle); if (GSS_ERROR(major)) displayStatus("gss_accept_sec_context", major, *minor); else { testPrf(minor, initiator_context, acceptor_context, GSS_C_PRF_KEY_FULL); testPrf(minor, initiator_context, acceptor_context, GSS_C_PRF_KEY_PARTIAL); } (void) gss_release_name(&tmp_minor, &source_name); (void) gss_delete_sec_context(&tmp_minor, &acceptor_context, NULL); (void) gss_delete_sec_context(minor, &initiator_context, NULL); (void) gss_release_buffer(&tmp_minor, &token); (void) gss_release_buffer(&tmp_minor, &tmp); (void) gss_release_oid(&tmp_minor, &mech); return major; }