void CoreIdentity::setSslKey(const QByteArray &encoded) { QSslKey key(encoded, QSsl::Rsa); #if QT_VERSION >= 0x050500 if (key.isNull()) key = QSslKey(encoded, QSsl::Ec); #endif if (key.isNull()) key = QSslKey(encoded, QSsl::Dsa); setSslKey(key); }
QSslKey Server::privateKeyFromPEM(const QByteArray &buf, const QByteArray &pass) { QSslKey key; key = QSslKey(buf, QSsl::Rsa, QSsl::Pem, QSsl::PrivateKey, pass); if (key.isNull()) key = QSslKey(buf, QSsl::Dsa, QSsl::Pem, QSsl::PrivateKey, pass); #if QT_VERSION >= 0x050500 if (key.isNull()) key = QSslKey(buf, QSsl::Ec, QSsl::Pem, QSsl::PrivateKey, pass); #endif return key; }
SslServer::SslServer(const QString &certFile, const QString &keyFile, QObject *parent) : QTcpServer(parent) { if(!QSslSocket::supportsSsl()) { logger::error() << "SSL support not available!"; return; } QFile cert(certFile); if(!cert.open(QFile::ReadOnly)) { logger::error() << "Couldn't open certificate:" << cert.errorString(); return; } QFile key(keyFile); if(!key.open(QFile::ReadOnly)) { logger::error() << "Couldn't open private key:" << key.errorString(); return; } _cert = QSslCertificate(&cert); if(_cert.isNull()) logger::error() << "Invalid certificate"; _key = QSslKey(&key, QSsl::Rsa); if(_key.isNull()) logger::error() << "Invalid private key"; }
void CoreIdentity::setSslKey(const QByteArray &encoded) { QSslKey key(encoded, QSsl::Rsa); if (key.isNull()) key = QSslKey(encoded, QSsl::Dsa); setSslKey(key); }
/*! Returns the certificate subject's public key. */ QSslKey QSslCertificate::publicKey() const { if (!d->x509) return QSslKey(); QSslKey key; key.d->type = QSsl::PublicKey; X509_PUBKEY *xkey = d->x509->cert_info->key; EVP_PKEY *pkey = q_X509_PUBKEY_get(xkey); Q_ASSERT(pkey); if (q_EVP_PKEY_type(pkey->type) == EVP_PKEY_RSA) { key.d->rsa = q_EVP_PKEY_get1_RSA(pkey); key.d->algorithm = QSsl::Rsa; key.d->isNull = false; } else if (q_EVP_PKEY_type(pkey->type) == EVP_PKEY_DSA) { key.d->dsa = q_EVP_PKEY_get1_DSA(pkey); key.d->algorithm = QSsl::Dsa; key.d->isNull = false; } else if (q_EVP_PKEY_type(pkey->type) == EVP_PKEY_DH) { // DH unsupported } else { // error? } q_EVP_PKEY_free(pkey); return key; }
bool RemoteDatabase::prepareSsl(QNetworkRequest* request, const QString& clientCert) { // Check if client cert exists const QSslCertificate& cert = m_clientCertFiles[clientCert]; if(cert.isNull()) { QMessageBox::warning(nullptr, qApp->applicationName(), tr("Error: Invalid client certificate specified.")); return false; } // Load private key for the client certificate QFile fileClientCert(clientCert); fileClientCert.open(QFile::ReadOnly); QSslKey clientKey(&fileClientCert, QSsl::Rsa, QSsl::Pem, QSsl::PrivateKey); while(clientKey.isNull()) { // If the private key couldn't be read, we assume it's password protected. So ask the user for the correct password and try reading it // again. If the user cancels the password dialog, abort the whole process. QString password = QInputDialog::getText(nullptr, qApp->applicationName(), tr("Please enter the passphrase for this client certificate in order to authenticate.")); if(password.isEmpty()) return false; clientKey = QSslKey(&fileClientCert, QSsl::Rsa, QSsl::Pem, QSsl::PrivateKey, password.toUtf8()); } fileClientCert.close(); // Set client certificate (from the cache) and private key (just loaded) m_sslConfiguration.setLocalCertificate(cert); m_sslConfiguration.setPrivateKey(clientKey); // Apply SSL configuration request->setSslConfiguration(m_sslConfiguration); return true; }
void IdentityEditWidget::saveToIdentity(CertIdentity *id) { QRegExp linebreaks = QRegExp("[\\r\\n]"); id->setRealName(ui.realName->text()); QStringList nicks; for (int i = 0; i < ui.nicknameList->count(); i++) { nicks << ui.nicknameList->item(i)->text(); } id->setNicks(nicks); id->setAwayNick(ui.awayNick->text()); id->setAwayNickEnabled(true); id->setAwayReason(ui.awayReason->text().remove(linebreaks)); id->setAwayReasonEnabled(true); id->setAutoAwayEnabled(ui.autoAwayEnabled->isChecked()); id->setAutoAwayTime(ui.autoAwayTime->value()); id->setAutoAwayReason(ui.autoAwayReason->text().remove(linebreaks)); id->setAutoAwayReasonEnabled(ui.autoAwayReasonEnabled->isChecked()); id->setDetachAwayEnabled(ui.detachAwayEnabled->isChecked()); id->setDetachAwayReason(ui.detachAwayReason->text().remove(linebreaks)); id->setDetachAwayReasonEnabled(true); id->setIdent(ui.ident->text()); id->setKickReason(ui.kickReason->text().remove(linebreaks)); id->setPartReason(ui.partReason->text().remove(linebreaks)); id->setQuitReason(ui.quitReason->text().remove(linebreaks)); #ifdef HAVE_SSL id->setSslKey(QSslKey(ui.keyTypeLabel->property("sslKey").toByteArray(), (QSsl::KeyAlgorithm)(ui.keyTypeLabel->property("sslKeyType").toInt()))); id->setSslCert(QSslCertificate(ui.certOrgLabel->property("sslCert").toByteArray())); #endif }
void QMQTT::ClientPrivate::init(const QString& hostName, const quint16 port, const bool ssl, const bool ignoreSelfSigned) { _hostName = hostName; _port = port; if (ssl) { #ifndef QT_NO_SSL QSslConfiguration sslConf = QSslConfiguration::defaultConfiguration(); QList<QSslCertificate> certs = QSslCertificate::fromPath(QStringLiteral("./cert.crt")); if (!certs.isEmpty()) sslConf.setLocalCertificate(certs.first()); QFile file(QStringLiteral("./cert.key")); if (file.open(QIODevice::ReadOnly)) { sslConf.setPrivateKey(QSslKey(file.readAll(), QSsl::Rsa)); } sslConf.setPeerVerifyMode(QSslSocket::VerifyNone); #if QT_VERSION < 0x050000 sslConf.setProtocol(QSsl::TlsV1); #endif init(hostName, port, sslConf, ignoreSelfSigned); #else Q_UNUSED(ignoreSelfSigned) qCritical() << "SSL not supported in this QT build"; #endif // QT_NO_SSL } else { init(new Network); } }
// ======================================== // ClientCertManager // ======================================== void ClientCertManager::setSslKey(const QByteArray &encoded) { QSslKey key(encoded, QSsl::Rsa); if (key.isNull()) key = QSslKey(encoded, QSsl::Dsa); _certIdentity->setSslKey(key); }
Settings::KeyPair CertWizard::importCert(QByteArray data, const QString &pw) { X509 *x509 = NULL; EVP_PKEY *pkey = NULL; PKCS12 *pkcs = NULL; BIO *mem = NULL; STACK_OF(X509) *certs = NULL; Settings::KeyPair kp; int ret = 0; mem = BIO_new_mem_buf(data.data(), data.size()); Q_UNUSED(BIO_set_close(mem, BIO_NOCLOSE)); pkcs = d2i_PKCS12_bio(mem, NULL); if (pkcs) { ret = PKCS12_parse(pkcs, NULL, &pkey, &x509, &certs); if (pkcs && !pkey && !x509 && ! pw.isEmpty()) { if (certs) { if (ret) sk_X509_free(certs); certs = NULL; } ret = PKCS12_parse(pkcs, pw.toUtf8().constData(), &pkey, &x509, &certs); } if (pkey && x509 && X509_check_private_key(x509, pkey)) { unsigned char *dptr; QByteArray key, crt; key.resize(i2d_PrivateKey(pkey, NULL)); dptr=reinterpret_cast<unsigned char *>(key.data()); i2d_PrivateKey(pkey, &dptr); crt.resize(i2d_X509(x509, NULL)); dptr=reinterpret_cast<unsigned char *>(crt.data()); i2d_X509(x509, &dptr); QSslCertificate qscCert = QSslCertificate(crt, QSsl::Der); QSslKey qskKey = QSslKey(key, QSsl::Rsa, QSsl::Der); QList<QSslCertificate> qlCerts; qlCerts << qscCert; if (certs) { for (int i=0;i<sk_X509_num(certs);++i) { X509 *c = sk_X509_value(certs, i); crt.resize(i2d_X509(c, NULL)); dptr=reinterpret_cast<unsigned char *>(crt.data()); i2d_X509(c, &dptr); QSslCertificate cert = QSslCertificate(crt, QSsl::Der); qlCerts << cert; } } bool valid = ! qskKey.isNull(); foreach(const QSslCertificate &cert, qlCerts) valid = valid && ! cert.isNull(); if (valid) kp = Settings::KeyPair(qlCerts, qskKey); } }
const QgsPkiBundle QgsPkiBundle::fromPemPaths( const QString &certPath, const QString &keyPath, const QString &keyPass, const QList<QSslCertificate> &caChain ) { QgsPkiBundle pkibundle; if ( !certPath.isEmpty() && !keyPath.isEmpty() && ( certPath.endsWith( QLatin1String( ".pem" ), Qt::CaseInsensitive ) || certPath.endsWith( QLatin1String( ".der" ), Qt::CaseInsensitive ) ) && ( keyPath.endsWith( QLatin1String( ".pem" ), Qt::CaseInsensitive ) || keyPath.endsWith( QLatin1String( ".der" ), Qt::CaseInsensitive ) ) && QFile::exists( certPath ) && QFile::exists( keyPath ) ) { // client cert bool pem = certPath.endsWith( QLatin1String( ".pem" ), Qt::CaseInsensitive ); QSslCertificate clientcert( fileData_( certPath, pem ), pem ? QSsl::Pem : QSsl::Der ); pkibundle.setClientCert( clientcert ); // client key bool pem_key = keyPath.endsWith( QLatin1String( ".pem" ), Qt::CaseInsensitive ); QByteArray keydata( fileData_( keyPath, pem_key ) ); QSslKey clientkey; clientkey = QSslKey( keydata, QSsl::Rsa, pem_key ? QSsl::Pem : QSsl::Der, QSsl::PrivateKey, !keyPass.isNull() ? keyPass.toUtf8() : QByteArray() ); if ( clientkey.isNull() ) { // try DSA algorithm, since Qt can't seem to determine it otherwise clientkey = QSslKey( keydata, QSsl::Dsa, pem_key ? QSsl::Pem : QSsl::Der, QSsl::PrivateKey, !keyPass.isNull() ? keyPass.toUtf8() : QByteArray() ); } pkibundle.setClientKey( clientkey ); if ( !caChain.isEmpty() ) { pkibundle.setCaChain( caChain ); } } return pkibundle; }
const QPair<QSslCertificate, QSslKey> QgsAuthImportIdentityDialog::certBundleToImport() { if ( mDisabled ) { return qMakePair( QSslCertificate(), QSslKey() ); } return mCertBundle; }
bool SslServer::setCertificate(const QString &path) { _isCertValid = false; if (path.isEmpty()) return false; QFile certFile(path); if (!certFile.exists()) { quWarning() << "SslServer: Certificate file" << qPrintable(path) << "does not exist"; return false; } if (!certFile.open(QIODevice::ReadOnly)) { quWarning() << "SslServer: Failed to open certificate file" << qPrintable(path) << "error:" << certFile.error(); return false; } QList<QSslCertificate> certList = QSslCertificate::fromDevice(&certFile); if (certList.isEmpty()) { quWarning() << "SslServer: Certificate file doesn't contain a certificate"; return false; } _cert = certList[0]; certList.removeFirst(); // remove server cert // store CA and intermediates certs _ca = certList; if (!certFile.reset()) { quWarning() << "SslServer: IO error reading certificate file"; return false; } _key = QSslKey(&certFile, QSsl::Rsa); certFile.close(); if (_cert.isNull()) { quWarning() << "SslServer:" << qPrintable(path) << "contains no certificate data"; return false; } if (!_cert.isValid()) { quWarning() << "SslServer: Invalid certificate (most likely expired)"; // We allow the core to offer SSL anyway, so no "return false" here. Client will warn about the cert being invalid. } if (_key.isNull()) { quWarning() << "SslServer:" << qPrintable(path) << "contains no key data"; return false; } _isCertValid = true; return _isCertValid; }
QgsPkiBundle::QgsPkiBundle( const QSslCertificate &clientCert, const QSslKey &clientKey, const QList<QSslCertificate> &caChain ) : mCert( QSslCertificate() ) , mCertKey( QSslKey() ) , mCaChain( caChain ) { setClientCert( clientCert ); setClientKey( clientKey ); }
// static const QByteArray QgsAuthProviderPkiPaths::keyAsPem( const QString &keypath, const QString &keypass, QString *algtype, bool reencrypt ) { bool pem = keypath.endsWith( ".pem", Qt::CaseInsensitive ); QByteArray keydata( fileData_( keypath, pem ) ); QSslKey clientkey; clientkey = QSslKey( keydata, QSsl::Rsa, pem ? QSsl::Pem : QSsl::Der, QSsl::PrivateKey, !keypass.isEmpty() ? keypass.toUtf8() : QByteArray() ); if ( clientkey.isNull() ) { // try DSA algorithm, since Qt can't seem to determine it otherwise clientkey = QSslKey( keydata, QSsl::Dsa, pem ? QSsl::Pem : QSsl::Der, QSsl::PrivateKey, !keypass.isEmpty() ? keypass.toUtf8() : QByteArray() ); if ( clientkey.isNull() ) { return QByteArray(); } if ( algtype ) *algtype = "dsa"; } else { if ( algtype ) *algtype = "rsa"; } // reapply passphrase if protection is requested and passphrase exists return ( clientkey.toPem( reencrypt && !keypass.isEmpty() ? keypass.toUtf8() : QByteArray() ) ); }
SslParams::SslParams( const QString & certFile, const QString & keyFile, QObject * parent ) : QObject( parent ) { QFile fc( certFile, this ); fc.open( QFile::ReadOnly ); certificate = QSslCertificate( fc.readAll() ); fc.close(); ca << certificate; QFile fk( keyFile, this ); fk.open( QFile::ReadOnly ); privateKey = QSslKey( fk.readAll(), QSsl::Rsa, QSsl::Pem, QSsl::PrivateKey);//, passwd ); fk.close(); }
Settings::KeyPair CertWizard::generateNewCert(QString qsname, const QString &qsemail) { CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON); X509 *x509 = X509_new(); EVP_PKEY *pkey = EVP_PKEY_new(); RSA *rsa = RSA_generate_key(2048,RSA_F4,NULL,NULL); EVP_PKEY_assign_RSA(pkey, rsa); X509_set_version(x509, 2); ASN1_INTEGER_set(X509_get_serialNumber(x509),1); X509_gmtime_adj(X509_get_notBefore(x509),0); X509_gmtime_adj(X509_get_notAfter(x509),60*60*24*365*20); X509_set_pubkey(x509, pkey); X509_NAME *name=X509_get_subject_name(x509); if (qsname.isEmpty()) qsname = tr("Mumble User"); X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_ASC, reinterpret_cast<unsigned char *>(qsname.toUtf8().data()), -1, -1, 0); X509_set_issuer_name(x509, name); add_ext(x509, NID_basic_constraints, SSL_STRING("critical,CA:FALSE")); add_ext(x509, NID_ext_key_usage, SSL_STRING("clientAuth")); add_ext(x509, NID_subject_key_identifier, SSL_STRING("hash")); add_ext(x509, NID_netscape_comment, SSL_STRING("Generated by Mumble")); add_ext(x509, NID_subject_alt_name, QString::fromLatin1("email:%1").arg(qsemail).toUtf8().data()); X509_sign(x509, pkey, EVP_sha1()); QByteArray crt, key; crt.resize(i2d_X509(x509, NULL)); unsigned char *dptr=reinterpret_cast<unsigned char *>(crt.data()); i2d_X509(x509, &dptr); QSslCertificate qscCert = QSslCertificate(crt, QSsl::Der); key.resize(i2d_PrivateKey(pkey, NULL)); dptr=reinterpret_cast<unsigned char *>(key.data()); i2d_PrivateKey(pkey, &dptr); QSslKey qskKey = QSslKey(key, QSsl::Rsa, QSsl::Der); QList<QSslCertificate> qlCert; qlCert << qscCert; return Settings::KeyPair(qlCert, qskKey); }
QSslKey IdentityEditWidget::keyByFilename(const QString &filename) { QSslKey key; QFile keyFile(filename); keyFile.open(QIODevice::ReadOnly); QByteArray keyRaw = keyFile.read(2 << 20); keyFile.close(); for (int i = 0; i < 2; i++) { for (int j = 0; j < 2; j++) { key = QSslKey(keyRaw, (QSsl::KeyAlgorithm)j, (QSsl::EncodingFormat)i); if (!key.isNull()) goto returnKey; } } QMessageBox::information(this, tr("Failed to read key"), tr("Failed to read the key file. It is either incompatible or invalid. Note that the key file must not have a passphrase.")); returnKey: return key; }
Messages::ArmaMessage Messages::createLoginMessage(QString & name, const QString & password, int port, bool reg) { QByteArray req, key; Krypto::createCert(key, req, "C=SK,O=Armadill,CN=" + name); localKey = QSslKey(key, QSsl::KeyAlgorithm::Rsa); ArmaMessage ret; ret.append(reg ? "r" : "l"); ret.append(Messages::armaSeparator); ret.append(name.toUtf8().toBase64()); ret.append(Messages::armaSeparator); ret.append(password.toUtf8().toBase64()); ret.append(Messages::armaSeparator); ret.append(QString::number(port).toUtf8().toBase64()); if (!reg) { ret.append(Messages::armaSeparator); ret.append(req); } return ret; }
NetworkManager::NetworkManager(QObject *parent) : QNetworkAccessManager(parent), m_answersReply(0), m_currentReply(0) { connect(this, SIGNAL(finished(QNetworkReply*)), SLOT(onReplyFinished(QNetworkReply*))); connect(this, SIGNAL(sslErrors(QNetworkReply*,QList<QSslError>)), SLOT(onSslErrors(QNetworkReply*,QList<QSslError>))); const QDir shareDir = SystemInfo::getDir(SystemInfo::SystemShareDir); struct { const char *fileName; QString error; QSslCertificate *cert; QSslKey *key; } files[] = { { "certs/client.pem", tr("Put local certificate at \"%1\""), &m_localCertificate, &m_privateKey }, { "certs/server.pem", tr("Put server's certificate at \"%1\""), &m_remoteCertificate, NULL } }; for (size_t i = 0; i < sizeof(files) / sizeof(files[0]); ++i) { QString file = shareDir.filePath(QLatin1String(files[i].fileName)); QSslCertificate &certificate = *files[i].cert; certificate = QSslCertificate::fromPath(file).value(0); if(files[i].key) { QFile device(file); device.open(QFile::ReadOnly); *files[i].key = QSslKey(&device, QSsl::Rsa); } debug() << file << certificate.isValid() << (files[i].key && !files[i].key->isNull()); if (!certificate.isValid()) { NotificationRequest request(Notification::System); request.setTitle(tr("Control plugin")); request.setText(files[i].error.arg(file)); request.send(); } } Config config("control"); m_crypter = new Crypter(QByteArray::fromHex(config.value("general/key", QString()).toLatin1())); }
QSslKey SafetPKCS12::keyFromEVP( EVP_PKEY * evp ) { EVP_PKEY *key = (EVP_PKEY*)evp; unsigned char *data = NULL; int len = 0; QSsl::KeyAlgorithm alg; QSsl::KeyType type; switch( EVP_PKEY_type( key->type ) ) { case EVP_PKEY_RSA: { RSA *rsa = EVP_PKEY_get1_RSA( key ); alg = QSsl::Rsa; type = rsa->d ? QSsl::PrivateKey : QSsl::PublicKey; len = rsa->d ? i2d_RSAPrivateKey( rsa, &data ) : i2d_RSAPublicKey( rsa, &data ); RSA_free( rsa ); break; } case EVP_PKEY_DSA: { DSA *dsa = EVP_PKEY_get1_DSA( key ); alg = QSsl::Dsa; type = dsa->priv_key ? QSsl::PrivateKey : QSsl::PublicKey; len = dsa->priv_key ? i2d_DSAPrivateKey( dsa, &data ) : i2d_DSAPublicKey( dsa, &data ); DSA_free( dsa ); break; } default: break; } QSslKey k; if( len > 0 ) k = QSslKey( QByteArray( (char*)data, len ), alg, QSsl::Der, type ); OPENSSL_free( data ); return k; }
/** \class Server \brief The Server class handles new connections to the %server. For every client that connects, it creates a new ClientSocket \param certificatFile certificat file name \param privateKeyFile private key file name \param sslPassword passphras for private key \param parent pointer to the parent object \sa ClientSocket \date 2008-11-06 \version 2.0 \author Daniel Rocher */ Server :: Server( const QString & certificatFile , const QString & privateKeyFile ,const QString & sslPassword , QObject* parent ) : QTcpServer ( parent ) { debugQt("Server::Server(): "+QString::number(++compteur_objet)); // Certificat QFile f_certif(certificatFile); if (!f_certif.open(QIODevice::ReadOnly | QIODevice::Text)) { qWarning() << "Impossible to open certificat file : " << certificatFile << " !\n\n"; exit (1); } certif=QSslCertificate( &f_certif ); if (! certif.isValid()) { qWarning() << "Bad certificate !\n\n"; exit (1); } debugQt("Certificate OK"); // private key QByteArray sslPassPhras; sslPassPhras.append(sslPassword); QFile f_pKey(privateKeyFile); if (!f_pKey.open(QIODevice::ReadOnly | QIODevice::Text)) { qWarning() << "Impossible to open private key file : " << privateKeyFile << " !\n\n"; exit (1); } s_key=QSslKey( &f_pKey, QSsl::Rsa, QSsl::Pem, QSsl::PrivateKey, sslPassPhras ); if (s_key.isNull()) { qWarning() << "the private key or password are bad !\n\n"; exit (1); } debugQt("Private key OK"); }
/*! Returns the \l {QSslKey} {SSL key} assigned to this connection or a null key if none has been assigned yet. \sa setPrivateKey(), localCertificate() */ QSslKey QSslConfiguration::privateKey() const { return d ? d->privateKey : QSslKey(); }
SslServer::SslServer(QObject *parent) : QObject(parent) { qRegisterMetaType<PeerData>("PeerData"); m_max_connections = 0; m_server = nullptr; QByteArray password; if (!QFileInfo("../data/cert.pem").exists() || !QFileInfo("../data/key.pem").exists()) { QByteArray confirm_password; password = getPassword("Enter password to encrypt private key:"); confirm_password = getPassword("Repeat password to encrypt private key:"); printf("\n"); fflush(stdout); if (password != confirm_password) { password.fill(char(0)); confirm_password.fill(char(0)); DEBUG_FUNCTION("Different passwords!"); return; } confirm_password.fill(char(0)); DEBUG_FUNCTION("Generating certificate..."); Certificate certificate_genarator; bool success = certificate_genarator.generate("US", "Server", "127.0.0.1", password); if (!success) { DEBUG_FUNCTION("Keys not generated!" << "Error(s):" << qPrintable(QString("\n%0").arg(certificate_genarator.errorString()))); return; } DEBUG_FUNCTION("Keys generated!"); } QFile key_file("../data/key.pem"); if (!key_file.open(QFile::ReadOnly)) { DEBUG_FUNCTION("Private key file could not be openned!"); return; } QFile cert_file("../data/cert.pem"); if (!cert_file.open(QFile::ReadOnly)) { DEBUG_FUNCTION("Public key file could not be openned!"); return; } if (password.isNull()) password = getPassword("Enter password to decrypt private key:"); printf("\n"); fflush(stdout); m_key = QSslKey(&key_file, QSsl::Rsa, QSsl::Pem, QSsl::PrivateKey, password); password.fill(char(0)); if (m_key.isNull()) { DEBUG_FUNCTION("Private key is null!"); return; } m_cert = QSslCertificate(&cert_file, QSsl::Pem); if (m_cert.isNull()) { DEBUG_FUNCTION("Public key is null!"); return; } QByteArray hash = m_cert.digest(QCryptographicHash::Sha256).toHex().toUpper(); QByteArray formatted_hash; for (int i = hash.size() - 2; i >= 0; i -= 2) { formatted_hash.prepend(hash.mid(i, 2)); formatted_hash.prepend(":"); } formatted_hash.remove(0, 1); DEBUG_FUNCTION("Certificate fingerprint:" << qPrintable(formatted_hash)); key_file.close(); cert_file.close(); DEBUG_FUNCTION("Openning database..."); if (!m_sql.open()) { DEBUG_FUNCTION("Could not open database!"); return; } DEBUG_FUNCTION("Database openned!"); listen(); }
void WebUI::init() { Preferences* const pref = Preferences::instance(); Logger* const logger = Logger::instance(); if (pref->isWebUiEnabled()) { const quint16 port = pref->getWebUiPort(); if (m_port != port) { Net::PortForwarder::instance()->deletePort(port); m_port = port; } if (httpServer_) { if (httpServer_->serverPort() != m_port) httpServer_->close(); } else { webapp_ = new WebApplication(this); httpServer_ = new Http::Server(webapp_, this); } #ifndef QT_NO_OPENSSL if (pref->isWebUiHttpsEnabled()) { QList<QSslCertificate> certs = QSslCertificate::fromData(pref->getWebUiHttpsCertificate()); QSslKey key; key = QSslKey(pref->getWebUiHttpsKey(), QSsl::Rsa); bool certsIsNull = std::any_of(certs.begin(), certs.end(), [](QSslCertificate c) { return c.isNull(); }); if (!certsIsNull && !certs.empty() && !key.isNull()) httpServer_->enableHttps(certs, key); else httpServer_->disableHttps(); } else { httpServer_->disableHttps(); } #endif if (!httpServer_->isListening()) { bool success = httpServer_->listen(QHostAddress::Any, m_port); if (success) logger->addMessage(tr("The Web UI is listening on port %1").arg(m_port)); else logger->addMessage(tr("Web UI Error - Unable to bind Web UI to port %1").arg(m_port), Log::CRITICAL); } // DynDNS if (pref->isDynDNSEnabled()) { if (!dynDNSUpdater_) dynDNSUpdater_ = new Net::DNSUpdater(this); else dynDNSUpdater_->updateCredentials(); } else { if (dynDNSUpdater_) delete dynDNSUpdater_; } // Use UPnP/NAT-PMP for Web UI if (pref->useUPnPForWebUIPort()) Net::PortForwarder::instance()->addPort(m_port); else Net::PortForwarder::instance()->deletePort(m_port); } else { if (httpServer_) delete httpServer_; if (webapp_) delete webapp_; if (dynDNSUpdater_) delete dynDNSUpdater_; Net::PortForwarder::instance()->deletePort(m_port); } }
bool SslServer::setCertificate(const QString &path, const QString &keyPath) { // Don't reset _isCertValid here, in case an older but valid certificate is still loaded. // Use temporary variables in order to avoid overwriting the existing certificates until // everything is confirmed good. QSslCertificate untestedCert; QList<QSslCertificate> untestedCA; QSslKey untestedKey; if (path.isEmpty()) return false; QFile certFile(path); if (!certFile.exists()) { quWarning() << "SslServer: Certificate file" << qPrintable(path) << "does not exist"; return false; } if (!certFile.open(QIODevice::ReadOnly)) { quWarning() << "SslServer: Failed to open certificate file" << qPrintable(path) << "error:" << certFile.error(); return false; } QList<QSslCertificate> certList = QSslCertificate::fromDevice(&certFile); if (certList.isEmpty()) { quWarning() << "SslServer: Certificate file doesn't contain a certificate"; return false; } untestedCert = certList[0]; certList.removeFirst(); // remove server cert // store CA and intermediates certs untestedCA = certList; if (!certFile.reset()) { quWarning() << "SslServer: IO error reading certificate file"; return false; } // load key from keyPath if it differs from path, otherwise load key from path if(path != keyPath) { QFile keyFile(keyPath); if(!keyFile.exists()) { quWarning() << "SslServer: Key file" << qPrintable(keyPath) << "does not exist"; return false; } if (!keyFile.open(QIODevice::ReadOnly)) { quWarning() << "SslServer: Failed to open key file" << qPrintable(keyPath) << "error:" << keyFile.error(); return false; } untestedKey = QSslKey(&keyFile, QSsl::Rsa); keyFile.close(); } else { untestedKey = QSslKey(&certFile, QSsl::Rsa); } certFile.close(); if (untestedCert.isNull()) { quWarning() << "SslServer:" << qPrintable(path) << "contains no certificate data"; return false; } // We allow the core to offer SSL anyway, so no "return false" here. Client will warn about the cert being invalid. const QDateTime now = QDateTime::currentDateTime(); if (now < untestedCert.effectiveDate()) quWarning() << "SslServer: Certificate won't be valid before" << untestedCert.effectiveDate().toString(); else if (now > untestedCert.expiryDate()) quWarning() << "SslServer: Certificate expired on" << untestedCert.expiryDate().toString(); else { // Qt4's isValid() checks for time range and blacklist; avoid a double warning, hence the else block #if QT_VERSION < 0x050000 if (!untestedCert.isValid()) #else if (untestedCert.isBlacklisted()) #endif quWarning() << "SslServer: Certificate blacklisted"; } if (untestedKey.isNull()) { quWarning() << "SslServer:" << qPrintable(keyPath) << "contains no key data"; return false; } _isCertValid = true; // All keys are valid, update the externally visible copy used for new connections. _cert = untestedCert; _ca = untestedCA; _key = untestedKey; return _isCertValid; }
void Server::initializeCert() { QByteArray crt, key, pass, dhparams; // Clear all exising SSL settings // for this server. qscCert.clear(); qlIntermediates.clear(); qskKey.clear(); #if defined(USE_QSSLDIFFIEHELLMANPARAMETERS) qsdhpDHParams = QSslDiffieHellmanParameters(); #endif crt = getConf("certificate", QString()).toByteArray(); key = getConf("key", QString()).toByteArray(); pass = getConf("passphrase", QByteArray()).toByteArray(); dhparams = getConf("sslDHParams", Meta::mp.qbaDHParams).toByteArray(); QList<QSslCertificate> ql; // Attempt to load the private key. if (! key.isEmpty()) { qskKey = Server::privateKeyFromPEM(key, pass); } // If we still can't load the key, try loading any keys from the certificate if (qskKey.isNull() && ! crt.isEmpty()) { qskKey = Server::privateKeyFromPEM(crt); } // If have a key, walk the list of certs, find the one for our key, // remove any certs for our key from the list, what's left is part of // the CA certificate chain. if (! qskKey.isNull()) { ql << QSslCertificate::fromData(crt); ql << QSslCertificate::fromData(key); for (int i=0;i<ql.size();++i) { const QSslCertificate &c = ql.at(i); if (isKeyForCert(qskKey, c)) { qscCert = c; ql.removeAt(i); } } qlIntermediates = ql; } #if defined(USE_QSSLDIFFIEHELLMANPARAMETERS) if (! dhparams.isEmpty()) { QSslDiffieHellmanParameters qdhp = QSslDiffieHellmanParameters::fromEncoded(dhparams); if (qdhp.isValid()) { qsdhpDHParams = qdhp; } else { log(QString::fromLatin1("Unable to use specified Diffie-Hellman parameters (sslDHParams): %1").arg(qdhp.errorString())); } } #else if (! dhparams.isEmpty()) { log("Diffie-Hellman parameters (sslDHParams) were specified, but will not be used. This version of Murmur does not support Diffie-Hellman parameters."); } #endif QString issuer; #if QT_VERSION >= 0x050000 QStringList issuerNames = qscCert.issuerInfo(QSslCertificate::CommonName); if (! issuerNames.isEmpty()) { issuer = issuerNames.first(); } #else issuer = qscCert.issuerInfo(QSslCertificate::CommonName); #endif // Really old certs/keys are no good, throw them away so we can // generate a new one below. if (issuer == QString::fromUtf8("Murmur Autogenerated Certificate")) { log("Old autogenerated certificate is unusable for registration, invalidating it"); qscCert = QSslCertificate(); qskKey = QSslKey(); } // If we have a cert, and it's a self-signed one, but we're binding to // all the same addresses as the Meta server is, use it's cert instead. // This allows a self-signed certificate generated by Murmur to be // replaced by a CA-signed certificate in the .ini file. if (!qscCert.isNull() && issuer.startsWith(QString::fromUtf8("Murmur Autogenerated Certificate")) && ! Meta::mp.qscCert.isNull() && ! Meta::mp.qskKey.isNull() && (Meta::mp.qlBind == qlBind)) { qscCert = Meta::mp.qscCert; qskKey = Meta::mp.qskKey; qlIntermediates = Meta::mp.qlIntermediates; if (!qscCert.isNull() && !qskKey.isNull()) { bUsingMetaCert = true; } } // If we still don't have a certificate by now, try to load the one from Meta if (qscCert.isNull() || qskKey.isNull()) { if (! key.isEmpty() || ! crt.isEmpty()) { log("Certificate specified, but failed to load."); } qskKey = Meta::mp.qskKey; qscCert = Meta::mp.qscCert; qlIntermediates = Meta::mp.qlIntermediates; if (!qscCert.isNull() && !qskKey.isNull()) { bUsingMetaCert = true; } // If loading from Meta doesn't work, build+sign a new one if (qscCert.isNull() || qskKey.isNull()) { log("Generating new server certificate."); if (!SelfSignedCertificate::generateMurmurV2Certificate(qscCert, qskKey)) { log("Certificate or key generation failed"); } setConf("certificate", qscCert.toPem()); setConf("key", qskKey.toPem()); } } // Drain OpenSSL's per-thread error queue // to ensure that errors from the operations // we've done in here do not leak out into // Qt's SSL module. // // If an error leaks, it can break all connections // to the server because each invocation of Qt's SSL // read callback checks OpenSSL's per-thread error // queue (albeit indirectly, via SSL_get_error()). // Qt expects any errors returned from SSL_get_error() // to be related to the QSslSocket it is currently // processing -- which is the obvious thing to expect: // SSL_get_error() takes a pointer to an SSL object // and the return code of the failed operation. // However, it is also documented as: // // "In addition to ssl and ret, SSL_get_error() // inspects the current thread's OpenSSL error // queue." // // So, if any OpenSSL operation on the main thread // forgets to clear the error queue, those errors // *will* leak into other things that *do* error // checking. In our case, into Qt's SSL read callback, // resulting in all clients being disconnected. ERR_clear_error(); }
void Server::initializeCert() { QByteArray crt, key, pass; crt = getConf("certificate", QString()).toByteArray(); key = getConf("key", QString()).toByteArray(); pass = getConf("passphrase", QByteArray()).toByteArray(); QList<QSslCertificate> ql; if (! key.isEmpty()) { qskKey = QSslKey(key, QSsl::Rsa, QSsl::Pem, QSsl::PrivateKey, pass); if (qskKey.isNull()) qskKey = QSslKey(key, QSsl::Dsa, QSsl::Pem, QSsl::PrivateKey, pass); } if (qskKey.isNull() && ! crt.isEmpty()) { qskKey = QSslKey(crt, QSsl::Rsa, QSsl::Pem, QSsl::PrivateKey, pass); if (qskKey.isNull()) qskKey = QSslKey(crt, QSsl::Dsa, QSsl::Pem, QSsl::PrivateKey, pass); } if (! qskKey.isNull()) { ql << QSslCertificate::fromData(crt); ql << QSslCertificate::fromData(key); for (int i=0;i<ql.size();++i) { const QSslCertificate &c = ql.at(i); if (isKeyForCert(qskKey, c)) { qscCert = c; ql.removeAt(i); } } qlCA = ql; } QString issuer; #if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0) QStringList issuerNames = qscCert.issuerInfo(QSslCertificate::CommonName); if (! issuerNames.isEmpty()) { issuer = issuerNames.first(); } #else issuer = qscCert.issuerInfo(QSslCertificate::CommonName); #endif if (issuer == QString::fromUtf8("Murmur Autogenerated Certificate")) { log("Old autogenerated certificate is unusable for registration, invalidating it"); qscCert = QSslCertificate(); qskKey = QSslKey(); } if (!qscCert.isNull() && issuer == QString::fromUtf8("Murmur Autogenerated Certificate v2") && ! Meta::mp.qscCert.isNull() && ! Meta::mp.qskKey.isNull() && (Meta::mp.qlBind == qlBind)) { qscCert = Meta::mp.qscCert; qskKey = Meta::mp.qskKey; } if (qscCert.isNull() || qskKey.isNull()) { if (! key.isEmpty() || ! crt.isEmpty()) { log("Certificate specified, but failed to load."); } qskKey = Meta::mp.qskKey; qscCert = Meta::mp.qscCert; if (qscCert.isNull() || qskKey.isNull()) { log("Generating new server certificate."); CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON); X509 *x509 = X509_new(); EVP_PKEY *pkey = EVP_PKEY_new(); RSA *rsa = RSA_generate_key(2048,RSA_F4,NULL,NULL); EVP_PKEY_assign_RSA(pkey, rsa); X509_set_version(x509, 2); ASN1_INTEGER_set(X509_get_serialNumber(x509),1); X509_gmtime_adj(X509_get_notBefore(x509),0); X509_gmtime_adj(X509_get_notAfter(x509),60*60*24*365*20); X509_set_pubkey(x509, pkey); X509_NAME *name=X509_get_subject_name(x509); X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_ASC, reinterpret_cast<unsigned char *>(const_cast<char *>("Murmur Autogenerated Certificate v2")), -1, -1, 0); X509_set_issuer_name(x509, name); add_ext(x509, NID_basic_constraints, SSL_STRING("critical,CA:FALSE")); add_ext(x509, NID_ext_key_usage, SSL_STRING("serverAuth,clientAuth")); add_ext(x509, NID_subject_key_identifier, SSL_STRING("hash")); add_ext(x509, NID_netscape_comment, SSL_STRING("Generated from murmur")); X509_sign(x509, pkey, EVP_sha1()); crt.resize(i2d_X509(x509, NULL)); unsigned char *dptr=reinterpret_cast<unsigned char *>(crt.data()); i2d_X509(x509, &dptr); qscCert = QSslCertificate(crt, QSsl::Der); if (qscCert.isNull()) log("Certificate generation failed"); key.resize(i2d_PrivateKey(pkey, NULL)); dptr=reinterpret_cast<unsigned char *>(key.data()); i2d_PrivateKey(pkey, &dptr); qskKey = QSslKey(key, QSsl::Rsa, QSsl::Der); if (qskKey.isNull()) log("Key generation failed"); setConf("certificate", qscCert.toPem()); setConf("key", qskKey.toPem()); } } }
/*! * This is an overloaded function, provided for convenience. * * Sets the private key used for encryption to the key contained in the file specified by * \a path. The specified algorithm, format, and pass phrase are used to decrypt the key. * * \sa privateKey */ void QxtSslServer::setPrivateKey(const QString& path, QSsl::KeyAlgorithm algo, QSsl::EncodingFormat format, const QByteArray& passPhrase) { QFile file(path); if(!file.open(QIODevice::ReadOnly)) return; setPrivateKey(QSslKey(&file, algo, format, QSsl::PrivateKey, passPhrase)); }
void Server::initializeCert() { QByteArray crt, key, pass, dhparams; crt = getConf("certificate", QString()).toByteArray(); key = getConf("key", QString()).toByteArray(); pass = getConf("passphrase", QByteArray()).toByteArray(); dhparams = getConf("sslDHParams", Meta::mp.qbaDHParams).toByteArray(); QList<QSslCertificate> ql; if (! key.isEmpty()) { qskKey = QSslKey(key, QSsl::Rsa, QSsl::Pem, QSsl::PrivateKey, pass); if (qskKey.isNull()) qskKey = QSslKey(key, QSsl::Dsa, QSsl::Pem, QSsl::PrivateKey, pass); } if (qskKey.isNull() && ! crt.isEmpty()) { qskKey = QSslKey(crt, QSsl::Rsa, QSsl::Pem, QSsl::PrivateKey, pass); if (qskKey.isNull()) qskKey = QSslKey(crt, QSsl::Dsa, QSsl::Pem, QSsl::PrivateKey, pass); } if (! qskKey.isNull()) { ql << QSslCertificate::fromData(crt); ql << QSslCertificate::fromData(key); for (int i=0;i<ql.size();++i) { const QSslCertificate &c = ql.at(i); if (isKeyForCert(qskKey, c)) { qscCert = c; ql.removeAt(i); } } qlCA = ql; } #if defined(USE_QSSLDIFFIEHELLMANPARAMETERS) if (! dhparams.isEmpty()) { QSslDiffieHellmanParameters qdhp = QSslDiffieHellmanParameters(dhparams); if (qdhp.isValid()) { qsdhpDHParams = qdhp; } else { log(QString::fromLatin1("Unable to use specified Diffie-Hellman parameters (sslDHParams): %1").arg(qdhp.errorString())); } } #else if (! dhparams.isEmpty()) { log("Diffie-Hellman parameters (sslDHParams) were specified, but will not be used. This version of Murmur does not support Diffie-Hellman parameters."); } #endif QString issuer; #if QT_VERSION >= 0x050000 QStringList issuerNames = qscCert.issuerInfo(QSslCertificate::CommonName); if (! issuerNames.isEmpty()) { issuer = issuerNames.first(); } #else issuer = qscCert.issuerInfo(QSslCertificate::CommonName); #endif if (issuer == QString::fromUtf8("Murmur Autogenerated Certificate")) { log("Old autogenerated certificate is unusable for registration, invalidating it"); qscCert = QSslCertificate(); qskKey = QSslKey(); } if (!qscCert.isNull() && issuer == QString::fromUtf8("Murmur Autogenerated Certificate v2") && ! Meta::mp.qscCert.isNull() && ! Meta::mp.qskKey.isNull() && (Meta::mp.qlBind == qlBind)) { qscCert = Meta::mp.qscCert; qskKey = Meta::mp.qskKey; } if (qscCert.isNull() || qskKey.isNull()) { if (! key.isEmpty() || ! crt.isEmpty()) { log("Certificate specified, but failed to load."); } qskKey = Meta::mp.qskKey; qscCert = Meta::mp.qscCert; if (qscCert.isNull() || qskKey.isNull()) { log("Generating new server certificate."); CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON); X509 *x509 = X509_new(); EVP_PKEY *pkey = EVP_PKEY_new(); RSA *rsa = RSA_generate_key(2048,RSA_F4,NULL,NULL); EVP_PKEY_assign_RSA(pkey, rsa); X509_set_version(x509, 2); ASN1_INTEGER_set(X509_get_serialNumber(x509),1); X509_gmtime_adj(X509_get_notBefore(x509),0); X509_gmtime_adj(X509_get_notAfter(x509),60*60*24*365*20); X509_set_pubkey(x509, pkey); X509_NAME *name=X509_get_subject_name(x509); X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_ASC, reinterpret_cast<unsigned char *>(const_cast<char *>("Murmur Autogenerated Certificate v2")), -1, -1, 0); X509_set_issuer_name(x509, name); add_ext(x509, NID_basic_constraints, SSL_STRING("critical,CA:FALSE")); add_ext(x509, NID_ext_key_usage, SSL_STRING("serverAuth,clientAuth")); add_ext(x509, NID_subject_key_identifier, SSL_STRING("hash")); add_ext(x509, NID_netscape_comment, SSL_STRING("Generated from murmur")); X509_sign(x509, pkey, EVP_sha1()); crt.resize(i2d_X509(x509, NULL)); unsigned char *dptr=reinterpret_cast<unsigned char *>(crt.data()); i2d_X509(x509, &dptr); qscCert = QSslCertificate(crt, QSsl::Der); if (qscCert.isNull()) log("Certificate generation failed"); key.resize(i2d_PrivateKey(pkey, NULL)); dptr=reinterpret_cast<unsigned char *>(key.data()); i2d_PrivateKey(pkey, &dptr); qskKey = QSslKey(key, QSsl::Rsa, QSsl::Der); if (qskKey.isNull()) log("Key generation failed"); setConf("certificate", qscCert.toPem()); setConf("key", qskKey.toPem()); } } #if defined(USE_QSSLDIFFIEHELLMANPARAMETERS) if (qsdhpDHParams.isEmpty()) { log("Generating new server 2048-bit Diffie-Hellman parameters. This could take a while..."); DH *dh = DH_new(); if (dh == NULL) { qFatal("DH_new failed: unable to generate Diffie-Hellman parameters for virtual server"); } // Generate DH params. // We register a status callback in order to update the UI // for Murmur on Windows. We don't show the actual status, // but we do it to keep Murmur on Windows responsive while // generating the parameters. BN_GENCB cb; memset(&cb, 0, sizeof(BN_GENCB)); BN_GENCB_set(&cb, dh_progress, NULL); if (DH_generate_parameters_ex(dh, 2048, 2, &cb) == 0) { qFatal("DH_generate_parameters_ex failed: unable to generate Diffie-Hellman parameters for virtual server"); } BIO *mem = BIO_new(BIO_s_mem()); if (PEM_write_bio_DHparams(mem, dh) == 0) { qFatal("PEM_write_bio_DHparams failed: unable to write generated Diffie-Hellman parameters to memory"); } char *pem = NULL; long len = BIO_get_mem_data(mem, &pem); if (len <= 0) { qFatal("BIO_get_mem_data returned an empty or invalid buffer"); } QByteArray pemdh(pem, len); QSslDiffieHellmanParameters qdhp(pemdh); if (!qdhp.isValid()) { qFatal("QSslDiffieHellmanParameters: unable to import generated Diffie-HellmanParameters: %s", qdhp.errorString().toStdString().c_str()); } qsdhpDHParams = qdhp; setConf("sslDHParams", pemdh); BIO_free(mem); DH_free(dh); } #endif }