OpenSSL中文手册之ERR库详解

本文详细介绍了OpenSSL中ERR库的功能,包括错误代码的结构、数据结构ERR_STRING_DATA和ERR_STATE,以及如何获取和处理错误信息。内容涵盖错误代码的计算、错误堆栈、错误信息的加载和清除,强调了错误处理在程序设计中的重要性。

  版权声明本文根据DragonKing牛,E-Mail:wzhah@263.NET发布在https://openssl.126.com的系列文章整理修改而成(这个网站已经不能访问了),我自己所做的工作主要是针对新的1.0.2版本进行验证,修改错别字,和错误,重新排版,以及整理分类,配图。 未经作者允许,严禁用于商业出版,否则追究法律责任。网络转载请注明出处,这是对原创者的起码的尊重!!!


1 概述

  程序设计时,一般通过函数的返回值来判断是否调用成功。设计良好的函数以及好的错误处理能帮助调用者快速找到错误原因。错误处理应该尽可能多的包含各种信息,包括:

  • 错误码;
  • 出错文件以及行号;
  • 错误原因;
  • 出错函数;
  • 出错库;
  • 出错模块与类别信息;
  • 错误堆栈信息等。
  • 出错信息最好能支持多种输出。可以是输出在标准输出上,也可以是文件等形式。

2 相关数据结构

