mirror of
https://github.com/Telecominfraproject/wlan-cloud-ucentralfms.git
synced 2026-01-12 23:05:03 +00:00
268 lines
12 KiB
C++
268 lines
12 KiB
C++
//
|
|
// License type: BSD 3-Clause License
|
|
// License copy: https://github.com/Telecominfraproject/wlan-cloud-ucentralgw/blob/master/LICENSE
|
|
//
|
|
// Created by Stephane Bourque on 2021-03-04.
|
|
// Arilia Wireless Inc.
|
|
//
|
|
|
|
#include "uSubSystemServer.h"
|
|
#include "uFirmwareDS.h"
|
|
|
|
#include "Poco/Net/X509Certificate.h"
|
|
#include "Poco/DateTimeFormatter.h"
|
|
#include "Poco/DateTimeFormat.h"
|
|
|
|
#include "openssl/ssl.h"
|
|
|
|
uSubSystemServer::uSubSystemServer( std::string Name,
|
|
const std::string & LoggingPrefix,
|
|
std::string SubSystemConfigPrefix )
|
|
: Name_(std::move(Name)),
|
|
Logger_(Poco::Logger::get(LoggingPrefix)),
|
|
SubSystemConfigPrefix_(std::move(SubSystemConfigPrefix))
|
|
{
|
|
Logger_.setLevel(Poco::Message::PRIO_NOTICE);
|
|
}
|
|
|
|
void uSubSystemServer::initialize(Poco::Util::Application & self)
|
|
{
|
|
Logger_.notice("Initializing...");
|
|
auto i=0;
|
|
bool good=true;
|
|
|
|
while(good) {
|
|
std::string root{SubSystemConfigPrefix_ + ".host." + std::to_string(i) + "."};
|
|
|
|
std::string address{root + "address"};
|
|
if(uCentral::ServiceConfig::GetString(address,"").empty()) {
|
|
good = false;
|
|
}
|
|
else {
|
|
std::string port{root + "port"};
|
|
std::string key{root + "key"};
|
|
std::string key_password{root + "key.password"};
|
|
std::string cert{root + "cert"};
|
|
std::string name{root + "name"};
|
|
std::string x509{root+"x509"};
|
|
std::string backlog{root+"backlog"};
|
|
std::string rootca{root+"rootca"};
|
|
std::string issuer{root+"issuer"};
|
|
std::string clientcas(root+"clientcas");
|
|
std::string cas{root+"cas"};
|
|
|
|
std::string level{root+"security"};
|
|
Poco::Net::Context::VerificationMode M=Poco::Net::Context::VERIFY_RELAXED;
|
|
|
|
auto L = uCentral::ServiceConfig::GetString(level,"");
|
|
|
|
if(L=="strict") {
|
|
M=Poco::Net::Context::VERIFY_STRICT;
|
|
} else if(L=="none") {
|
|
M=Poco::Net::Context::VERIFY_NONE;
|
|
} else if(L=="relaxed") {
|
|
M=Poco::Net::Context::VERIFY_RELAXED;
|
|
} else if(L=="once")
|
|
M=Poco::Net::Context::VERIFY_ONCE;
|
|
|
|
PropertiesFileServerEntry entry( uCentral::ServiceConfig::GetString(address,""),
|
|
uCentral::ServiceConfig::GetInt(port,0),
|
|
uCentral::ServiceConfig::GetString(key,""),
|
|
uCentral::ServiceConfig::GetString(cert,""),
|
|
uCentral::ServiceConfig::GetString(rootca,""),
|
|
uCentral::ServiceConfig::GetString(issuer,""),
|
|
uCentral::ServiceConfig::GetString(clientcas,""),
|
|
uCentral::ServiceConfig::GetString(cas,""),
|
|
uCentral::ServiceConfig::GetString(key_password,""),
|
|
uCentral::ServiceConfig::GetString(name,""),
|
|
uCentral::ServiceConfig::GetBool(x509,false),
|
|
M,
|
|
(int) uCentral::ServiceConfig::GetInt(backlog,64));
|
|
ConfigServersList_.push_back(entry);
|
|
i++;
|
|
}
|
|
}
|
|
}
|
|
|
|
void uSubSystemServer::uninitialize()
|
|
{
|
|
}
|
|
|
|
void uSubSystemServer::reinitialize(Poco::Util::Application & self)
|
|
{
|
|
// add your own reinitialization code here
|
|
}
|
|
|
|
void uSubSystemServer::defineOptions(Poco::Util::OptionSet& options)
|
|
{
|
|
}
|
|
|
|
Poco::Net::SecureServerSocket PropertiesFileServerEntry::CreateSecureSocket(Poco::Logger & L) const
|
|
{
|
|
Poco::Net::Context::Params P;
|
|
|
|
P.verificationMode = level_;
|
|
P.verificationDepth = 9;
|
|
P.loadDefaultCAs = root_ca_.empty();
|
|
P.cipherList = "ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH";
|
|
P.dhUse2048Bits = true;
|
|
P.caLocation = cas_;
|
|
|
|
auto Context = new Poco::Net::Context(Poco::Net::Context::TLS_SERVER_USE, P);
|
|
|
|
if(!cert_file_.empty() && !key_file_.empty()) {
|
|
Poco::Crypto::X509Certificate Cert(cert_file_);
|
|
Poco::Crypto::X509Certificate Root(root_ca_);
|
|
|
|
Context->useCertificate(Cert);
|
|
Context->addChainCertificate(Root);
|
|
|
|
Context->addCertificateAuthority(Root);
|
|
|
|
if (level_ == Poco::Net::Context::VERIFY_STRICT) {
|
|
if (issuer_cert_file_.empty()) {
|
|
L.fatal("In strict mode, you must supply ans issuer certificate");
|
|
}
|
|
if(client_cas_.empty()) {
|
|
L.fatal("In strict mode, client cas must be supplied");
|
|
}
|
|
Poco::Crypto::X509Certificate Issuing(issuer_cert_file_);
|
|
Context->addChainCertificate(Issuing);
|
|
Context->addCertificateAuthority(Issuing);
|
|
}
|
|
|
|
Poco::Crypto::RSAKey Key("", key_file_, "");
|
|
Context->usePrivateKey(Key);
|
|
|
|
SSL_CTX *SSLCtx = Context->sslContext();
|
|
if (!SSL_CTX_check_private_key(SSLCtx)) {
|
|
L.fatal(Poco::format("Wrong Certificate(%s) for Key(%s)", cert_file_, key_file_));
|
|
}
|
|
|
|
SSL_CTX_set_verify(SSLCtx, SSL_VERIFY_PEER, nullptr);
|
|
|
|
if(level_==Poco::Net::Context::VERIFY_STRICT) {
|
|
SSL_CTX_set_client_CA_list(SSLCtx, SSL_load_client_CA_file(client_cas_.c_str()));
|
|
}
|
|
SSL_CTX_enable_ct(SSLCtx, SSL_CT_VALIDATION_STRICT);
|
|
SSL_CTX_dane_enable(SSLCtx);
|
|
|
|
Context->enableSessionCache();
|
|
Context->setSessionCacheSize(0);
|
|
Context->setSessionTimeout(10);
|
|
Context->enableExtendedCertificateVerification(true);
|
|
Context->disableStatelessSessionResumption();
|
|
}
|
|
|
|
if (address_ == "*") {
|
|
Poco::Net::IPAddress Addr(Poco::Net::IPAddress::wildcard(Poco::Net::Socket::supportsIPv6() ? Poco::Net::AddressFamily::IPv6 : Poco::Net::AddressFamily::IPv4 ));
|
|
Poco::Net::SocketAddress SockAddr(Addr, port_);
|
|
|
|
return Poco::Net::SecureServerSocket(SockAddr, backlog_, Context);
|
|
}
|
|
else {
|
|
Poco::Net::IPAddress Addr(address_);
|
|
Poco::Net::SocketAddress SockAddr(Addr, port_);
|
|
|
|
return Poco::Net::SecureServerSocket(SockAddr, backlog_, Context);
|
|
}
|
|
}
|
|
|
|
void PropertiesFileServerEntry::LogCertInfo(Poco::Logger &L, const Poco::Crypto::X509Certificate &C) {
|
|
|
|
L.information("=============================================================================================");
|
|
L.information(Poco::format("> Issuer: %s",C.issuerName()));
|
|
L.information("---------------------------------------------------------------------------------------------");
|
|
L.information(Poco::format("> Common Name: %s",C.issuerName(Poco::Crypto::X509Certificate::NID_COMMON_NAME)));
|
|
L.information(Poco::format("> Country: %s",C.issuerName(Poco::Crypto::X509Certificate::NID_COUNTRY)));
|
|
L.information(Poco::format("> Locality: %s",C.issuerName(Poco::Crypto::X509Certificate::NID_LOCALITY_NAME)));
|
|
L.information(Poco::format("> State/Prov: %s",C.issuerName(Poco::Crypto::X509Certificate::NID_STATE_OR_PROVINCE)));
|
|
L.information(Poco::format("> Org name: %s",C.issuerName(Poco::Crypto::X509Certificate::NID_ORGANIZATION_NAME)));
|
|
L.information(Poco::format("> Org unit: %s",C.issuerName(Poco::Crypto::X509Certificate::NID_ORGANIZATION_UNIT_NAME)));
|
|
L.information(Poco::format("> Email: %s",C.issuerName(Poco::Crypto::X509Certificate::NID_PKCS9_EMAIL_ADDRESS)));
|
|
L.information(Poco::format("> Serial#: %s",C.issuerName(Poco::Crypto::X509Certificate::NID_SERIAL_NUMBER)));
|
|
L.information("---------------------------------------------------------------------------------------------");
|
|
L.information(Poco::format("> Subject: %s",C.subjectName()));
|
|
L.information("---------------------------------------------------------------------------------------------");
|
|
L.information(Poco::format("> Common Name: %s",C.subjectName(Poco::Crypto::X509Certificate::NID_COMMON_NAME)));
|
|
L.information(Poco::format("> Country: %s",C.subjectName(Poco::Crypto::X509Certificate::NID_COUNTRY)));
|
|
L.information(Poco::format("> Locality: %s",C.subjectName(Poco::Crypto::X509Certificate::NID_LOCALITY_NAME)));
|
|
L.information(Poco::format("> State/Prov: %s",C.subjectName(Poco::Crypto::X509Certificate::NID_STATE_OR_PROVINCE)));
|
|
L.information(Poco::format("> Org name: %s",C.subjectName(Poco::Crypto::X509Certificate::NID_ORGANIZATION_NAME)));
|
|
L.information(Poco::format("> Org unit: %s",C.subjectName(Poco::Crypto::X509Certificate::NID_ORGANIZATION_UNIT_NAME)));
|
|
L.information(Poco::format("> Email: %s",C.subjectName(Poco::Crypto::X509Certificate::NID_PKCS9_EMAIL_ADDRESS)));
|
|
L.information(Poco::format("> Serial#: %s",C.subjectName(Poco::Crypto::X509Certificate::NID_SERIAL_NUMBER)));
|
|
L.information("---------------------------------------------------------------------------------------------");
|
|
L.information(Poco::format("> Signature Algo: %s",C.signatureAlgorithm()));
|
|
auto From = Poco::DateTimeFormatter::format(C.validFrom(),Poco::DateTimeFormat::HTTP_FORMAT);
|
|
L.information(Poco::format("> Valid from: %s",From));
|
|
auto Expires = Poco::DateTimeFormatter::format(C.expiresOn(),Poco::DateTimeFormat::HTTP_FORMAT);
|
|
L.information(Poco::format("> Expires on: %s",Expires));
|
|
L.information(Poco::format("> Version: %d",(int)C.version()));
|
|
L.information(Poco::format("> Serial #: %s",C.serialNumber()));
|
|
L.information("=============================================================================================");
|
|
}
|
|
|
|
void PropertiesFileServerEntry::LogCert(Poco::Logger & L) const {
|
|
try {
|
|
Poco::Crypto::X509Certificate C(cert_file_);
|
|
L.information("=============================================================================================");
|
|
L.information("=============================================================================================");
|
|
L.information(Poco::format("Certificate Filename: %s",cert_file_));
|
|
LogCertInfo(L,C);
|
|
L.information("=============================================================================================");
|
|
|
|
if(!issuer_cert_file_.empty()) {
|
|
Poco::Crypto::X509Certificate C1(issuer_cert_file_);
|
|
L.information("=============================================================================================");
|
|
L.information("=============================================================================================");
|
|
L.information(Poco::format("Issues Certificate Filename: %s",issuer_cert_file_));
|
|
LogCertInfo(L,C1);
|
|
L.information("=============================================================================================");
|
|
}
|
|
|
|
if(!client_cas_.empty()) {
|
|
std::vector<Poco::Crypto::X509Certificate> Certs=Poco::Net::X509Certificate::readPEM(client_cas_);
|
|
|
|
L.information("=============================================================================================");
|
|
L.information("=============================================================================================");
|
|
L.information(Poco::format("Client CAs Filename: %s",client_cas_));
|
|
L.information("=============================================================================================");
|
|
auto i=1;
|
|
for(const auto & C3 : Certs)
|
|
{
|
|
L.information(Poco::format(" Index: %d",i));
|
|
L.information("=============================================================================================");
|
|
LogCertInfo(L, C3);
|
|
i++;
|
|
}
|
|
L.information("=============================================================================================");
|
|
}
|
|
|
|
} catch( const Poco::Exception & E) {
|
|
L.log(E);
|
|
}
|
|
}
|
|
|
|
void PropertiesFileServerEntry::LogCas(Poco::Logger & L) const {
|
|
try {
|
|
std::vector<Poco::Crypto::X509Certificate> Certs=Poco::Net::X509Certificate::readPEM(root_ca_);
|
|
|
|
L.information("=============================================================================================");
|
|
L.information("=============================================================================================");
|
|
L.information(Poco::format("CA Filename: %s",root_ca_));
|
|
L.information("=============================================================================================");
|
|
auto i=1;
|
|
for(const auto & C : Certs)
|
|
{
|
|
L.information(Poco::format(" Index: %d",i));
|
|
L.information("=============================================================================================");
|
|
LogCertInfo(L, C);
|
|
i++;
|
|
}
|
|
L.information("=============================================================================================");
|
|
} catch ( const Poco::Exception & E ) {
|
|
L.log(E);
|
|
}
|
|
}
|