OpenSSL坏主机名查找Windows C

时间:2017-10-05 18:43:31

标签: c windows openssl

我正在尝试从这里获取带有OpenSSL的SSL / TLS客户端:https://wiki.openssl.org/index.php/SSL/TLS_Client以在Visual Studio中构建和运行。

我已成功在visual studio中构建,但它无法成功运行。 目前它将运行到res = BIO_do_connect(web);并且ssl_err = ERR_get_error();最终在以下if (!(1 == res))失败,控制台输出为bad hostname lookup 我环顾四周试图找到一些解决方案,但似乎没有什么效果。

我使用的H文件与openssl.org上的文件非常相似。 <添加

除外
typedef struct {
    int status_code;
    char *reason;
    char *content;
}   HttpResponse;

这几乎是我在C中的第一次运行,之前我已经完成了Java,所以如果有人有任何见解,那就太棒了。或者,如果他们可以在C中指向Windows的https发布请求的示例。

#include "openssl-bio-fetch.h"
#include "corecrt_wstdio.h"

#ifndef HEADER_X509_H
#include <openssl/x509.h>
/* openssl/x509.h ends up #include-ing this file at about the only
* appropriate moment. */
#endif

int verify_callback(int preverify, X509_STORE_CTX* x509_ctx);

void init_openssl_library(void);
void print_cn_name(const char* label, X509_NAME* const name);
void print_san_name(const char* label, X509* const cert);
void print_error_string(unsigned long err, const char* const label);


const char* const PREFERRED_CIPHERS = "HIGH:!aNULL:!kRSA:!SRP:!PSK:!CAMELLIA:!RC4:!MD5:!DSS";

#if 0
const char* const PREFERRED_CIPHERS = "kEECDH:kEDH:kRSA:AESGCM:AES256:AES128:3DES:SHA256:SHA84:SHA1:!aNULL:!eNULL:!EXP:!LOW:!MEDIUM!ADH:!AECDH";
#endif

#if 0
const char* const PREFERRED_CIPHERS = NULL;
#endif

#if 0
const char* PREFERRED_CIPHERS =

/* TLS 1.2 only */
"ECDHE-ECDSA-AES256-GCM-SHA384:"
"ECDHE-RSA-AES256-GCM-SHA384:"
"ECDHE-ECDSA-AES128-GCM-SHA256:"
"ECDHE-RSA-AES128-GCM-SHA256:"

/* TLS 1.2 only */
"DHE-DSS-AES256-GCM-SHA384:"
"DHE-RSA-AES256-GCM-SHA384:"
"DHE-DSS-AES128-GCM-SHA256:"
"DHE-RSA-AES128-GCM-SHA256:"

/* TLS 1.0 only */
"DHE-DSS-AES256-SHA:"
"DHE-RSA-AES256-SHA:"
"DHE-DSS-AES128-SHA:"
"DHE-RSA-AES128-SHA:"

/* SSL 3.0 and TLS 1.0 */
"EDH-DSS-DES-CBC3-SHA:"
"EDH-RSA-DES-CBC3-SHA:"
"DH-DSS-DES-CBC3-SHA:"
"DH-RSA-DES-CBC3-SHA";
#endif


void add_char_header(char *current, char *key, char *value)
{
    strcat(current, "\r\n");
    strcat(current, key);
    strcat(current, ": ");
    strcat(current, value);
}

void add_int_header(char *current, char *key, int value)
{
    char *buffer = malloc(5);
    sprintf(buffer, "%d", value);
    strcat(current, "\r\n");
    strcat(current, key);
    strcat(current, ": ");
    strcat(current, buffer);
    free(buffer);
}

void parse_http_response(char *resp, HttpResponse *response)
{
  response.reason = "";
  response.content = "";
}

char * buildRequest(char *request) {

    size_t size;
    size = strlen("{\"client_ip\":\"10.20.30.40\"}");
    strcpy(request, "{\"client_ip\":\"10.20.30.40\"}");
    printf("pks-368\n");
    return request;
}

int
main(int ac, char **av)
{
    char *request = malloc(225);
    buildRequest(request);

    HttpResponse response;
    response.reason = calloc(1, 64);
    response.content = calloc(1, 10 * 1024);
    response.status_code = 0;
    int a = openssl_fetch(request, &response);
    fprintf(stderr, "C %d", response.status_code);
    fprintf(stderr, "A %s", response.content);
    fprintf(stderr, "B %s", response.reason);
    printf("Paused");
}