2.1 错误代码

  openssl中,通过unsigned long类型来存放错误信息。它包含三部分内容:库代码、函数代码以及错误原因代码。其中,库代码在openssl/err.h中定义,比如err.h中为库定义如下库代码:

        /* library */
        # define ERR_LIB_NONE            1
        # define ERR_LIB_SYS             2
        # define ERR_LIB_BN              3
        # define ERR_LIB_RSA             4
        # define ERR_LIB_DH              5
        # define ERR_LIB_EVP             6
        # define ERR_LIB_BUF             7
        # define ERR_LIB_OBJ             8
        # define ERR_LIB_PEM             9
        # define ERR_LIB_DSA             10
        # define ERR_LIB_X509            11
        /* #define ERR_LIB_METH         12 */
        # define ERR_LIB_ASN1            13
        # define ERR_LIB_CONF            14
        # define ERR_LIB_CRYPTO          15
        # define ERR_LIB_EC              16
        # define ERR_LIB_SSL             20
        /* #define ERR_LIB_SSL23        21 */
        /* #define ERR_LIB_SSL2         22 */
        /* #define ERR_LIB_SSL3         23 */
        /* #define ERR_LIB_RSAREF       30 */
        /* #define ERR_LIB_PROXY        31 */
        # define ERR_LIB_BIO             32
        # define ERR_LIB_PKCS7           33
        # define ERR_LIB_X509V3          34
        # define ERR_LIB_PKCS12          35
        # define ERR_LIB_RAND            36
        # define ERR_LIB_DSO             37
        # define ERR_LIB_ENGINE          38
        # define ERR_LIB_OCSP            39
        # define ERR_LIB_UI              40
        # define ERR_LIB_COMP            41
        # define ERR_LIB_ECDSA           42
        # define ERR_LIB_ECDH            43
        # define ERR_LIB_STORE           44
        # define ERR_LIB_FIPS            45
        # define ERR_LIB_CMS             46
        # define ERR_LIB_TS              47
        # define ERR_LIB_HMAC            48
        /* # define ERR_LIB_JPAKE       49 */
        # define ERR_LIB_CT              50
        # define ERR_LIB_ASYNC           51
        # define ERR_LIB_KDF             52

        # define ERR_LIB_USER            128

  函数代码以及错误原因代码由各个功能模块定义(同类代码不能与其他的重复,也不能超过一定的大小)。如:openssl/bio.h中定义了如下函数和错误原因代号:

          /* Error codes for the BIO functions. */

          /* Function codes. */
          # define BIO_F_ACPT_STATE                                 100
          # define BIO_F_ADDR_STRINGS                               134
          # define BIO_F_BIO_ACCEPT                                 101
          # define BIO_F_BIO_ACCEPT_EX                              137
          # define BIO_F_BIO_ADDR_NEW                               144
          # define BIO_F_BIO_CALLBACK_CTRL                          131
          # define BIO_F_BIO_CONNECT                                138
          # define BIO_F_BIO_CTRL                                   103
          # define BIO_F_BIO_GETS                                   104
          # define BIO_F_BIO_GET_HOST_IP                            106
          # define BIO_F_BIO_GET_NEW_INDEX                          102
          # define BIO_F_BIO_GET_PORT                               107
          # define BIO_F_BIO_LISTEN                                 139
          # define BIO_F_BIO_LOOKUP                                 135
          # define BIO_F_BIO_MAKE_PAIR                              121
          # define BIO_F_BIO_NEW                                    108
          # define BIO_F_BIO_NEW_FILE                               109
          # define BIO_F_BIO_NEW_MEM_BUF                            126
          # define BIO_F_BIO_NREAD                                  123
          # define BIO_F_BIO_NREAD0                                 124
          # define BIO_F_BIO_NWRITE                                 125
          # define BIO_F_BIO_NWRITE0                                122
          # define BIO_F_BIO_PARSE_HOSTSERV                         136
          # define BIO_F_BIO_PUTS                                   110
          # define BIO_F_BIO_READ                                   111
          # define BIO_F_BIO_SOCKET                                 140
          # define BIO_F_BIO_SOCKET_NBIO                            142
          # define BIO_F_BIO_SOCK_INFO                              141
          # define BIO_F_BIO_SOCK_INIT                              112
          # define BIO_F_BIO_WRITE                                  113
          # define BIO_F_BUFFER_CTRL                                114
          # define BIO_F_CONN_CTRL                                  127
          # define BIO_F_CONN_STATE                                 115
          # define BIO_F_DGRAM_SCTP_READ                            132
          # define BIO_F_DGRAM_SCTP_WRITE                           133
          # define BIO_F_FILE_CTRL                                  116
          # define BIO_F_FILE_READ                                  130
          # define BIO_F_LINEBUFFER_CTRL                            129
          # define BIO_F_MEM_WRITE                                  117
          # define BIO_F_SSL_NEW                                    118

          /* Reason codes. */
          # define BIO_R_ACCEPT_ERROR                               100
          # define BIO_R_ADDRINFO_ADDR_IS_NOT_AF_INET               141
          # define BIO_R_AMBIGUOUS_HOST_OR_SERVICE                  129
          # define BIO_R_BAD_FOPEN_MODE                             101
          # define BIO_R_BROKEN_PIPE                                124
          # define BIO_R_CONNECT_ERROR                              103
          # define BIO_R_GETHOSTBYNAME_ADDR_IS_NOT_AF_INET          107
          # define BIO_R_GETSOCKNAME_ERROR                          132
          # define BIO_R_GETSOCKNAME_TRUNCATED_ADDRESS              133
          # define BIO_R_GETTING_SOCKTYPE                           134
          # define BIO_R_INVALID_ARGUMENT                           125
          # define BIO_R_INVALID_SOCKET                             135
          # define BIO_R_IN_USE                                     123
          # define BIO_R_LISTEN_V6_ONLY                             136
          # define BIO_R_LOOKUP_RETURNED_NOTHING                    142
          # define BIO_R_MALFORMED_HOST_OR_SERVICE                  130
          # define BIO_R_NBIO_CONNECT_ERROR                         110
          # define BIO_R_NO_ACCEPT_ADDR_OR_SERVICE_SPECIFIED        143
          # define BIO_R_NO_HOSTNAME_OR_SERVICE_SPECIFIED           144
          # define BIO_R_NO_PORT_DEFINED                            113
          # define BIO_R_NO_SUCH_FILE                               128
          # define BIO_R_NULL_PARAMETER                             115
          # define BIO_R_UNABLE_TO_BIND_SOCKET                      117
          # define BIO_R_UNABLE_TO_CREATE_SOCKET                    118
          # define BIO_R_UNABLE_TO_KEEPALIVE                        137
          # define BIO_R_UNABLE_TO_LISTEN_SOCKET                    119
          # define BIO_R_UNABLE_TO_NODELAY                          138
          # define BIO_R_UNABLE_TO_REUSEADDR                        139
          # define BIO_R_UNAVAILABLE_IP_FAMILY                      145
          # define BIO_R_UNINITIALIZED                              120
          # define BIO_R_UNKNOWN_INFO_TYPE                          140
          # define BIO_R_UNSUPPORTED_IP_FAMILY                      146
          # define BIO_R_UNSUPPORTED_METHOD                         121
          # define BIO_R_UNSUPPORTED_PROTOCOL_FAMILY                131
          # define BIO_R_WRITE_TO_READ_ONLY_BIO                     126
          # define BIO_R_WSASTARTUP                                 122

  错误代码通过上述三部分通过计算得到,并且根据此信息能提取各个代码。计算函数在err.h中定义如下:

/*由库代码,函数代码,原因代码计算错误代码*/
# define ERR_PACK(l,f,r) ( 
                           (((unsigned int)(l) & 0x0FF) << 24L) |
                           (((unsigned int)(f) & 0xFFF) << 12L) | 
                           (((unsigned int)(r) & 0xFFF)       )    
                         ) 
/*由错误代码计算库代码,函数代码,原因代码*/
# define ERR_GET_LIB(l)          (int)(((l) >> 24L) & 0x0FFL)
# define ERR_GET_FUNC(l)         (int)(((l) >> 12L) & 0xFFFL)
# define ERR_GET_REASON(l)       (int)( (l)         & 0xFFFL)
# define ERR_FATAL_ERROR(l)      (int)( (l)         & ERR_R_FATAL) //致命错误

  可以看出,库的个数不能大于255(0xff),函数个数和错误原因不能大于4095(0xfff)。

2.2 基本数据结构

  主要数据结构有两个,定义在err.h中。

2.2.1 ERR_STRING_DATA

typedef struct ERR_string_data_st
{

    unsigned long error; //错误码
    const char *string;  //string用来存放文本信息,可以是函数名也可以是错误原因。

} ERR_STRING_DATA;

  该数据结构的内容由各个功能模块来设置。其中,error用来存放错误信息(由库代码、函数代码以及错误原因代码计算得来),string用来存放文本信息,可以是函数名也可以是错误原因。以crypto/bio/bio_err.c为例,它定义了两个全局表,分别用来存放函数信息和错误信息:

# define ERR_FUNC(func) ERR_PACK(ERR_LIB_BIO,func,0)
# define ERR_REASON(reason) ERR_PACK(ERR_LIB_BIO,0,reason)

