SSL_load_error_strings()
时间: 2023-08-15 07:06:55 浏览: 54
SSL_load_error_strings() 是一个函数,它用于加载 OpenSSL 库中的错误字符串信息。在使用 OpenSSL 进行 SSL/TLS 通信时,如果出现错误,可以通过调用 SSL_load_error_strings() 函数来获取相应的错误信息。
这个函数会将错误信息加载到 OpenSSL 库的错误堆栈中,以便在需要时可以通过其他函数获取并打印错误信息。这些错误信息包括错误码和相关的文本描述,可以帮助开发人员进行故障排查和错误处理。
示例代码:
```c
#include <openssl/ssl.h>
#include <openssl/err.h>
int main() {
// 初始化 OpenSSL 库
SSL_library_init();
// 加载 OpenSSL 错误字符串
SSL_load_error_strings();
// 其他操作...
return 0;
}
```
调用 SSL_load_error_strings() 函数后,可以使用 ERR_get_error()、ERR_reason_error_string() 等函数来获取和打印具体的错误信息。这些函数可以帮助开发人员定位和解决 SSL/TLS 通信过程中可能出现的错误。
相关问题
将如下代码改成一个函数#include <string.h> #include <unistd.h> #include <sys/socket.h> #include <arpa/inet.h> #include <openssl/ssl.h> #include <openssl/err.h> #define MAX_BUF_SIZE 1024 int main(int argc, char *argv[]) { int sockfd, ret; char *url = argv[1]; // 输入的 url char *cert_path = argv[2]; // 输入的证书路径 struct sockaddr_in servaddr; SSL_CTX *ctx; SSL *ssl; char buf[MAX_BUF_SIZE]; // 初始化 SSL 库 SSL_library_init(); OpenSSL_add_all_algorithms(); SSL_load_error_strings(); // 创建 SSL 上下文 ctx = SSL_CTX_new(TLS_client_method()); if (ctx == NULL) { printf("SSL_CTX_new error.\n"); return -1; } // 加载证书 ret = SSL_CTX_load_verify_locations(ctx, cert_path, NULL); if (ret != 1) { printf("SSL_CTX_load_verify_locations error.\n"); return -1; } // 创建 socket sockfd = socket(AF_INET, SOCK_STREAM, 0); if (sockfd < 0) { printf("socket error.\n"); return -1; } // 设置服务器地址 memset(&servaddr, 0, sizeof(servaddr)); servaddr.sin_family = AF_INET; servaddr.sin_port = htons(443); inet_pton(AF_INET, url, &servaddr.sin_addr); // 连接服务器 ret = connect(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr)); if (ret < 0) { printf("connect error.\n"); return -1; } // 创建 SSL 对象 ssl = SSL_new(ctx); if (ssl == NULL) { printf("SSL_new error.\n"); return -1; } SSL_set_fd(ssl, sockfd); // 建立 SSL 连接 ret = SSL_connect(ssl); if (ret != 1) { printf("SSL_connect error.\n"); return -1; } // 发送请求 char *request = "GET / HTTP/1.1\r\nHost: %s\r\n\r\n"; sprintf(buf, request, url); SSL_write(ssl, buf, strlen(buf)); // 接收响应 while (1) { memset(buf, 0, sizeof(buf)); ret = SSL_read(ssl, buf, sizeof(buf) - 1); if (ret < 0) { printf("SSL_read error.\n"); break; } else if (ret == 0) { break; } else { printf("%s", buf); } } // 关闭 SSL 连接 SSL_shutdown(ssl); SSL_free(ssl); // 关闭 socket close(sockfd); // 清理 SSL 上下文 SSL_CTX_free(ctx); return 0; }
好的,下面是将代码改写成一个函数的结果:
```
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <openssl/ssl.h>
#include <openssl/err.h>
#define MAX_BUF_SIZE 1024
int https_request(const char *url, const char *cert_path) {
int sockfd, ret;
struct sockaddr_in servaddr;
SSL_CTX *ctx;
SSL *ssl;
char buf[MAX_BUF_SIZE];
// 初始化 SSL 库
SSL_library_init();
OpenSSL_add_all_algorithms();
SSL_load_error_strings();
// 创建 SSL 上下文
ctx = SSL_CTX_new(TLS_client_method());
if (ctx == NULL) {
printf("SSL_CTX_new error.\n");
return -1;
}
// 加载证书
ret = SSL_CTX_load_verify_locations(ctx, cert_path, NULL);
if (ret != 1) {
printf("SSL_CTX_load_verify_locations error.\n");
return -1;
}
// 创建 socket
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0) {
printf("socket error.\n");
return -1;
}
// 设置服务器地址
memset(&servaddr, 0, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(443);
inet_pton(AF_INET, url, &servaddr.sin_addr);
// 连接服务器
ret = connect(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr));
if (ret < 0) {
printf("connect error.\n");
return -1;
}
// 创建 SSL 对象
ssl = SSL_new(ctx);
if (ssl == NULL) {
printf("SSL_new error.\n");
return -1;
}
SSL_set_fd(ssl, sockfd);
// 建立 SSL 连接
ret = SSL_connect(ssl);
if (ret != 1) {
printf("SSL_connect error.\n");
return -1;
}
// 发送请求
char *request = "GET / HTTP/1.1\r\nHost: %s\r\n\r\n";
sprintf(buf, request, url);
SSL_write(ssl, buf, strlen(buf));
// 接收响应
while (1) {
memset(buf, 0, sizeof(buf));
ret = SSL_read(ssl, buf, sizeof(buf) - 1);
if (ret < 0) {
printf("SSL_read error.\n");
break;
} else if (ret == 0) {
break;
} else {
printf("%s", buf);
}
}
// 关闭 SSL 连接
SSL_shutdown(ssl);
SSL_free(ssl);
// 关闭 socket
close(sockfd);
// 清理 SSL 上下文
SSL_CTX_free(ctx);
return 0;
}
```
函数名称为 `https_request`,接受两个参数,分别是 `url` 和 `cert_path`。函数返回值为整型,表示函数执行结果。在函数内部,我们使用了原始代码中的大部分代码,只是将 `main` 函数中的一些变量名做了一些修改,以符合函数的参数列表。
请检查一下如下代码是否存在问题 int https_post(const char *cert_path, const char *url, const char *body, char *response) { int sockfd, len; struct sockaddr_in dest; struct hostent *host; SSL_CTX *ctx; SSL *ssl; char request[MAX_BUF_SIZE], buf[MAX_BUF_SIZE]; // 初始化OpenSSL库 SSL_library_init(); SSL_load_error_strings(); OpenSSL_add_all_algorithms(); // 解析主机名 printf("66666666 %s\n", url); host = gethostbyname(url); //printf("Child process created with PID %s\n", host); if (host == NULL) { perror("gethostbyname"); return -1; } // 创建套接字 printf("Child process created with PID %d\n", 2222); sockfd = socket(AF_INET, SOCK_STREAM, 0); if (sockfd < 0) { perror("socket"); return -1; } // 设置目标地址 bzero(&dest, sizeof(dest)); dest.sin_family = AF_INET; dest.sin_port = htons(443); dest.sin_addr.s_addr = *(long*)host->h_addr; // 连接服务器 printf("Child process created with PID %d\n", 3333); if (connect(sockfd, (struct sockaddr*)&dest, sizeof(dest)) != 0) { perror("connect"); return -1; } ctx = SSL_CTX_new(TLS_method()); // 设置支持的协议版本为 TLSv1.2 SSL_CTX_set_min_proto_version(ctx, TLS1_2_VERSION); SSL_CTX_set_max_proto_version(ctx, TLS1_2_VERSION); // 创建SSL上下文 //ctx = SSL_CTX_new(TLSv1_2_client_method()); printf("Child process created with PID %d\n", 4444); if (ctx == NULL) { perror("SSL_CTX_new"); return -1; } // 加载证书 printf("Child process created with PID %d\n", 5555); if (SSL_CTX_load_verify_locations(ctx, cert_path, NULL) != 1) { perror("SSL_CTX_load_verify_locations"); return -1; } // 创建SSL printf("Child process created with PID %d\n", 6666); ssl = SSL_new(ctx); if (ssl == NULL) { perror("SSL_new"); return -1; } printf("Child process created with PID %d\n", 7777); // 将套接字绑定到SSL SSL_set_fd(ssl, sockfd); printf("Child process created with PID %d\n", 9999); // SSL握手 if (SSL_connect(ssl) == -1) { perror("SSL_connect"); return -1; } // 构造HTTP请求 printf("Child process created with PID %d\n", 8888); sprintf(request, "POST / HTTP/1.1\r\n" "Host: %s\r\n" "Content-Type: application/json\r\n" "Content-Length: %d\r\n" "\r\n" "%s", url, strlen(body), body); // 发送HTTP请求 printf("Child process created with PID %d\n", 00000); SSL_write(ssl, request, strlen(request)); // 接收HTTP响应 len = SSL_read(ssl, buf, MAX_BUF_SIZE); // 关闭SSL和套接字 SSL_free(ssl); close(sockfd); // 处理响应 strncpy(response, buf, len); response[len] = '\0'; // 清理OpenSSL库 SSL_CTX_free(ctx); EVP_cleanup(); printf("Child process created with PID %d\n", 11111); return 0; }
这段代码存在一些问题,比如:
1. 在 SSL_CTX_new() 函数之前需要调用 SSL_library_init()、SSL_load_error_strings() 和 OpenSSL_add_all_algorithms(),来初始化 OpenSSL 库。
2. 在 gethostbyname() 函数返回 NULL 时,应该使用 herror() 或者 perror() 函数来输出错误信息。
3. 在 socket() 函数返回 -1 时,应该使用 perror() 函数来输出错误信息。
4. 在 SSL_CTX_new() 函数返回 NULL 时,应该使用 ERR_error_string() 函数来输出错误信息。
5. 在 SSL_CTX_load_verify_locations() 函数返回 -1 时,应该使用 ERR_error_string() 函数来输出错误信息。
6. 在 SSL_new() 函数返回 NULL 时,应该使用 ERR_error_string() 函数来输出错误信息。
7. 在 SSL_set_fd() 函数返回 -1 时,应该使用 ERR_error_string() 函数来输出错误信息。
8. 在 SSL_connect() 函数返回 -1 时,应该使用 ERR_error_string() 函数来输出错误信息。
9. 在 SSL_read() 函数返回 -1 时,应该使用 ERR_error_string() 函数来输出错误信息。
10. 在 SSL_free() 函数之前应该先判断 ssl 是否为 NULL。
11. 在 SSL_CTX_free() 函数之前应该先判断 ctx 是否为 NULL。
12. 在 EVP_cleanup() 函数之前应该先调用 ERR_free_strings() 函数来释放 OpenSSL 库中的错误字符串。