/** * @brief Wrap * @ingroup globus_gsi_gss_assist * * @param minor_status * GSSAPI return code. If the call was successful, the minor * status is equal to GLOBUS_SUCCESS. Otherwise, it is an * error object ID for which * globus_error_get() and globus_object_free() * can be used to get and destroy it. * @param context_handle * the context. * @param data * pointer to application data to wrap and send * @param length * length of the @a data array * @param token_status * assist routine get/send token status * @param gss_assist_send_token * a send_token routine * @param gss_assist_send_context * first arg for the send_token * @param fperr * file handle to write error message to. * * @return * GSS_S_COMPLETE on success * Other GSSAPI errors on failure. * * @see gss_wrap() */ OM_uint32 globus_gss_assist_wrap_send( OM_uint32 * minor_status, const gss_ctx_id_t context_handle, char * data, size_t length, int * token_status, int (*gss_assist_send_token)(void *, void *, size_t), void * gss_assist_send_context, FILE * fperr) { OM_uint32 major_status = GSS_S_COMPLETE; OM_uint32 local_minor_status; globus_result_t local_result = GLOBUS_SUCCESS; gss_buffer_desc input_token_desc = GSS_C_EMPTY_BUFFER; gss_buffer_t input_token = &input_token_desc; gss_buffer_desc output_token_desc = GSS_C_EMPTY_BUFFER; gss_buffer_t output_token = &output_token_desc; static char * _function_name_ = "globus_gss_assist_wrap_send"; GLOBUS_I_GSI_GSS_ASSIST_DEBUG_ENTER; *token_status = 0; input_token->value = data; input_token->length = length; major_status = gss_wrap(&local_minor_status, context_handle, 0, GSS_C_QOP_DEFAULT, input_token, NULL, output_token); GLOBUS_I_GSI_GSS_ASSIST_DEBUG_FPRINTF( 3, (globus_i_gsi_gss_assist_debug_fstream, _GASL("Wrap_send:maj:%8.8x min:%8.8x inlen:%u outlen:%u\n"), (unsigned int) major_status, (unsigned int) *minor_status, input_token->length = length, output_token->length)); if (major_status != GSS_S_COMPLETE) { globus_object_t * error_obj; globus_object_t * error_copy; error_obj = globus_error_get((globus_result_t) local_minor_status); error_copy = globus_object_copy(error_obj); local_minor_status = (OM_uint32) globus_error_put(error_obj); if(fperr) { globus_gss_assist_display_status( stderr, _GASL("gss_assist_wrap_send failure:"), major_status, local_minor_status, *token_status); } local_result = globus_error_put(error_copy); GLOBUS_GSI_GSS_ASSIST_ERROR_CHAIN_RESULT( local_result, GLOBUS_GSI_GSS_ASSIST_ERROR_WITH_WRAP); *minor_status = (OM_uint32) local_result; goto release_output_token; } *token_status = (*gss_assist_send_token)(gss_assist_send_context, output_token->value, output_token->length); if(*token_status != 0) { GLOBUS_GSI_GSS_ASSIST_ERROR_RESULT( local_result, GLOBUS_GSI_GSS_ASSIST_ERROR_WITH_WRAP, (_GASL("Error sending output token. token status: %d\n"), *token_status)); *minor_status = (OM_uint32) local_result; major_status = GSS_S_FAILURE; goto release_output_token; } major_status = gss_release_buffer(& local_minor_status, output_token); if(GSS_ERROR(major_status)) { GLOBUS_GSI_GSS_ASSIST_ERROR_CHAIN_RESULT( local_result, GLOBUS_GSI_GSS_ASSIST_ERROR_WITH_WRAP); *minor_status = (OM_uint32) local_result; } goto exit; release_output_token: gss_release_buffer(&local_minor_status, output_token); exit: GLOBUS_I_GSI_GSS_ASSIST_DEBUG_EXIT; return major_status; }
/** * @ingroup globus_gss_assist_context * This is a asynchronous version of the * globus_gss_assist_init_sec_context() function. Instead of looping * itself it passes in and out the read and written buffers and * the calling application is responsible for doing the I/O directly. * * @param minor_status * GSSAPI return code. The new minor status is a globus_result_t * cast to a OM_uint32. If an error occurred (GSS_ERROR(major_status)) * the minor_status is a globus error object id. The error object * can be obtained via globus_error_get and should be destroyed * with globus_object_free when no longer needed. If no error * occurred, the minor status is equal to GLOBUS_SUCCESS. * @param cred_handle * the cred handle obtained by acquire_cred. * @param context_handle * pointer to returned context. * @param target_name_char * char string representation of the * server to be contacted. * @param req_flags * request flags, such as GSS_C_DELEG_FLAG for delegation * and the GSS_C_MUTUAL_FLAG for mutual authentication. * @param ret_flags * Pointer to which services are available after * the connection is established. Maybe NULL if not wanted. * @param input_buffer * pointer to a buffer received from peer. Should * be NULL on first call. * @param input_buffer_len * length of the buffer input_buffer. Should * be zero on first call. * @param output_bufferp * pointer to a pointer which will be filled in * with a pointer to a allocated block of memory. If * non-NULL the contents of this block should be written * to the peer where they will be fed into the * gss_assist_init_sec_context_async() function. * @param output_buffer_lenp * pointer to an integer which will be filled * in with the length of the allocated output buffer * pointed to by *output_bufferp. * @return * GSS_S_COMPLETE on successful completion when this function does not * need to be called again. * * GSS_S_CONTINUE_NEEDED when *output_bufferp should be sent to the * peer and a new input_buffer read and this function called again. * * Other gss errors on failure. */ OM_uint32 globus_gss_assist_init_sec_context_async( OM_uint32 * minor_status, const gss_cred_id_t cred_handle, gss_ctx_id_t * context_handle, char * target_name_char, OM_uint32 req_flags, OM_uint32 * ret_flags, void * input_buffer, size_t input_buffer_len, void ** output_bufferp, size_t * output_buffer_lenp) { OM_uint32 major_status = GSS_S_COMPLETE; OM_uint32 minor_status1 = 0; OM_uint32 minor_status2 = 0; gss_buffer_desc input_token_desc = GSS_C_EMPTY_BUFFER; gss_buffer_t input_token = &input_token_desc; gss_buffer_desc output_token_desc = GSS_C_EMPTY_BUFFER; gss_buffer_t output_token = &output_token_desc; gss_name_t target_name = GSS_C_NO_NAME; gss_OID target_name_type = GSS_C_NO_OID; gss_OID mech_type = GSS_C_NO_OID; OM_uint32 time_req = 0; OM_uint32 time_rec = 0; gss_channel_bindings_t input_chan_bindings = GSS_C_NO_CHANNEL_BINDINGS; gss_OID * actual_mech_type = NULL; gss_buffer_desc tmp_buffer_desc = GSS_C_EMPTY_BUFFER; gss_buffer_t tmp_buffer = &tmp_buffer_desc; globus_result_t result = GLOBUS_SUCCESS; static char * _function_name_ = "globus_gss_assist_init_sec_context_async"; GLOBUS_I_GSI_GSS_ASSIST_DEBUG_ENTER; /* Set up our input token from passed buffer */ if ((input_buffer != NULL) && (input_buffer_len != 0)) { input_token_desc.length = input_buffer_len; input_token_desc.value = input_buffer; } /* Do initialization first time through the loop */ /* This will not work if the context handle has been initialized before the first call. Don't know how to fix it since I can't access fields in the handle outside the GSS API. - Sam */ if (*context_handle == GSS_C_NO_CONTEXT) { if(ret_flags) { *ret_flags = 0; } } /* supply the service name to the gss-api * If NULL, then we want user_to_user * so get it from the cred */ if (target_name_char) { if(!strncmp("GSI-NO-TARGET",target_name_char,13)) { target_name = GSS_C_NO_NAME; } else { tmp_buffer->value = target_name_char; tmp_buffer->length = strlen(target_name_char); /* * A gss_nt_service_name is of the form service@FQDN * At least the Globus gssapi, and the Kerberos gssapi * use the same form. We will check for * two special forms here: host@FQDN and ftp@FQDN * This could be another parameter to the gss_assist * instead. */ if (strchr(target_name_char, '@') && !strstr(target_name_char, "CN=")) { target_name_type = gss_nt_service_name; } major_status = gss_import_name(&minor_status1, tmp_buffer, target_name_type, &target_name); } } else { major_status = gss_inquire_cred(&minor_status1, cred_handle, &target_name, NULL, NULL, NULL); } if (major_status == GSS_S_COMPLETE) { GLOBUS_I_GSI_GSS_ASSIST_DEBUG_FPRINTF( 4, (globus_i_gsi_gss_assist_debug_fstream, _GASL("req_flags: %8.8x input_token length: %u\n"), (unsigned int) req_flags, input_token->length)); major_status = gss_init_sec_context(&minor_status1, cred_handle, context_handle, target_name, mech_type, req_flags, time_req, input_chan_bindings, input_token, actual_mech_type, output_token, ret_flags, &time_rec); GLOBUS_I_GSI_GSS_ASSIST_DEBUG_FPRINTF( 4, (globus_i_gsi_gss_assist_debug_fstream, _GASL("major: %8.8x minor: %8.8x ret_flags: %8.8x\n" "output_token length: %u context_handle: %p\n"), (unsigned int) major_status, (unsigned int) minor_status1, (unsigned int) ((ret_flags) ? *ret_flags : -1), output_token->length, *context_handle)); if (output_token->length != 0) { *output_bufferp = output_token->value; *output_buffer_lenp = output_token->length; /* These will now be freed by the caller */ } else { *output_bufferp = NULL; *output_buffer_lenp = 0; } if (GSS_ERROR(major_status)) { if (*context_handle != GSS_C_NO_CONTEXT) gss_delete_sec_context(&minor_status2, context_handle, GSS_C_NO_BUFFER); } } if (target_name != GSS_C_NO_NAME) { gss_release_name(&minor_status2,&target_name); } result = (globus_result_t) minor_status1; if(result != GLOBUS_SUCCESS) { GLOBUS_GSI_GSS_ASSIST_ERROR_CHAIN_RESULT( result, GLOBUS_GSI_GSS_ASSIST_ERROR_WITH_INIT); } *minor_status = (OM_uint32) result; GLOBUS_I_GSI_GSS_ASSIST_DEBUG_EXIT; return major_status; }
/** * @ingroup globus_gss_assist_context * Initialize a GSSAPI security connection. Used by the client. * The context_handle is returned, and there is one for each * connection. This routine will take cake of the looping * and token processing, using the supplied get_token and * send_token routines. * * @param minor_status * GSSAPI return code. The new minor_status is a globus_result_t * cast to an OM_uint32. If the call was successful, the minor * status is equivalent to GLOBUS_SUCCESS. Otherwise, it is a * globus error object ID that can be passed to globus_error_get * to get the error object. The error object needs to be freed * with globus_object_free. * @param cred_handle * the cred handle obtained by acquire_cred. * @param context_handle * pointer to returned context. * @param target_name_char * char string representation of the * server to be contacted. * @param req_flags * request flags, such as GSS_C_DELEG_FLAG for delegation * and the GSS_C_MUTUAL_FLAG for mutual authentication. * @param ret_flags * Pointer to which services are available after * the connection is established. Maybe NULL if not wanted. * * The following are particular to this assist routine: * * @param token_status * the assist routine's get/send token status * @param gss_assist_get_token * function pointer for getting the token * @param gss_assist_get_context * first argument passed to the * gss_assist_get_token function * @param gss_assist_send_token * function pointer for setting the token * @param gss_assist_send_context * first argument passed to the * gss_assist_set_token function pointer * * @return * The major status */ OM_uint32 globus_gss_assist_init_sec_context( OM_uint32 * minor_status, const gss_cred_id_t cred_handle, gss_ctx_id_t * context_handle, char * target_name_char, OM_uint32 req_flags, OM_uint32 * ret_flags, int * token_status, int (*gss_assist_get_token)(void *, void **, size_t *), void * gss_assist_get_context, int (*gss_assist_send_token)(void *, void *, size_t), void * gss_assist_send_context) { int context_established = 0; OM_uint32 major_status = GSS_S_COMPLETE; OM_uint32 minor_status1 = 0; OM_uint32 minor_status2 = 0; gss_buffer_desc input_token_desc = GSS_C_EMPTY_BUFFER; gss_buffer_t input_token = &input_token_desc; gss_buffer_desc output_token_desc = GSS_C_EMPTY_BUFFER; gss_buffer_t output_token = &output_token_desc; gss_name_t target_name = GSS_C_NO_NAME; gss_OID target_name_type = GSS_C_NO_OID; gss_OID mech_type = GSS_C_NO_OID; OM_uint32 time_req = 0; OM_uint32 time_rec = 0; gss_channel_bindings_t input_chan_bindings = GSS_C_NO_CHANNEL_BINDINGS; gss_OID * actual_mech_type = NULL; gss_buffer_desc tmp_buffer_desc = GSS_C_EMPTY_BUFFER; gss_buffer_t tmp_buffer = &tmp_buffer_desc; globus_result_t result = GLOBUS_SUCCESS; static char * _function_name_ = "globus_gss_assist_init_sec_context"; GLOBUS_I_GSI_GSS_ASSIST_DEBUG_ENTER; /* * should not set context_handle to NULL since it may have been * allocated by a call to set_sec_context_option */ /* *context_handle = GSS_C_NO_CONTEXT; */ if(ret_flags) { *ret_flags = 0; } /* supply the service name to the gss-api * If NULL, then we want user_to_user * so get it from the cred */ if (target_name_char) { if(!strncmp("GSI-NO-TARGET", target_name_char, 13)) { target_name = GSS_C_NO_NAME; } else { tmp_buffer->value = target_name_char; tmp_buffer->length = strlen(target_name_char); /* * A gss_nt_service_name is of the form service@FQDN * At least the Globus GSSAPI, and the Kerberos GSSAPI * use the same form. We will check for * two special forms here: host@FQDN and ftp@FQDN * This could be another parameter to the gss_assist * instead. */ if (strchr(target_name_char,'@') && !strstr(target_name_char,"CN=")) { target_name_type = gss_nt_service_name; } major_status = gss_import_name(&minor_status1, tmp_buffer, target_name_type, &target_name); } } else { major_status = gss_inquire_cred(&minor_status1, cred_handle, &target_name, NULL, NULL, NULL); } if (major_status == GSS_S_COMPLETE) { while (!context_established) { GLOBUS_I_GSI_GSS_ASSIST_DEBUG_FPRINTF( 4, (globus_i_gsi_gss_assist_debug_fstream, _GASL("req_flags: %8.8x input_token length: %u\n"), (unsigned int) req_flags, input_token->length)); major_status = gss_init_sec_context(&minor_status1, cred_handle, context_handle, target_name, mech_type, req_flags, time_req, input_chan_bindings, input_token, actual_mech_type, output_token, ret_flags, &time_rec); GLOBUS_I_GSI_GSS_ASSIST_DEBUG_FPRINTF( 4, (globus_i_gsi_gss_assist_debug_fstream, _GASL("major:%8.8x minor:%8.8x ret_flags: %8.8x\n " "output_token length: %u context_handle: %p\n"), (unsigned int) major_status, (unsigned int) minor_status1, (unsigned int) ((ret_flags) ? *ret_flags : -1), output_token->length, *context_handle)); if (input_token->length > 0) { free(input_token->value); input_token->length = 0; } if (output_token->length != 0) { if ((*token_status = gss_assist_send_token( gss_assist_send_context, output_token->value, output_token->length)) != 0) { major_status = GSS_S_DEFECTIVE_TOKEN | GSS_S_CALL_INACCESSIBLE_WRITE; } gss_release_buffer(&minor_status2, output_token); } if (GSS_ERROR(major_status)) { if (*context_handle != GSS_C_NO_CONTEXT) { gss_delete_sec_context(&minor_status2, context_handle, GSS_C_NO_BUFFER); } break; } if (major_status & GSS_S_CONTINUE_NEEDED) { if ((*token_status = gss_assist_get_token( gss_assist_get_context, &input_token->value, &input_token->length)) != 0) { major_status = GSS_S_DEFECTIVE_TOKEN | GSS_S_CALL_INACCESSIBLE_READ; break; } } else { context_established = 1; } } /* end of GSS loop */ } if (input_token->length > 0) { free(input_token->value); /* alloc done by g_get_token */ input_token->value = NULL; input_token->length = 0; } if (target_name != GSS_C_NO_NAME) { gss_release_name(&minor_status2,&target_name); } result = (globus_result_t) minor_status1; if(result != GLOBUS_SUCCESS) { GLOBUS_GSI_GSS_ASSIST_ERROR_CHAIN_RESULT( result, GLOBUS_GSI_GSS_ASSIST_ERROR_WITH_INIT); } *minor_status = (OM_uint32) result; GLOBUS_I_GSI_GSS_ASSIST_DEBUG_EXIT; return major_status; }
/** * @ingroup globus_gsi_gss_assist * Gets a token using the specific tokenizing functions, * and performs the GSS unwrap of that token * * @see gss_unwrap * * @param minor_status * GSSAPI return code, @see gss_unwrap * @param context_handle * the context * @param data * pointer to be set to the unwrapped application data. This must be * freed by the caller. * @param length * pointer to be set to the length of the @a data byte array. * @param token_status * assist routine get/send token status * @param gss_assist_get_token * a detokenizing routine * @param gss_assist_get_context * first arg for above routine * @param fperr * error stream to print to * * @return * GSS_S_COMPLETE on sucess * Other gss errors on failure. */ OM_uint32 globus_gss_assist_get_unwrap( OM_uint32 * minor_status, const gss_ctx_id_t context_handle, char ** data, size_t * length, int * token_status, int (*gss_assist_get_token)(void *, void **, size_t *), void * gss_assist_get_context, FILE * fperr) { OM_uint32 major_status = GSS_S_COMPLETE; OM_uint32 minor_status1 = 0; gss_buffer_desc input_token_desc = GSS_C_EMPTY_BUFFER; gss_buffer_t input_token = &input_token_desc; gss_buffer_desc output_token_desc = GSS_C_EMPTY_BUFFER; gss_buffer_t output_token = &output_token_desc; static char * _function_name_ = "globus_gss_assist_get_unwrap"; GLOBUS_I_GSI_GSS_ASSIST_DEBUG_ENTER; *token_status = (*gss_assist_get_token)(gss_assist_get_context, &input_token->value, &input_token->length); if (*token_status == 0) { major_status = gss_unwrap(minor_status, context_handle, input_token, output_token, NULL, NULL); GLOBUS_I_GSI_GSS_ASSIST_DEBUG_FPRINTF( 3, (globus_i_gsi_gss_assist_debug_fstream, _GASL("unwrap: maj: %8.8x min: %8.8x inlen: %u outlen: %u\n"), (unsigned int) major_status, (unsigned int) *minor_status, input_token->length, output_token->length)); gss_release_buffer(&minor_status1, input_token); *data = output_token->value; *length = output_token->length; } if (fperr && (major_status != GSS_S_COMPLETE || *token_status != 0)) { globus_gss_assist_display_status(stderr, _GASL("gss_assist_get_unwrap failure:"), major_status, *minor_status, *token_status); } *data = output_token->value; *length = output_token->length; if (*token_status) { major_status = GSS_S_FAILURE; } GLOBUS_I_GSI_GSS_ASSIST_DEBUG_EXIT; return major_status; }