/**
 * Set the public/private key generation callback that provides status
 * during the generation of the keys
 *
 * @param handle_attrs
 *        The handle_attrs to get the callback from
 * @param callback
 *        The callback from the handle attributes
 *
 * @return
 *        GLOBUS_SUCCESS if the handle_attrs is valid, otherwise an error
 *        is returned
 */
globus_result_t
globus_gsi_proxy_handle_attrs_set_key_gen_callback(
    globus_gsi_proxy_handle_attrs_t     handle_attrs,
    void                                (*callback)(int, int, void *))
{
    globus_result_t                     result;
    static char *                       _function_name_ =
        "globus_gsi_proxy_handle_attrs_set_clock_skew_allowable";

    GLOBUS_I_GSI_PROXY_DEBUG_ENTER;

    if(handle_attrs == NULL)
    {
        GLOBUS_GSI_PROXY_ERROR_RESULT(
            result,
            GLOBUS_GSI_PROXY_ERROR_WITH_HANDLE_ATTRS,
            (_PCSL("NULL handle attributes passed to function: %s"),
             _function_name_));
        goto exit;
    }
    handle_attrs->key_gen_callback = callback;
    result = GLOBUS_SUCCESS;

 exit:
    
    GLOBUS_I_GSI_PROXY_DEBUG_EXIT;
    return result;
}
/**
 * Gets the Signing Algorithm to used to sign
 * the certificate request.  In most cases, the
 * signing party will ignore this value, and sign
 * with an algorithm of its choice.
 *
 * @param handle_attrs
 *        The proxy handle_attrs to get the signing algorithm of
 * @param algorithm
 *        Parameter used to return the signing algorithm used
 * @return
 *        Returns 
 *        GLOBUS_SUCCESS if the handle is valid, otherwise
 *        an error object is returned.
 */
globus_result_t
globus_gsi_proxy_handle_attrs_get_signing_algorithm(
    globus_gsi_proxy_handle_attrs_t     handle_attrs,
    EVP_MD **                           algorithm)
{
    globus_result_t                     result;
    static char *                       _function_name_ =
        "globus_gsi_proxy_handle_attrs_get_signing_algorithm";

    GLOBUS_I_GSI_PROXY_DEBUG_ENTER;

    if(handle_attrs == NULL)
    {
        GLOBUS_GSI_PROXY_ERROR_RESULT(
            result,
            GLOBUS_GSI_PROXY_ERROR_WITH_HANDLE_ATTRS,
            (_PCSL("NULL handle attributes passed to function: %s"),
             _function_name_));
        goto exit;
    }

    *algorithm = handle_attrs->signing_algorithm;

    result = GLOBUS_SUCCESS;

 exit:
    
    GLOBUS_I_GSI_PROXY_DEBUG_EXIT;
    return result;
}
/**
 * @ingroup globus_gsi_proxy_handle_attrs
 * Initialize GSI Proxy Handle Attributes.
 *
 * Initialize proxy handle attributes, which
 * can (and should) be associated with a proxy handle.
 * For most purposes, these attributes should primarily
 * be used by the proxy handle. 
 *
 * Currently, no attibute values are initialized.
 *
 * @param handle_attrs
 *        The handle attributes structure to be initialized
 * @return
 *        GLOBUS_SUCCESS unless an error occurred, in which case, 
 *        a globus error object ID is returned
 *
 * @see globus_gsi_proxy_handle_attrs_destroy()
 */
