OAuth2Lib/ssl.c

184 lines
4.5 KiB
C

#include "ssl.h"
#include "log.h"
#include <errno.h>
#include <unistd.h>
#include <openssl/core_names.h>
#include <openssl/err.h>
#include <openssl/evp.h>
#include <openssl/ssl.h>
#include <openssl/x509.h>
#define LOG_NAME "SSL"
static bool _initialized = false;
static SSL_CTX* _ssl_ctx = NULL;
static EVP_MD* _sha256_ctx = NULL;
static const char _pkey_file_name[] = "key.pem";
static const char _cert_file_name[] = "cert.pem";
static const char _passphrase[] = "This is absolutely insecure.";
static int _pem_passphrase_cb(char* buf, int size, int rwflag, void* userdata) {
int len = strlen(_passphrase);
memcpy(buf, _passphrase, len < size ? len : size);
return len;
}
bool _initialize_ssl() {
SSL_library_init();
SSL_load_error_strings();
_ssl_ctx = SSL_CTX_new(TLS_client_method());
if (_ssl_ctx == NULL) {
fprintf(stderr, "Failed to initialize Openssl.\n");
return false;
}
SSL_CTX_set_verify(_ssl_ctx, SSL_VERIFY_PEER, NULL);
if (!SSL_CTX_set_default_verify_paths(_ssl_ctx)) {
fprintf(stderr, "Failed to set default paths for openssl.\n");
return false;
}
if (!SSL_CTX_set_min_proto_version(_ssl_ctx, TLS1_3_VERSION)) {
fprintf(stderr, "Failed to set minimum TLS version.\n");
return false;
}
return true;
}
bool initialize_ssl() {
if (!_initialized) {
_initialized = _initialize_ssl();
}
return _initialized;
}
void ssl_close_ssl() {
SSL_CTX_free(_ssl_ctx);
EVP_MD_free(_sha256_ctx);
}
SSL_CTX* ssl_get_ctx() { return _ssl_ctx; }
EVP_MD* ssl_get_sha256() { return _sha256_ctx; }
bool ssl_generate_cert() {
EVP_PKEY* pkey = NULL;
X509* cert = NULL;
X509_NAME* cert_issuer;
bool success = false;
pkey = EVP_EC_gen("P-256");
if (pkey == NULL) {
log_log_ssl_err(LOG_NAME, LOG_ERR, "Failed to generate private key for certificate.");
goto generate_cert_cleanup;
}
cert = X509_new();
if (cert == NULL) {
log_log_ssl_err(LOG_NAME, LOG_ERR, "Failed to generate certificate.");
goto generate_cert_cleanup;
}
ASN1_INTEGER_set(X509_get_serialNumber(cert), 1);
X509_gmtime_adj(X509_get_notBefore(cert), 0);
X509_gmtime_adj(X509_get_notAfter(cert), 31536000L);
cert_issuer = X509_get_subject_name(cert);
if (cert_issuer == NULL ||
!( X509_NAME_add_entry_by_txt(cert_issuer, "C", MBSTRING_ASC, (unsigned char*)"AT", -1, -1, 0)
&& X509_NAME_add_entry_by_txt(cert_issuer, "O", MBSTRING_ASC, (unsigned char*)"me", -1, -1, 0)
&& X509_NAME_add_entry_by_txt(cert_issuer, "CN", MBSTRING_ASC, (unsigned char*)"localhost", -1, -1, 0))) {
log_log_ssl_err(LOG_NAME, LOG_ERR, "Failed to create issuer name.");
goto generate_cert_cleanup;
}
if (!X509_set_issuer_name(cert, cert_issuer)) {
log_log_ssl_err(LOG_NAME, LOG_ERR, "Failed to set issuer name on certificate.");
goto generate_cert_cleanup;
}
if (!X509_set_pubkey(cert, pkey)) {
log_log_ssl_err(LOG_NAME, LOG_ERR, "Failed to set private key on certificate");
goto generate_cert_cleanup;
}
if (!X509_sign(cert, pkey, EVP_sha256())) {
log_log_ssl_err(LOG_NAME, LOG_ERR, "Failed to sign certificate.");
goto generate_cert_cleanup;
}
FILE* key_file = NULL;
key_file = fopen(_pkey_file_name, "wb");
if (!PEM_write_PrivateKey(key_file, pkey, EVP_des_ede3_cbc(), (unsigned char*)_passphrase, sizeof(_passphrase), NULL, NULL)) {
log_log_ssl_err(LOG_NAME, LOG_ERR, "Failed to write private certificate to disk.");
fclose(key_file);
goto generate_cert_cleanup;
}
fclose(key_file);
key_file = fopen(_cert_file_name, "wb");
if (!PEM_write_X509(key_file, cert)) {
log_log_ssl_err(LOG_NAME, LOG_ERR, "Failed to write certificate to disk.");
fclose(key_file);
goto generate_cert_cleanup;
}
fclose(key_file);
success = true;
generate_cert_cleanup:
EVP_PKEY_free(pkey);
X509_free(cert);
X509_NAME_free(cert_issuer);
return success;
}
bool ssl_use_ppcerts(SSL_CTX* ctx) {
if (access(_cert_file_name, R_OK) != 0 && access(_pkey_file_name, R_OK) != 0) {
log_log(LOG_NAME, LOG_INFO, "Could not access certificates - Generating new ones");
bool res = ssl_generate_cert();
if (!res) {
log_log(LOG_NAME, LOG_ERR, "Failed to generate certificates");
return false;
}
}
if (SSL_CTX_use_certificate_chain_file(ctx, _cert_file_name) != 1) {
log_log_ssl_err(LOG_NAME, LOG_ERR, "Failed to load SSL certificate.");
return false;
}
SSL_CTX_set_default_passwd_cb(ctx, _pem_passphrase_cb);
if (SSL_CTX_use_PrivateKey_file(ctx, _pkey_file_name, SSL_FILETYPE_PEM) != 1) {
log_log_ssl_err(LOG_NAME, LOG_ERR, "Failed to load SSL Private Key.");
return false;
}
SSL_CTX_set_default_passwd_cb(ctx, NULL);
return true;
}