c - openssl ERR_print_errors_fp() 函数,无法将错误写入文件

标签 c sockets error-handling openssl

该程序使用 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/

相关文章:

java - 小消息的套接字缓冲区大小

objective-c - Cocoa API 的 C 绑定(bind)?

c - 什么是左值和右值?

c++ - Clang 或 GCC 是否能够自动矢量化手动展开的循环?

c - 卡普雷卡数计算失败超过两位数

python - 从python中的套接字读取二进制数据

ruby - 关于 Perl 和 Ruby 套接字编程的问题

python - 仅捕获由导入直接引起的导入错误

react-native - Catch block 没有捕捉到我的自定义 react 钩子(Hook)中抛出的错误

forms - Symfony2 在错误页面上包含表单(404)