Как повторно согласовать TLS 1.2 с помощью OpenSSL 3?C++

Программы на C++. Форум разработчиков
Ответить
Anonymous
 Как повторно согласовать TLS 1.2 с помощью OpenSSL 3?

Сообщение Anonymous »

При использовании OpenSSL 3.3.0 у нас возникли проблемы с повторным согласованием TLS 1.2.
Мы реализовали приложения C++ как на стороне сервера, так и на стороне клиента и настроили параметры для включения повторного согласования. На практике, когда сервер инициирует повторное согласование, само повторное согласование завершается успешно как на сервере, так и на клиенте.

Однако сразу после этого вызов SSL_write на стороне клиента завершается неудачно. У нас есть клиент, который периодически отправляет сообщения, а сервер настроен на повторное согласование по истечении одной минуты. Однако передача сразу после завершения повторного согласования всегда завершается неудачей.
Клиент тоже ожидает, так может ли возникнуть проблема с тем, как мы выполняем отправку?
Клиент
#define _WINSOCK_DEPRECATED_NO_WARNINGS
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include

namespace fs = std::filesystem;

#pragma comment (lib, "ws2_32.lib")

#define FAIL -1

void LoadCertificates(SSL_CTX* ctx, const char* CertFile, const char* KeyFile, const char* CAFile)
{
SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, NULL);
SSL_CTX_set_verify_depth(ctx, 4);
}

int OpenConnection(const char* hostname, int port)
{
int sd;
struct hostent* host;
struct sockaddr_in addr;
WSAData data;
WORD ver = MAKEWORD(2, 2);
int wsResult = WSAStartup(ver, &data);
if (wsResult != 0)
{
printf("winsock error");
return 0;
}

if ((host = gethostbyname(hostname)) == NULL)
{
perror(hostname);
abort();
}
sd = (int)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);
if (connect(sd, (struct sockaddr*)&addr, sizeof(addr)) != 0)
{
closesocket(sd);
perror(hostname);
abort();
}
return sd;
}

SSL_CTX* InitCTX(void)
{
SSL_CTX* ctx;

OpenSSL_add_all_algorithms(); /* Load cryptos, et.al. */
SSL_load_error_strings(); /* Bring in and register error messages */

const SSL_METHOD* method = TLS_client_method(); /* Create new client-method instance */
ctx = SSL_CTX_new(method); /* Create new context */
if (ctx == NULL)
{
ERR_print_errors_fp(stderr);
abort();
}

// TLS1.2
SSL_CTX_set_min_proto_version(ctx, TLS1_2_VERSION);
SSL_CTX_set_max_proto_version(ctx, TLS1_2_VERSION);

#ifdef SSL_OP_NO_RENEGOTIATION
SSL_CTX_clear_options(ctx, SSL_OP_NO_RENEGOTIATION);
#endif

return ctx;
}

void ShowCerts(SSL* ssl)
{
X509* cert;
char* line;

cert = SSL_get_peer_certificate(ssl); /* get the server's certificate */
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); /* free the malloc'ed string */
line = X509_NAME_oneline(X509_get_issuer_name(cert), 0, 0);
printf("Issuer: %s\n", line);
free(line); /* free the malloc'ed string */

X509_free(cert); /* free the malloc'ed certificate copy */
}
else
printf("No certificates.\n");
}

