Я написал C программу, которая защищает http traffi c с использованием библиотеки openssl:
#include <openssl/ssl.h>
#include <openssl/bio.h>
#include <openssl/err.h>
#include <openssl/crypto.h>
#include <openssl/bn.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#define IP_ADDR INADDR_ANY
#define PORT 8082
int password_cb(char *buf, int size, int rwflag, void *password);
EVP_PKEY *generatePrivateKey();
X509 *generateCertificate(EVP_PKEY *pkey);
/**
* Example SSL server that accepts a client and echos back anything it receives.
* Test using `curl -I https://10.10.10.101:443 --insecure --sslv3`
*/
int main(int arc, char **argv)
{
int fd = socket(AF_INET, SOCK_STREAM, 0);
if (fd < 0) {
printf("opening socket\n");
return -4;
}
struct sockaddr_in s_addr;
bzero((char *)&s_addr, sizeof(s_addr));
s_addr.sin_family = AF_INET;
s_addr.sin_addr.s_addr = IP_ADDR;
s_addr.sin_port = htons(PORT);
if (bind(fd, (struct sockaddr*)&s_addr, sizeof(s_addr)) < 0) {
printf("binding\n");
return -5;
}
listen(fd, 2);
int cfd;
while (cfd = accept(fd, 0, 0))
{
SSL_load_error_strings();
ERR_load_crypto_strings();
OpenSSL_add_all_algorithms();
SSL_library_init();
SSL_CTX *ctx = SSL_CTX_new(SSLv3_server_method());
//SSL_CTX *ctx = SSL_CTX_new(TLS_server_method());
if (ctx == NULL) {
printf("errored; unable to load context.\n");
ERR_print_errors_fp(stderr);
return -3;
}
EVP_PKEY *pkey = generatePrivateKey();
X509 *x509 = generateCertificate(pkey);
SSL_CTX_use_certificate(ctx, x509);
SSL_CTX_set_default_passwd_cb(ctx, password_cb);
SSL_CTX_use_PrivateKey(ctx, pkey);
RSA *rsa=RSA_generate_key(512, RSA_F4, NULL, NULL);
SSL_CTX_set_tmp_rsa(ctx, rsa);
RSA_free(rsa);
SSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, 0);
SSL *ssl = SSL_new(ctx);
BIO *accept_bio = BIO_new_socket(cfd, BIO_CLOSE);
SSL_set_bio(ssl, accept_bio, accept_bio);
int n = SSL_accept(ssl);
switch (SSL_get_error(ssl, n))
{
case SSL_ERROR_NONE:
printf("SSL_ERROR_NONE\n");
break;
case SSL_ERROR_ZERO_RETURN:
printf("SSL_ERROR_ZERO_RETURN\n");
goto end;
case SSL_ERROR_WANT_READ:
printf("SSL_ERROR_WANT_READ\n");
goto end;
case SSL_ERROR_WANT_WRITE:
printf("SSL_ERROR_WANT_WRITE\n");
goto end;
case SSL_ERROR_WANT_CONNECT:
printf("SSL_ERROR_WANT_CONNECT\n");
goto end;
case SSL_ERROR_WANT_ACCEPT:
printf("SSL_ERROR_WANT_ACCEPT\n");
goto end;
case SSL_ERROR_SSL:
printf("SSL_ERROR_SSL\n");
goto end;
case SSL_ERROR_SYSCALL:
printf("SSL_ERROR_SYSCALL\n");
goto end;
default:
printf("SSL accept problem\n");
goto end;
}*/
//printf("ssl accept return value : %d", n);
//ERR_print_errors_fp(stderr);
BIO *bio = BIO_pop(accept_bio);
char buf[1024];
while (1)
{
// first read data
int r = SSL_read(ssl, buf, 1024);
FILE *file1 = fopen("logfile", "a");
fprintf(file1, "len of read data : %d\n", r);
fprintf(file1, "content of read data : %s\n", buf);
fclose(file1);
int ssl_error = SSL_get_error(ssl, r);
fprintf(file1, " SSL_get_error : %d\n", ssl_error);
printf ("\nsize of read data : %d\n", r);
printf ("actual data : %s\n", buf);
switch (SSL_get_error(ssl, r))
{
case SSL_ERROR_NONE:
break;
case SSL_ERROR_ZERO_RETURN:
goto end;
default:
printf("SSL read problem");
goto end;
}
int len = r;
// now keep writing until we've written everything
int offset = 0;
while (len)
{
r = SSL_write(ssl, buf + offset, len);
switch (SSL_get_error(ssl, r))
{
case SSL_ERROR_NONE:
len -= r;
offset += r;
break;
default:
printf("SSL write problem");
goto end;
}
}
}
end:
SSL_shutdown(ssl);
BIO_free_all(bio);
BIO_free_all(accept_bio);
}
return 0;
}
int password_cb(char *buf, int size, int rwflag, void *password)
{
strncpy(buf, (char *)(password), size);
buf[size - 1] = '\0';
return strlen(buf);
}
EVP_PKEY *generatePrivateKey()
{
EVP_PKEY *pkey = NULL;
EVP_PKEY_CTX *pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_RSA, NULL);
EVP_PKEY_keygen_init(pctx);
EVP_PKEY_CTX_set_rsa_keygen_bits(pctx, 2048);
EVP_PKEY_keygen(pctx, &pkey);
return pkey;
}
X509 *generateCertificate(EVP_PKEY *pkey)
{
X509 *x509 = X509_new();
X509_set_version(x509, 2);
ASN1_INTEGER_set(X509_get_serialNumber(x509), 0);
X509_gmtime_adj(X509_get_notBefore(x509), 0);
X509_gmtime_adj(X509_get_notAfter(x509), (long)60*60*24*365);
X509_set_pubkey(x509, pkey);
X509_NAME *name = X509_get_subject_name(x509);
X509_NAME_add_entry_by_txt(name, "C", MBSTRING_ASC, (const unsigned char*)"US", -1, -1, 0);
X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_ASC, (const unsigned char*)"YourCN", -1, -1, 0);
X509_set_issuer_name(x509, name);
X509_sign(x509, pkey, EVP_md5());
return x509;
}
Я использую эту команду для подключения и тестирования программы:
curl -I https://10.10.10.101:443 --insecure --sslv3
Проблема в том, что строка int n = ssl_accept (ssl) возвращает -1 значение. Когда я использую get_ssl_error () , чтобы точно определить проблему, он показывает ssl_error_syscall .
, также я использую printf ("error:% s \ n" , strerror (errno)) после ssl_accept (), и я получаю это в качестве вывода:
bad file descriptor
Я искал эти сообщения. в ссылке https://linux.die.net/man/3/ssl_accept говорится, что значение -1, возвращаемое ssl_accept , равно:
Рукопожатие TLS / SSL не было успешным, потому что фатальное ошибка произошла либо на уровне протокола, либо произошел сбой соединения. Выключение не было чистым. Также может возникнуть действие, необходимо продолжить операцию для неблокирования B IOs. Вызовите SSL_get_error () с возвращаемым значением ret, чтобы выяснить причину.
также по ссылке https://man.openbsd.org/SSL_get_error.3, где говорится о ssl_error_syscall :
Произошла ошибка ввода-вывода. Очередь ошибок OpenSSL может содержать больше информации об ошибке. Если очередь ошибок пуста (т. Е. ERR_get_error () возвращает 0), ret можно использовать, чтобы узнать больше об ошибке: если ret == 0, наблюдался EOF, который нарушает протокол. Если ret == -1, базовый BIO сообщил об ошибке ввода / вывода (для ввода / вывода с сокетом в Unix системах обратитесь к errno для получения подробной информации).
Я новичок в C программирование и сокеты, и я не понял что-то полезное из приведенных выше ссылок. (например, что такое фатальная ошибка или чистое отключение) кто-нибудь может объяснить их простым способом или дать мне руководство, чтобы понять, что происходит? это связано с сетью или кодом?