コード例 #1
0
/**
 * @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;
}
コード例 #2
0
ファイル: tg_gateway.c プロジェクト: bbockelm/globus-toolkit
int
globus_i_gram_get_tg_gateway_user(
    gss_ctx_id_t                        context,
    globus_gsi_cred_handle_t            peer_cred,
    char **                             gateway_user)
{
#if HAVE_LIBXML2
    OM_uint32                           maj_stat, min_stat;
    gss_buffer_set_t                    data_set;
    ASN1_UTF8STRING *                   asn1_str;
    char *                              assertion_string;
    unsigned char *                     p;
    long                                pl;
    xmlDocPtr                           doc;
    xmlXPathContextPtr                  xpath_ctx;
    xmlXPathObjectPtr                   xresult;
    int                                 rc;
    ASN1_OBJECT *                       asn1_desired_object = NULL;
    int                                 cert_count;
    int                                 found_index;
    int                                 chain_index;
    X509                               *cert;
    X509_EXTENSION *                    extension;
    ASN1_OCTET_STRING                  *asn1_oct_string;
    STACK_OF(X509)                     *chain = NULL;

    *gateway_user = NULL;

    if (context == GSS_C_NO_CONTEXT && peer_cred != NULL)
    {
        globus_result_t result;
        /* This basically duplicates the gss_inquire_sec_context_by_oid(), but
         * instead uses a gsi credential object
         */
        rc = GLOBUS_SUCCESS;
        asn1_desired_object = ASN1_OBJECT_new();
        if (asn1_desired_object == NULL)
        {
            rc = GLOBUS_GRAM_PROTOCOL_ERROR_MALLOC_FAILED;
            goto no_extension_in_cred_chain;
        }

        asn1_desired_object->length = globus_l_saml_oid_desc.length;
        asn1_desired_object->data = globus_l_saml_oid_desc.elements;

        result = globus_gsi_cred_get_cert_chain(peer_cred, &chain);
        if (result != GLOBUS_SUCCESS)
        {
            char * msg;
            
            msg = globus_error_print_friendly(
                globus_error_peek(result));
            globus_gram_protocol_error_7_hack_replace_message(
                    msg);

            free(msg);
            rc = GLOBUS_GRAM_PROTOCOL_ERROR_AUTHORIZATION;

            goto no_extension_in_cred_chain;
        }

        cert_count = sk_X509_num(chain);
        found_index = -1;
        for (chain_index = 0; chain_index < cert_count; chain_index++)
        {
            cert = sk_X509_value(chain, chain_index);
            found_index = X509_get_ext_by_OBJ(cert, asn1_desired_object, found_index);
            if (found_index >= 0)
            {
                extension = X509_get_ext(cert, found_index);
                if (extension == NULL)
                {
                    rc = GLOBUS_GRAM_PROTOCOL_ERROR_AUTHORIZATION;
                    globus_gram_protocol_error_7_hack_replace_message(
                        "Unable to extract SAML assertion extension from certificate chain");
                    goto no_extension_in_cred_chain;
                }
                asn1_oct_string = X509_EXTENSION_get_data(extension);
                if (asn1_oct_string == NULL)
                {
                    rc = GLOBUS_GRAM_PROTOCOL_ERROR_AUTHORIZATION;
                    globus_gram_protocol_error_7_hack_replace_message(
                        "Unable to extract SAML assertion extension from certificate chain");
                    goto no_extension_in_cred_chain;
                }
                p = asn1_oct_string->data;

                asn1_str = d2i_ASN1_UTF8STRING(NULL, (void *)&p, asn1_oct_string->length);
                if (asn1_str == NULL)
                {
                    rc = GLOBUS_GRAM_PROTOCOL_ERROR_AUTHORIZATION;
                    globus_gram_protocol_error_7_hack_replace_message(
                        "Unable to convert SAML assertion text from DER to UTF8");
                    goto no_extension_in_cred_chain;
                }
                assertion_string = malloc(asn1_str->length + 1);
                if (assertion_string == NULL)
                {
                    rc = GLOBUS_GRAM_PROTOCOL_ERROR_MALLOC_FAILED;
                    goto no_extension_in_cred_chain;
                }
                memcpy(assertion_string, asn1_str->data, asn1_str->length);
                assertion_string[asn1_str->length] = 0;
                break;
            }
        }
        if (chain_index == cert_count)
        {
            goto no_extension_in_cred_chain;
        }
    }
    else if (context == GSS_C_NO_CONTEXT)
    {
        rc = GLOBUS_SUCCESS;
        goto no_context;
    }
    else
    {
        maj_stat =  gss_inquire_sec_context_by_oid(
                &min_stat,
                context,
                globus_saml_oid,
                &data_set);

        if (GSS_ERROR(maj_stat))
        {
            globus_gram_protocol_error_7_hack_replace_message(
                    "Error extracting SAML assertion");

            rc = GLOBUS_GRAM_PROTOCOL_ERROR_AUTHORIZATION;

            goto inquire_failed;
        }

        /* We'll process only the first SAML assertion bound in the X.509 chain */
        if (data_set->count < 1)
        {
            rc = GLOBUS_SUCCESS;

            goto empty_data_set;
        }

        p = data_set->elements[0].value;
        pl = data_set->elements[0].length;

        /* Convert DER-Encoded string to UTF8 */
        asn1_str = d2i_ASN1_UTF8STRING(NULL, (void *) &p, pl);
        if (!asn1_str)
        {
            globus_gram_protocol_error_7_hack_replace_message(
                    "Error decoding SAML assertion");
            rc = GLOBUS_GRAM_PROTOCOL_ERROR_AUTHORIZATION;

            goto utfstring_failed;
        }

        assertion_string = malloc(asn1_str->length + 1);
        if (assertion_string == NULL)
        {
            rc = GLOBUS_GRAM_PROTOCOL_ERROR_MALLOC_FAILED;

            goto assertion_string_malloc_failed;
        }
        memcpy(assertion_string, asn1_str->data, asn1_str->length);
        assertion_string[asn1_str->length] = 0;
    }

    /* Parse SAML assertion */
    doc = xmlParseDoc(BAD_CAST assertion_string);
    if (doc == NULL)
    {
        globus_gram_protocol_error_7_hack_replace_message(
                "Error parsing SAML assertion");
        rc = GLOBUS_GRAM_PROTOCOL_ERROR_AUTHORIZATION;

        goto parse_assertion_failed;
    }

    xmlXPathInit();

    /* Use XPATH to extract Issuer */
    xpath_ctx = xmlXPathNewContext(doc);
    if (xpath_ctx == NULL)
    {
        rc = GLOBUS_GRAM_PROTOCOL_ERROR_MALLOC_FAILED;

        goto xpath_ctx_init_failed;
    }
    rc = xmlXPathRegisterNs(
            xpath_ctx,
            (xmlChar *) "s",
            (xmlChar *) "urn:oasis:names:tc:SAML:1.0:assertion");

    if (rc != 0)
    {
        rc = GLOBUS_GRAM_PROTOCOL_ERROR_MALLOC_FAILED;

        goto xpath_register_ns_failed;
    }

    xresult = xmlXPathEvalExpression(
            (const xmlChar *) "string(/s:Assertion/@Issuer)",
            xpath_ctx);

    if (xresult == NULL)
    {
        globus_gram_protocol_error_7_hack_replace_message(
                "Error processing SAML assertion: no \"Issuer\" attribute");
        rc = GLOBUS_GRAM_PROTOCOL_ERROR_AUTHORIZATION;

        goto xpath_eval_issuer_failed;
    }

    if (! globus_l_tg_saml_assertion_is_self_issued(
                context,
                (const char *) xresult->stringval))
    {
        /* Ignore non-self issued assertions */
        rc = GLOBUS_SUCCESS;

        goto non_self_issued;
    }

    xmlXPathFreeObject(xresult);

    /* Use XPATH to extract the sender-vouches, self-issued, TG principal name
     * Subject attribute from the Assertion's AuthenticationStatement
     */
    xresult = xmlXPathEvalExpression(
            (const xmlChar *) "string(/s:Assertion/s:AuthenticationStatement/s:Subject[string(s:SubjectConfirmation/s:ConfirmationMethod) = 'urn:oasis:names:tc:SAML:1.0:cm:sender-vouches' and s:NameIdentifier/@Format = 'http://teragrid.org/names/nameid-format/principalname']/s:NameIdentifier[1])",
            xpath_ctx);

    if (xresult == NULL)
    {
        globus_gram_protocol_error_7_hack_replace_message(
                "Error processing SAML assertion: no teragrid principal");
        rc = GLOBUS_GRAM_PROTOCOL_ERROR_AUTHORIZATION;

        goto get_gateway_name_failed;
    }

    if (xresult != NULL &&
        xresult->stringval != NULL &&
        *(xresult->stringval) != 0)
    {
        *gateway_user = strdup((char *) xresult->stringval);
    }

get_gateway_name_failed:
non_self_issued:
    if (xresult != NULL)
    {
        xmlXPathFreeObject(xresult);
    }
xpath_eval_issuer_failed:
xpath_register_ns_failed:
    xmlXPathFreeContext(xpath_ctx);
xpath_ctx_init_failed:
    xmlFreeDoc(doc);
parse_assertion_failed:
    free(assertion_string);
assertion_string_malloc_failed:
    ASN1_UTF8STRING_free(asn1_str);
utfstring_failed:
empty_data_set:
    gss_release_buffer_set(&min_stat, &data_set);
inquire_failed:
no_extension_in_cred_chain:
no_context:
    if (asn1_desired_object != NULL)
    {
        ASN1_OBJECT_free(asn1_desired_object);
    }
    if (chain != NULL)
    {
        sk_X509_free(chain);
    }
    return rc;
#else
    *gateway_user = NULL;
    return GLOBUS_SUCCESS;
#endif /* HAVE_LIBXML2 */
}