static ERR_STRING_DATA BIO_str_functs[] = 
{
    {ERR_FUNC(BIO_F_ACPT_STATE), "acpt_state"},
    {ERR_FUNC(BIO_F_ADDR_STRINGS), "addr_strings"},
    {ERR_FUNC(BIO_F_BIO_ACCEPT), "BIO_accept"},
    {ERR_FUNC(BIO_F_BIO_ACCEPT_EX), "BIO_accept_ex"},
    {ERR_FUNC(BIO_F_BIO_ADDR_NEW), "BIO_ADDR_new"},
    {ERR_FUNC(BIO_F_BIO_CALLBACK_CTRL), "BIO_callback_ctrl"},
    {ERR_FUNC(BIO_F_BIO_CONNECT), "BIO_connect"},
    {ERR_FUNC(BIO_F_BIO_CTRL), "BIO_ctrl"},
    {ERR_FUNC(BIO_F_BIO_GETS), "BIO_gets"},
    {ERR_FUNC(BIO_F_BIO_GET_HOST_IP), "BIO_get_host_ip"},
    {ERR_FUNC(BIO_F_BIO_GET_NEW_INDEX), "BIO_get_new_index"},
    {ERR_FUNC(BIO_F_BIO_GET_PORT), "BIO_get_port"},
    {ERR_FUNC(BIO_F_BIO_LISTEN), "BIO_listen"},
    {ERR_FUNC(BIO_F_BIO_LOOKUP), "BIO_lookup"},
    {ERR_FUNC(BIO_F_BIO_MAKE_PAIR), "bio_make_pair"},
    {ERR_FUNC(BIO_F_BIO_NEW), "BIO_new"},
    {ERR_FUNC(BIO_F_BIO_NEW_FILE), "BIO_new_file"},
    {ERR_FUNC(BIO_F_BIO_NEW_MEM_BUF), "BIO_new_mem_buf"},
    {ERR_FUNC(BIO_F_BIO_NREAD), "BIO_nread"},
    {ERR_FUNC(BIO_F_BIO_NREAD0), "BIO_nread0"},
    {ERR_FUNC(BIO_F_BIO_NWRITE), "BIO_nwrite"},
    {ERR_FUNC(BIO_F_BIO_NWRITE0), "BIO_nwrite0"},
    {ERR_FUNC(BIO_F_BIO_PARSE_HOSTSERV), "BIO_parse_hostserv"},
    {ERR_FUNC(BIO_F_BIO_PUTS), "BIO_puts"},
    {ERR_FUNC(BIO_F_BIO_READ), "BIO_read"},
    {ERR_FUNC(BIO_F_BIO_SOCKET), "BIO_socket"},
    {ERR_FUNC(BIO_F_BIO_SOCKET_NBIO), "BIO_socket_nbio"},
    {ERR_FUNC(BIO_F_BIO_SOCK_INFO), "BIO_sock_info"},
    {ERR_FUNC(BIO_F_BIO_SOCK_INIT), "BIO_sock_init"},
    {ERR_FUNC(BIO_F_BIO_WRITE), "BIO_write"},
    {ERR_FUNC(BIO_F_BUFFER_CTRL), "buffer_ctrl"},
    {ERR_FUNC(BIO_F_CONN_CTRL), "conn_ctrl"},
    {ERR_FUNC(BIO_F_CONN_STATE), "conn_state"},
    {ERR_FUNC(BIO_F_DGRAM_SCTP_READ), "dgram_sctp_read"},
    {ERR_FUNC(BIO_F_DGRAM_SCTP_WRITE), "dgram_sctp_write"},
    {ERR_FUNC(BIO_F_FILE_CTRL), "file_ctrl"},
    {ERR_FUNC(BIO_F_FILE_READ), "file_read"},
    {ERR_FUNC(BIO_F_LINEBUFFER_CTRL), "linebuffer_ctrl"},
    {ERR_FUNC(BIO_F_MEM_WRITE), "mem_write"},
    {ERR_FUNC(BIO_F_SSL_NEW), "SSL_new"},
    {0, NULL}
};