int main()
{
SSL_CTX* ctx;
int server;
SSL* ssl;
char buf[1024];
int bytes;
char hostname[] = "127.0.0.1";
char portnum[] = "54000";

int counter = 0;
bool running = true;

auto current_dir_path = fs::current_path();
auto pem_cert_file_path = current_dir_path / "Client_certificate.pem";
auto pem_pkey_file_path = current_dir_path / "Client_private_key.pem";
auto pem_ca_file_path = current_dir_path / "Server_CA_certificate.pem";

SSL_library_init();

ctx = InitCTX();
LoadCertificates(ctx,
pem_cert_file_path.string().c_str(),
pem_pkey_file_path.string().c_str(),
pem_ca_file_path.string().c_str()
);

printf("client certificate loaded\n");
server = OpenConnection(hostname, atoi(portnum));
ssl = SSL_new(ctx); /* create new SSL connection state */
SSL_set_fd(ssl, server); /* attach the socket descriptor */
if (SSL_connect(ssl) == FAIL) /* perform the connection */ {
printf("Connection failed\n");
ERR_print_errors_fp(stderr);
}
else
{

while (running) {
// Send message by 10 seconds
std::string msg = "Hello from client #" + std::to_string(++counter);
int w = SSL_write(ssl, msg.data(), (int)msg.size());
if (w 0) {
buf[n] = '\0';
printf("[Client] Received: \"%s\"\n", buf);
if (std::string(buf).find("[SERVER] RENEGO-OK") != std::string::npos) {
printf("[Client] Server renegotiation confirmed.\n");
}
}
else {
int err = SSL_get_error(ssl, n);
if (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE) {
printf("[Client] WANT READ or WANT WRITE.\n");
}
else if (err == SSL_ERROR_ZERO_RETURN) {
printf("[Client] Server closed connection.\n");
break;
}
else {
printf("[Client] SSL_read error.\n");
ERR_print_errors_fp(stderr);
break;
}
}

std::this_thread::sleep_for(std::chrono::seconds(10));
}
SSL_free(ssl); /* release connection state */
}
closesocket(server); /* close socket */
SSL_CTX_free(ctx); /* release context */
return 0;
}

Сервер
#define _WINSOCK_DEPRECATED_NO_WARNINGS
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include

namespace fs = std::filesystem;

#pragma comment (lib, "ws2_32.lib")

#define FAIL -1

int OpenListener(int port)
{
int sd;
struct sockaddr_in addr;
WSAData data;
WORD ver = MAKEWORD(2, 2);
int wsResult = WSAStartup(ver, &data);
if (wsResult != 0)
{
printf("winsock error");
return 0;
}

sd = (int)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 = INADDR_ANY;
if (bind(sd, (struct sockaddr*)&addr, sizeof(addr)) != 0)
{
perror("can't bind port");
abort();
}
if (listen(sd, 10) != 0)
{
perror("Can't configure listening port");
abort();
}
listen(sd, SOMAXCONN);
return sd;
}

SSL_CTX* InitServerCTX(void)
{
SSL_CTX* ctx;

OpenSSL_add_all_algorithms(); /* load & register all cryptos, etc. */
SSL_load_error_strings(); /* load all error messages */

const SSL_METHOD* method = TLS_server_method(); /* Create new server-method instance */
ctx = SSL_CTX_new(method); /* create new context from method */
if (ctx == NULL)
{
ERR_print_errors_fp(stderr);
abort();
}

// TLS1.2
SSL_CTX_set_min_proto_version(ctx, TLS1_2_VERSION);
SSL_CTX_set_max_proto_version(ctx, TLS1_2_VERSION);

#ifdef SSL_OP_NO_RENEGOTIATION
SSL_CTX_clear_options(ctx, SSL_OP_NO_RENEGOTIATION);
#endif

const unsigned char sid_ctx[] = "MyServerSessionContext";
if (!SSL_CTX_set_session_id_context(ctx, sid_ctx, sizeof(sid_ctx) - 1)) {
ERR_print_errors_fp(stderr);
abort();
}
return ctx;
}

void LoadCertificates(SSL_CTX* ctx, const char* CertFile, const char* KeyFile, const char* CAFile)
{
SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, NULL);
SSL_CTX_set_verify_depth(ctx, 4);
if (SSL_CTX_load_verify_locations(ctx, CAFile, NULL) != 1) {
const char* err = ERR_reason_error_string(ERR_get_error());
printf("%s\n", err);
}

