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; }
/*! Returns true if this key is equal to \a other; otherwise returns false. */ bool QSslKey::operator==(const QSslKey &other) const { if (isNull()) return other.isNull(); if (other.isNull()) return isNull(); if (algorithm() != other.algorithm()) return false; if (type() != other.type()) return false; if (length() != other.length()) return false; return toDer() == other.toDer(); }
bool Server::isKeyForCert(const QSslKey &key, const QSslCertificate &cert) { if (key.isNull() || cert.isNull() || (key.type() != QSsl::PrivateKey)) return false; QByteArray qbaKey = key.toDer(); QByteArray qbaCert = cert.toDer(); X509 *x509 = NULL; EVP_PKEY *pkey = NULL; BIO *mem = NULL; mem = BIO_new_mem_buf(qbaKey.data(), qbaKey.size()); Q_UNUSED(BIO_set_close(mem, BIO_NOCLOSE)); pkey = d2i_PrivateKey_bio(mem, NULL); BIO_free(mem); mem = BIO_new_mem_buf(qbaCert.data(), qbaCert.size()); Q_UNUSED(BIO_set_close(mem, BIO_NOCLOSE)); x509 = d2i_X509_bio(mem, NULL); BIO_free(mem); mem = NULL; if (x509 && pkey && X509_check_private_key(x509, pkey)) { EVP_PKEY_free(pkey); X509_free(x509); return true; } if (pkey) EVP_PKEY_free(pkey); if (x509) X509_free(x509); return false; }
bool QSslKeyProto::isNull() const { QSslKey *item = qscriptvalue_cast<QSslKey*>(thisObject()); if (item) return item->isNull(); return false; }
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); } }
void QgsPkiBundle::setClientKey( const QSslKey &certkey ) { mCertKey.clear(); if ( !certkey.isNull() && certkey.type() == QSsl::PrivateKey ) { mCertKey = certkey; } }
// 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() ) ); }
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; }
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; }
void IdentityEditWidget::showKeyState(const QSslKey &key) { if (key.isNull()) { ui.keyTypeLabel->setText(tr("No Key loaded")); ui.clearOrLoadKeyButton->setText(tr("Load")); } else { switch (key.algorithm()) { case QSsl::Rsa: ui.keyTypeLabel->setText(tr("RSA")); break; case QSsl::Dsa: ui.keyTypeLabel->setText(tr("DSA")); break; default: ui.keyTypeLabel->setText(tr("No Key loaded")); } ui.clearOrLoadKeyButton->setText(tr("Clear")); } ui.keyTypeLabel->setProperty("sslKey", key.toPem()); ui.keyTypeLabel->setProperty("sslKeyType", (int)key.algorithm()); }
void IdentityEditWidget::sslDropEvent(QDropEvent *event, bool isCert) { QByteArray rawUris; if (event->mimeData()->hasFormat("text/uri-list")) rawUris = event->mimeData()->data("text/uri-list"); else rawUris = event->mimeData()->data("text/uri"); QTextStream uriStream(rawUris); QString filename = QUrl(uriStream.readLine()).toLocalFile(); if (isCert) { QSslCertificate cert = certByFilename(filename); if (!cert.isNull()) showCertState(cert); } else { QSslKey key = keyByFilename(filename); if (!key.isNull()) showKeyState(key); } event->accept(); emit widgetHasChanged(); }
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; }