static ERR_STRING_DATA BIO_str_reasons[] = 
{
    {ERR_REASON(BIO_R_ACCEPT_ERROR), "accept error"},
    {ERR_REASON(BIO_R_ADDRINFO_ADDR_IS_NOT_AF_INET),"addrinfo addr is not af inet"},
    {ERR_REASON(BIO_R_AMBIGUOUS_HOST_OR_SERVICE),"ambiguous host or service"},
    {ERR_REASON(BIO_R_BAD_FOPEN_MODE), "bad fopen mode"},
    {ERR_REASON(BIO_R_BROKEN_PIPE), "broken pipe"},
    {ERR_REASON(BIO_R_CONNECT_ERROR), "connect error"},
    {ERR_REASON(BIO_R_GETHOSTBYNAME_ADDR_IS_NOT_AF_INET),"gethostbyname addr is not af inet"},
    {ERR_REASON(BIO_R_GETSOCKNAME_ERROR), "getsockname error"},
    {ERR_REASON(BIO_R_GETSOCKNAME_TRUNCATED_ADDRESS),"getsockname truncated address"},
    {ERR_REASON(BIO_R_GETTING_SOCKTYPE), "getting socktype"},
    {ERR_REASON(BIO_R_INVALID_ARGUMENT), "invalid argument"},
    {ERR_REASON(BIO_R_INVALID_SOCKET), "invalid socket"},
    {ERR_REASON(BIO_R_IN_USE), "in use"},
    {ERR_REASON(BIO_R_LISTEN_V6_ONLY), "listen v6 only"},
    {ERR_REASON(BIO_R_LOOKUP_RETURNED_NOTHING), "lookup returned nothing"},
    {ERR_REASON(BIO_R_MALFORMED_HOST_OR_SERVICE), "malformed host or service"},
    {ERR_REASON(BIO_R_NBIO_CONNECT_ERROR), "nbio connect error"},
    {ERR_REASON(BIO_R_NO_ACCEPT_ADDR_OR_SERVICE_SPECIFIED),"no accept addr or service specified"},
    {ERR_REASON(BIO_R_NO_HOSTNAME_OR_SERVICE_SPECIFIED), "no hostname or service specified"},
    {ERR_REASON(BIO_R_NO_PORT_DEFINED), "no port defined"},
    {ERR_REASON(BIO_R_NO_SUCH_FILE), "no such file"},
    {ERR_REASON(BIO_R_NULL_PARAMETER), "null parameter"},
    {ERR_REASON(BIO_R_UNABLE_TO_BIND_SOCKET), "unable to bind socket"},
    {ERR_REASON(BIO_R_UNABLE_TO_CREATE_SOCKET), "unable to create socket"},
    {ERR_REASON(BIO_R_UNABLE_TO_KEEPALIVE), "unable to keepalive"},
    {ERR_REASON(BIO_R_UNABLE_TO_LISTEN_SOCKET), "unable to listen socket"},
    {ERR_REASON(BIO_R_UNABLE_TO_NODELAY), "unable to nodelay"},
    {ERR_REASON(BIO_R_UNABLE_TO_REUSEADDR), "unable to reuseaddr"},
    {ERR_REASON(BIO_R_UNAVAILABLE_IP_FAMILY), "unavailable ip family"},
    {ERR_REASON(BIO_R_UNINITIALIZED), "uninitialized"},
    {ERR_REASON(BIO_R_UNKNOWN_INFO_TYPE), "unknown info type"},
    {ERR_REASON(BIO_R_UNSUPPORTED_IP_FAMILY), "unsupported ip family"},
    {ERR_REASON(BIO_R_UNSUPPORTED_METHOD), "unsupported method"},
    {ERR_REASON(BIO_R_UNSUPPORTED_PROTOCOL_FAMILY),"unsupported protocol family"},
    {ERR_REASON(BIO_R_WRITE_TO_READ_ONLY_BIO), "write to read only BIO"},
    {ERR_REASON(BIO_R_WSASTARTUP), "WSAStartup"},
    {0, NULL}
};

  这两个表通过ERR_load_BIO_strings函数来添加到错误信息哈希表中去。为了便于查找,所有模块的错误信息存放在一个全局哈希表中,在crypto/err/err.c实现。

2.2.2 ERR_STATE

typedef struct err_state_st 
{
    int err_flags[ERR_NUM_ERRORS];
    unsigned long err_buffer[ERR_NUM_ERRORS];  //第i层错误码,包含库、函数以及错误原因信息。
    char *err_data[ERR_NUM_ERRORS];   //存放第i层操作信息。
    int err_data_flags[ERR_NUM_ERRORS];  /*存放err_data[i]相关的标记;比如:
                         为ERR_TXT_MALLOCED时,表err_data[i]动态分配内存的,需要释放;
                         为ERR_TXT_STRING表名err_data[i]中的数据是一个字符串,可以用来打印。*/
    const char *err_file[ERR_NUM_ERRORS];   //第i层错误的文件名。
    int err_line[ERR_NUM_ERRORS];  //第i层错误的行号。
    int top, bottom;               //用于指明ERR_STATE的使用状态。
                                   //top对应与最后一个错误(错误堆栈的最上层)
                                   //bottom对应第一个错误(错误堆栈的最底层)。
} ERR_STATE;

  该结构用于存放和获取错误信息。由于可能会有多层函数调用(错误堆栈),这些信息都是一个数组。每个数组代表了一层函数的错误信息。用户需要扩展openssl的模块时,可以仿照其他已有模块来实现自己的错误处理。

3 相关函数

3.1 获取错误代码

  每当有ERROR产生,一些重要的信息会被记录下来。一些信息可用于尝试自动恢复错误,但是其中的大多数都是用于调试和向用户报告错误。有6个API用于从Error队列中获取信息。ERROR是依产生的顺序记录在队列中的,这些函数都能获取到当前队列中最早的信息。
  最基本的消息是一个32-bit integer型的Error code。如果Error队列中无任何消息,error处理函数将返回0,0不是一个有效的错误号。
  9个获取error信息的API,实质上都是对get_error_values()的不同参数调用

