【发布时间】:2021-05-20 18:49:32
【问题描述】:
我正在尝试连接到安全 (https:) 网站并执行写入/读取操作。我试图找到一个使用 OpenSSL 的简单示例,但所有示例似乎都是针对早期版本的,并且文档差异很大。我尽我所能,制作了一些模组,并创建了一个简单的“Hello, World”SSL 程序(如下)。它主要工作,但在 SSL_write() 上失败。错误是 SSL_ERROR_SSL。
// client.c - SSL client program
// Uses OpenSSL v1.1.1i for Win32
#include <windows.h>
#include <stdio.h>
#include <conio.h>
#include "openssl/ssl.h" // openSSL includes
#include "client.h"
// LINK TO THESE LIBRARIES
#pragma comment( lib, "libssl.lib" )
#pragma comment( lib, "Ws2_32.lib" )
//@ Main program
int
main(
int argc, // count of args
char **argv) //ptr to array or arg strings
{
#define HOSTNAME "www.fax.plus" // secure host
#define PORT 443 // https port
int i,ok;
WSADATA data;
SSL_METHOD *method;
SSL_CTX *ctx;
SSL *ssl;
SOCKET s;
char request[1024+1];
SSL_METHOD *TLSv1_2_client_method(); // not defined in includes!?
i = WSAStartup( 0x002, &data ); // start winsock
if( i ) sslFatalExit( "on WSAStartup" );
printf( "OK: WinSock Started.\n" );
method = TLSv1_2_client_method(); // get method
ctx = SSL_CTX_new( method ); // get ctx
if( !ctx ) sslFatalExit( "on SSL_CTX_new" );
printf( "OK: SSL CTX created\n" );
ssl = SSL_new( ctx ); // get ssl
if( !ssl ) sslFatalExit( "on SSL_new" );
printf( "OK: SSL ssl created.\n" );
s = sslConnect( HOSTNAME, PORT ); // connect to host
if( s <= 0 ) sslFatalExit( "on sslConnect" );
printf( "OK: Connected to %s:%u\n", HOSTNAME, PORT );
ok = SSL_set_fd( ssl, s ); // set ssl socket
if( !ok ) sslFatalExit( "SSL_set_fd" );
printf( "OK: SSL socket set.\n" );
strncpy( request, "GET / HTTP/1.00\r\n\r\n", 1024 );
i = SSL_write( ssl, request, strlen( request ) ); // write request to host
if( i != 1 ) sslReportError( i, ssl ); // ALWAYS FAILS !
// more...
return( 0 );
}
//@ Connect to host:port
SOCKET
sslConnect(
char *hostname, // host name
WORD port) // port number
{
int i,sd;
struct hostent *host;
struct sockaddr_in addr;
host = gethostbyname( hostname );
if( host == NULL ) {
perror( hostname );
return( 0 );
}
sd = socket(PF_INET, SOCK_STREAM, 0 );
ZeroMemory( &addr, sizeof(addr ) );
addr.sin_family = AF_INET;
addr.sin_port = htons( port );
addr.sin_addr.s_addr = *(long *)(host->h_addr);
i = connect( sd, (struct sockaddr*)&addr, sizeof(addr));
if( i != 0 ) {
perror( hostname );
return( 0 );
}
return( sd );
//r Returns connected socket or 0 on error
}
//@ Report SSL error
void
sslReportError(
int code,
SSL *ssl)
{
int sslerr;
char *msg;
sslerr = SSL_get_error( ssl, code );
msg = sslErrorName( sslerr );
printf( "ERROR: %s\n", msg );
sslFatalExit( "on SSL_write" );
}
//@ Get string of ssl error code
char *
sslErrorName(
int code) // code returned by SSL_get_error()
{
switch( code ) {
case SSL_ERROR_NONE: return( "[0] SSL_ERROR_NONE" );
case SSL_ERROR_SSL: return( "[1] SSL_ERROR_SSL" );
case SSL_ERROR_WANT_READ: return( "[2] SSL_ERROR_WANT_READ" );
case SSL_ERROR_WANT_WRITE: return( "[4] SSL_ERROR_WANT_WRITE" );
case SSL_ERROR_WANT_X509_LOOKUP: return( "[4] SSL_ERROR_WANT_X509_LOOKUP" );
case SSL_ERROR_SYSCALL: return( "[5] SSL_ERROR_SYSCALL" );
case SSL_ERROR_ZERO_RETURN: return( "[6] SSL_ERROR_ZERO_RETURN" );
case SSL_ERROR_WANT_CONNECT: return( "[7] SSL_ERROR_WANT_CONNECT" );
case SSL_ERROR_WANT_ACCEPT: return( "[8] SSL_ERROR_WANT_ACCEPT" );
//case SSL_ERROR_WANT_ASYNC: return( "[9] SSL_ERROR_WANT_ASYNC" );
//case SSL_ERROR_WANT_ASYNC_JOB: return( "[10] SSL_ERROR_WANT_ASYNC_JOB" );
//case SSL_ERROR_WANT_CLIENT_HELLO_CB: return( "[11] SSL_ERROR_WANT_CLIENT_HELLO_CB" );
default: return( "ERROR_UNKNOWN" );
//r Returns string of error code
}
}
//@ Print msg, pause and exit
void
sslFatalExit(
char *msg) // msg to print
{
printf( "FATAL ERROR: %s\n", msg );
printf( "Press any key to exit...\n" );
getch();
exit( 1 );
}
程序输出:
OK: WinSock Started.
OK: SSL CTX created
OK: SSL ssl created.
OK: Connected to www.fax.plus:443
OK: SSL socket set.
ERROR: [1] SSL_ERROR_SSL
FATAL ERROR: on SSL_write
Press any key to exit...
我的尝试和奇怪的地方
- 许多示例都调用了诸如“SSL_add_all_algorithms()”之类的东西,但这在 libssl.lib 中没有得到解决
- 一些称为 SSL_init_ssl。这已解决,但导致 'SSL_CTX_new()' 失败。一些文档表示这是不必要的。
- ''TLSv1_2_client_method()' 已解决,但未包含在 SSL 包含文件中,因此我自己声明了。
有人对我的问题有任何见解或替代方法吗?
【问题讨论】:
-
检查在
libssl之前添加lcrypto是否解决链接问题,同时检查链接是动态的还是静态的 -
试过但结果相同。库是静态的。
-
你用过哪些库?
-
我制作了一个运行良好的windows客户端程序,它需要与静态库和程序目录中的dll链接。
-
你在某处调用 SSL_connect 吗?