/* set the local certificate from CertFile */
if (SSL_CTX_use_certificate_file(ctx, CertFile, SSL_FILETYPE_PEM) = std::chrono::minutes(1)) {
printf("[Server] Trigger renegotiation...\n");

if (SSL_renegotiate(ssl) 0)
{
buf[n] = 0;
printf("Client msg: \"%s\"\n", buf);
sprintf_s(reply, HTMLecho, buf); /* construct reply */
SSL_write(ssl, reply, (int)strlen(reply)); /* send reply */
}
else {
int err = SSL_get_error(ssl, n);
if (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE) {
// next roop
}
else if (err == SSL_ERROR_ZERO_RETURN) {
printf("[Server] Peer closed connection.\n");
running = false;
}
else {
printf("[Server] SSL_read error.\n");
ERR_print_errors_fp(stderr);
running = false;
}

}
}
}
sd = SSL_get_fd(ssl); /* get socket connection */
SSL_free(ssl); /* release SSL state */
closesocket(sd); /* close connection */
}

int main()
{
SSL_CTX* ctx;
int server;
char portnum[] = "54000";

auto current_dir_path = fs::current_path();
auto pem_cert_file_path = current_dir_path / "Server_certificate.pem";
auto pem_pkey_file_path = current_dir_path / "Server_private_key.pem";
auto pem_ca_file_path = current_dir_path / "Client_CA_certificate.pem";

SSL_library_init();

ctx = InitServerCTX(); /* initialize SSL */
LoadCertificates(ctx,
pem_cert_file_path.string().c_str(),
pem_pkey_file_path.string().c_str(),
pem_ca_file_path.string().c_str()
); /* load certs */
printf("Certificate loaded\n");

server = OpenListener(atoi(portnum)); /* create server socket */
printf("Listener opened\n");

auto last_reneg = std::chrono::steady_clock::now();

while (1) {
struct sockaddr_in addr;
socklen_t len = sizeof(addr);

int client = (int)accept(server, (struct sockaddr*)&addr, &len); /* accept connection as usual */
printf("Accepted: Client %d\n", client);

std::thread th(&Servlet, ctx, client);
th.detach();
}

closesocket(server); /* close server socket */
SSL_CTX_free(ctx); /* release context */
}

/\* Server Console \*/

Certificate loaded
Listener opened
Accepted: Client 420
Client certificates:
Subject: /CN=Client
Issuer: /CN=Client
Client msg: "Hello from client #1"
Client msg: "Hello from client #2"
Client msg: "Hello from client #3"
Client msg: "Hello from client #4"
Client msg: "Hello from client #5"
Client msg: "Hello from client #6"
Client msg: "Hello from client #7"
\[Server\] Trigger renegotiation...
\[Server\] Renegotiation completed successfully (TLS1.2)
Client msg: "Hello from client #8"
\[Server\] SSL_read error.
/\* Client Console \*/
client certificate loaded
\[Client\] Sent: "Hello from client #1"
\[Client\] Received: "\\\Hello from client #1\\\
"
\[Client\] Sent: "Hello from client #2"
\[Client\] Received: "\\\Hello from client #2\\\
"
\[Client\] Sent: "Hello from client #3"
\[Client\] Received: "\\\Hello from client #3\\\
"
\[Client\] Sent: "Hello from client #4"
\[Client\] Received: "\\\Hello from client #4\\\
"
\[Client\] Sent: "Hello from client #5"
\[Client\] Received: "\\\Hello from client #5\\\
"
\[Client\] Sent: "Hello from client #6"
\[Client\] Received: "\\\Hello from client #6\\\
"
\[Client\] Sent: "Hello from client #7"
\[Client\] Received: "\\\Hello from client #7\\\
"
\[Client\] Sent: "Hello from client #8"
\[Client\] Received: "\[SERVER\] RENEGO-OK
"
\[Client\] Server renegotiation confirmed.
Client finishing renegotiation...


Подробнее здесь: https://stackoverflow.com/questions/798 ... -openssl-3
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «C++»