我正在尝试从这里获取带有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);
}