From 807c2bc385c5936f0c689dc47b6f72c70c683cf6 Mon Sep 17 00:00:00 2001 From: Michael Zanetti Date: Wed, 6 Sep 2017 14:23:18 +0200 Subject: [PATCH] move certificategerneator to a separate file --- server/certificategenerator.cpp | 113 ++++++++++++++++++++++++++++++++ server/certificategenerator.h | 36 ++++++++++ server/server.pri | 6 +- server/servermanager.cpp | 80 +--------------------- server/servermanager.h | 8 --- 5 files changed, 154 insertions(+), 89 deletions(-) create mode 100644 server/certificategenerator.cpp create mode 100644 server/certificategenerator.h diff --git a/server/certificategenerator.cpp b/server/certificategenerator.cpp new file mode 100644 index 00000000..f376a935 --- /dev/null +++ b/server/certificategenerator.cpp @@ -0,0 +1,113 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * * + * Copyright (C) 2017 Michael Zanetti * + * * + * This file is part of guh. * + * * + * Guh is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, version 2 of the License. * + * * + * Guh is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with guh. If not, see . * + * * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +#include "certificategenerator.h" + +#include "openssl/ssl.h" + +#include +#include +#include +#include +#include + +namespace guhserver { + +void CertificateGenerator::generate(const QString &certificateFilename, const QString &keyFilename) +{ + EVP_PKEY * pkey = nullptr; + RSA * rsa = nullptr; + X509 * x509 = nullptr; + X509_NAME * name = nullptr; + BIO * bp_public = nullptr, * bp_private = nullptr; + const char * buffer = nullptr; + long size; + + pkey = EVP_PKEY_new(); + q_check_ptr(pkey); + rsa = RSA_generate_key(2048, RSA_F4, nullptr, nullptr); + q_check_ptr(rsa); + EVP_PKEY_assign_RSA(pkey, rsa); + x509 = X509_new(); + q_check_ptr(x509); + // Randomize serial number in case a previous one is stuck in a browser (Chromium + // completely rejects reused serial numbers and doesn't even allow to bypass it by an exception) + qsrand(QUuid::createUuid().toString().remove(QRegExp("[a-zA-Z{}-]")).left(5).toInt()); + ASN1_INTEGER_set(X509_get_serialNumber(x509), qrand()); + X509_gmtime_adj(X509_get_notBefore(x509), 0); // not before current time + X509_gmtime_adj(X509_get_notAfter(x509), 31536000L*10); // not after 10 years from this point + X509_set_pubkey(x509, pkey); + name = X509_get_subject_name(x509); + q_check_ptr(name); + X509_NAME_add_entry_by_txt(name, "E", MBSTRING_ASC, (unsigned char *)"guh.io", -1, -1, 0); + X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_ASC, (unsigned char *)"guh.io", -1, -1, 0); + X509_NAME_add_entry_by_txt(name, "OU", MBSTRING_ASC, (unsigned char *)"home", -1, -1, 0); + X509_NAME_add_entry_by_txt(name, "O", MBSTRING_ASC, (unsigned char *)"guh.io", -1, -1, 0); + X509_NAME_add_entry_by_txt(name, "L", MBSTRING_ASC, (unsigned char *)"Vienna", -1, -1, 0); + X509_NAME_add_entry_by_txt(name, "C", MBSTRING_ASC, (unsigned char *)"AT", -1, -1, 0); + X509_set_issuer_name(x509, name); + X509_sign(x509, pkey, EVP_sha256()); + bp_private = BIO_new(BIO_s_mem()); + q_check_ptr(bp_private); + if(PEM_write_bio_PrivateKey(bp_private, pkey, nullptr, nullptr, 0, nullptr, nullptr) != 1) + { + EVP_PKEY_free(pkey); + X509_free(x509); + BIO_free_all(bp_private); + qFatal("PEM_write_bio_PrivateKey"); + } + bp_public = BIO_new(BIO_s_mem()); + q_check_ptr(bp_public); + if(PEM_write_bio_X509(bp_public, x509) != 1) + { + EVP_PKEY_free(pkey); + X509_free(x509); + BIO_free_all(bp_public); + BIO_free_all(bp_private); + qFatal("PEM_write_bio_X509"); + } + size = BIO_get_mem_data(bp_public, &buffer); + q_check_ptr(buffer); + QFileInfo certFi(certificateFilename); + QDir dir; + QFile certfile(certificateFilename); + if (!dir.mkpath(certFi.absolutePath()) || !certfile.open(QFile::WriteOnly | QFile::Truncate) || certfile.write(buffer, size) != size) { + qWarning() << "Error writing certificate file" << certificateFilename; + } + certfile.close(); + + size = BIO_get_mem_data(bp_private, &buffer); + q_check_ptr(buffer); + QFileInfo keyFi(keyFilename); + QFile keyFile(keyFilename); + if (!dir.mkpath(keyFi.absolutePath()) || !keyFile.open(QFile::WriteOnly | QFile::Truncate) || keyFile.write(buffer, size) != size) { + qWarning() << "Error writing key file" << keyFilename; + } + keyFile.close(); + + EVP_PKEY_free(pkey); // this will also free the rsa key + X509_free(x509); + BIO_free_all(bp_public); + BIO_free_all(bp_private); + +} + +} + diff --git a/server/certificategenerator.h b/server/certificategenerator.h new file mode 100644 index 00000000..32a25274 --- /dev/null +++ b/server/certificategenerator.h @@ -0,0 +1,36 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * * + * Copyright (C) 2017 Michael Zanetti * + * * + * This file is part of guh. * + * * + * Guh is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, version 2 of the License. * + * * + * Guh is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with guh. If not, see . * + * * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +#ifndef CERTIFICATEGENERATOR_H +#define CERTIFICATEGENERATOR_H + +#include + +namespace guhserver { + +class CertificateGenerator +{ +public: + static void generate(const QString &certificateFilename, const QString &keyFilename); +}; + +} + +#endif // CERTIFICATEGENERATOR_H diff --git a/server/server.pri b/server/server.pri index 0091880a..c2eda1f2 100644 --- a/server/server.pri +++ b/server/server.pri @@ -57,7 +57,8 @@ HEADERS += $$top_srcdir/server/guhcore.h \ $$top_srcdir/server/networkmanager/networkconnection.h \ $$top_srcdir/server/networkmanager/wirednetworkdevice.h \ $$top_srcdir/server/usermanager.h \ - $$top_srcdir/server/tokeninfo.h + $$top_srcdir/server/tokeninfo.h \ + $$PWD/certificategenerator.h SOURCES += $$top_srcdir/server/guhcore.cpp \ @@ -114,5 +115,6 @@ SOURCES += $$top_srcdir/server/guhcore.cpp \ $$top_srcdir/server/networkmanager/networkconnection.cpp \ $$top_srcdir/server/networkmanager/wirednetworkdevice.cpp \ $$top_srcdir/server/usermanager.cpp \ - $$top_srcdir/server/tokeninfo.cpp + $$top_srcdir/server/tokeninfo.cpp \ + $$PWD/certificategenerator.cpp diff --git a/server/servermanager.cpp b/server/servermanager.cpp index ab271750..2cc4611e 100644 --- a/server/servermanager.cpp +++ b/server/servermanager.cpp @@ -35,6 +35,7 @@ #include "servermanager.h" #include "guhcore.h" +#include "certificategenerator.h" #include #include @@ -171,83 +172,4 @@ bool ServerManager::loadCertificate(const QString &certificateKeyFileName, const return true; } -void CertificateGenerator::generate(const QString &certificateFilename, const QString &keyFilename) -{ - EVP_PKEY * pkey = nullptr; - RSA * rsa = nullptr; - X509 * x509 = nullptr; - X509_NAME * name = nullptr; - BIO * bp_public = nullptr, * bp_private = nullptr; - const char * buffer = nullptr; - long size; - - pkey = EVP_PKEY_new(); - q_check_ptr(pkey); - rsa = RSA_generate_key(2048, RSA_F4, nullptr, nullptr); - q_check_ptr(rsa); - EVP_PKEY_assign_RSA(pkey, rsa); - x509 = X509_new(); - q_check_ptr(x509); - // Randomize serial number in case a previous one is stuck in a browser (Chromium - // completely rejects reused serial numbers and doesn't even allow to bypass it by an exception) - qsrand(QUuid::createUuid().toString().remove(QRegExp("[a-zA-Z{}-]")).left(5).toInt()); - ASN1_INTEGER_set(X509_get_serialNumber(x509), qrand()); - X509_gmtime_adj(X509_get_notBefore(x509), 0); // not before current time - X509_gmtime_adj(X509_get_notAfter(x509), 31536000L*10); // not after 10 years from this point - X509_set_pubkey(x509, pkey); - name = X509_get_subject_name(x509); - q_check_ptr(name); - X509_NAME_add_entry_by_txt(name, "E", MBSTRING_ASC, (unsigned char *)"guh.io", -1, -1, 0); - X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_ASC, (unsigned char *)"guh.io", -1, -1, 0); - X509_NAME_add_entry_by_txt(name, "OU", MBSTRING_ASC, (unsigned char *)"home", -1, -1, 0); - X509_NAME_add_entry_by_txt(name, "O", MBSTRING_ASC, (unsigned char *)"guh.io", -1, -1, 0); - X509_NAME_add_entry_by_txt(name, "L", MBSTRING_ASC, (unsigned char *)"Vienna", -1, -1, 0); - X509_NAME_add_entry_by_txt(name, "C", MBSTRING_ASC, (unsigned char *)"AT", -1, -1, 0); - X509_set_issuer_name(x509, name); - X509_sign(x509, pkey, EVP_sha256()); - bp_private = BIO_new(BIO_s_mem()); - q_check_ptr(bp_private); - if(PEM_write_bio_PrivateKey(bp_private, pkey, nullptr, nullptr, 0, nullptr, nullptr) != 1) - { - EVP_PKEY_free(pkey); - X509_free(x509); - BIO_free_all(bp_private); - qFatal("PEM_write_bio_PrivateKey"); - } - bp_public = BIO_new(BIO_s_mem()); - q_check_ptr(bp_public); - if(PEM_write_bio_X509(bp_public, x509) != 1) - { - EVP_PKEY_free(pkey); - X509_free(x509); - BIO_free_all(bp_public); - BIO_free_all(bp_private); - qFatal("PEM_write_bio_X509"); - } - size = BIO_get_mem_data(bp_public, &buffer); - q_check_ptr(buffer); - QFileInfo certFi(certificateFilename); - QDir dir; - QFile certfile(certificateFilename); - if (!dir.mkpath(certFi.absolutePath()) || !certfile.open(QFile::WriteOnly | QFile::Truncate) || certfile.write(buffer, size) != size) { - qWarning() << "Error writing certificate file" << certificateFilename; - } - certfile.close(); - - size = BIO_get_mem_data(bp_private, &buffer); - q_check_ptr(buffer); - QFileInfo keyFi(keyFilename); - QFile keyFile(keyFilename); - if (!dir.mkpath(keyFi.absolutePath()) || !keyFile.open(QFile::WriteOnly | QFile::Truncate) || keyFile.write(buffer, size) != size) { - qWarning() << "Error writing key file" << keyFilename; - } - keyFile.close(); - - EVP_PKEY_free(pkey); // this will also free the rsa key - X509_free(x509); - BIO_free_all(bp_public); - BIO_free_all(bp_private); - -} - } diff --git a/server/servermanager.h b/server/servermanager.h index 414545c5..401ef7a5 100644 --- a/server/servermanager.h +++ b/server/servermanager.h @@ -35,8 +35,6 @@ #include "mocktcpserver.h" #endif -#include "openssl/ssl.h" - class QSslConfiguration; class QSslCertificate; class QSslKey; @@ -87,12 +85,6 @@ private: bool loadCertificate(const QString &certificateKeyFileName, const QString &certificateFileName); }; - -class CertificateGenerator -{ -public: - static void generate(const QString &certificateFilename, const QString &keyFilename); -}; } #endif // SERVERMANAGER_H