//只获取错误代码
unsigned long ERR_get_error(void);  //获取第一个,并将其移除队列
unsigned long ERR_peek_error(void);  //获取第一个,不移除队列
unsigned long ERR_peek_last_error(void);  //获取最后一个,不移除队列

//获取Error code、错误产生的源文件(file)、行号(line)
unsigned long ERR_get_error_line(const char **file, int *line);
unsigned long ERR_peek_error_line(const char **file, int *line);
unsigned long ERR_peek_last_error_line(const char **file, int *line);

//获取Error code,错误产生的源文件(file)、行号(line),另提供额外的数据及标识如何处理这些数据的flag
unsigned long ERR_get_error_line_data(const char **file, int *line,
                                      const char **data, int *flags);
unsigned long ERR_peek_error_line_data(const char **file, int *line,
                                      const char **data, int *flags);
unsigned long ERR_peek_last_error_line_data(const char **file, int *line,
                                           const char **data, int *flags);


//所获得的数据可能是任意的,但大多数情况下会是一个字符串。
//如flag的ERR_TXT_MALLOCED被置1,则data所使用的内存可以使用OPENSSL_free函数释放。
//如flag的ERR_TXT_STRING被置1,则相应的data可以按C-style字串使用。

  例:打印error队列

void print_errors(void)
{
    int    flags, line;
    char    *data, *file;
    unsigned long code;

    code = ERR_get_error_line_data(&file, &line, &data, &flags);
    while(code)
    {
        printf("error code: %lu in %s line %d.\n", code,  file, line);
        if(data && (flags & ERR_TXT_STRING))
            printf("error data: %s\n", data);
        code = ERR_get_error_line_data(&file, &line, &data, &flags);
    }
}

3.2 获取错误码对应的错误消息

  error handling package为其定义的error code提供标准的错误消息,但是在使用前需被载入。

// libcrypto和libssl的错误消息全部载入
void SSL_load_error_strings(void)
{
#ifndef OPENSSL_NO_ERR
        ERR_load_crypto_strings();
        ERR_load_SSL_strings();
#endif:
}

//libcrypto的错误消息的载入
void ERR_load_crypto_strings(void)
{
#ifndef OPENSSL_NO_ERR
        ERR_load_ERR_strings(); /* include error strings for SYSerr */
        ERR_load_BN_strings();
#ifndef OPENSSL_NO_RSA
        ERR_load_RSA_strings();
#endif
#ifndef OPENSSL_NO_DH
        ERR_load_DH_strings();
#endif
        ERR_load_EVP_strings();
        ERR_load_BUF_strings();
        ERR_load_OBJ_strings();
        ERR_load_PEM_strings();
#ifndef OPENSSL_NO_DSA
        ERR_load_DSA_strings();
#endif
        ERR_load_X509_strings();
        ERR_load_ASN1_strings();
        ERR_load_CONF_strings();
        ERR_load_CRYPTO_strings();
        ERR_load_COMP_strings();
#ifndef OPENSSL_NO_EC
        ERR_load_EC_strings();
#endif
#ifndef OPENSSL_NO_ECDSA
        ERR_load_ECDSA_strings();
#endif
#ifndef OPENSSL_NO_ECDH
        ERR_load_ECDH_strings();
#endif
        /* skip ERR_load_SSL_strings() because it is not in this library */
        ERR_load_BIO_strings();
        ERR_load_PKCS7_strings();   
        ERR_load_X509V3_strings();
        ERR_load_PKCS12_strings();
        ERR_load_RAND_strings();
        ERR_load_DSO_strings();
        ERR_load_TS_strings();
#ifndef OPENSSL_NO_ENGINE
        ERR_load_ENGINE_strings();
#endif
        ERR_load_OCSP_strings();
        ERR_load_UI_strings();
#ifndef OPENSSL_NO_CMS
        ERR_load_CMS_strings();
#endif
#ifndef OPENSSL_NO_JPAKE
        ERR_load_JPAKE_strings();
#endif
        ERR_load_COMP_strings();
#endif
#ifdef OPENSSL_FIPS
        ERR_load_FIPS_strings();
#endif
}

