C 使用 openssl 执行 HTTPS 请求



我是C语言的新手,我正在尝试在Linux Ubuntu 18.04中使用OpenSSL执行一个简单的SSL GET请求。我在执行HTTP POST并使用响应的Simple C示例中找到了这个

#include <stdio.h>
#include <openssl/ssl.h>
#include <openssl/err.h>
#include <openssl/bio.h>
#define HOST "www.google.com"
#define PORT "443"
int main() {
//
//  Initialize the variables
//
BIO* bio;
SSL* ssl;
SSL_CTX* ctx;
//
//   Registers the SSL/TLS ciphers and digests.
//
//   Basically start the security layer.
//
SSL_library_init();
//
//  Creates a new SSL_CTX object as a framework to establish TLS/SSL
//  or DTLS enabled connections
//
ctx = SSL_CTX_new(SSLv23_client_method());
//
//  -> Error check
//
if (ctx == NULL)
{
printf("Ctx is nulln");
}
//
//   Creates a new BIO chain consisting of an SSL BIO
//
bio = BIO_new_ssl_connect(ctx);
//
//  Use the variable from the beginning of the file to create a 
//  string that contains the URL to the site that you want to connect
//  to while also specifying the port.
//
BIO_set_conn_hostname(bio, HOST ":" PORT);
//
//   Attempts to connect the supplied BIO
//
if(BIO_do_connect(bio) <= 0)
{
printf("Failed connectionn");
return 1;
}
else
{
printf("Connectedn");
}
//
//  The bare minimum to make a HTTP request.
//
char* write_buf = "GET / HTTP/1.1rn"
"Host: " HOST "rn"
"Connection: closern"
"rn";
//
//   Attempts to write len bytes from buf to BIO
//
if(BIO_write(bio, write_buf, strlen(write_buf)) <= 0)
{
//
//  Handle failed writes here
//
if(!BIO_should_retry(bio))
{
// Not worth implementing, but worth knowing.
}
//
//  -> Let us know about the failed writes
//
printf("Failed writen");
}
//
//  Variables used to read the response from the server
//
int size;
char buf[1024];
//
//  Read the response message
//
for(;;)
{
//
//  Get chunks of the response 1023 at the time.
//
size = BIO_read(bio, buf, 1023);
//
//  If no more data, then exit the loop
//
if(size <= 0)
{
break;
}
//
//  Terminate the string with a 0, to let know C when the string 
//  ends.
//
buf[size] = 0;
//
//  ->  Print out the response
//
printf("%s", buf);
}
//
//  Clean after ourselves
//
BIO_free_all(bio);
SSL_CTX_free(ctx);
return 0;
}

这段代码运行良好,但对于某些站点(例如ghostbin.co(,连接失败......是什么原因造成的? 我使用gcc test.c -o test -lssl -lcrypto编译代码。 我正在使用OpenSSL 1.1.1 11 Sep 2018

几乎总是当OpenSSL例程返回错误指示时,您可以并且应该从错误堆栈中获取其他信息;请参阅 https://www.openssl.org/docs/faq.html#PROG8 和手册页,例如
https://www.openssl.org/docs/manmaster/man3/ERR_print_errors.html
https://www.openssl.org/docs/manmaster/man3/ERR_get_error.html
https://www.openssl.org/docs/manmaster/man3/ERR_error_string.html
https://www.openssl.org/docs/manmaster/man3/ERR_load_crypto_strings.html

但是,在这种情况下,它只会告诉您服务器通过发送警报 40 中止了握手,这是 SSL/TLS 中信息量较小的警报代码之一。这需要一点知识,并希望在CloudFlare上找到 ghostbin.co,这要求连接使用服务器名称指示(又名SNI( - 本世纪的许多SSL/TLS服务器都是如此(因为顶级IPv4耗尽(,特别是那些像CDN服务或共享主机一样共享的服务器。OpenSSL API 确实允许客户端发送 SNI,但仅使用每连接 SSL 对象而不是SSL_CTX,并且 SSL对象隐藏了(相当古老且相当吱吱作响的(BIO_ssl,因此您需要BIO_get_ssl(bio,&sslptr)然后SSL_set_tlsext_host_name(sslptr,name)(尽管我注意到手册页弄错了常量;这实际上是一个使用SSL_ctrl的宏,它采用绝对非常量指针(。

最新更新