mirror of
https://github.com/debauchee/barrier.git
synced 2026-05-11 00:58:14 +08:00
Use openssl library instead of CLI to generate certificates
This commit is contained in:
@@ -30,16 +30,8 @@
|
||||
#include <openssl/pem.h>
|
||||
#include <openssl/x509.h>
|
||||
|
||||
static const char kCertificateLifetime[] = "365";
|
||||
static const char kCertificateSubjectInfo[] = "/CN=Barrier";
|
||||
static const char kCertificateFilename[] = "Barrier.pem";
|
||||
static const char kSslDir[] = "SSL";
|
||||
static const char kUnixOpenSslCommand[] = "openssl";
|
||||
|
||||
#if defined(Q_OS_WIN)
|
||||
static const char kWinOpenSslBinary[] = "openssl.exe";
|
||||
static const char kConfigFile[] = "barrier.conf";
|
||||
#endif
|
||||
|
||||
SslCertificate::SslCertificate(QObject *parent) :
|
||||
QObject(parent)
|
||||
@@ -50,93 +42,21 @@ SslCertificate::SslCertificate(QObject *parent) :
|
||||
}
|
||||
}
|
||||
|
||||
std::pair<bool, std::string> SslCertificate::runTool(const QStringList& args)
|
||||
{
|
||||
QString program;
|
||||
#if defined(Q_OS_WIN)
|
||||
program = QCoreApplication::applicationDirPath();
|
||||
program.append("\\").append(kWinOpenSslBinary);
|
||||
#else
|
||||
program = kUnixOpenSslCommand;
|
||||
#endif
|
||||
|
||||
|
||||
QStringList environment;
|
||||
#if defined(Q_OS_WIN)
|
||||
environment << QString("OPENSSL_CONF=%1\\%2")
|
||||
.arg(QCoreApplication::applicationDirPath())
|
||||
.arg(kConfigFile);
|
||||
#endif
|
||||
|
||||
QProcess process;
|
||||
process.setEnvironment(environment);
|
||||
process.start(program, args);
|
||||
|
||||
bool success = process.waitForStarted();
|
||||
std::string output;
|
||||
|
||||
QString standardError;
|
||||
if (success && process.waitForFinished())
|
||||
{
|
||||
output = process.readAllStandardOutput().trimmed().toStdString();
|
||||
standardError = process.readAllStandardError().trimmed();
|
||||
}
|
||||
|
||||
int code = process.exitCode();
|
||||
if (!success || code != 0)
|
||||
{
|
||||
emit error(
|
||||
QString("SSL tool failed: %1\n\nCode: %2\nError: %3")
|
||||
.arg(program)
|
||||
.arg(process.exitCode())
|
||||
.arg(standardError.isEmpty() ? "Unknown" : standardError));
|
||||
return {false, output};
|
||||
}
|
||||
|
||||
return {true, output};
|
||||
}
|
||||
|
||||
void SslCertificate::generateCertificate()
|
||||
{
|
||||
auto filename = QString::fromStdString(getCertificatePath());
|
||||
|
||||
QFile file(filename);
|
||||
if (!file.exists() || !isCertificateValid(filename)) {
|
||||
QStringList arguments;
|
||||
|
||||
// self signed certificate
|
||||
arguments.append("req");
|
||||
arguments.append("-x509");
|
||||
arguments.append("-nodes");
|
||||
|
||||
// valid duration
|
||||
arguments.append("-days");
|
||||
arguments.append(kCertificateLifetime);
|
||||
|
||||
// subject information
|
||||
arguments.append("-subj");
|
||||
|
||||
QString subInfo(kCertificateSubjectInfo);
|
||||
arguments.append(subInfo);
|
||||
|
||||
// private key
|
||||
arguments.append("-newkey");
|
||||
arguments.append("rsa:2048");
|
||||
|
||||
QDir sslDir(QString::fromStdString(getCertificateDirectory()));
|
||||
if (!sslDir.exists()) {
|
||||
sslDir.mkpath(".");
|
||||
}
|
||||
|
||||
// key output filename
|
||||
arguments.append("-keyout");
|
||||
arguments.append(filename);
|
||||
|
||||
// certificate output filename
|
||||
arguments.append("-out");
|
||||
arguments.append(filename);
|
||||
|
||||
if (!runTool(arguments).first) {
|
||||
try {
|
||||
barrier::generate_pem_self_signed_cert(filename.toStdString());
|
||||
} catch (const std::exception& e) {
|
||||
emit error(QString("SSL tool failed: %1").arg(e.what()));
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
#include "base/finally.h"
|
||||
#include "io/fstream.h"
|
||||
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/x509.h>
|
||||
#include <openssl/x509v3.h>
|
||||
#include <openssl/pem.h>
|
||||
@@ -97,4 +98,48 @@ std::vector<std::uint8_t> get_pem_file_cert_fingerprint(const std::string& path,
|
||||
return get_ssl_cert_fingerprint(cert, type);
|
||||
}
|
||||
|
||||
void generate_pem_self_signed_cert(const std::string& path)
|
||||
{
|
||||
auto expiration_days = 365;
|
||||
|
||||
auto* private_key = EVP_PKEY_new();
|
||||
if (!private_key) {
|
||||
throw std::runtime_error("Could not allocate private key for certificate");
|
||||
}
|
||||
auto private_key_free = finally([private_key](){ EVP_PKEY_free(private_key); });
|
||||
|
||||
auto* rsa = RSA_generate_key(2048, RSA_F4, nullptr, nullptr);
|
||||
if (!rsa) {
|
||||
throw std::runtime_error("Failed to generate RSA key");
|
||||
}
|
||||
EVP_PKEY_assign_RSA(private_key, rsa);
|
||||
|
||||
auto* cert = X509_new();
|
||||
if (!cert) {
|
||||
throw std::runtime_error("Could not allocate certificate");
|
||||
}
|
||||
auto cert_free = finally([cert]() { X509_free(cert); });
|
||||
|
||||
ASN1_INTEGER_set(X509_get_serialNumber(cert), 1);
|
||||
X509_gmtime_adj(X509_get_notBefore(cert), 0);
|
||||
X509_gmtime_adj(X509_get_notAfter(cert), expiration_days * 24 * 3600);
|
||||
X509_set_pubkey(cert, private_key);
|
||||
|
||||
auto* name = X509_get_subject_name(cert);
|
||||
X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_ASC,
|
||||
reinterpret_cast<const unsigned char *>("Barrier"), -1, -1, 0);
|
||||
X509_set_issuer_name(cert, name);
|
||||
|
||||
X509_sign(cert, private_key, EVP_sha256());
|
||||
|
||||
auto fp = fopen_utf8_path(path.c_str(), "r");
|
||||
if (!fp) {
|
||||
throw std::runtime_error("Could not open certificate output path");
|
||||
}
|
||||
auto file_close = finally([fp]() { std::fclose(fp); });
|
||||
|
||||
PEM_write_PrivateKey(fp, private_key, nullptr, nullptr, 0, nullptr, nullptr);
|
||||
PEM_write_X509(fp, cert);
|
||||
}
|
||||
|
||||
} // namespace barrier
|
||||
|
||||
@@ -38,6 +38,8 @@ std::vector<std::uint8_t> get_ssl_cert_fingerprint(X509* cert, FingerprintType t
|
||||
std::vector<std::uint8_t> get_pem_file_cert_fingerprint(const std::string& path,
|
||||
FingerprintType type);
|
||||
|
||||
void generate_pem_self_signed_cert(const std::string& path);
|
||||
|
||||
} // namespace barrier
|
||||
|
||||
#endif // BARRIER_LIB_NET_SECUREUTILS_H
|
||||
|
||||
Reference in New Issue
Block a user