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; } } } } }
/** * @brief Initiate Delegation * @ingroup globus_gsi_gssapi_extensions_delegation * @details * This functions drives the initiating side of the credential * delegation process. It is expected to be called in tandem with the * gss_accept_delegation function. * * @param minor_status * The minor status returned by this function. This parameter * will be 0 upon success. * @param context_handle * The security context over which the credential is * delegated. * @param cred_handle * The credential to be delegated. May be GSS_C_NO_CREDENTIAL * in which case the credential associated with the security * context is used. * @param desired_mech * The desired security mechanism. Currently not used. May be * GSS_C_NO_OID. * @param extension_oids * A set of extension OIDs corresponding to buffers in the * extension_buffers parameter below. The extensions specified * will be added to the delegated credential. May be * GSS_C_NO_BUFFER_SET. * @param extension_buffers * A set of extension buffers corresponding to OIDs in the * extension_oids parameter above. May be * GSS_C_NO_BUFFER_SET. * @param input_token * The token that was produced by a prior call to * gss_accept_delegation. This parameter will be ignored the * first time this function is called. * @param req_flags * Flags that modify the behavior of the function. Currently * only GSS_C_GLOBUS_SSL_COMPATIBLE and * GSS_C_GLOBUS_LIMITED_DELEG_PROXY_FLAG are checked for. The * GSS_C_GLOBUS_SSL_COMPATIBLE flag results in tokens that * aren't wrapped and GSS_C_GLOBUS_LIMITED_DELEG_PROXY_FLAG * causes the delegated proxy to be limited (requires that no * extensions are specified. * * @param time_req * The requested period of validity (seconds) of the delegated * credential. Passing a time_req of 0 cause the delegated credential to * have the same lifetime as the credential that issued it. * @param output_token * A token that should be passed to gss_accept_delegation if the * return value is GSS_S_CONTINUE_NEEDED. * @retval GSS_S_COMPLETE Success * @retval GSS_S_CONTINUE_NEEDED This function needs to be called again. * @retval GSS_S_FAILURE upon failure */ OM_uint32 GSS_CALLCONV gss_init_delegation( OM_uint32 * minor_status, const gss_ctx_id_t context_handle, const gss_cred_id_t cred_handle, const gss_OID desired_mech, const gss_OID_set extension_oids, const gss_buffer_set_t extension_buffers, const gss_buffer_t input_token, OM_uint32 req_flags, OM_uint32 time_req, gss_buffer_t output_token) { BIO * bio = NULL; BIO * read_bio = NULL; BIO * write_bio = NULL; OM_uint32 major_status = GSS_S_COMPLETE; OM_uint32 local_minor_status; gss_ctx_id_desc * context; gss_cred_id_desc * cred; X509 * cert = NULL; STACK_OF(X509) * cert_chain = NULL; PROXYCERTINFO * pci; globus_gsi_cert_utils_cert_type_t cert_type; int index; globus_result_t local_result = GLOBUS_SUCCESS; static char * _function_name_ = "init_delegation"; GLOBUS_I_GSI_GSSAPI_DEBUG_ENTER; if(minor_status == NULL) { major_status = GSS_S_FAILURE; goto exit; } *minor_status = (OM_uint32) GLOBUS_SUCCESS; if(context_handle == GSS_C_NO_CONTEXT) { GLOBUS_GSI_GSSAPI_ERROR_RESULT( minor_status, GLOBUS_GSI_GSSAPI_ERROR_BAD_ARGUMENT, (_GGSL("Invalid context_handle passed to function"))); major_status = GSS_S_FAILURE; goto exit; } context = (gss_ctx_id_desc *) context_handle; cred = (gss_cred_id_desc *) cred_handle; if (cred_handle == GSS_C_NO_CREDENTIAL) { cred = (gss_cred_id_desc *) context->cred_handle; } if(cred == GSS_C_NO_CREDENTIAL) { GLOBUS_GSI_GSSAPI_ERROR_RESULT( minor_status, GLOBUS_GSI_GSSAPI_ERROR_BAD_ARGUMENT, (_GGSL("Couldn't initialize delegation credential handle"))); major_status = GSS_S_FAILURE; goto exit; } if(desired_mech != GSS_C_NO_OID && desired_mech != (gss_OID) gss_mech_globus_gssapi_openssl) { GLOBUS_GSI_GSSAPI_ERROR_RESULT( minor_status, GLOBUS_GSI_GSSAPI_ERROR_BAD_ARGUMENT, (_GGSL("Invalid desired_mech passed to function"))); major_status = GSS_S_FAILURE; goto exit; } if(extension_oids != GSS_C_NO_OID_SET && (extension_buffers == GSS_C_NO_BUFFER_SET || extension_oids->count != extension_buffers->count)) { GLOBUS_GSI_GSSAPI_ERROR_RESULT( minor_status, GLOBUS_GSI_GSSAPI_ERROR_BAD_ARGUMENT, (_GGSL("Invalid extension parameters passed to function"))); major_status = GSS_S_FAILURE; goto exit; } if(output_token == GSS_C_NO_BUFFER) { GLOBUS_GSI_GSSAPI_ERROR_RESULT( minor_status, GLOBUS_GSI_GSSAPI_ERROR_BAD_ARGUMENT, (_GGSL("Invalid output_token passed to function"))); major_status = GSS_S_FAILURE; goto exit; } output_token->length = 0; if(req_flags & GSS_C_GLOBUS_SSL_COMPATIBLE) { bio = BIO_new(BIO_s_mem()); read_bio = bio; write_bio = bio; } else { bio = context->gss_sslbio; } /* lock the context mutex */ globus_mutex_lock(&context->mutex); /* pass the input to the BIO */ if(context->delegation_state != GSS_DELEGATION_START) { /* * first time there is no input token, but after that * there will always be one */ if(input_token == GSS_C_NO_BUFFER) { GLOBUS_GSI_GSSAPI_ERROR_RESULT( minor_status, GLOBUS_GSI_GSSAPI_ERROR_BAD_ARGUMENT, (_GGSL("Invalid input_token passed to function: " "delegation is not at initial state"))); major_status = GSS_S_FAILURE; goto mutex_unlock; } major_status = globus_i_gsi_gss_put_token(&local_minor_status, context, read_bio, input_token); if (GSS_ERROR(major_status)) { GLOBUS_GSI_GSSAPI_ERROR_CHAIN_RESULT( minor_status, local_minor_status, GLOBUS_GSI_GSSAPI_ERROR_TOKEN_FAIL); goto mutex_unlock; } } /* delegation state machine */ switch (context->delegation_state) { case GSS_DELEGATION_START: /* start delegation by sending a "D" */ BIO_write(bio, "D", 1); context->delegation_state = GSS_DELEGATION_SIGN_CERT; break; case GSS_DELEGATION_SIGN_CERT: /* get the returned cert from the ssl BIO, make sure it is * correct and then sign it and place it in the output_token */ local_result = globus_gsi_proxy_inquire_req(context->proxy_handle, bio); if(local_result != GLOBUS_SUCCESS) { GLOBUS_GSI_GSSAPI_ERROR_CHAIN_RESULT( minor_status, local_result, GLOBUS_GSI_GSSAPI_ERROR_WITH_GSI_PROXY); major_status = GSS_S_FAILURE; goto mutex_unlock; } local_result = globus_gsi_cred_get_cert_type( context->cred_handle->cred_handle, &cert_type); if(local_result != GLOBUS_SUCCESS) { GLOBUS_GSI_GSSAPI_ERROR_CHAIN_RESULT( minor_status, local_result, GLOBUS_GSI_GSSAPI_ERROR_WITH_GSI_CREDENTIAL); major_status = GSS_S_FAILURE; context->delegation_state = GSS_DELEGATION_DONE; goto mutex_unlock; } /* set the requested time */ if(time_req != 0) { if(time_req%60) { /* round up */ time_req += 60; } local_result = globus_gsi_proxy_handle_set_time_valid( context->proxy_handle, time_req/60); if(local_result != GLOBUS_SUCCESS) { GLOBUS_GSI_GSSAPI_ERROR_CHAIN_RESULT( minor_status, local_result, GLOBUS_GSI_GSSAPI_ERROR_WITH_GSI_PROXY); major_status = GSS_S_FAILURE; context->delegation_state = GSS_DELEGATION_DONE; goto mutex_unlock; } } /* clear the proxycertinfo */ local_result = globus_gsi_proxy_handle_clear_cert_info(context->proxy_handle); if(local_result != GLOBUS_SUCCESS) { GLOBUS_GSI_GSSAPI_ERROR_CHAIN_RESULT( minor_status, local_result, GLOBUS_GSI_GSSAPI_ERROR_WITH_GSI_PROXY); major_status = GSS_S_FAILURE; context->delegation_state = GSS_DELEGATION_DONE; goto mutex_unlock; } if(cert_type == GLOBUS_GSI_CERT_UTILS_TYPE_CA) { GLOBUS_GSI_GSSAPI_ERROR_CHAIN_RESULT( minor_status, local_result, GLOBUS_GSI_GSSAPI_ERROR_WITH_GSI_CREDENTIAL); major_status = GSS_S_FAILURE; context->delegation_state = GSS_DELEGATION_DONE; goto mutex_unlock; } local_result = globus_gsi_proxy_handle_set_type( context->proxy_handle, (req_flags & GSS_C_GLOBUS_DELEGATE_LIMITED_PROXY_FLAG) ? GLOBUS_GSI_CERT_UTILS_TYPE_LIMITED_PROXY : GLOBUS_GSI_CERT_UTILS_TYPE_IMPERSONATION_PROXY); if(local_result != GLOBUS_SUCCESS) { GLOBUS_GSI_GSSAPI_ERROR_CHAIN_RESULT( minor_status, local_result, GLOBUS_GSI_GSSAPI_ERROR_WITH_GSI_PROXY); major_status = GSS_S_FAILURE; context->delegation_state = GSS_DELEGATION_DONE; goto mutex_unlock; } /* set the proxycertinfo here */ if(extension_oids != GSS_C_NO_OID_SET) { if(GLOBUS_GSI_CERT_UTILS_IS_GSI_2_PROXY(cert_type)) { GLOBUS_GSI_GSSAPI_ERROR_RESULT( minor_status, GLOBUS_GSI_GSSAPI_ERROR_BAD_ARGUMENT, (_GGSL("A restricted globus proxy may not be created " "from a legacy globus proxy"))); context->delegation_state = GSS_DELEGATION_DONE; major_status = GSS_S_FAILURE; goto mutex_unlock; } for(index = 0; index < extension_oids->count; index++) { if(g_OID_equal((gss_OID) &extension_oids->elements[index], gss_proxycertinfo_extension)) { pci = extension_buffers->elements[index].value; local_result = globus_gsi_proxy_handle_set_proxy_cert_info( context->proxy_handle, pci); if(local_result != GLOBUS_SUCCESS) { GLOBUS_GSI_GSSAPI_ERROR_CHAIN_RESULT( minor_status, local_result, GLOBUS_GSI_GSSAPI_ERROR_WITH_GSI_PROXY); major_status = GSS_S_FAILURE; context->delegation_state = GSS_DELEGATION_DONE; goto mutex_unlock; } } } } local_result = globus_gsi_proxy_sign_req( context->proxy_handle, cred->cred_handle, bio); if(local_result != GLOBUS_SUCCESS) { GLOBUS_GSI_GSSAPI_ERROR_CHAIN_RESULT( minor_status, local_result, GLOBUS_GSI_GSSAPI_ERROR_WITH_GSI_PROXY); major_status = GSS_S_FAILURE; context->delegation_state = GSS_DELEGATION_DONE; goto mutex_unlock; } local_result = globus_gsi_cred_get_cert(cred->cred_handle, &cert); if(local_result != GLOBUS_SUCCESS) { GLOBUS_GSI_GSSAPI_ERROR_CHAIN_RESULT( minor_status, local_result, GLOBUS_GSI_GSSAPI_ERROR_WITH_GSI_CREDENTIAL); major_status = GSS_S_FAILURE; context->delegation_state = GSS_DELEGATION_DONE; goto mutex_unlock; } /* push the cert used to sign the proxy */ i2d_X509_bio(bio, cert); X509_free(cert); /* push the number of certs in the cert chain */ local_result = globus_gsi_cred_get_cert_chain(cred->cred_handle, &cert_chain); if(local_result != GLOBUS_SUCCESS) { GLOBUS_GSI_GSSAPI_ERROR_CHAIN_RESULT( minor_status, local_result, GLOBUS_GSI_GSSAPI_ERROR_WITH_GSI_CREDENTIAL); major_status = GSS_S_FAILURE; context->delegation_state = GSS_DELEGATION_DONE; goto mutex_unlock; } for(index = 0; index < sk_X509_num(cert_chain); index++) { cert = sk_X509_value(cert_chain, index); if(!cert) { GLOBUS_GSI_GSSAPI_OPENSSL_ERROR_RESULT( minor_status, GLOBUS_GSI_GSSAPI_ERROR_WITH_OPENSSL, (_GGSL("Couldn't get cert from cert chain"))); major_status = GSS_S_FAILURE; context->delegation_state = GSS_DELEGATION_DONE; goto mutex_unlock; } i2d_X509_bio(bio, cert); } sk_X509_pop_free(cert_chain, X509_free); /* reset state machine */ context->delegation_state = GSS_DELEGATION_START; break; case GSS_DELEGATION_COMPLETE_CRED: case GSS_DELEGATION_DONE: break; } major_status = globus_i_gsi_gss_get_token(&local_minor_status, context, write_bio, output_token); if(GSS_ERROR(major_status)) { GLOBUS_GSI_GSSAPI_ERROR_CHAIN_RESULT( minor_status, local_minor_status, GLOBUS_GSI_GSSAPI_ERROR_TOKEN_FAIL); goto mutex_unlock; } if (context->delegation_state != GSS_DELEGATION_START) { major_status |= GSS_S_CONTINUE_NEEDED; } mutex_unlock: globus_mutex_unlock(&context->mutex); exit: if(req_flags & GSS_C_GLOBUS_SSL_COMPATIBLE) { BIO_free(bio); } GLOBUS_I_GSI_GSSAPI_DEBUG_EXIT; return major_status; }
/** * Accept a delegated credential. * * This functions drives the accepting side of the credential * delegation process. It is expected to be called in tandem with the * gss_init_delegation function. * * @param minor_status * The minor status returned by this function. This paramter * will be 0 upon success. * @param context_handle * The security context over which the credential is * delegated. * @param extension_oids * A set of extension oids corresponding to buffers in the * extension_buffers paramter below. May be * GSS_C_NO_BUFFER_SET. Currently not used. * @param extension_buffers * A set of extension buffers corresponding to oids in the * extension_oids paramter above. May be * GSS_C_NO_BUFFER_SET. Currently not used. * @param input_token * The token that was produced by a prior call to * gss_init_delegation. * @param req_flags * Flags that modify the behavior of the function. Currently * only GSS_C_GLOBUS_SSL_COMPATIBLE is checked for. This flag * results in tokens that aren't wrapped. * @param time_req * The requested period of validity (seconds) of the delegated * credential. Currently a noop. * @param time_rec * This parameter will contain the received period of validity * of the delegated credential upon success. May be NULL. * @param delegated_cred_handle * This parameter will contain the delegated credential upon * success. * @param mech_type * Returns the security mechanism upon success. Currently not * implemented. May be NULL. * @param output_token * A token that should be passed to gss_init_delegation if the * return value is GSS_S_CONTINUE_NEEDED. * @return * GSS_S_COMPLETE upon successful completion * GSS_S_CONTINUE_NEEDED if the function needs to be called * again. * GSS_S_FAILURE upon failure */ OM_uint32 GSS_CALLCONV gss_accept_delegation( OM_uint32 * minor_status, const gss_ctx_id_t context_handle, const gss_OID_set extension_oids, const gss_buffer_set_t extension_buffers, const gss_buffer_t input_token, OM_uint32 req_flags, OM_uint32 time_req, OM_uint32 * time_rec, gss_cred_id_t * delegated_cred_handle, gss_OID * mech_type, gss_buffer_t output_token) { BIO * bio = NULL; BIO * read_bio = NULL; BIO * write_bio = NULL; X509 * peer_cert = NULL; const EVP_MD * peer_digest; OM_uint32 major_status = GSS_S_COMPLETE; OM_uint32 local_minor_status; globus_result_t local_result = GLOBUS_SUCCESS; gss_ctx_id_desc * context; globus_gsi_cred_handle_t delegated_cred = NULL; char dbuf[1]; static char * _function_name_ = "gss_accept_delegation"; GLOBUS_I_GSI_GSSAPI_DEBUG_ENTER; /* parameter checking goes here */ if(minor_status == NULL) { major_status = GSS_S_FAILURE; goto exit; } *minor_status = (OM_uint32) GLOBUS_SUCCESS; if(context_handle == GSS_C_NO_CONTEXT) { GLOBUS_GSI_GSSAPI_ERROR_RESULT( minor_status, GLOBUS_GSI_GSSAPI_ERROR_BAD_ARGUMENT, (_GGSL("Invalid context_handle passed to function"))); major_status = GSS_S_FAILURE; goto exit; } context = (gss_ctx_id_desc *) context_handle; if(delegated_cred_handle == NULL) { GLOBUS_GSI_GSSAPI_ERROR_RESULT( minor_status, GLOBUS_GSI_GSSAPI_ERROR_BAD_ARGUMENT, (_GGSL("Invalid delegated_cred_handle passed to function"))); major_status = GSS_S_FAILURE; goto exit; } if(extension_oids != GSS_C_NO_OID_SET && (extension_buffers == GSS_C_NO_BUFFER_SET || extension_oids->count != extension_buffers->count)) { GLOBUS_GSI_GSSAPI_ERROR_RESULT( minor_status, GLOBUS_GSI_GSSAPI_ERROR_BAD_ARGUMENT, (_GGSL("Invalid restriction parameters passed to function"))); major_status = GSS_S_FAILURE; goto exit; } if(output_token == GSS_C_NO_BUFFER) { GLOBUS_GSI_GSSAPI_ERROR_RESULT( minor_status, GLOBUS_GSI_GSSAPI_ERROR_BAD_ARGUMENT, (_GGSL("Invalid output token passed to function"))); major_status = GSS_S_FAILURE; goto exit; } output_token->length = 0; if(input_token == GSS_C_NO_BUFFER) { major_status |= GSS_S_CONTINUE_NEEDED; goto exit; } if(req_flags & GSS_C_GLOBUS_SSL_COMPATIBLE) { bio = BIO_new(BIO_s_mem()); read_bio = bio; write_bio = bio; } else { bio = context->gss_sslbio; } /* lock the context mutex */ globus_mutex_lock(&context->mutex); major_status = globus_i_gsi_gss_put_token(&local_minor_status, context, read_bio, input_token); if (GSS_ERROR(major_status)) { GLOBUS_GSI_GSSAPI_ERROR_CHAIN_RESULT( minor_status, local_minor_status, GLOBUS_GSI_GSSAPI_ERROR_TOKEN_FAIL); goto mutex_unlock; } switch(context->delegation_state) { case GSS_DELEGATION_START: /* generate the proxy */ BIO_read(bio, dbuf, 1); GLOBUS_I_GSI_GSSAPI_DEBUG_FPRINTF( 2, (globus_i_gsi_gssapi_debug_fstream, "delegation flag: %.1s\n", dbuf)); if (dbuf[0] == 'D') { globus_gsi_proxy_handle_attrs_t proxy_handle_attrs; int key_bits; /* * The delegated credential always generated 512 bit keys * irrespective of the key strength of the peer credential (bug * 3794). Fix for that is added below. */ local_result = globus_gsi_cred_get_key_bits( context->peer_cred_handle->cred_handle, &key_bits); if(local_result != GLOBUS_SUCCESS) { GLOBUS_GSI_GSSAPI_ERROR_CHAIN_RESULT( minor_status, local_result, GLOBUS_GSI_GSSAPI_ERROR_WITH_DELEGATION); major_status = GSS_S_FAILURE; goto mutex_unlock; } local_result = globus_gsi_proxy_handle_attrs_init( &proxy_handle_attrs); if(local_result != GLOBUS_SUCCESS) { GLOBUS_GSI_GSSAPI_ERROR_CHAIN_RESULT( minor_status, local_result, GLOBUS_GSI_GSSAPI_ERROR_WITH_DELEGATION); major_status = GSS_S_FAILURE; goto mutex_unlock; } local_result = globus_gsi_proxy_handle_attrs_set_keybits( proxy_handle_attrs, key_bits); if(local_result != GLOBUS_SUCCESS) { globus_gsi_proxy_handle_attrs_destroy(proxy_handle_attrs); GLOBUS_GSI_GSSAPI_ERROR_CHAIN_RESULT( minor_status, local_result, GLOBUS_GSI_GSSAPI_ERROR_WITH_DELEGATION); major_status = GSS_S_FAILURE; goto mutex_unlock; } local_result = globus_gsi_cred_get_cert( context->peer_cred_handle->cred_handle, &peer_cert); if (local_result != GLOBUS_SUCCESS) { globus_gsi_proxy_handle_attrs_destroy(proxy_handle_attrs); GLOBUS_GSI_GSSAPI_ERROR_CHAIN_RESULT( minor_status, local_result, GLOBUS_GSI_GSSAPI_ERROR_WITH_DELEGATION); major_status = GSS_S_FAILURE; goto mutex_unlock; } peer_digest = EVP_get_digestbynid( OBJ_obj2nid(peer_cert->sig_alg->algorithm)); local_result = globus_gsi_proxy_handle_attrs_set_signing_algorithm( proxy_handle_attrs, (EVP_MD *) peer_digest); if (local_result != GLOBUS_SUCCESS) { globus_gsi_proxy_handle_attrs_destroy(proxy_handle_attrs); GLOBUS_GSI_GSSAPI_ERROR_CHAIN_RESULT( minor_status, local_result, GLOBUS_GSI_GSSAPI_ERROR_WITH_DELEGATION); major_status = GSS_S_FAILURE; goto mutex_unlock; } if(context->proxy_handle) { globus_gsi_proxy_handle_destroy(context->proxy_handle); } local_result = globus_gsi_proxy_handle_init( &context->proxy_handle, proxy_handle_attrs); if(local_result != GLOBUS_SUCCESS) { globus_gsi_proxy_handle_attrs_destroy(proxy_handle_attrs); GLOBUS_GSI_GSSAPI_ERROR_CHAIN_RESULT( minor_status, local_result, GLOBUS_GSI_GSSAPI_ERROR_WITH_DELEGATION); major_status = GSS_S_FAILURE; goto mutex_unlock; } local_result = globus_gsi_proxy_handle_attrs_destroy( proxy_handle_attrs); if(local_result != GLOBUS_SUCCESS) { GLOBUS_GSI_GSSAPI_ERROR_CHAIN_RESULT( minor_status, local_result, GLOBUS_GSI_GSSAPI_ERROR_WITH_DELEGATION); major_status = GSS_S_FAILURE; goto mutex_unlock; } local_result = globus_gsi_proxy_create_req(context->proxy_handle, bio); if(local_result != GLOBUS_SUCCESS) { GLOBUS_GSI_GSSAPI_ERROR_CHAIN_RESULT( minor_status, local_result, GLOBUS_GSI_GSSAPI_ERROR_WITH_DELEGATION); major_status = GSS_S_FAILURE; goto mutex_unlock; } context->delegation_state = GSS_DELEGATION_COMPLETE_CRED; } else { GLOBUS_GSI_GSSAPI_ERROR_RESULT( minor_status, GLOBUS_GSI_GSSAPI_ERROR_WITH_DELEGATION, (_GGSL("Invalid initial hello message, expecting: 'D', " "received: '%c'"), dbuf[0])); major_status = GSS_S_FAILURE; goto mutex_unlock; } break; case GSS_DELEGATION_COMPLETE_CRED: /* get the signed cert and the key chain and insert them into * the cred structure */ local_result = globus_gsi_proxy_assemble_cred( context->proxy_handle, &delegated_cred, bio); if(local_result != GLOBUS_SUCCESS) { GLOBUS_GSI_GSSAPI_ERROR_CHAIN_RESULT( minor_status, local_result, GLOBUS_GSI_GSSAPI_ERROR_WITH_GSI_PROXY); major_status = GSS_S_FAILURE; goto mutex_unlock; } major_status = globus_i_gsi_gss_create_cred(&local_minor_status, GSS_C_BOTH, delegated_cred_handle, &delegated_cred); if(GSS_ERROR(major_status)) { globus_gsi_cred_handle_destroy(delegated_cred); GLOBUS_GSI_GSSAPI_ERROR_CHAIN_RESULT( minor_status, local_minor_status, GLOBUS_GSI_GSSAPI_ERROR_WITH_GSI_CREDENTIAL); goto mutex_unlock; } /* reset state machine */ context->delegation_state = GSS_DELEGATION_START; if (time_rec != NULL) { time_t lifetime; local_result = globus_gsi_cred_get_lifetime( ((gss_cred_id_desc *)(*delegated_cred_handle))->cred_handle, &lifetime); if(local_result != GLOBUS_SUCCESS) { GLOBUS_GSI_GSSAPI_ERROR_CHAIN_RESULT( minor_status, local_result, GLOBUS_GSI_GSSAPI_ERROR_WITH_GSI_CREDENTIAL); major_status = GSS_S_FAILURE; goto mutex_unlock; } *time_rec = (OM_uint32) lifetime; } case GSS_DELEGATION_SIGN_CERT: case GSS_DELEGATION_DONE: break; } /* returns empty token when there is no output */ major_status = globus_i_gsi_gss_get_token(&local_minor_status, context, write_bio, output_token); if(GSS_ERROR(major_status)) { GLOBUS_GSI_GSSAPI_ERROR_CHAIN_RESULT( minor_status, local_minor_status, GLOBUS_GSI_GSSAPI_ERROR_TOKEN_FAIL); goto mutex_unlock; } if (context->delegation_state != GSS_DELEGATION_START) { major_status |= GSS_S_CONTINUE_NEEDED; } mutex_unlock: if (peer_cert) { X509_free(peer_cert); } globus_mutex_unlock(&context->mutex); exit: if(req_flags & GSS_C_GLOBUS_SSL_COMPATIBLE) { BIO_free(bio); } GLOBUS_I_GSI_GSSAPI_DEBUG_EXIT; return major_status; }