C SSL例程:SSL3\u读取\N:未设置读取bio
我在C中发现了一个非常好的方法,我想将其应用到BIO库中。除了运行服务器时出现的一个错误外,我几乎成功了:C SSL例程:SSL3\u读取\N:未设置读取bio,c,ssl,network-programming,openssl,client-server,C,Ssl,Network Programming,Openssl,Client Server,我在C中发现了一个非常好的方法,我想将其应用到BIO库中。除了运行服务器时出现的一个错误外,我几乎成功了: //SSL-Server.c #include <errno.h> #include <unistd.h> #include <stdlib.h> #include <string.h> #include <arpa/inet.h> #include <sys/socket.h> #include <sys/ty
//SSL-Server.c
#include <errno.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <resolv.h>
#include "openssl/ssl.h"
#include "openssl/err.h"
#define FAIL -1
#define PORT "2013"
SSL_CTX* InitServerCTX(void)
{
SSL_METHOD *method;
SSL_CTX *ctx;
OpenSSL_add_all_algorithms();
SSL_load_error_strings();
method = SSLv3_server_method();
ctx = SSL_CTX_new(method);
if( ctx == NULL )
{
ERR_print_errors_fp(stderr);
abort();
}
return ctx;
}
void LoadCertificates(SSL_CTX* ctx, char* CertFile, char* KeyFile)
{
if( SSL_CTX_use_certificate_file(ctx, CertFile, SSL_FILETYPE_PEM) <= 0 )
{
ERR_print_errors_fp(stderr);
abort();
}
if( SSL_CTX_use_PrivateKey_file(ctx, KeyFile, SSL_FILETYPE_PEM) <= 0 )
{
ERR_print_errors_fp(stderr);
abort();
}
if( !SSL_CTX_check_private_key(ctx) )
{
fprintf(stderr, "Private key does not match the public certificate\n");
abort();
}
}
void ShowCerts(SSL* ssl)
{
X509 *cert;
char *line;
cert = SSL_get_peer_certificate(ssl);
if ( cert != NULL )
{
printf("Server certificates:\n");
line = X509_NAME_oneline(X509_get_subject_name(cert), 0, 0);
printf("Subject: %s\n", line);
free(line);
line = X509_NAME_oneline(X509_get_issuer_name(cert), 0, 0);
printf("Issuer: %s\n", line);
free(line);
X509_free(cert);
}
else
{
printf("No certificates.\n");
}
}
void Servlet(SSL* ssl)
{
char buf[1024];
int sd, bytes;
if( SSL_accept(ssl) == FAIL )
{
ERR_print_errors_fp(stderr);
}
else
{
ShowCerts(ssl);
bytes = SSL_read(ssl, buf, sizeof(buf));
if( bytes > 0 )
{
buf[bytes] = 0;
printf("Client msg: \"%s\"\n", buf);
SSL_write(ssl, "back message", strlen("back message"));
}
else
{
ERR_print_errors_fp(stderr);
}
}
sd = SSL_get_fd(ssl);
SSL_free(ssl);
close(sd);
}
int main(int count, char *strings[])
{
SSL_CTX *ctx;
BIO *acc, *client;
SSL_library_init();
ctx = InitServerCTX();
LoadCertificates(ctx, "mycert.pem", "mycert.pem");
acc = BIO_new_accept(PORT);
if(!acc)
{
printf("Error creating server socket");
}
while(1)
{
if(BIO_do_accept(acc) <= 0)
{
printf("Error binding server socket");
}
SSL *ssl;
client = BIO_pop(acc);
if(!(ssl = SSL_new(ctx)))
{
printf("Error creating SSL context");
}
SSL_set_bio(ssl, client, client);
// Here should be created threads
Servlet(ssl);
}
SSL_CTX_free(ctx);
}
$。/ssl服务器
68671:错误:140950D3:SSL例程:SSL3\u READ\N:READ bio not set:/SourceCache/OpenSSL098/OpenSSL098-35.1/src/SSL/s3\u pkt.c:203:
我正在使用gcc-o ssl server ssl server.c-lssl-lcrypto-Wall
编译服务器:
//SSL-Server.c
#include <errno.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <resolv.h>
#include "openssl/ssl.h"
#include "openssl/err.h"
#define FAIL -1
#define PORT "2013"
SSL_CTX* InitServerCTX(void)
{
SSL_METHOD *method;
SSL_CTX *ctx;
OpenSSL_add_all_algorithms();
SSL_load_error_strings();
method = SSLv3_server_method();
ctx = SSL_CTX_new(method);
if( ctx == NULL )
{
ERR_print_errors_fp(stderr);
abort();
}
return ctx;
}
void LoadCertificates(SSL_CTX* ctx, char* CertFile, char* KeyFile)
{
if( SSL_CTX_use_certificate_file(ctx, CertFile, SSL_FILETYPE_PEM) <= 0 )
{
ERR_print_errors_fp(stderr);
abort();
}
if( SSL_CTX_use_PrivateKey_file(ctx, KeyFile, SSL_FILETYPE_PEM) <= 0 )
{
ERR_print_errors_fp(stderr);
abort();
}
if( !SSL_CTX_check_private_key(ctx) )
{
fprintf(stderr, "Private key does not match the public certificate\n");
abort();
}
}
void ShowCerts(SSL* ssl)
{
X509 *cert;
char *line;
cert = SSL_get_peer_certificate(ssl);
if ( cert != NULL )
{
printf("Server certificates:\n");
line = X509_NAME_oneline(X509_get_subject_name(cert), 0, 0);
printf("Subject: %s\n", line);
free(line);
line = X509_NAME_oneline(X509_get_issuer_name(cert), 0, 0);
printf("Issuer: %s\n", line);
free(line);
X509_free(cert);
}
else
{
printf("No certificates.\n");
}
}
void Servlet(SSL* ssl)
{
char buf[1024];
int sd, bytes;
if( SSL_accept(ssl) == FAIL )
{
ERR_print_errors_fp(stderr);
}
else
{
ShowCerts(ssl);
bytes = SSL_read(ssl, buf, sizeof(buf));
if( bytes > 0 )
{
buf[bytes] = 0;
printf("Client msg: \"%s\"\n", buf);
SSL_write(ssl, "back message", strlen("back message"));
}
else
{
ERR_print_errors_fp(stderr);
}
}
sd = SSL_get_fd(ssl);
SSL_free(ssl);
close(sd);
}
int main(int count, char *strings[])
{
SSL_CTX *ctx;
BIO *acc, *client;
SSL_library_init();
ctx = InitServerCTX();
LoadCertificates(ctx, "mycert.pem", "mycert.pem");
acc = BIO_new_accept(PORT);
if(!acc)
{
printf("Error creating server socket");
}
while(1)
{
if(BIO_do_accept(acc) <= 0)
{
printf("Error binding server socket");
}
SSL *ssl;
client = BIO_pop(acc);
if(!(ssl = SSL_new(ctx)))
{
printf("Error creating SSL context");
}
SSL_set_bio(ssl, client, client);
// Here should be created threads
Servlet(ssl);
}
SSL_CTX_free(ctx);
}
我使用openssl req-x509-nodes-days 365-newkey rsa:1024-keyout mycert.pem-out mycert.pem
命令生成证书
一切正常,信息发送正常。请忽略错误检查的缺失,原谅代码中的混乱,这只是为了学习
有人能告诉我怎么了吗?另外,你能告诉我我是否犯了重大错误,我正在努力学习?(例如,例行呼叫命令、重大安全问题等)
谢谢 根据(底部的示例代码非常具有说明性),第一次调用BIO\u do\u accept()
将设置accept BIO,而不执行其他操作。只有第二次和所有后续调用是接受连接的实际调用。这很好地说明了为什么OpenSSL永远不会赢得“最直观的API设计”奖
那么代码中发生了什么?您只能在循环中调用BIO\u do\u accept()
。第一次通过循环时,它将设置BIO并立即返回。您的代码在不存在的连接上调用Servlet()
,并且SSL\u accept()
失败,返回您看到的错误。在Servlet()
返回后,您的代码愉快地循环到BIO\u do\u accept()
的第二次调用中,此时阻塞该调用,等待第一次连接,并且从这里开始一切都按预期工作
要解决此问题,您需要在循环之前调用BIO\u do\u accept()
一次,如下所示(使用错误处理的中断样式以保持一致性--您确实需要修复错误处理!):
[…]
acc=BIO_new_accept(端口);
如果(!acc)
{
printf(“创建服务器套接字时出错”);
}
/*第一个调用是设置accept BIO*/
如果(BIO_do__)接受(acc)“缺少错误检查和…代码中的混乱”绝对不会教你什么。它几乎肯定会向你隐瞒这个问题的原因。你无法从错误编写的代码中学到任何东西,除了如何不编写它。缺少错误检查只是为了让代码更清楚。我不认为你在指出错误正确的方向更多的错误检查的方向当然是正确的。如果您进行更多的错误检查,您将发现更多的错误,包括您当前正在调试的错误之前的任何错误。
[...]
acc = BIO_new_accept(PORT);
if(!acc)
{
printf("Error creating server socket");
}
/* first call is to set up accept BIO */
if(BIO_do_accept(acc) <= 0)
{
printf("Error calling BIO_do_accept() the first time");
}
while(1)
{
if(BIO_do_accept(acc) <= 0)
{
printf("Error binding server socket");
}
[...]