int openssl_fetch(char *request, HttpResponse *response)
{
    char *HOST_NAME = "google.com";
    char *HOST_PORT = "443";

    char *hostname = calloc(1, 100);
    strcpy(hostname, HOST_NAME);
    strcat(hostname, ":");
    strcat(hostname, HOST_PORT);

    long res = 1;
    int ret = 1;
    unsigned long ssl_err = 0;

    SSL_CTX* ctx = NULL;
    BIO *web = NULL, *out = NULL;
    SSL *ssl = NULL;

    do {
        init_openssl_library();

        const SSL_METHOD* method = SSLv23_method();
        ssl_err = ERR_get_error();

        if (!(NULL != method))
        {
            print_error_string(ssl_err, "SSLv23_method");
            break; /* failed */
        }

        ctx = SSL_CTX_new(method);
        ssl_err = ERR_get_error();

        if (!(ctx != NULL))
        {
            print_error_string(ssl_err, "SSL_CTX_new");
            break; /* failed */
        }

        SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, verify_callback);

        SSL_CTX_set_verify_depth(ctx, 5);
        const long flags = SSL_OP_ALL | SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_COMPRESSION;
        long old_opts = SSL_CTX_set_options(ctx, flags);
        UNUSED(old_opts);

        const char *file_loc = "C:\\Users\\$USER\\Desktop\\trusted-roots.pem";

        res = SSL_CTX_load_verify_locations(ctx, file_loc, NULL);
        ssl_err = ERR_get_error();

        if (!(1 == res))
        {
            fprintf(stderr, "SSL_CTX_load_verify_locations -- [%s]\n", ssl_err);
        }

        web = BIO_new_ssl_connect(ctx);
        ssl_err = ERR_get_error();

        if (!(web != NULL))
        {
            print_error_string(ssl_err, "BIO_new_ssl_connect");
            break; /* failed */
        }

        res = BIO_set_conn_hostname(web, hostname);
        ssl_err = ERR_get_error();

        if (!(1 == res))
        {
            print_error_string(ssl_err, "BIO_set_conn_hostname");
            break; /* failed */
        }

        BIO_get_ssl(web, &ssl);
        ssl_err = ERR_get_error();

        if (!(ssl != NULL))
        {
            print_error_string(ssl_err, "BIO_get_ssl");
            break; /* failed */
        }

        res = SSL_set_cipher_list(ssl, PREFERRED_CIPHERS);
        ssl_err = ERR_get_error();

        if (!(1 == res))
        {
            print_error_string(ssl_err, "SSL_set_cipher_list");
            break; /* failed */
        }

        res = SSL_set_tlsext_host_name(ssl, HOST_NAME);
        ssl_err = ERR_get_error();

        if (!(1 == res))
        {
            print_error_string(ssl_err, "SSL_set_tlsext_host_name");
        }

        out = BIO_new_fp(stdout, BIO_NOCLOSE);
        ssl_err = ERR_get_error();

        if (!(NULL != out))
        {
            print_error_string(ssl_err, "BIO_new_fp");
            break; /* failed */
        }

        res = BIO_do_connect(web);
        ssl_err = ERR_get_error();

        if (!(1 == res))
        {
            print_error_string(ssl_err, "BIO_do_connect");
            break; /* failed */
        }

        res = BIO_do_handshake(web);
        ssl_err = ERR_get_error();

        if (!(1 == res))
        {
            print_error_string(ssl_err, "BIO_do_handshake");
            break; /* failed */
        }

        X509* cert = SSL_get_peer_certificate(ssl);
        if (cert) { X509_free(cert); } /* Free immediately */

        if (NULL == cert)
        {
            print_error_string(X509_V_ERR_APPLICATION_VERIFICATION, "SSL_get_peer_certificate");
            break; /* failed */
        }

        res = SSL_get_verify_result(ssl);

        if (!(X509_V_OK == res))
        {
            print_error_string((unsigned long)res, "SSL_get_verify_results");
            break; /* failed */
        }

        char message[2048];
        strcpy(message, "POST ");
        strcat(message, HOST_RESOURCE);
        strcat(message, " HTTP/1.1 ");
        add_char_header(message, "Host", HOST_NAME);
        add_char_header(message, "Connection", "close");
        add_char_header(message, "Accept", "*/*");
        add_int_header(message, "Content-Length", (int)strlen(request));
        strcat(message, "\r\n\r\n");
        strcat(message, request);

        BIO_puts(web, message);

        char buff[6144] = { 0 };
        int len = 0;
        do {

            len = BIO_read(web, buff, sizeof(buff));
        } while (len > 0 || BIO_should_retry(web));

        ret = 0;

        parse_http_response(buff, response);
        free(hostname);
    } while (0);

    if (out)
        BIO_free(out);

    if (web != NULL)
        BIO_free_all(web);

    if (NULL != ctx)
        SSL_CTX_free(ctx);

    return ret;
}