// libssl的错误消息的载入
void ERR_load_SSL_strings(void)
{
#ifndef OPENSSL_NO_ERR

     if (ERR_func_error_string(SSL_str_functs[0].error) == NULL)
     {
          ERR_load_strings(0,SSL_str_functs);
          ERR_load_strings(0,SSL_str_reasons);
     }
#endif
}

  获取错误消息:

//获取全部错误消息
char* ERR_error_string(unsigned long e, char *buf)
void  ERR_error_string_n(unsigned long e, char *buf, size_t len)

//获取错误发生的 库,函数,原因
const char *ERR_lib_error_string(unsigned long e);
const char *ERR_func_error_string(unsigned long e);
const char *ERR_reason_error_string(unsigned long e);

参数e : error code
参数buf:error message(最少256Byte)
参数len: 写入的消息的最大长度

  error message的格式:

error:error code(hex):error name:产生error的函数名:产生error的原因

  为了获取error信息,必需先获取错误代码ERR_get_error,然后转为错误消息ERR_error_string,OpenSSL提供了下列API来简化这个过程:

//生成一个error list并将其写入BIO
void ERR_print_errors(BIO *bp)
{
        ERR_print_errors_cb(print_bio, bp);
}

//生成一个error list并将其写入一个标准的C FILE对象
void ERR_print_errors_fp(FILE *fp)
{
        ERR_print_errors_cb(print_fp, fp);
 }

3.3 其它函数

  • ERR_add_error_data

在本层错误的err_data元素中添加说明信息。该函数一般由各个模块调用,比如可以用它说明什么操作导致了错误。

  • ERR_clear_error

清除所有的错误信息。如果不清楚所有错误信息,可能会有其他无关错误遗留在ERR_STATE表中。

  • ERR_free_strings

释放错误信息哈希表;通常在最后调用。

  • ERR_get_err_state_table

获取存放错误的哈希表。

  • ERR_get_implementation

获取错误处理函数,与哈希表操作相关。

  • ERR_get_state

获取ERR_STATE表。

  • ERR_load_strings

加载错误信息,由各个模块调用。

  • 各个模块实现的,加载各自错误信息。
    ERR_load_ASN1_strings
    ERR_load_BIO_strings
    ERR_load_BN_strings
    ERR_load_BUF_strings
    ERR_load_COMP_strings
    ERR_load_CONF_strings
    ERR_load_CRYPTO_strings
    ERR_load_crypto_strings
    ERR_load_DH_strings
    ERR_load_DSA_strings
    ERR_load_DSO_strings
    ERR_load_EC_strings
    ERR_load_ENGINE_strings
    ERR_load_ERR_strings
    ERR_load_EVP_strings
    ERR_load_OBJ_strings
    ERR_load_OCSP_strings
    ERR_load_PEM_strings
    ERR_load_PKCS12_strings
    ERR_load_PKCS7_strings
    ERR_load_RAND_strings
    ERR_load_RSA_strings
    ERR_load_UI_strings
    ERR_load_X509_strings
    ERR_load_X509V3_strings

  • ERR_print_errors

将错误信息输出到bio中。

  • ERR_print_errors_cb

根据用户设置的回调函数来打印错误信息。

  • ERR_print_errors_fp

将错误打印到FILE中。

  • ERR_put_error

将错误信息存放到ERR_STATE 表中top指定的错误堆栈(最后的错误)。

  • ERR_remove_state

删除线程相关的错误信息。

  • ERR_set_error_data

将错误信息存放到ERR_STATE 表中top指定的错误堆栈(最后的错误)。

  • ERR_unload_strings

从错误哈希表中删除相关信息。


  版权声明本文根据DragonKing牛,E-Mail:wzhah@263.NET发布在https://openssl.126.com的系列文章整理修改而成(这个网站已经不能访问了),我自己所做的工作主要是针对新的1.0.2版本进行验证,修改错别字,和错误,重新排版,以及整理分类,配图。 未经作者允许,严禁用于商业出版,否则追究法律责任。网络转载请注明出处,这是对原创者的起码的尊重!!!


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

蓝月心语

你的鼓励是我最大的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值