globus_result_t
globus_gsi_proxy_handle_attrs_init(
    globus_gsi_proxy_handle_attrs_t *   handle_attrs)
{
    globus_result_t                     result;
    globus_gsi_proxy_handle_attrs_t     attrs;
    int                                 len;
    static char *                       _function_name_ =
        "globus_gsi_proxy_handle_attrs_init";

    GLOBUS_I_GSI_PROXY_DEBUG_ENTER;

    if(handle_attrs == NULL)
    {
        GLOBUS_GSI_PROXY_ERROR_RESULT(
            result,
            GLOBUS_GSI_PROXY_ERROR_WITH_HANDLE_ATTRS,
            (_PCSL("NULL handle attributes passed to function: %s"), 
             _function_name_));
        goto exit;
    }

    len = sizeof(globus_i_gsi_proxy_handle_attrs_t);
    if((*handle_attrs = (globus_gsi_proxy_handle_attrs_t)
       malloc(len)) == NULL)
    {
        result = GLOBUS_GSI_PROXY_HANDLE_ATTRS_MALLOC_ERROR;
        goto exit;
    }

    attrs = *handle_attrs;

    attrs->key_bits = DEFAULT_KEY_BITS;
    attrs->init_prime = DEFAULT_PUB_EXPONENT;
    attrs->signing_algorithm = DEFAULT_SIGNING_ALGORITHM;
    attrs->clock_skew = DEFAULT_CLOCK_SKEW;
    attrs->key_gen_callback = NULL;
    
    result = GLOBUS_SUCCESS;
   
 exit:

    GLOBUS_I_GSI_PROXY_DEBUG_EXIT;
    return result;
}
globus_result_t
globus_i_gsi_proxy_error_chain_result(
    globus_result_t                     chain_result,
    int                                 error_type,
    const char *                        filename,
    const char *                        function_name,
    int                                 line_number,
    const char *                        short_desc,
    const char *                        long_desc)
{
    globus_result_t                     result;
    globus_object_t *                   error_object;
    
    static char *                       _function_name_ =
        "globus_i_gsi_proxy_error_chain_result";

    GLOBUS_I_GSI_PROXY_DEBUG_ENTER;

    error_object = 
        globus_error_construct_error(
            GLOBUS_GSI_PROXY_MODULE,
            globus_error_get(chain_result),
            error_type,
            filename,
            function_name,
            line_number, 
            "%s%s%s",
            _PCSL(globus_l_gsi_proxy_error_strings[error_type]),
            short_desc ? ": " : "",
            short_desc ? short_desc : "");
        
    if(long_desc)
    {
        globus_error_set_long_desc(error_object, long_desc);
    }

    result = globus_error_put(error_object);

    GLOBUS_I_GSI_PROXY_DEBUG_EXIT;
    return result;
}
/**
 * @ingroup globus_gsi_proxy_handle_attrs
 * Make a copy of GSI Proxy handle attributes
 *
 * @param a 
 *        The handle attributes to copy
 * @param b 
 *        The copy
 * @return
 *        GLOBUS_SUCCESS
 */
globus_result_t
globus_gsi_proxy_handle_attrs_copy(
    globus_gsi_proxy_handle_attrs_t     a,
    globus_gsi_proxy_handle_attrs_t *   b)
{
    globus_result_t                     result;
    static char *                       _function_name_ =
        "globus_gsi_proxy_handle_attrs_copy";
    
    GLOBUS_I_GSI_PROXY_DEBUG_ENTER;

    if(a == NULL)
    {
        GLOBUS_GSI_PROXY_ERROR_RESULT(
            result,
            GLOBUS_GSI_PROXY_ERROR_WITH_HANDLE_ATTRS,
            (_PCSL("NULL handle attributes passed to function: %s"),
             _function_name_));
        goto error_exit;
    }
    if(b == NULL)
    {
        GLOBUS_GSI_PROXY_ERROR_RESULT(
            result,
            GLOBUS_GSI_PROXY_ERROR_WITH_HANDLE_ATTRS,
            (_PCSL("NULL handle attributes passed to function: %s"),
             _function_name_));
        goto error_exit;
    }

    result = globus_gsi_proxy_handle_attrs_init(b);
    if(result != GLOBUS_SUCCESS)
    {
        GLOBUS_GSI_PROXY_ERROR_CHAIN_RESULT(
            result,
            GLOBUS_GSI_PROXY_ERROR_WITH_HANDLE_ATTRS);
        goto destroy_b_exit;
    }

    (*b)->key_bits = a->key_bits;
    (*b)->init_prime = a->init_prime;
    (*b)->signing_algorithm = a->signing_algorithm;
    (*b)->clock_skew = a->clock_skew;
    (*b)->key_gen_callback = a->key_gen_callback;

    result = GLOBUS_SUCCESS;
    goto exit;


destroy_b_exit:
    if(*b)
    {
        globus_gsi_proxy_handle_attrs_destroy(*b);
    }

error_exit:
    if (b)
    {
        *b = NULL;
    }

exit:

    GLOBUS_I_GSI_PROXY_DEBUG_EXIT;
    return result;
}