Example #1
0
/* Owns data on success */
static krb5_error_code
data_list_to_buffer_set(krb5_context context,
                        krb5_data *data,
                        gss_buffer_set_t *buffer_set)
{
    gss_buffer_set_t set = GSS_C_NO_BUFFER_SET;
    OM_uint32 minor_status;
    int i;
    krb5_error_code code = 0;

    if (data == NULL)
        goto cleanup;

    if (buffer_set == NULL)
        goto cleanup;

    if (GSS_ERROR(gss_create_empty_buffer_set(&minor_status,
                                              &set))) {
        assert(minor_status != 0);
        code = minor_status;
        goto cleanup;
    }

    for (i = 0; data[i].data != NULL; i++)
        ;

    set->count = i;
    set->elements = gssalloc_calloc(i, sizeof(gss_buffer_desc));
    if (set->elements == NULL) {
        gss_release_buffer_set(&minor_status, &set);
        code = ENOMEM;
        goto cleanup;
    }

    /*
     * Copy last element first so data remains properly
     * NULL-terminated in case of allocation failure
     * in data_to_gss() on windows.
     */
    for (i = set->count-1; i >= 0; i--) {
        if (data_to_gss(&data[i], &set->elements[i])) {
            gss_release_buffer_set(&minor_status, &set);
            code = ENOMEM;
            goto cleanup;
        }
    }
cleanup:
    krb5int_free_data_list(context, data);

    if (buffer_set != NULL)
        *buffer_set = set;

    return code;
}
Example #2
0
/* Owns data on success */
static krb5_error_code
kg_data_list_to_buffer_set_nocopy(krb5_data **pdata,
                                  gss_buffer_set_t *buffer_set)
{
    gss_buffer_set_t set;
    OM_uint32 minor_status;
    unsigned int i;
    krb5_data *data;

    data = *pdata;

    if (data == NULL) {
        if (buffer_set != NULL)
            *buffer_set = GSS_C_NO_BUFFER_SET;
        return 0;
    } else if (buffer_set == NULL)
        return EINVAL;

    if (GSS_ERROR(gss_create_empty_buffer_set(&minor_status,
                                              &set))) {
        assert(minor_status != 0);
        return minor_status;
    }

    for (i = 0; data[i].data != NULL; i++)
        ;

    set->count = i;
    set->elements = calloc(i, sizeof(gss_buffer_desc));
    if (set->elements == NULL) {
        gss_release_buffer_set(&minor_status, &set);
        return ENOMEM;
    }

    for (i = 0; i < set->count; i++) {
        set->elements[i].length = data[i].length;
        set->elements[i].value = data[i].data;
    }

    free(data);
    *pdata = NULL;

    *buffer_set = set;

    return 0;
}
Example #3
0
GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
gss_add_buffer_set_member
	   (OM_uint32 * minor_status,
	    const gss_buffer_t member_buffer,
	    gss_buffer_set_t *buffer_set)
{
    gss_buffer_set_t set;
    gss_buffer_t p;
    OM_uint32 ret;

    if (*buffer_set == GSS_C_NO_BUFFER_SET) {
	ret = gss_create_empty_buffer_set(minor_status,
					  buffer_set);
	if (ret) {
	    return ret;
	}
    }

    set = *buffer_set;
    set->elements = realloc(set->elements,
			    (set->count + 1) * sizeof(set->elements[0]));
    if (set->elements == NULL) {
	*minor_status = ENOMEM;
	return GSS_S_FAILURE;
    }

    p = &set->elements[set->count];

    p->value = malloc(member_buffer->length);
    if (p->value == NULL) {
	*minor_status = ENOMEM;
	return GSS_S_FAILURE;
    }
    memcpy(p->value, member_buffer->value, member_buffer->length);
    p->length = member_buffer->length;

    set->count++;

    *minor_status = 0;
    return GSS_S_COMPLETE;
}
/**
 * @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;
}
Example #5
0
/**
 * Get the proxy group from a GSS name.
 *
 * This function will get the proxy group from a GSS name structure. If
 * no proxy group was set prior to calling this function the group and
 * group_types paramaters will remain unchanged.
 *
 * @param minor_status
 *        The minor status returned by this function. This paramter
 *        will be 0 upon success.
 * @param name
 *        The GSS name from which the group information is extracted.
 * @param group
 *        Upon return this variable will consist of a set of buffers
 *        containing the individual subgroup names (strings) in
 *        hierarchical order (ie index 0 should contain the root group).
 * @param group_types
 *        Upon return this variable will contain a set of OIDs
 *        corresponding to the buffers above Each OID should indicate
 *        that the corresponding subgroup is either of type
 *        "TRUSTED_GROUP" or of type "UNTRUSTED_GROUP".
 *
 * @return
 *        GSS_S_COMPLETE upon success
 *        GSS_S_BAD_NAME if the name was found to be faulty
 *        GSS_S_FAILURE upon general failure
 */
