/** * @brief Create a empty buffer set. * @ingroup globus_gsi_gssapi_buffer_set * @details * This function allocates and initializes a empty buffer set. The * memory allocated in this function should be freed by a call to * gss_release_buffer_set. * * @param minor_status * The minor status returned by this function. This parameter * will be 0 upon success. * @param buffer_set * Pointer to a buffer set structure. * * @retval GSS_S_COMPLETE Success * @retval GSS_S_FAILURE Failure * * @see gss_add_buffer_set_member * @see gss_release_buffer_set */ OM_uint32 GSS_CALLCONV gss_create_empty_buffer_set( OM_uint32 * minor_status, gss_buffer_set_t * buffer_set) { OM_uint32 major_status = GSS_S_COMPLETE; static char * _function_name_ = "gss_create_empty_buffer_set"; GLOBUS_I_GSI_GSSAPI_DEBUG_ENTER; /* Sanity check */ if ((buffer_set == NULL) || (minor_status == NULL)) { major_status = GSS_S_FAILURE; GLOBUS_GSI_GSSAPI_ERROR_RESULT( minor_status, GLOBUS_GSI_GSSAPI_ERROR_BAD_ARGUMENT, (_GGSL("NULL parameters passed to function: %s"), _function_name_)); goto exit; } *minor_status = GLOBUS_SUCCESS; *buffer_set = (gss_buffer_set_desc *) malloc( sizeof(gss_buffer_set_desc)); if (!*buffer_set) { GLOBUS_GSI_GSSAPI_MALLOC_ERROR(minor_status); major_status = GSS_S_FAILURE; goto exit; } (*buffer_set)->count = 0; (*buffer_set)->elements = NULL; exit: GLOBUS_I_GSI_GSSAPI_DEBUG_EXIT; return GSS_S_COMPLETE; }
/** * * Creates an object identifier set containing no object identifiers, * to which members may be subsequently added * using the GSS_Add_OID_set_member() * routine. These routines are intended to be * used to construct sets of mechanism * object identifiers, for input to GSS_Acquire_cred(). * * @param minor_status * @param oid_set * * @return * GSS_S_COMPLETE indicates successful completion * GSS_S_FAILURE indicates that the operation failed */ OM_uint32 GSS_CALLCONV gss_create_empty_oid_set( OM_uint32 * minor_status, gss_OID_set * oid_set) { OM_uint32 major_status = GSS_S_COMPLETE; static char * _function_name_ = "gss_create_empty_oid_set"; GLOBUS_I_GSI_GSSAPI_DEBUG_ENTER; /* Sanity check */ if ((oid_set == NULL) || (minor_status == NULL)) { major_status = GSS_S_FAILURE; GLOBUS_GSI_GSSAPI_ERROR_RESULT( minor_status, GLOBUS_GSI_GSSAPI_ERROR_BAD_ARGUMENT, (_GGSL("Invalid argument passed to function"))); goto exit; } *minor_status = (OM_uint32) GLOBUS_SUCCESS; *oid_set = (gss_OID_set_desc *) malloc(sizeof(gss_OID_set_desc)); if (!*oid_set) { GLOBUS_GSI_GSSAPI_MALLOC_ERROR(minor_status); major_status = GSS_S_FAILURE; goto exit; } (*oid_set)->count = 0; (*oid_set)->elements = NULL; exit: GLOBUS_I_GSI_GSSAPI_DEBUG_EXIT; return major_status; }
/** * @brief Set Security Context Option * @ingroup globus_gsi_gssapi_extensions * @details * GSSAPI routine to initiate the sending of a security context * See: <draft-ietf-cat-gssv2-cbind-04.txt> * * @param minor_status * @param context_handle * @param option * @param value * * @return */ OM_uint32 GSS_CALLCONV gss_set_sec_context_option( OM_uint32 * minor_status, gss_ctx_id_t * context_handle, const gss_OID option, const gss_buffer_t value) { gss_ctx_id_desc * context = NULL; OM_uint32 major_status = GSS_S_COMPLETE; OM_uint32 local_minor_status; globus_result_t local_result = GLOBUS_SUCCESS; int index; 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 == NULL) { GLOBUS_GSI_GSSAPI_ERROR_RESULT( minor_status, GLOBUS_GSI_GSSAPI_ERROR_BAD_ARGUMENT, (_GGSL("Invalid context_handle passed to function - cannot be NULL"))); major_status = GSS_S_FAILURE; goto exit; } context = *context_handle; if(option == GSS_C_NO_OID) { GLOBUS_GSI_GSSAPI_ERROR_RESULT( minor_status, GLOBUS_GSI_GSSAPI_ERROR_BAD_ARGUMENT, (_GGSL("Invalid option passed to function with value: GSS_C_NO_OID"))); major_status = GSS_S_FAILURE; goto exit; } if (*context_handle == GSS_C_NO_CONTEXT) { /* for now just malloc and zero the context */ context = (gss_ctx_id_desc *) malloc(sizeof(gss_ctx_id_desc)); if (context == NULL) { GLOBUS_GSI_GSSAPI_MALLOC_ERROR(minor_status); major_status = GSS_S_FAILURE; goto exit; } *context_handle = context; memset(context, 0, sizeof(gss_ctx_id_desc)); context->ctx_flags = 0; major_status = gss_create_empty_oid_set( &local_minor_status, (gss_OID_set *) &context->extension_oids); /* initialize the callback_data in the context. This needs * to be done so the verify_callback func can be set later. */ local_result = globus_gsi_callback_data_init( &context->callback_data); if(local_result != GLOBUS_SUCCESS) { GLOBUS_GSI_GSSAPI_ERROR_RESULT( minor_status, GLOBUS_GSI_GSSAPI_ERROR_WITH_GSS_CONTEXT, (_GGSL("The callback data in the context " "could not be initialized."))); major_status = GSS_S_FAILURE; goto exit; } } else if(context->ctx_flags & GSS_I_CTX_INITIALIZED) { GLOBUS_GSI_GSSAPI_ERROR_RESULT( minor_status, GLOBUS_GSI_GSSAPI_ERROR_WITH_GSS_CONTEXT, (_GGSL("The context has already been initialized! %s should be " "called on a context before initialization"), __func__)); major_status = GSS_S_FAILURE; goto exit; } if(g_OID_equal(option, GSS_DISALLOW_ENCRYPTION)) { context->ctx_flags |= GSS_I_DISALLOW_ENCRYPTION; } else if(g_OID_equal(option, GSS_PROTECTION_FAIL_ON_CONTEXT_EXPIRATION)) { context->ctx_flags |= GSS_I_PROTECTION_FAIL_ON_CONTEXT_EXPIRATION; } else if(g_OID_equal(option, GSS_APPLICATION_WILL_HANDLE_EXTENSIONS)) { if(value == GSS_C_NO_BUFFER) { GLOBUS_GSI_GSSAPI_ERROR_RESULT( minor_status, GLOBUS_GSI_GSSAPI_ERROR_BAD_ARGUMENT, (_GGSL("Invalid buffer passed to function"))); major_status = GSS_S_FAILURE; goto exit; } for(index = 0; index < ((gss_OID_set_desc *) value->value)->count; index++) { major_status = gss_add_oid_set_member( &local_minor_status, (gss_OID) &((gss_OID_set_desc *) value->value)->elements[index], (gss_OID_set *) &context->extension_oids); if(GSS_ERROR(major_status)) { GLOBUS_GSI_GSSAPI_ERROR_CHAIN_RESULT( minor_status, local_minor_status, GLOBUS_GSI_GSSAPI_ERROR_WITH_OID); goto exit; } } local_result = globus_gsi_callback_set_extension_cb( context->callback_data, globus_i_gsi_gss_verify_extensions_callback); if(local_result != GLOBUS_SUCCESS) { GLOBUS_GSI_GSSAPI_ERROR_CHAIN_RESULT( minor_status, local_result, GLOBUS_GSI_GSSAPI_ERROR_WITH_CALLBACK_DATA); major_status = GSS_S_FAILURE; goto exit; } /* if the extension_oids are set, * then we set them in the callback data */ local_result = globus_gsi_callback_set_extension_oids( context->callback_data, (void *) context->extension_oids); if(local_result != GLOBUS_SUCCESS) { GLOBUS_GSI_GSSAPI_ERROR_CHAIN_RESULT( minor_status, local_result, GLOBUS_GSI_GSSAPI_ERROR_WITH_CALLBACK_DATA); major_status = GSS_S_FAILURE; goto exit; } context->ctx_flags |= GSS_I_APPLICATION_WILL_HANDLE_EXTENSIONS; } else { /* unknown option */ GLOBUS_GSI_GSSAPI_ERROR_RESULT( minor_status, GLOBUS_GSI_GSSAPI_ERROR_UNKNOWN_OPTION, (NULL)); major_status = GSS_S_FAILURE; goto exit; } *context_handle = context; exit: GLOBUS_I_GSI_GSSAPI_DEBUG_EXIT; return major_status; }
/** * @brief Export a GSSAPI credential * @ingroup globus_gsi_gssapi_extensions * @details * Saves the credential so it can be checkpointed and * imported by gss_import_cred * * @param minor_status * @param cred_handle * @param desired_mech * Should either be gss_mech_globus_gssapi_openssl or * NULL (in which case gss_mech_globus_gssapi_openssl is * assumed). * @param option_req * @param export_buffer * * @return */ OM_uint32 GSS_CALLCONV gss_export_cred( OM_uint32 * minor_status, const gss_cred_id_t cred_handle, const gss_OID desired_mech, OM_uint32 option_req, gss_buffer_t export_buffer) { OM_uint32 major_status = GLOBUS_SUCCESS; BIO * bp = NULL; gss_cred_id_desc * cred_desc = NULL; globus_result_t local_result; char * proxy_filename = NULL; GLOBUS_I_GSI_GSSAPI_DEBUG_ENTER; cred_desc = (gss_cred_id_desc *) cred_handle; *minor_status = (OM_uint32) GLOBUS_SUCCESS; if (export_buffer == NULL || export_buffer == GSS_C_NO_BUFFER) { major_status = GSS_S_FAILURE; GLOBUS_GSI_GSSAPI_ERROR_RESULT( minor_status, GLOBUS_GSI_GSSAPI_ERROR_BAD_ARGUMENT, (_GGSL("NULL or empty export_buffer parameter passed to function: %s"), __func__)); goto exit; } export_buffer->length = 0; export_buffer->value = NULL; if (cred_handle == NULL) { major_status = GSS_S_FAILURE; GLOBUS_GSI_GSSAPI_ERROR_RESULT( minor_status, GLOBUS_GSI_GSSAPI_ERROR_BAD_ARGUMENT, (_GGSL("NULL or empty export_buffer parameter passed to function: %s"), __func__)); goto exit; } if(desired_mech != NULL && g_OID_equal(desired_mech, (gss_OID) gss_mech_globus_gssapi_openssl)) { major_status = GSS_S_BAD_MECH; GLOBUS_GSI_GSSAPI_ERROR_RESULT( minor_status, GLOBUS_GSI_GSSAPI_ERROR_BAD_MECH, (_GGSL("The desired mechanism of: %s, is not supported by this " "GSS implementation"), desired_mech->elements)); goto exit; } if(option_req == GSS_IMPEXP_OPAQUE_FORM) { /* When option_req is equal to EXPORT_OPAQUE_FORM (0), it exports * an opaque buffer suitable for storage in memory or on * disk or passing to another process, which * can import the buffer with gss_import_cred(). */ bp = BIO_new(BIO_s_mem()); if(bp == NULL) { GLOBUS_GSI_GSSAPI_OPENSSL_ERROR_RESULT( minor_status, GLOBUS_GSI_GSSAPI_ERROR_WITH_OPENSSL, (_GGSL("Couldn't initialize IO bio for exporting credential"))); major_status = GSS_S_FAILURE; goto exit; } local_result = globus_gsi_cred_write(cred_desc->cred_handle, bp); if(local_result != GLOBUS_SUCCESS) { GLOBUS_GSI_GSSAPI_ERROR_CHAIN_RESULT( minor_status, local_result, GLOBUS_GSI_GSSAPI_ERROR_IMPEXP_BIO_SSL); major_status = GSS_S_FAILURE; goto exit; } export_buffer->length = BIO_pending(bp); if (export_buffer->length > 0) { export_buffer->value = (char *) malloc(export_buffer->length); if (export_buffer->value == NULL) { export_buffer->length = 0; GLOBUS_GSI_GSSAPI_MALLOC_ERROR(minor_status); major_status = GSS_S_FAILURE; goto exit; } BIO_read(bp, export_buffer->value, export_buffer->length); } else { export_buffer->value = NULL; } major_status = GSS_S_COMPLETE; } else if(option_req == GSS_IMPEXP_MECH_SPECIFIC) { /* With option_req is equal to EXPORT_MECH_SPECIFIC (1), * it exports a buffer filled with mechanism-specific * information that the calling application can use * to pass the credentials to another process that * is not written to the GSS-API. */ local_result = GLOBUS_GSI_SYSCONFIG_GET_UNIQUE_PROXY_FILENAME(&proxy_filename); if(local_result != GLOBUS_SUCCESS) { proxy_filename = NULL; GLOBUS_GSI_GSSAPI_ERROR_CHAIN_RESULT( minor_status, local_result, GLOBUS_GSI_GSSAPI_ERROR_WITH_GSI_PROXY); major_status = GSS_S_FAILURE; goto exit; } GLOBUS_I_GSI_GSSAPI_DEBUG_FPRINTF( 3, (globus_i_gsi_gssapi_debug_fstream, "Writing exported cred to: %s\n", proxy_filename)); local_result = globus_gsi_cred_write_proxy(cred_desc->cred_handle, proxy_filename); 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 exit; } export_buffer->value = globus_common_create_string( "X509_USER_PROXY=%s", proxy_filename); export_buffer->length = strlen(export_buffer->value)+1; } else { major_status = GSS_S_FAILURE; GLOBUS_GSI_GSSAPI_ERROR_RESULT( minor_status, GLOBUS_GSI_GSSAPI_ERROR_BAD_ARGUMENT, (_GGSL("Unrecognized option_req of: %d"), option_req)); goto exit; } exit: if(proxy_filename != NULL) { free(proxy_filename); } if (bp) { BIO_free(bp); } GLOBUS_I_GSI_GSSAPI_DEBUG_EXIT; return major_status; }
/** * @brief Wrap * @ingroup globus_gsi_gssapi * @details * Wrap a message for integrity and protection. * We do this using the SSLv3 routines, by writing to the * SSL bio, and pulling off the buffer from the back * of the write BIO. But we can't do everything SSL * might want, such as control messages, or segment the messages * here, since we are forced to using the GSSAPI tokens, * and can not communicate directly with our peer. * So there maybe some failures which would work with true * SSL. * * @param minor_status * @param context_handle * @param conf_req_flag * @param qop_req * @param input_message_buffer * @param conf_state * @param output_message_buffer * * @return */ OM_uint32 GSS_CALLCONV gss_wrap( OM_uint32 * minor_status, const gss_ctx_id_t context_handle, int conf_req_flag, gss_qop_t qop_req, const gss_buffer_t input_message_buffer, int * conf_state, gss_buffer_t output_message_buffer) { gss_ctx_id_desc * context = (gss_ctx_id_desc *)context_handle; gss_buffer_desc mic_buf_desc; gss_buffer_t mic_buf = (gss_buffer_desc *) &mic_buf_desc; OM_uint32 major_status = GSS_S_COMPLETE; OM_uint32 local_minor_status; unsigned char * message_value; time_t context_goodtill; static char * _function_name_ = "gss_wrap"; GLOBUS_I_GSI_GSSAPI_DEBUG_ENTER; *minor_status = (OM_uint32) GLOBUS_SUCCESS; if(GLOBUS_I_GSI_GSSAPI_DEBUG(3)) { BIO * debug_bio; fprintf(globus_i_gsi_gssapi_debug_fstream, "input message: length = %u\n" " value = \n", (unsigned) input_message_buffer->length); debug_bio = BIO_new_fp(globus_i_gsi_gssapi_debug_fstream, BIO_NOCLOSE); BIO_dump(debug_bio, input_message_buffer->value, input_message_buffer->length); } output_message_buffer->value = NULL; output_message_buffer->length = 0; GLOBUS_I_GSI_GSSAPI_DEBUG_FPRINTF( 2, (globus_i_gsi_gssapi_debug_fstream, "gss_wrap conf_req_flag=%d qop_req=%d\n", conf_req_flag, (int) qop_req)); if (context_handle == GSS_C_NO_CONTEXT) { major_status = GSS_S_NO_CONTEXT; GLOBUS_GSI_GSSAPI_ERROR_RESULT( minor_status, GLOBUS_GSI_GSSAPI_ERROR_BAD_ARGUMENT, (_GGSL("Invalid context handle passed to function"))); goto exit; } /* lock the context mutex */ globus_mutex_lock(&context->mutex); if(context->ctx_flags & GSS_I_PROTECTION_FAIL_ON_CONTEXT_EXPIRATION) { time_t current_time; current_time = time(NULL); major_status = globus_i_gsi_gss_get_context_goodtill( &local_minor_status, context, &context_goodtill); if(GSS_ERROR(major_status)) { GLOBUS_GSI_GSSAPI_ERROR_CHAIN_RESULT( minor_status, local_minor_status, GLOBUS_GSI_GSSAPI_ERROR_WITH_GSS_CONTEXT); goto unlock_mutex_error; } if(current_time > context_goodtill) { major_status = GSS_S_CONTEXT_EXPIRED; GLOBUS_GSI_GSSAPI_ERROR_RESULT( minor_status, GLOBUS_GSI_GSSAPI_ERROR_EXPIRED_CREDENTIAL, (_GGSL("Expired credential: %s < %s"), ctime(&context_goodtill), ctime(¤t_time))); goto unlock_mutex_error; } } if (conf_req_flag == GSS_INTEGRITY_ONLY && qop_req == GSS_C_QOP_GLOBUS_GSSAPI_OPENSSL_BIG) { /* unlock the context mutex */ globus_mutex_unlock(&context->mutex); major_status = gss_get_mic(&local_minor_status, context_handle, qop_req, input_message_buffer, mic_buf); if (GSS_ERROR(major_status)) { GLOBUS_GSI_GSSAPI_ERROR_CHAIN_RESULT( minor_status, local_minor_status, GLOBUS_GSI_GSSAPI_ERROR_WITH_MIC); goto unlock_mutex_error; } /* lock the context mutex */ globus_mutex_lock(&context->mutex); output_message_buffer->value = (char *) malloc(5 + mic_buf->length + input_message_buffer->length); if (output_message_buffer->value == NULL) { GLOBUS_GSI_GSSAPI_MALLOC_ERROR(minor_status); gss_release_buffer(&local_minor_status, mic_buf); major_status = GSS_S_FAILURE; goto unlock_mutex_error; } output_message_buffer->length = 5 + mic_buf->length + input_message_buffer->length; message_value = output_message_buffer->value; *message_value++ = SSL3_RT_GSSAPI_OPENSSL; *message_value++ = 3; *message_value++ = 0; S2N(mic_buf->length, (char *) message_value); message_value += 2; memcpy(message_value, mic_buf->value, mic_buf->length); message_value = message_value + mic_buf->length; memcpy(message_value, input_message_buffer->value, input_message_buffer->length); if (conf_state) { *conf_state = GSS_INTEGRITY_ONLY; } } else { int rc; rc = SSL_write(context->gss_ssl, input_message_buffer->value, input_message_buffer->length); if (rc != input_message_buffer->length) { /* problem, did not take the whole buffer */ GLOBUS_GSI_GSSAPI_ERROR_RESULT( minor_status, GLOBUS_GSI_GSSAPI_ERROR_WRAP_BIO, (_GGSL("SSL failed wrapping entire message: " "SSL_write wrote %d bytes, should be %d bytes"), rc, input_message_buffer->length)); major_status = GSS_S_FAILURE; goto unlock_mutex_error; } if (conf_state) { if (SSL_CIPHER_get_bits( SSL_get_current_cipher(context->gss_ssl), NULL) == 0) { *conf_state = GSS_INTEGRITY_ONLY; } else { *conf_state = GSS_CONFIDENTIALITY; } } /* get the data from the write BIO */ major_status = globus_i_gsi_gss_get_token(&local_minor_status, context, NULL, output_message_buffer); if(GSS_ERROR(major_status)) { GLOBUS_GSI_GSSAPI_ERROR_CHAIN_RESULT( minor_status, local_minor_status, GLOBUS_GSI_GSSAPI_ERROR_TOKEN_FAIL); goto unlock_mutex_error; } } unlock_mutex_error: globus_mutex_unlock(&context->mutex); exit: GLOBUS_I_GSI_GSSAPI_DEBUG_EXIT; return major_status; }
/** * @brief Inquire Sec Context by OID * @ingroup globus_gsi_gssapi_extensions */ OM_uint32 GSS_CALLCONV gss_inquire_sec_context_by_oid( OM_uint32 * minor_status, const gss_ctx_id_t context_handle, const gss_OID desired_object, gss_buffer_set_t * data_set) { OM_uint32 major_status = GSS_S_COMPLETE; OM_uint32 local_minor_status; gss_ctx_id_desc * context = NULL; int found_index; int chain_index; int cert_count; X509_EXTENSION * extension; X509 * cert = NULL; STACK_OF(X509) * cert_chain = NULL; ASN1_OBJECT * asn1_desired_obj = NULL; ASN1_OCTET_STRING * asn1_oct_string; gss_buffer_desc data_set_buffer = GSS_C_EMPTY_BUFFER; globus_result_t local_result = GLOBUS_SUCCESS; unsigned char * tmp_ptr; static char * _function_name_ = "gss_inquire_sec_context_by_oid"; GLOBUS_I_GSI_GSSAPI_DEBUG_ENTER; /* parameter checking goes here */ if(minor_status == NULL) { GLOBUS_GSI_GSSAPI_ERROR_RESULT( minor_status, GLOBUS_GSI_GSSAPI_ERROR_BAD_ARGUMENT, (_GGSL("Invalid minor_status (NULL) passed to function"))); major_status = GSS_S_FAILURE; goto exit; } 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; } *minor_status = (OM_uint32) GLOBUS_SUCCESS; context = (gss_ctx_id_desc *) context_handle; if(desired_object == GSS_C_NO_OID) { GLOBUS_GSI_GSSAPI_ERROR_RESULT( minor_status, GLOBUS_GSI_GSSAPI_ERROR_BAD_ARGUMENT, (_GGSL("Invalid desired_object passed to function"))); major_status = GSS_S_FAILURE; goto exit; } if(data_set == NULL) { GLOBUS_GSI_GSSAPI_ERROR_RESULT( minor_status, GLOBUS_GSI_GSSAPI_ERROR_BAD_ARGUMENT, (_GGSL("Invalid data_set (NULL) passed to function"))); major_status = GSS_S_FAILURE; goto exit; } *data_set = NULL; /* lock the context mutex */ globus_mutex_lock(&context->mutex); local_result = globus_gsi_callback_get_cert_depth(context->callback_data, &cert_count); if(local_result != GLOBUS_SUCCESS) { GLOBUS_GSI_GSSAPI_ERROR_CHAIN_RESULT( minor_status, local_result, GLOBUS_GSI_GSSAPI_ERROR_WITH_CALLBACK_DATA); major_status = GSS_S_FAILURE; goto unlock_exit; } if(cert_count == 0) { goto unlock_exit; } major_status = gss_create_empty_buffer_set(&local_minor_status, data_set); if(GSS_ERROR(major_status)) { GLOBUS_GSI_GSSAPI_ERROR_CHAIN_RESULT( minor_status, local_minor_status, GLOBUS_GSI_GSSAPI_ERROR_WITH_BUFFER); goto unlock_exit; } local_result = globus_gsi_callback_get_cert_chain( context->callback_data, &cert_chain); if(local_result != GLOBUS_SUCCESS) { GLOBUS_GSI_GSSAPI_ERROR_CHAIN_RESULT( minor_status, local_result, GLOBUS_GSI_GSSAPI_ERROR_WITH_CALLBACK_DATA); major_status = GSS_S_FAILURE; cert_chain = NULL; goto unlock_exit; } if(((gss_OID_desc *)desired_object)->length != gss_ext_x509_cert_chain_oid->length || memcmp(((gss_OID_desc *)desired_object)->elements, gss_ext_x509_cert_chain_oid->elements, gss_ext_x509_cert_chain_oid->length)) { /* figure out what object was asked for */ asn1_desired_obj = ASN1_OBJECT_new(); if(!asn1_desired_obj) { GLOBUS_GSI_GSSAPI_OPENSSL_ERROR_RESULT( minor_status, GLOBUS_GSI_GSSAPI_ERROR_WITH_OPENSSL, (_GGSL("Couldn't create ASN1 object"))); major_status = GSS_S_FAILURE; goto unlock_exit; } asn1_desired_obj->length = ((gss_OID_desc *)desired_object)->length; asn1_desired_obj->data = ((gss_OID_desc *)desired_object)->elements; found_index = -1; for(chain_index = 0; chain_index < cert_count; chain_index++) { cert = sk_X509_value(cert_chain, chain_index); data_set_buffer.value = NULL; data_set_buffer.length = 0; found_index = X509_get_ext_by_OBJ(cert, asn1_desired_obj, found_index); if(found_index >= 0) { extension = X509_get_ext(cert, found_index); if(!extension) { GLOBUS_GSI_GSSAPI_OPENSSL_ERROR_RESULT( minor_status, GLOBUS_GSI_GSSAPI_ERROR_WITH_OPENSSL, (_GGSL("Couldn't get extension at index %d " "from cert in credential."), found_index)); major_status = GSS_S_FAILURE; goto unlock_exit; } asn1_oct_string = X509_EXTENSION_get_data(extension); if(!asn1_oct_string) { GLOBUS_GSI_GSSAPI_OPENSSL_ERROR_RESULT( minor_status, GLOBUS_GSI_GSSAPI_ERROR_WITH_OPENSSL, (_GGSL("Couldn't get cert extension in the form of an " "ASN1 octet string."))); major_status = GSS_S_FAILURE; goto unlock_exit; } asn1_oct_string = ASN1_OCTET_STRING_dup(asn1_oct_string); if(!asn1_oct_string) { GLOBUS_GSI_GSSAPI_OPENSSL_ERROR_RESULT( minor_status, GLOBUS_GSI_GSSAPI_ERROR_WITH_OPENSSL, (_GGSL("Failed to make copy of extension data"))); major_status = GSS_S_FAILURE; goto unlock_exit; } data_set_buffer.value = asn1_oct_string->data; data_set_buffer.length = asn1_oct_string->length; OPENSSL_free(asn1_oct_string); major_status = gss_add_buffer_set_member( &local_minor_status, &data_set_buffer, data_set); if(GSS_ERROR(major_status)) { GLOBUS_GSI_GSSAPI_ERROR_CHAIN_RESULT( minor_status, local_minor_status, GLOBUS_GSI_GSSAPI_ERROR_WITH_BUFFER); goto unlock_exit; } } } } else { for(chain_index = 0; chain_index < cert_count; chain_index++) { int certlen; cert = sk_X509_value(cert_chain, chain_index); certlen = i2d_X509(cert, NULL); data_set_buffer.length = certlen; if (certlen < 0) { GLOBUS_GSI_GSSAPI_OPENSSL_ERROR_RESULT( minor_status, GLOBUS_GSI_GSSAPI_ERROR_WITH_OPENSSL, (_GGSL("Failed to serialize certificate"))); major_status = GSS_S_FAILURE; goto unlock_exit; } tmp_ptr = realloc(data_set_buffer.value, data_set_buffer.length); if(tmp_ptr == NULL) { GLOBUS_GSI_GSSAPI_MALLOC_ERROR(minor_status); major_status = GSS_S_FAILURE; goto unlock_exit; } data_set_buffer.value = tmp_ptr; if(i2d_X509(cert,&tmp_ptr) < 0) { free(data_set_buffer.value); GLOBUS_GSI_GSSAPI_OPENSSL_ERROR_RESULT( minor_status, GLOBUS_GSI_GSSAPI_ERROR_WITH_OPENSSL, (_GGSL("Failed to serialize certificate"))); major_status = GSS_S_FAILURE; goto unlock_exit; } major_status = gss_add_buffer_set_member( &local_minor_status, &data_set_buffer, data_set); if(GSS_ERROR(major_status)) { GLOBUS_GSI_GSSAPI_ERROR_CHAIN_RESULT( minor_status, local_minor_status, GLOBUS_GSI_GSSAPI_ERROR_WITH_BUFFER); goto unlock_exit; } } if(data_set_buffer.value != NULL) { free(data_set_buffer.value); } } unlock_exit: /* unlock the context mutex */ globus_mutex_unlock(&context->mutex); exit: if (asn1_desired_obj != NULL) { ASN1_OBJECT_free(asn1_desired_obj); } if(cert_chain != NULL) { sk_X509_pop_free(cert_chain, X509_free); } GLOBUS_I_GSI_GSSAPI_DEBUG_EXIT; return major_status; }
OM_uint32 GSS_CALLCONV gss_add_oid_set_member( OM_uint32 * minor_status, const gss_OID member_oid, gss_OID_set * oid_set) { int new_count; gss_OID new_elements; gss_OID_set set = NULL; OM_uint32 major_status = GSS_S_COMPLETE; static char * _function_name_ = "gss_add_oid_set_member"; GLOBUS_I_GSI_GSSAPI_DEBUG_ENTER; /* Sanity check */ if ((minor_status == NULL) || (member_oid == NULL) || (oid_set == NULL)) { major_status = GSS_S_FAILURE; GLOBUS_GSI_GSSAPI_ERROR_RESULT( minor_status, GLOBUS_GSI_GSSAPI_ERROR_BAD_ARGUMENT, (_GGSL("Invalid argument passed to function"))); goto exit; } *minor_status = (OM_uint32) GLOBUS_SUCCESS; set = *oid_set; new_count = set->count + 1; new_elements = malloc(sizeof(gss_OID_desc) * new_count); if (new_elements == NULL) { GLOBUS_GSI_GSSAPI_MALLOC_ERROR(minor_status); major_status = GSS_S_FAILURE; goto free_set_exit; } if (set->count > 0) { /* Copy existing oids */ memcpy(new_elements, set->elements, sizeof(gss_OID_desc) * set->count); } /* And append new oid */ memcpy(&new_elements[set->count], member_oid, sizeof(gss_OID_desc)); free_set_exit: if (set->elements) { free(set->elements); } set->count = new_count; set->elements = new_elements; exit: GLOBUS_I_GSI_GSSAPI_DEBUG_EXIT; return major_status; }
/** * @brief Add a buffer to a buffer set * @ingroup globus_gsi_gssapi_buffer_set * @details * This function allocates a new gss_buffer_t, initializes it with the * values in the member_buffer parameter. * * * @param minor_status * The minor status returned by this function. This parameter * will be 0 upon success. * @param member_buffer * Buffer to insert into the buffer set. * @param buffer_set * Pointer to a initialized buffer set structure. * * @retval GSS_S_COMPLETE Success * @retval GSS_S_FAILURE Failure * * @see gss_create_empty_buffer_set * @see gss_release_buffer_set */ OM_uint32 GSS_CALLCONV gss_add_buffer_set_member( OM_uint32 * minor_status, const gss_buffer_t member_buffer, gss_buffer_set_t * buffer_set) { int new_count; gss_buffer_t new_elements; gss_buffer_set_t set; OM_uint32 major_status = GSS_S_COMPLETE; static char * _function_name_ = "gss_add_buffer_set_member"; GLOBUS_I_GSI_GSSAPI_DEBUG_ENTER; /* Sanity check */ if ((minor_status == NULL) || (member_buffer == NULL) || (buffer_set == NULL) || (*buffer_set == GSS_C_NO_BUFFER_SET)) { major_status = GSS_S_FAILURE; GLOBUS_GSI_GSSAPI_ERROR_RESULT( minor_status, GLOBUS_GSI_GSSAPI_ERROR_BAD_ARGUMENT, (_GGSL("Invalid buffer_set passed to function"))); goto exit; } set = *buffer_set; new_count = set->count + 1; new_elements = malloc(sizeof(gss_buffer_desc) * new_count); if (new_elements == NULL) { GLOBUS_GSI_GSSAPI_MALLOC_ERROR(minor_status); major_status = GSS_S_FAILURE; goto exit; } if (set->count > 0) { /* Copy existing buffers */ memcpy(new_elements, set->elements, sizeof(gss_buffer_desc) * set->count); } /* And append new buffer */ new_elements[set->count].value = malloc(member_buffer->length); if(new_elements[set->count].value == NULL) { free(new_elements); GLOBUS_GSI_GSSAPI_MALLOC_ERROR(minor_status); major_status = GSS_S_FAILURE; goto exit; } memcpy(new_elements[set->count].value, member_buffer->value, member_buffer->length); new_elements[set->count].length = member_buffer->length; set->count = new_count; free(set->elements); set->elements = new_elements; exit: GLOBUS_I_GSI_GSSAPI_DEBUG_EXIT; return major_status; }