我的代码出现了部分故障,因为我可以建立到 www.hp.com 和 www.google.com 等地方的非安全连接,但是当向套接字添加 SSL 时,我无法再连接到www.google.com 即使我仍然可以连接到 www.hp.com
作为对此的回应,我做了相当多的研究并得出了好坏参半的答案。我尝试测试不同的站点,结果参差不齐。所以我觉得我在这里遗漏了 SSL 握手的一个关键部分,它不是很明显(至少对我而言)。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <resolv.h>
#include <netdb.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <openssl/bio.h>
#include <openssl/ssl.h>
#include <openssl/err.h>
#include <openssl/pem.h>
#include <openssl/x509.h>
#include <openssl/x509_vfy.h>
#include <errno.h>
#define SW_SUCCESS 1
#define SW_ERROR 0
typedef struct socket_info
{
int SocketHandle;
unsigned long AddressLong;
unsigned short Port;
char Host[256];
char Address[16];
char Request[256];
char Agent[128];
char Headers[512];
SSL *SecureHandle;
SSL_CTX *SecureContext;
const SSL_METHOD *SecureMethod;
BIO *SecureCertificate;
} SOCKETINFO, *PSOCKETINFO, *LPSOCKETINFO;
int secinit()
{
OpenSSL_add_all_algorithms();
ERR_load_BIO_strings();
ERR_load_crypto_strings();
SSL_load_error_strings();
return SW_SUCCESS;
}
int rawclose(struct socket_info *psi)
{
return (!close(psi->SocketHandle) ? SW_SUCCESS : SW_ERROR);
}
int secclose(struct socket_info *psi)
{
SSL_free(psi->SecureHandle);
SSL_CTX_free(psi->SecureContext);
return (rawclose(psi) ? SW_SUCCESS : SW_ERROR);
}
int rawconnect(struct socket_info *psi)
{
struct hostent *host;
struct sockaddr_in addr;
if ( (host = gethostbyname(psi->Host)) == NULL ) return SW_ERROR;
if ( (psi->SocketHandle = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0 )
{
psi->SocketHandle = 0;
return SW_ERROR;
}
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_port = htons(psi->Port);
addr.sin_addr.s_addr = *(long *)host->h_addr;
if ( connect(psi->SocketHandle, (struct sockaddr *)&addr, sizeof(struct sockaddr)) == -1 )
{
psi->SocketHandle = 0;
return SW_ERROR;
}
return SW_SUCCESS;
}
int secconnect(struct socket_info *psi)
{
// Initialise certificate BIO.
psi->SecureCertificate = BIO_new(BIO_s_file());
if ( SSL_library_init() < 0 ) return SW_ERROR;
// Initialise SSL method and deprecate SSLv2.
psi->SecureMethod = SSLv23_client_method();
if ( (psi->SecureContext = SSL_CTX_new(psi->SecureMethod)) == NULL ) return SW_ERROR;
SSL_CTX_set_options(psi->SecureContext, SSL_OP_NO_SSLv2);
psi->SecureHandle = SSL_new(psi->SecureContext);
// Connect to host with raw socket.
if ( !rawconnect(psi) )
{
SSL_free(psi->SecureHandle);
SSL_CTX_free(psi->SecureContext);
return SW_ERROR;
}
// Upgrade socket to SSL enabled.
SSL_set_fd(psi->SecureHandle, psi->SocketHandle);
if ( SSL_connect(psi->SecureHandle) != 1 )
{
SSL_free(psi->SecureHandle);
close(psi->SocketHandle);
SSL_CTX_free(psi->SecureContext);
return SW_ERROR;
}
return SW_SUCCESS;
}
int main(int argc, char **argv)
{
SOCKETINFO si;
int ret;
// SSLWrap module initialisation.
if ( secinit() != SW_SUCCESS ) return SW_ERROR;
memset(&si, 0, sizeof(si));
strncpy(si.Host, "www.google.com", 10);
si.Port = 80;
if ( (ret = rawconnect(&si)) != SW_SUCCESS ) return SW_ERROR;
if ( (ret = rawclose(&si)) != SW_SUCCESS ) return SW_ERROR;
memset(&si, 0, sizeof(si));
strncpy(si.Host, "www.google.com", 10);
si.Port = 443;
if ( (ret = secconnect(&si)) != SW_SUCCESS ) return SW_ERROR;
if ( (ret = secclose(&si)) != SW_SUCCESS ) return SW_ERROR;
return 0;
}
最佳答案
strncpy(si.Host, "www.google.com", 10);
10 太短;只需使用 strcpy()
在这里。
[也是一个强烈的建议:永远不要使用 strncpy() ,至少在您知道它的作用之前...]
why is strncpy() considered evil?主要是因为它令人困惑,至少对于新手用户而言。怎么办?
使用 strncpy(dst, src, siz);
:
- 如果目标缓冲区中有足够的空间
(strlen(src) < siz)
,缓冲区的其余部分将填充空字节 - 如果没有足够的空间
(strlen(src) >= siz)
, 不超过siz
字节将写入*dst
,但复制的字符串将不会以 nul 结尾。
第一种情况并不那么重要,一些周期被浪费在写入额外的空值上。如果您希望生成的字符串以 null 结尾,则第二种情况可能是灾难性的。 (大多数人都这样做)这就是为什么 strncpy()
发出危险信号。
如何避免 strncpy()
?有几种方法。最简单的一种:
len = strlen(src);
if (len >=siz) len=siz-1;
memcpy(dst, src, len);
dst[len]= 0;
关于c - C 中的 SSL 套接字无法连接到某些站点,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44765339/