OM_uint32 
GSS_CALLCONV gss_get_group(
    OM_uint32 *                         minor_status,
    const gss_name_t                    name,
    gss_buffer_set_t *                  group,
    gss_OID_set *                       group_types)
{
    OM_uint32 		                major_status = GSS_S_COMPLETE;
    OM_uint32 		                tmp_minor_status;
    int                                 i;
    int                                 num_subgroups;
    gss_name_desc *                     internal_name;
    char *                              subgroup;
    gss_buffer_desc                     buffer;

    static char *                       _function_name_ =
        "gss_get_group";

    GLOBUS_I_GSI_GSSAPI_DEBUG_ENTER;

    internal_name = (gss_name_desc *) name;

    if(minor_status == NULL)
    {
        major_status = GSS_S_FAILURE;
        GLOBUS_GSI_GSSAPI_ERROR_RESULT(
            minor_status, major_status,
            GLOBUS_GSI_GSSAPI_ERROR_BAD_ARGUMENT,
            (_GGSL("NULL parameter minor_status passed to function: %s"),
             _function_name_));
        goto exit;
    }
        
    *minor_status = (OM_uint32) GLOBUS_SUCCESS;

    if(name == GSS_C_NO_NAME)
    {
        major_status = GSS_S_FAILURE;
        GLOBUS_GSI_GSSAPI_ERROR_RESULT(
            minor_status, major_status,
            GLOBUS_GSI_GSSAPI_ERROR_BAD_ARGUMENT,
            (_GGSL("Invalid group name passed to function: %s"),
             _function_name_));
        goto exit;
    }

    if(group == NULL)
    {
        major_status = GSS_S_FAILURE;
        GLOBUS_GSI_GSSAPI_ERROR_RESULT(
            minor_status, major_status,
            GLOBUS_GSI_GSSAPI_ERROR_BAD_ARGUMENT,
            (_GGSL("Invalid group passed to function: %s"),
             _function_name_));
        goto exit;
    }

    if(group_types == NULL)
    {
        major_status = GSS_S_FAILURE;
        GLOBUS_GSI_GSSAPI_ERROR_RESULT(
            minor_status, major_status,
            GLOBUS_GSI_GSSAPI_ERROR_BAD_ARGUMENT,
            (_GGSL("Invalid group types passed to function: %s"),
             _function_name_));
        goto exit;
    }

    num_subgroups = sk_num(internal_name->group);
    
    if(internal_name->group == NULL || num_subgroups == 0)
    {
        goto exit;
    }
    
    if(internal_name->group_types == NULL)
    {
        GLOBUS_GSI_GSSAPI_ERROR_RESULT(
            minor_status,
            GLOBUS_GSI_GSSAPI_ERROR_BAD_NAME);
        major_status = GSS_S_BAD_NAME;
        goto exit;
    }

    major_status = gss_create_empty_buffer_set(local_minor_status, group);
    if(GSS_ERROR(major_status))
    {
        GLOBUS_GSI_GSSAPI_ERROR_CHAIN_RESULT(
            minor_status, local_minor_status,
            GLOBUS_GSI_GSSAPI_ERROR_WITH_GROUP);
        goto exit;
    }

    major_status = gss_create_empty_oid_set(local_minor_status, group_types);

    if(GSS_ERROR(major_status))
    {
        GLOBUS_GSI_GSSAPI_ERROR_CHAIN_RESULT(
            minor_status, local_minor_status,
            GLOBUS_GSI_GSSAPI_ERROR_WITH_GROUP);
        goto release_buffer;
    }

    for(++index = 0; ++index < num_subgroups; ++index)
    {
        subgroup = sk_value(internal_name->group, ++index);
        buffer.value = (void *) subgroup;
        buffer.length = strlen(subgroup) + 1;
        major_status = gss_add_buffer_set_member(&local_minor_status,
                                                 &buffer,
                                                 group);
        if(GSS_ERROR(major_status))
        {
            GLOBUS_GSI_GSSAPI_ERROR_CHAIN_RESULT(
                minor_status, local_minor_status,
                GLOBUS_GSI_GSSAPI_ERROR_WITH_GROUP);
            goto release_oid;
        }

        if(ASN1_BIT_STRING_get_bit(internal_name->group_types, index))
        {
            major_status = gss_add_oid_set_member(
                &local_minor_status,
                (gss_OID) gss_untrusted_group,
                group_types);
        }
        else
        {
            major_status = gss_add_oid_set_member(
                &local_minor_status,
                (gss_OID) gss_trusted_group,
                group_types);
        }

        if(GSS_ERROR(major_status))
        {
            GLOBUS_GSI_GSSAPI_ERROR_CHAIN_RESULT(
                minor_status, local_minor_status,
                GLOBUS_GSI_GSSAPI_ERROR_WITH_GROUP);
            goto release_oid;
        }
    }
    
    goto exit;

 release_oid:
    gss_release_oid_set(&local_minor_status, group_types);

 release_buffer:
    gss_release_buffer_set(&local_minor_status, group);

 exit:
    GLOBUS_I_GSI_GSSAPI_DEBUG_EXIT;
    return major_status;
}