该程序使用 openssl 来保护 http 连接:
#include <openssl/ssl.h>
#include <openssl/bio.h>
#include <openssl/err.h>
#include <openssl/crypto.h>
#include <openssl/bn.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#define IP_ADDR INADDR_ANY
#define PORT 8081
int password_cb(char *buf, int size, int rwflag, void *password);
EVP_PKEY *generatePrivateKey();
X509 *generateCertificate(EVP_PKEY *pkey);
/**
* Example SSL server that accepts a client and echos back anything it receives.
* Test using `curl -I https://127.0.0.1:8081 --insecure --sslv3`
*/
int main(int arc, char **argv)
{
int fd = socket(AF_INET, SOCK_STREAM, 0);
if (fd < 0) {
printf("opening socket\n");
return -4;
}
struct sockaddr_in s_addr;
bzero((char *)&s_addr, sizeof(s_addr));
s_addr.sin_family = AF_INET;
s_addr.sin_addr.s_addr = IP_ADDR;
s_addr.sin_port = htons(PORT);
if (bind(fd, (struct sockaddr*)&s_addr, sizeof(s_addr)) < 0) {
printf("binding\n");
return -5;
}
listen(fd, 2);
int cfd;
while (cfd = accept(fd, 0, 0))
{
SSL_load_error_strings();
ERR_load_crypto_strings();
OpenSSL_add_all_algorithms();
SSL_library_init();
SSL_CTX *ctx = SSL_CTX_new(SSLv3_server_method());
//SSL_CTX *ctx = SSL_CTX_new(TLS_server_method());
if (ctx == NULL) {
printf("errored; unable to load context.\n");
ERR_print_errors_fp(stderr);
return -3;
}
EVP_PKEY *pkey = generatePrivateKey();
X509 *x509 = generateCertificate(pkey);
SSL_CTX_use_certificate(ctx, x509);
SSL_CTX_set_default_passwd_cb(ctx, password_cb);
SSL_CTX_use_PrivateKey(ctx, pkey);
RSA *rsa=RSA_generate_key(512, RSA_F4, NULL, NULL);
SSL_CTX_set_tmp_rsa(ctx, rsa);
RSA_free(rsa);
SSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, 0);
SSL *ssl = SSL_new(ctx);
BIO *accept_bio = BIO_new_socket(cfd, BIO_CLOSE);
SSL_set_bio(ssl, accept_bio, accept_bio);
SSL_accept(ssl);
BIO *bio = BIO_pop(accept_bio);
char buf[1024];
FILE *file1 = fopen("logfile", "a");
while (1)
{
// first read data
int r = SSL_read(ssl, buf, 1024);
ERR_print_errors_fp(file1);
printf ("\nsize of read data : %d\n", r);
printf ("actual data : %s\n", buf);
switch (SSL_get_error(ssl, r))
{
case SSL_ERROR_NONE:
break;
case SSL_ERROR_ZERO_RETURN:
goto end;
default:
printf("SSL read problem");
goto end;
}
int len = r;
// now keep writing until we've written everything
int offset = 0;
while (len)
{
r = SSL_write(ssl, buf + offset, len);
switch (SSL_get_error(ssl, r))
{
case SSL_ERROR_NONE:
len -= r;
offset += r;
break;
default:
printf("SSL write problem");
goto end;
}
}
}
end:
SSL_shutdown(ssl);
BIO_free_all(bio);
BIO_free_all(accept_bio);
}
return 0;
}
int password_cb(char *buf, int size, int rwflag, void *password)
{
strncpy(buf, (char *)(password), size);
buf[size - 1] = '\0';
return strlen(buf);
}
EVP_PKEY *generatePrivateKey()
{
EVP_PKEY *pkey = NULL;
EVP_PKEY_CTX *pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_RSA, NULL);
EVP_PKEY_keygen_init(pctx);
EVP_PKEY_CTX_set_rsa_keygen_bits(pctx, 2048);
EVP_PKEY_keygen(pctx, &pkey);
return pkey;
}
X509 *generateCertificate(EVP_PKEY *pkey)
{
X509 *x509 = X509_new();
X509_set_version(x509, 2);
ASN1_INTEGER_set(X509_get_serialNumber(x509), 0);
X509_gmtime_adj(X509_get_notBefore(x509), 0);
X509_gmtime_adj(X509_get_notAfter(x509), (long)60*60*24*365);
X509_set_pubkey(x509, pkey);
X509_NAME *name = X509_get_subject_name(x509);
X509_NAME_add_entry_by_txt(name, "C", MBSTRING_ASC, (const unsigned char*)"US", -1, -1, 0);
X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_ASC, (const unsigned char*)"YourCN", -1, -1, 0);
X509_set_issuer_name(x509, name);
X509_sign(x509, pkey, EVP_md5());
return x509;
}
它可以正确执行此功能,但问题是关于ERR_print_errors_fp函数无法在文件中写入错误。例如,我打开一个名为 file1 的文件,并将此行放在读取数据之后
ERR_print_errors_fp(file1);
运行程序后,我用这一行连接到它:
curl -I https://127.0.0.1:8081 --insecure
我从导致此错误的行尾删除了--sslv3:
139796745827984:error:140940E5:SSL routines:SSL3_READ_BYTES:ssl handshake failure:s3_pkt.c:1038:
以上错误必须使用 ERR_print_errors_fp() 函数写入 file1。问题是文件已创建但它是空的。 注意:我可以使用 ERR_print_errors_fp(stderr) 将相同的错误打印到 stderr; 如何将 openssl 错误写入文件?
最佳答案
您没有关闭文件。在 switch case 之后使用 fclose(file1)
。 fclose 的目的是关闭流以及与其关联的所有结构,同时刷新数据流(这是实际写入发生的地方)。
关于c - openssl ERR_print_errors_fp() 函数,无法将错误写入文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59588573/