void init_openssl_library(void)
{
    (void)SSL_library_init();

    SSL_load_error_strings();
#if defined (OPENSSL_THREADS)
    //    fprintf(stdout, "Warning: thread locking is not implemented\n");
#endif
}

void print_cn_name(const char* label, X509_NAME* const name)
{
    int idx = -1, success = 0;
    unsigned char *utf8 = NULL;

    do
    {
        if (!name) break; /* failed */

        idx = X509_NAME_get_index_by_NID(name, NID_commonName, -1);
        if (!(idx > -1))  break; /* failed */

        X509_NAME_ENTRY* entry = X509_NAME_get_entry(name, idx);
        if (!entry) break; /* failed */

        ASN1_STRING* data = X509_NAME_ENTRY_get_data(entry);
        if (!data) break; /* failed */

        int length = ASN1_STRING_to_UTF8(&utf8, data);
        if (!utf8 || !(length > 0))  break; /* failed */

        fprintf(stdout, "  %s: %s\n", label, utf8);
        success = 1;

    } while (0);

    if (utf8)
        OPENSSL_free(utf8);

    if (!success)
        fprintf(stdout, "  %s: <not available>\n", label);
}

void print_san_name(const char* label, X509* const cert)
{
    int success = 0;
    GENERAL_NAMES* names = NULL;
    unsigned char* utf8 = NULL;

    do
    {
        if (!cert) break; /* failed */

        names = X509_get_ext_d2i(cert, NID_subject_alt_name, 0, 0);
        if (!names) break;

        int i = 0, count = sk_GENERAL_NAME_num(names);
        if (!count) break; /* failed */

        for (i = 0; i < count; ++i)
        {
            GENERAL_NAME* entry = sk_GENERAL_NAME_value(names, i);
            if (!entry) continue;

            if (GEN_DNS == entry->type)
            {
                int len1 = 0, len2 = -1;

                len1 = ASN1_STRING_to_UTF8(&utf8, entry->d.dNSName);
                if (utf8) {
                    len2 = (int)strlen((const char*)utf8);
                }

                if (len1 != len2) {
                    fprintf(stderr, "  Strlen and ASN1_STRING size do not match (embedded null?): %d vs %d\n", len2, len1);
                }

                if (utf8 && len1 && len2 && (len1 == len2)) {
                    fprintf(stdout, "  %s: %s\n", label, utf8);
                    success = 1;
                }

                if (utf8) {
                    OPENSSL_free(utf8), utf8 = NULL;
                }
            }
            else
            {
                fprintf(stderr, "  Unknown GENERAL_NAME type: %d\n", entry->type);
            }
        }

    } while (0);

    if (names)
        GENERAL_NAMES_free(names);

    if (utf8)
        OPENSSL_free(utf8);

    if (!success)
        fprintf(stdout, "  %s: <not available>\n", label);

}

int verify_callback(int preverify, X509_STORE_CTX* x509_ctx)
{
    int depth = X509_STORE_CTX_get_error_depth(x509_ctx);
    int err = X509_STORE_CTX_get_error(x509_ctx);

    if (depth == 0) {
    }

    if (preverify == 0)
    {
        if (err == X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY)
            fprintf(stdout, "  Error = X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY\n");
        else if (err == X509_V_ERR_CERT_UNTRUSTED)
            fprintf(stdout, "  Error = X509_V_ERR_CERT_UNTRUSTED\n");
        else if (err == X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN)
            fprintf(stdout, "  Error = X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN\n");
        else if (err == X509_V_ERR_CERT_NOT_YET_VALID)
            fprintf(stdout, "  Error = X509_V_ERR_CERT_NOT_YET_VALID\n");
        else if (err == X509_V_ERR_CERT_HAS_EXPIRED)
            fprintf(stdout, "  Error = X509_V_ERR_CERT_HAS_EXPIRED\n");
        else if (err == X509_V_OK)
            fprintf(stdout, "  Error = X509_V_OK\n");
        else
            fprintf(stdout, "  Error = %d\n", err);
    }

#if !defined(NDEBUG)
    return 1;
#else
    return preverify;
#endif
}

void print_error_string(unsigned long err, const char* const label)
{
    const char* const str = ERR_reason_error_string(err);
    if (str)
        fprintf(stderr, "%s\n", str);
    else
        fprintf(stderr, "%s failed: %lu (0x%lx)\n", label, err, err);
}

0 个答案:

没有答案