virtual void SetUp() { std::ofstream cert(certfname()); cert << "-----BEGIN CERTIFICATE-----\n" "MIIC2DCCAkGgAwIBAgIJALptEXUhC5kTMA0GCSqGSIb3DQEBBQUAMFIxCzAJBgNV\n" "BAYTAkFVMRMwEQYDVQQIEwpTb21lLVN0YXRlMRYwFAYDVQQKEw1NeUNvbXBhbnlO\n" "YW1lMRYwFAYDVQQDEw1NeUNvbXBhbnlOYW1lMB4XDTA4MDcxMDA5MzMxNFoXDTA5\n" "MDcxMDA5MzMxNFowUjELMAkGA1UEBhMCQVUxEzARBgNVBAgTClNvbWUtU3RhdGUx\n" "FjAUBgNVBAoTDU15Q29tcGFueU5hbWUxFjAUBgNVBAMTDU15Q29tcGFueU5hbWUw\n" "gZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAMMcKQ/dau+wJDPaXHPndsgCKQgs\n" "AUMnqSw4DZoapBlWJ1J5CvEIJJIqnFHbxk9kDAz1g9zgwSMJE311hC0tRw6idSDh\n" "7CznKdgJaD/Hp7Y+vAK7yr6H9vHKDZA6wRhr99bjuZcqQS87mTH1QT86xwJGrttP\n" "CSYNiiB9NHV7jyRZAgMBAAGjgbUwgbIwHQYDVR0OBBYEFN2yRL8s0pU48FubdhJK\n" "gBds6zphMIGCBgNVHSMEezB5gBTdskS/LNKVOPBbm3YSSoAXbOs6YaFWpFQwUjEL\n" "MAkGA1UEBhMCQVUxEzARBgNVBAgTClNvbWUtU3RhdGUxFjAUBgNVBAoTDU15Q29t\n" "cGFueU5hbWUxFjAUBgNVBAMTDU15Q29tcGFueU5hbWWCCQC6bRF1IQuZEzAMBgNV\n" "HRMEBTADAQH/MA0GCSqGSIb3DQEBBQUAA4GBAHrEQf8iDUYeTO2jx/AlVsYC1nx6\n" "zEh1kPtdcN57hVpnIooP9NlhZBJ/Cc7DtJikpZhHU4AJdZx9O5uenS06fFdjHD0X\n" "1zWzI27GpT4kBwQPygexRjeb+6JopwibigmVIxE+u2dLwrQzrCOXxxuYDHgfZZmv\n" "WvKs6j3JlDKL3hS9\n" "-----END CERTIFICATE-----\n" ; std::ofstream key(keyfname()); key << "-----BEGIN RSA PRIVATE KEY-----\n" "MIICXAIBAAKBgQDDHCkP3WrvsCQz2lxz53bIAikILAFDJ6ksOA2aGqQZVidSeQrx\n" "CCSSKpxR28ZPZAwM9YPc4MEjCRN9dYQtLUcOonUg4ews5ynYCWg/x6e2PrwCu8q+\n" "h/bxyg2QOsEYa/fW47mXKkEvO5kx9UE/OscCRq7bTwkmDYogfTR1e48kWQIDAQAB\n" "AoGAYlt538OROw+i0HkODmfrG1zrbnEwmbgOsnn3cW5ot1UVMaBPgb7HIOBWOXX/\n" "fNpEsOu788dh1dWne6GYZmXi4X5E2uLksnD9CfD356X8RjK8fX3un8XpYE64X3FF\n" "9+cdSJdklbSDPPGGzjkwTkAzF68hnp0uYvt4t3KrAARpRWECQQDopNSBPtKN7Fr2\n" "H8wNMH8fyPs4Rknt6wfWvA5CNQvI6M6EkLXpK8ae2su6TAaytcNboYW43NdFlpNd\n" "y6Kj8AOdAkEA1rKsjk3w8DgOrCZOhSvJ22ggDuY2+vUxcFRzb+lxSJd9H4i826l1\n" "aDmuriUweBBRHDr9ycV3YpX4rcOl45887QJAQ1UxjBa6qgj2arXZQRgAMxrgWvE9\n" "BHc51ZSoK9Fej8+RthyMCeh5nBCHVmwapC6nVCXzpgWE6Mcj78m4UOpuoQJAPV2c\n" "jKAiecbMCtB4KQA3FgtQ/nE2zcw/cUfyJs6mnoUOMnE26eIpuLyj/QqMLAUd6d/C\n" "omValkcfaSs+wyzEkQJBANpYQPve57avZiw9U20L77VXq0aM4+Dcy1qPmxDI9vss\n" "SnaQRfzJBhk+LkyLt1CiSysrp9RcsxHN0zvXl98wCNw=\n" "-----END RSA PRIVATE KEY-----\n" ; }
SECStatus BuildCertChain(TrustDomain& trustDomain, const CERTCertificate* nssCert, PRTime time, EndEntityOrCA endEntityOrCA, /*optional*/ KeyUsages requiredKeyUsagesIfPresent, /*optional*/ KeyPurposeId requiredEKUIfPresent, const CertPolicyId& requiredPolicy, /*optional*/ const SECItem* stapledOCSPResponse, /*out*/ ScopedCERTCertList& results) { if (!nssCert) { PR_NOT_REACHED("null cert passed to BuildCertChain"); PR_SetError(SEC_ERROR_INVALID_ARGS, 0); return SECFailure; } // XXX: Support the legacy use of the subject CN field for indicating the // domain name the certificate is valid for. BackCert::IncludeCN includeCN = endEntityOrCA == EndEntityOrCA::MustBeEndEntity && requiredEKUIfPresent == KeyPurposeId::id_kp_serverAuth ? BackCert::IncludeCN::Yes : BackCert::IncludeCN::No; BackCert cert(nullptr, includeCN); Result rv = cert.Init(nssCert->derCert); if (rv != Success) { return SECFailure; } rv = BuildForward(trustDomain, cert, time, endEntityOrCA, requiredKeyUsagesIfPresent, requiredEKUIfPresent, requiredPolicy, stapledOCSPResponse, 0, results); if (rv != Success) { results = nullptr; return SECFailure; } return SECSuccess; }
const QgsPkiBundle QgsPkiBundle::fromPkcs12Paths( const QString &bundlepath, const QString &bundlepass ) { QgsPkiBundle pkibundle; if ( QCA::isSupported( "pkcs12" ) && !bundlepath.isEmpty() && ( bundlepath.endsWith( ".p12", Qt::CaseInsensitive ) || bundlepath.endsWith( ".pfx", Qt::CaseInsensitive ) ) && QFile::exists( bundlepath ) ) { QCA::SecureArray passarray; if ( !bundlepass.isNull() ) passarray = QCA::SecureArray( bundlepass.toUtf8() ); QCA::ConvertResult res; QCA::KeyBundle bundle( QCA::KeyBundle::fromFile( bundlepath, passarray, &res, QString( "qca-ossl" ) ) ); if ( res == QCA::ConvertGood && !bundle.isNull() ) { QCA::CertificateChain cert_chain( bundle.certificateChain() ); QSslCertificate cert( cert_chain.primary().toPEM().toAscii() ); if ( !cert.isNull() ) { pkibundle.setClientCert( cert ); } QSslKey cert_key( bundle.privateKey().toPEM().toAscii(), QSsl::Rsa, QSsl::Pem, QSsl::PrivateKey, QByteArray() ); if ( !cert_key.isNull() ) { pkibundle.setClientKey( cert_key ); } if ( cert_chain.size() > 1 ) { QList<QSslCertificate> ca_chain; Q_FOREACH ( const QCA::Certificate& ca_cert, cert_chain ) { if ( ca_cert != cert_chain.primary() ) { ca_chain << QSslCertificate( ca_cert.toPEM().toAscii() ); } } pkibundle.setCaChain( ca_chain ); }
ChooseCertificateScreen::ChooseCertificateScreen() : CursesContainer(mainScreen), CursesKeyHandler(PRI_SCREENHANDLER), title(this, _("Certificates")), menu(this) { setRow(2); setAlignment(Curses::PARENTCENTER); title.setAlignment(Curses::PARENTCENTER); menu.setRow(2); std::map<std::string, Certificates::cert>::iterator p; for (p=myServer::certs->certs.begin(); p != myServer::certs->certs.end(); ++p) { certs.push_back(cert(this, p->second.name, p->first)); menu.addPrompt(NULL, &certs.back()); } }
bool OpenSSLContext::setClientCertificate(CertificateWithKey::ref certificate) { boost::shared_ptr<PKCS12Certificate> pkcs12Certificate = boost::dynamic_pointer_cast<PKCS12Certificate>(certificate); if (!pkcs12Certificate || pkcs12Certificate->isNull()) { return false; } // Create a PKCS12 structure BIO* bio = BIO_new(BIO_s_mem()); BIO_write(bio, vecptr(pkcs12Certificate->getData()), pkcs12Certificate->getData().size()); boost::shared_ptr<PKCS12> pkcs12(d2i_PKCS12_bio(bio, NULL), PKCS12_free); BIO_free(bio); if (!pkcs12) { return false; } // Parse PKCS12 X509 *certPtr = 0; EVP_PKEY* privateKeyPtr = 0; STACK_OF(X509)* caCertsPtr = 0; int result = PKCS12_parse(pkcs12.get(), reinterpret_cast<const char*>(vecptr(pkcs12Certificate->getPassword())), &privateKeyPtr, &certPtr, &caCertsPtr); if (result != 1) { return false; } boost::shared_ptr<X509> cert(certPtr, X509_free); boost::shared_ptr<EVP_PKEY> privateKey(privateKeyPtr, EVP_PKEY_free); boost::shared_ptr<STACK_OF(X509)> caCerts(caCertsPtr, freeX509Stack); // Use the key & certificates if (SSL_CTX_use_certificate(context_, cert.get()) != 1) { return false; } if (SSL_CTX_use_PrivateKey(context_, privateKey.get()) != 1) { return false; } for (int i = 0; i < sk_X509_num(caCerts.get()); ++i) { SSL_CTX_add_extra_chain_cert(context_, sk_X509_value(caCerts.get(), i)); } return true; }
void SettingsDialog::validateP12Cert() { d->showP12Cert->setEnabled( false ); d->p12Error->clear(); QFile f( d->p12Cert->text() ); if( !f.open( QIODevice::ReadOnly ) ) return; PKCS12Certificate cert( &f, d->p12Pass->text().toLatin1() ); switch( cert.error() ) { case PKCS12Certificate::NullError: d->showP12Cert->setEnabled( !cert.isNull() ); break; case PKCS12Certificate::InvalidPasswordError: d->p12Error->setText( tr("Invalid password") ); break; default: d->p12Error->setText( tr("Server access certificate error: %1").arg( cert.errorString() ) ); break; } }
// ----------------------------------------------------------------------------- // RoapStorageClient::VerifyL // ----------------------------------------------------------------------------- // EXPORT_C TBool Roap::RRoapStorageClient::VerifyL( const TDesC8& aSignature, const TDesC8& aHash, const RPointerArray<HBufC8>& aCertificateChain ) { CRSAPublicKey* publicKey( NULL ); TBool r( ETrue ); CX509Certificate* cert( NULL ); TX509KeyFactory factory; if ( aCertificateChain.Count() <= 0 ) { User::Leave( KErrArgument ); } cert = CX509Certificate::NewLC( *aCertificateChain[0] ); publicKey = factory.RSAPublicKeyL( cert->PublicKey().KeyData() ); CleanupStack::PushL( publicKey ); r = OmaCrypto::RsaPssVerifyHashL( publicKey, aSignature, aHash ); CleanupStack::PopAndDestroy( publicKey ); CleanupStack::PopAndDestroy( cert ); return r; }
/** \brief Return true if the router_lident_t is_sane() false otherwise */ bool router_lident_t::is_sane() const throw() { // sanity check - the router_lident_t MUST be either selfsigned/authsigned/nonesigned DBG_ASSERT( is_selfsigned() || is_authsigned() || is_nonesigned() ); // sanity check - the router_peerid_t MUST NOT be null DBG_ASSERT( !peerid().is_null() ); // sanity check - the x509_privkey_t MUST NOT be null DBG_ASSERT( !privkey().is_null() ); // sanity check - the x509_cert_t MUST NOT be null DBG_ASSERT( !cert().is_null() ); // sanity check - m_dnsname MUST be either is_host_only() or is_fully_qualified() DBG_ASSERT( dnsname().is_host_only() || dnsname().is_fully_qualified() ); // sanity check - if the dnsname() is_selfsigned_ok if( dnsname().is_selfsigned_ok() ){ // sanity check - the subject_name MUST be the peerid canonical string DBG_ASSERT( peerid() == router_peerid_t::from_canonical_string(cert().subject_name()) ); // sanity check - the cert MUST be selfsigned DBG_ASSERT( cert().subject_name() == cert().issuer_name() ); } // sanity check - if dnsname() is_authsigned_ok if( dnsname().is_authsigned_ok() ){ // sanity check - peerid MUST be directly derived from the dnsname DBG_ASSERT( peerid() == dnsname().to_string() ); // sanity check - the cert MUST NOT be selfsigned DBG_ASSERT( cert().subject_name() != cert().issuer_name() ); } // sanity check - if dnsname() is_nonesigned_ok if( dnsname().is_nonesigned_ok() ){ // sanity check - peerid MUST be directly derived from router_name_t::host() DBG_ASSERT( peerid() == router_peerid_t::from_canonical_string(dnsname().host()) ); // sanity check - the cert MUST be selfsigned DBG_ASSERT( cert().subject_name() == cert().issuer_name() ); } // if all tests passed, it is considered sane, so return true return true; }
void SSLSocket::attach() { ssl_internal_stack *stack; if(idata != 0) { stack = (ssl_internal_stack *)idata; delete stack; } stack = new ssl_internal_stack(); stack->ssl = SSL_new((SSL_CTX *)ctx.getInternal()); stack->sbio=BIO_new_socket(tsock,BIO_NOCLOSE); if(stack->sbio == 0x00) throw SSLSocketAddIOFailure(); SSL_set_bio(stack->ssl, stack->sbio, stack->sbio); if(SSL_connect(stack->ssl) <= 0) throw SSLConnectFailed(); //Verify certificate now int vres; if((vres = SSL_get_verify_result(stack->ssl)) != X509_V_OK) { #ifdef USE_DEBUG ::X509 *x5; x5 = SSL_get_peer_certificate(stack->ssl); X509 cert(x5); X509_free(x5); #endif switch(vres) { case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT: throw X509IssuerCertificateNotFound(); case X509_V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE: throw X509UnableToDecryptCertificate(); case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY: #ifdef USE_DEBUG debugmsg(this, "Certificate not found locally.\n"); #endif throw CertificateIssuerNotFoundLocally(); default: throw SSLInvalidCertificate(); } } }
void QgsAuthTrustedCAsDialog::showCertInfo( QTreeWidgetItem *item ) { if ( !item ) return; QString digest( item->data( 0, Qt::UserRole ).toString() ); QMap<QString, QPair<QgsAuthCertUtils::CaCertSource, QSslCertificate> > cacertscache( QgsApplication::authManager()->caCertsCache() ); if ( !cacertscache.contains( digest ) ) { QgsDebugMsg( QStringLiteral( "Certificate Authority not in CA certs cache" ) ); return; } QSslCertificate cert( cacertscache.value( digest ).second ); QgsAuthCertInfoDialog *dlg = new QgsAuthCertInfoDialog( cert, false, this ); dlg->setWindowModality( Qt::WindowModal ); dlg->resize( 675, 500 ); dlg->exec(); dlg->deleteLater(); }
SECStatus AddCertificateFromFile(const char* basePath, const char* filename) { char buf[16384] = { 0 }; SECStatus rv = ReadFileToBuffer(basePath, filename, buf); if (rv != SECSuccess) { return rv; } SECItem certDER; rv = CERT_DecodeCertPackage(buf, strlen(buf), DecodeCertCallback, &certDER); if (rv != SECSuccess) { PrintPRError("CERT_DecodeCertPackage failed"); return rv; } ScopedCERTCertificate cert(CERT_NewTempCertificate(CERT_GetDefaultCertDB(), &certDER, nullptr, false, true)); PORT_Free(certDER.data); if (!cert) { PrintPRError("CERT_NewTempCertificate failed"); return SECFailure; } ScopedPK11SlotInfo slot(PK11_GetInternalKeySlot()); if (!slot) { PrintPRError("PK11_GetInternalKeySlot failed"); return SECFailure; } // The nickname is the filename without '.pem'. std::string nickname(filename, strlen(filename) - 4); rv = PK11_ImportCert(slot, cert, CK_INVALID_HANDLE, nickname.c_str(), false); if (rv != SECSuccess) { PrintPRError("PK11_ImportCert failed"); return rv; } return SECSuccess; }
void QCACryptoInterface::generateKeyPair(const char* certificateFile, const char *publicKeyFile, const char *privateKeyFile, const char *keyPassword) { if(!QCA::isSupported("pkey") || !QCA::PKey::supportedIOTypes().contains(QCA::PKey::RSA)) { qDebug() << "RSA not supported!\n"; return; } QCA::PrivateKey secretKey = QCA::KeyGenerator().createRSA(2048); if(secretKey.isNull()) { qDebug() << "Failed to make private RSA key\n"; return; } secretKey.toPEMFile(privateKeyFile, keyPassword); // public QCA::CertificateOptions opts; QCA::Certificate cert(opts, secretKey); cert.toPEMFile(certificateFile); QCA::PublicKey pubkey = secretKey.toPublicKey(); pubkey.toPEMFile(publicKeyFile); }
bool QgsAuthPkcs12Edit::validateConfig() { // required components QString bundlepath( lePkcs12Bundle->text() ); bool bundlefound = QFile::exists( bundlepath ); QgsAuthGuiUtils::fileFound( bundlepath.isEmpty() || bundlefound, lePkcs12Bundle ); if ( !bundlefound ) { writePkiMessage( lePkcs12Msg, tr( "Missing components" ), Invalid ); return validityChange( false ); } if ( !QCA::isSupported( "pkcs12" ) ) { writePkiMessage( lePkcs12Msg, tr( "QCA library has no PKCS#12 support" ), Invalid ); return validityChange( false ); } // load the bundle QCA::SecureArray passarray; if ( !lePkcs12KeyPass->text().isEmpty() ) passarray = QCA::SecureArray( lePkcs12KeyPass->text().toUtf8() ); QCA::ConvertResult res; QCA::KeyBundle bundle( QCA::KeyBundle::fromFile( bundlepath, passarray, &res, QString( "qca-ossl" ) ) ); if ( res == QCA::ErrorFile ) { writePkiMessage( lePkcs12Msg, tr( "Failed to read bundle file" ), Invalid ); return validityChange( false ); } else if ( res == QCA::ErrorPassphrase ) { writePkiMessage( lePkcs12Msg, tr( "Incorrect bundle password" ), Invalid ); lePkcs12KeyPass->setPlaceholderText( QString( "Required passphrase" ) ); return validityChange( false ); } else if ( res == QCA::ErrorDecode ) { writePkiMessage( lePkcs12Msg, tr( "Failed to decode (try entering password)" ), Invalid ); return validityChange( false ); } if ( bundle.isNull() ) { writePkiMessage( lePkcs12Msg, tr( "Bundle empty or can not be loaded" ), Invalid ); return validityChange( false ); } // check for primary cert and that it is valid QCA::Certificate cert( bundle.certificateChain().primary() ); if ( cert.isNull() ) { writePkiMessage( lePkcs12Msg, tr( "Bundle client cert can not be loaded" ), Invalid ); return validityChange( false ); } // TODO: add more robust validation, including cert chain resolution QDateTime startdate( cert.notValidBefore() ); QDateTime enddate( cert.notValidAfter() ); QDateTime now( QDateTime::currentDateTime() ); bool bundlevalid = ( now >= startdate && now <= enddate ); writePkiMessage( lePkcs12Msg, tr( "%1 thru %2" ).arg( startdate.toString() ).arg( enddate.toString() ), ( bundlevalid ? Valid : Invalid ) ); return validityChange( bundlevalid ); }
nsresult VerifyCMSDetachedSignatureIncludingCertificate( const SECItem& buffer, const SECItem& detachedDigest, nsresult (*verifyCertificate)(CERTCertificate* cert, void* context, void* pinArg), void *verifyCertificateContext, void* pinArg) { // XXX: missing pinArg is tolerated. if (NS_WARN_IF(!buffer.data && buffer.len > 0) || NS_WARN_IF(!detachedDigest.data && detachedDigest.len > 0) || (!verifyCertificate) || NS_WARN_IF(!verifyCertificateContext)) { return NS_ERROR_INVALID_ARG; } ScopedNSSCMSMessage cmsMsg(NSS_CMSMessage_CreateFromDER(const_cast<SECItem*>(&buffer), nullptr, nullptr, nullptr, nullptr, nullptr, nullptr)); if (!cmsMsg) { return NS_ERROR_CMS_VERIFY_ERROR_PROCESSING; } if (!NSS_CMSMessage_IsSigned(cmsMsg.get())) { return NS_ERROR_CMS_VERIFY_NOT_SIGNED; } NSSCMSContentInfo* cinfo = NSS_CMSMessage_ContentLevel(cmsMsg.get(), 0); if (!cinfo) { return NS_ERROR_CMS_VERIFY_NO_CONTENT_INFO; } // signedData is non-owning NSSCMSSignedData* signedData = reinterpret_cast<NSSCMSSignedData*>(NSS_CMSContentInfo_GetContent(cinfo)); if (!signedData) { return NS_ERROR_CMS_VERIFY_NO_CONTENT_INFO; } // Set digest value. if (NSS_CMSSignedData_SetDigestValue(signedData, SEC_OID_SHA1, const_cast<SECItem*>(&detachedDigest))) { return NS_ERROR_CMS_VERIFY_BAD_DIGEST; } // Parse the certificates into CERTCertificate objects held in memory so // verifyCertificate will be able to find them during path building. ScopedCERTCertList certs(CERT_NewCertList()); if (!certs) { return NS_ERROR_OUT_OF_MEMORY; } if (signedData->rawCerts) { for (size_t i = 0; signedData->rawCerts[i]; ++i) { ScopedCERTCertificate cert(CERT_NewTempCertificate(CERT_GetDefaultCertDB(), signedData->rawCerts[i], nullptr, false, true)); // Skip certificates that fail to parse if (cert) { if (CERT_AddCertToListTail(certs.get(), cert.get()) == SECSuccess) { cert.forget(); // ownership transfered } else { return NS_ERROR_OUT_OF_MEMORY; } } } } // Get the end-entity certificate. int numSigners = NSS_CMSSignedData_SignerInfoCount(signedData); if (NS_WARN_IF(numSigners != 1)) { return NS_ERROR_CMS_VERIFY_ERROR_PROCESSING; } // signer is non-owning. NSSCMSSignerInfo* signer = NSS_CMSSignedData_GetSignerInfo(signedData, 0); if (NS_WARN_IF(!signer)) { return NS_ERROR_CMS_VERIFY_ERROR_PROCESSING; } CERTCertificate* signerCert = NSS_CMSSignerInfo_GetSigningCertificate(signer, CERT_GetDefaultCertDB()); if (!signerCert) { return NS_ERROR_CMS_VERIFY_ERROR_PROCESSING; } nsresult rv = verifyCertificate(signerCert, verifyCertificateContext, pinArg); if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } // See NSS_CMSContentInfo_GetContentTypeOID, which isn't exported from NSS. SECOidData* contentTypeOidData = SECOID_FindOID(&signedData->contentInfo.contentType); if (!contentTypeOidData) { return NS_ERROR_CMS_VERIFY_ERROR_PROCESSING; } return MapSECStatus(NSS_CMSSignerInfo_Verify(signer, const_cast<SECItem*>(&detachedDigest), &contentTypeOidData->oid)); }
KdeConnectConfig::KdeConnectConfig() : d(new KdeConnectConfigPrivate) { //qCDebug(KDECONNECT_CORE) << "QCA supported capabilities:" << QCA::supportedFeatures().join(","); if(!QCA::isSupported("rsa")) { qCritical() << "Could not find support for RSA in your QCA installation"; Daemon::instance()->reportError( i18n("KDE Connect failed to start"), i18n("Could not find support for RSA in your QCA installation. If your " "distribution provides separate packages for QCA-ossl and QCA-gnupg, " "make sure you have them installed and try again.")); return; } //Make sure base directory exists QDir().mkpath(baseConfigDir().path()); //.config/kdeconnect/config d->config = new QSettings(baseConfigDir().absoluteFilePath(QStringLiteral("config")), QSettings::IniFormat); d->trusted_devices = new QSettings(baseConfigDir().absoluteFilePath(QStringLiteral("trusted_devices")), QSettings::IniFormat); //Register my own id if not there yet if (!d->config->contains(QStringLiteral("id"))) { QString uuid = QUuid::createUuid().toString(); DbusHelper::filterNonExportableCharacters(uuid); d->config->setValue(QStringLiteral("id"), uuid); d->config->sync(); qCDebug(KDECONNECT_CORE) << "My id:" << uuid; } const QFile::Permissions strict = QFile::ReadOwner | QFile::WriteOwner | QFile::ReadUser | QFile::WriteUser; QString keyPath = privateKeyPath(); QFile privKey(keyPath); if (privKey.exists() && privKey.open(QIODevice::ReadOnly)) { d->privateKey = QCA::PrivateKey::fromPEM(privKey.readAll()); } else { d->privateKey = QCA::KeyGenerator().createRSA(2048); if (!privKey.open(QIODevice::ReadWrite | QIODevice::Truncate)) { Daemon::instance()->reportError(QStringLiteral("KDE Connect"), i18n("Could not store private key file: %1", keyPath)); } else { privKey.setPermissions(strict); privKey.write(d->privateKey.toPEM().toLatin1()); } } QString certPath = certificatePath(); QFile cert(certPath); if (cert.exists() && cert.open(QIODevice::ReadOnly)) { d->certificate = QSslCertificate::fromPath(certPath).at(0); } else { // FIXME: We only use QCA here to generate the cert and key, would be nice to get rid of it completely. // The same thing we are doing with QCA could be done invoking openssl (altought it's potentially less portable): // openssl req -new -x509 -sha256 -newkey rsa:2048 -nodes -keyout privateKey.pem -days 3650 -out certificate.pem -subj "/O=KDE/OU=KDE Connect/CN=_e6e29ad4_2b31_4b6d_8f7a_9872dbaa9095_" QCA::CertificateOptions certificateOptions = QCA::CertificateOptions(); QDateTime startTime = QDateTime::currentDateTime().addYears(-1); QDateTime endTime = startTime.addYears(10); QCA::CertificateInfo certificateInfo; certificateInfo.insert(QCA::CommonName,deviceId()); certificateInfo.insert(QCA::Organization,QStringLiteral("KDE")); certificateInfo.insert(QCA::OrganizationalUnit,QStringLiteral("Kde connect")); certificateOptions.setInfo(certificateInfo); certificateOptions.setFormat(QCA::PKCS10); certificateOptions.setSerialNumber(QCA::BigInteger(10)); certificateOptions.setValidityPeriod(startTime, endTime); d->certificate = QSslCertificate(QCA::Certificate(certificateOptions, d->privateKey).toPEM().toLatin1()); if (!cert.open(QIODevice::ReadWrite | QIODevice::Truncate)) { Daemon::instance()->reportError(QStringLiteral("KDE Connect"), i18n("Could not store certificate file: %1", certPath)); } else { cert.setPermissions(strict); cert.write(d->certificate.toPem()); } } //Extra security check if (QFile::permissions(keyPath) != strict) { qCWarning(KDECONNECT_CORE) << "Warning: KDE Connect private key file has too open permissions " << keyPath; } }
void WebSocketQt::setupSocketWithSSLDataSource(SSLDataSource * dataSource) { QSslConfiguration config; QFile localFile(WebSocketQt::toString(dataSource->clientLocalCertificateFilePath())); if (localFile.open(QIODevice::ReadOnly)) { QSslCertificate cert(localFile.readAll()); localFile.close(); if (cert.isNull()) { #ifdef FAYECPP_DEBUG_MESSAGES qDebug() << "SocketQT: LocalCertificate is NULL"; #endif } else { config.setLocalCertificate(cert); } } QFile keyFile(WebSocketQt::toString(dataSource->clientPrivateKeyFilePath())); if (keyFile.open(QIODevice::ReadOnly)) { QByteArray pp; pp.append(WebSocketQt::toString(dataSource->clientPrivateKeyPassPhrase())); QSslKey key(keyFile.readAll(), QSsl::Rsa, QSsl::Pem, QSsl::PrivateKey, pp); pp.clear(); keyFile.close(); if (key.isNull()) { #ifdef FAYECPP_DEBUG_MESSAGES qDebug() << "SocketQT: PrivateKey is NULL"; #endif } else { config.setPrivateKey(key); } } QFile caFile(WebSocketQt::toString(dataSource->clientCACertificateFilePath())); if (caFile.open(QIODevice::ReadOnly)) { QSslCertificate cert(caFile.readAll()); caFile.close(); if (cert.isNull()) { #ifdef FAYECPP_DEBUG_MESSAGES qDebug() << "SocketQT: CACertificate is NULL"; #endif } else { QList<QSslCertificate> caList(config.caCertificates()); caList.append(cert); config.setCaCertificates(caList); } } _socket->setSslConfiguration(config); }
Core::Core() : QObject(), _storage(0) { #ifdef HAVE_UMASK umask(S_IRWXG | S_IRWXO); #endif _startTime = QDateTime::currentDateTime().toUTC(); // for uptime :) Quassel::loadTranslation(QLocale::system()); // FIXME: MIGRATION 0.3 -> 0.4: Move database and core config to new location // Move settings, note this does not delete the old files #ifdef Q_WS_MAC QSettings newSettings("quassel-irc.org", "quasselcore"); #else # ifdef Q_WS_WIN QSettings::Format format = QSettings::IniFormat; # else QSettings::Format format = QSettings::NativeFormat; # endif QString newFilePath = Quassel::configDirPath() + "quasselcore" + ((format == QSettings::NativeFormat) ? QLatin1String(".conf") : QLatin1String(".ini")); QSettings newSettings(newFilePath, format); #endif /* Q_WS_MAC */ if (newSettings.value("Config/Version").toUInt() == 0) { # ifdef Q_WS_MAC QString org = "quassel-irc.org"; # else QString org = "Quassel Project"; # endif QSettings oldSettings(org, "Quassel Core"); if (oldSettings.allKeys().count()) { qWarning() << "\n\n*** IMPORTANT: Config and data file locations have changed. Attempting to auto-migrate your core settings..."; foreach(QString key, oldSettings.allKeys()) newSettings.setValue(key, oldSettings.value(key)); newSettings.setValue("Config/Version", 1); qWarning() << "* Your core settings have been migrated to" << newSettings.fileName(); #ifndef Q_WS_MAC /* we don't need to move the db and cert for mac */ #ifdef Q_OS_WIN32 QString quasselDir = qgetenv("APPDATA") + "/quassel/"; #elif defined Q_WS_MAC QString quasselDir = QDir::homePath() + "/Library/Application Support/Quassel/"; #else QString quasselDir = QDir::homePath() + "/.quassel/"; #endif QFileInfo info(Quassel::configDirPath() + "quassel-storage.sqlite"); if (!info.exists()) { // move database, if we found it QFile oldDb(quasselDir + "quassel-storage.sqlite"); if (oldDb.exists()) { bool success = oldDb.rename(Quassel::configDirPath() + "quassel-storage.sqlite"); if (success) qWarning() << "* Your database has been moved to" << Quassel::configDirPath() + "quassel-storage.sqlite"; else qWarning() << "!!! Moving your database has failed. Please move it manually into" << Quassel::configDirPath(); } } // move certificate QFileInfo certInfo(quasselDir + "quasselCert.pem"); if (certInfo.exists()) { QFile cert(quasselDir + "quasselCert.pem"); bool success = cert.rename(Quassel::configDirPath() + "quasselCert.pem"); if (success) qWarning() << "* Your certificate has been moved to" << Quassel::configDirPath() + "quasselCert.pem"; else qWarning() << "!!! Moving your certificate has failed. Please move it manually into" << Quassel::configDirPath(); } #endif /* !Q_WS_MAC */ qWarning() << "*** Migration completed.\n\n"; } } // MIGRATION end // check settings version // so far, we only have 1 CoreSettings s; if (s.version() != 1) { qCritical() << "Invalid core settings version, terminating!"; exit(EXIT_FAILURE); } registerStorageBackends(); connect(&_storageSyncTimer, SIGNAL(timeout()), this, SLOT(syncStorage())); _storageSyncTimer.start(10 * 60 * 1000); // 10 minutes }
int main(int argc, char* argv[]) { ScopedXPCOM xpcom("TestCertDB"); if (xpcom.failed()) { fail("couldn't initialize XPCOM"); return 1; } { nsCOMPtr<nsIPrefBranch> prefs(do_GetService(NS_PREFSERVICE_CONTRACTID)); if (!prefs) { fail("couldn't get nsIPrefBranch"); return 1; } // When PSM initializes, it attempts to get some localized strings. // As a result, Android flips out if this isn't set. nsresult rv = prefs->SetBoolPref("intl.locale.matchOS", true); if (NS_FAILED(rv)) { fail("couldn't set pref 'intl.locale.matchOS'"); return 1; } nsCOMPtr<nsIX509CertDB> certdb(do_GetService(NS_X509CERTDB_CONTRACTID)); if (!certdb) { fail("couldn't get certdb"); return 1; } nsCOMPtr<nsIX509CertList> certList; rv = certdb->GetCerts(getter_AddRefs(certList)); if (NS_FAILED(rv)) { fail("couldn't get list of certificates"); return 1; } nsCOMPtr<nsISimpleEnumerator> enumerator; rv = certList->GetEnumerator(getter_AddRefs(enumerator)); if (NS_FAILED(rv)) { fail("couldn't enumerate certificate list"); return 1; } bool foundBuiltIn = false; bool hasMore = false; while (NS_SUCCEEDED(enumerator->HasMoreElements(&hasMore)) && hasMore) { nsCOMPtr<nsISupports> supports; if (NS_FAILED(enumerator->GetNext(getter_AddRefs(supports)))) { fail("couldn't get next certificate"); return 1; } nsCOMPtr<nsIX509Cert> cert(do_QueryInterface(supports)); if (!cert) { fail("couldn't QI to nsIX509Cert"); return 1; } if (NS_FAILED(cert->GetIsBuiltInRoot(&foundBuiltIn))) { fail("GetIsBuiltInRoot failed"); return 1; } if (foundBuiltIn) { break; } } if (foundBuiltIn) { passed("successfully loaded at least one built-in certificate"); } else { fail("didn't load any built-in certificates"); return 1; } } // this scopes the nsCOMPtrs // no nsCOMPtrs are allowed to be alive when you call NS_ShutdownXPCOM return 0; }
int main(int argc, char* argv[]) { try { log_init(); cxxtools::Arg<std::string> ip(argc, argv, 'i'); cxxtools::Arg<unsigned short> port(argc, argv, 'p', 1234); cxxtools::Arg<unsigned> bufsize(argc, argv, 'b', 8192); cxxtools::Arg<bool> listen(argc, argv, 'l'); cxxtools::Arg<bool> read_reply(argc, argv, 'r'); cxxtools::Arg<bool> ssl(argc, argv, 's'); cxxtools::Arg<std::string> cert(argc, argv, "--cert"); cxxtools::Arg<std::string> ca(argc, argv, "--CA"); if (listen) { // I'm a server // listen to a port cxxtools::net::TcpServer server(ip.getValue(), port); // accept a connetion cxxtools::net::TcpStream worker(server, bufsize); if (ssl) { if (cert.isSet()) worker.loadSslCertificateFile(cert); if (ca.isSet()) worker.setSslVerify(2, ca); worker.sslAccept(); } // copy to stdout std::cout << worker.rdbuf(); } else { // I'm a client // connect to server cxxtools::net::TcpStream peer(ip, port, bufsize); if (ssl) { if (cert.isSet()) peer.loadSslCertificateFile(cert); peer.sslConnect(); } if (argc > 1) { for (int a = 1; a < argc; ++a) { std::ifstream in(argv[a]); peer << in.rdbuf() << std::flush; } } else { // copy stdin to server peer << std::cin.rdbuf() << std::flush; } if (read_reply) // copy answer to stdout std::cout << peer.rdbuf() << std::flush; } } catch (const std::exception& e) { std::cerr << e.what() << std::endl; } }
// Validate the peer's certificate list, from root to peer (last to first) int CertManager::Validate() { CertList::reverse_iterator last = peerList_.rbegin(); size_t count = peerList_.size(); while ( count > 1 ) { TaoCrypt::Source source((*last)->get_buffer(), (*last)->get_length()); TaoCrypt::CertDecoder cert(source, true, &signers_, verifyNone_); if (int err = cert.GetError().What()) return err; const TaoCrypt::PublicKey& key = cert.GetPublicKey(); signers_.push_back(NEW_YS TaoCrypt::Signer(key.GetKey(), key.size(), cert.GetCommonName(), cert.GetHash())); ++last; --count; } if (count) { // peer's is at the front TaoCrypt::Source source((*last)->get_buffer(), (*last)->get_length()); TaoCrypt::CertDecoder cert(source, true, &signers_, verifyNone_); int err = cert.GetError().What(); if ( err && err != TaoCrypt::SIG_OTHER_E) return err; uint sz = cert.GetPublicKey().size(); peerPublicKey_.allocate(sz); peerPublicKey_.assign(cert.GetPublicKey().GetKey(), sz); if (cert.GetKeyType() == TaoCrypt::RSAk) peerKeyType_ = rsa_sa_algo; else peerKeyType_ = dsa_sa_algo; size_t iSz = strlen(cert.GetIssuer()) + 1; size_t sSz = strlen(cert.GetCommonName()) + 1; ASN1_STRING beforeDate, afterDate; beforeDate.data= (unsigned char *) cert.GetBeforeDate(); beforeDate.type= cert.GetBeforeDateType(); beforeDate.length= strlen((char *) beforeDate.data) + 1; afterDate.data= (unsigned char *) cert.GetAfterDate(); afterDate.type= cert.GetAfterDateType(); afterDate.length= strlen((char *) afterDate.data) + 1; peerX509_ = NEW_YS X509(cert.GetIssuer(), iSz, cert.GetCommonName(), sSz, &beforeDate, &afterDate); if (err == TaoCrypt::SIG_OTHER_E && verifyCallback_) { X509_STORE_CTX store; store.error = err; store.error_depth = static_cast<int>(count) - 1; store.current_cert = peerX509_; int ok = verifyCallback_(0, &store); if (ok) return 0; } if (err == TaoCrypt::SIG_OTHER_E) return err; } return 0; }
bool verify_X509_cert_chain(const std::vector<std::string> &certChain, const std::string &hostName) { JNIEnv* env = get_jvm_env(); // Possible performance improvement: // In the future we could gain performance by turning all the jclass local // references into global references. Then we could lazy initialize and // save them globally. If this is done I'm not exactly sure where the release // should be. // ByteArrayInputStream java_local_ref<jclass> byteArrayInputStreamClass(env->FindClass("java/io/ByteArrayInputStream")); CHECK_JREF(env, byteArrayInputStreamClass); jmethodID byteArrayInputStreamConstructorMethod = env->GetMethodID( byteArrayInputStreamClass.get(), "<init>", "([B)V"); CHECK_JMID(env, byteArrayInputStreamConstructorMethod); // CertificateFactory java_local_ref<jclass> certificateFactoryClass(env->FindClass("java/security/cert/CertificateFactory")); CHECK_JREF(env, certificateFactoryClass); jmethodID certificateFactoryGetInstanceMethod = env->GetStaticMethodID( certificateFactoryClass.get(), "getInstance", "(Ljava/lang/String;)Ljava/security/cert/CertificateFactory;"); CHECK_JMID(env, certificateFactoryGetInstanceMethod); jmethodID generateCertificateMethod = env->GetMethodID( certificateFactoryClass.get(), "generateCertificate", "(Ljava/io/InputStream;)Ljava/security/cert/Certificate;"); CHECK_JMID(env, generateCertificateMethod); // X509Certificate java_local_ref<jclass> X509CertificateClass(env->FindClass("java/security/cert/X509Certificate")); CHECK_JREF(env, X509CertificateClass); // TrustManagerFactory java_local_ref<jclass> trustManagerFactoryClass(env->FindClass("javax/net/ssl/TrustManagerFactory")); CHECK_JREF(env, trustManagerFactoryClass); jmethodID trustManagerFactoryGetInstanceMethod = env->GetStaticMethodID( trustManagerFactoryClass.get(), "getInstance", "(Ljava/lang/String;)Ljavax/net/ssl/TrustManagerFactory;"); CHECK_JMID(env, trustManagerFactoryGetInstanceMethod); jmethodID trustManagerFactoryInitMethod = env->GetMethodID( trustManagerFactoryClass.get(), "init", "(Ljava/security/KeyStore;)V"); CHECK_JMID(env, trustManagerFactoryInitMethod); jmethodID trustManagerFactoryGetTrustManagersMethod = env->GetMethodID( trustManagerFactoryClass.get(), "getTrustManagers", "()[Ljavax/net/ssl/TrustManager;"); CHECK_JMID(env, trustManagerFactoryGetTrustManagersMethod); // X509TrustManager java_local_ref<jclass> X509TrustManagerClass(env->FindClass("javax/net/ssl/X509TrustManager")); CHECK_JREF(env, X509TrustManagerClass); jmethodID X509TrustManagerCheckServerTrustedMethod = env->GetMethodID( X509TrustManagerClass.get(), "checkServerTrusted", "([Ljava/security/cert/X509Certificate;Ljava/lang/String;)V"); CHECK_JMID(env, X509TrustManagerCheckServerTrustedMethod); // StrictHostnameVerifier java_local_ref<jclass> strictHostnameVerifierClass(env->FindClass("org/apache/http/conn/ssl/StrictHostnameVerifier")); CHECK_JREF(env, strictHostnameVerifierClass); jmethodID strictHostnameVerifierConstructorMethod = env->GetMethodID(strictHostnameVerifierClass.get(), "<init>", "()V"); CHECK_JMID(env, strictHostnameVerifierConstructorMethod); jmethodID strictHostnameVerifierVerifyMethod = env->GetMethodID( strictHostnameVerifierClass.get(), "verify", "(Ljava/lang/String;Ljava/security/cert/X509Certificate;)V"); CHECK_JMID(env, strictHostnameVerifierVerifyMethod); // Create CertificateFactory java_local_ref<jstring> XDot509String(env->NewStringUTF("X.509")); CHECK_JREF(env, XDot509String); java_local_ref<jobject> certificateFactory(env->CallStaticObjectMethod( certificateFactoryClass.get(), certificateFactoryGetInstanceMethod, XDot509String.get())); CHECK_JREF(env, certificateFactory); // Create Java array to store all the certs in. java_local_ref<jobjectArray> certsArray(env->NewObjectArray(certChain.size(), X509CertificateClass.get(), nullptr)); CHECK_JREF(env, certsArray); // For each certificate perform the following steps: // 1. Create ByteArrayInputStream backed by DER certificate bytes // 2. Create Certificate using CertificateFactory.generateCertificate // 3. Add Certificate to array int i = 0; for(const auto &certData : certChain) { java_local_ref<jbyteArray> byteArray(env->NewByteArray(certData.size())); CHECK_JREF(env, byteArray); env->SetByteArrayRegion(byteArray.get(), 0, certData.size(), reinterpret_cast<const jbyte *>(certData.c_str())); CHECK_JNI(env); java_local_ref<jobject> byteArrayInputStream(env->NewObject( byteArrayInputStreamClass.get(), byteArrayInputStreamConstructorMethod, byteArray.get())); CHECK_JREF(env, byteArrayInputStream); java_local_ref<jobject> cert(env->CallObjectMethod( certificateFactory.get(), generateCertificateMethod, byteArrayInputStream.get())); CHECK_JREF(env, cert); env->SetObjectArrayElement(certsArray.get(), i, cert.get()); CHECK_JNI(env); ++i; } // Create TrustManagerFactory, init with Android system certs java_local_ref<jstring> X509String(env->NewStringUTF("X509")); CHECK_JREF(env, X509String); java_local_ref<jobject> trustFactoryManager(env->CallStaticObjectMethod( trustManagerFactoryClass.get(), trustManagerFactoryGetInstanceMethod, X509String.get())); CHECK_JREF(env, trustFactoryManager); env->CallVoidMethod(trustFactoryManager.get(), trustManagerFactoryInitMethod, nullptr); CHECK_JNI(env); // Get TrustManager java_local_ref<jobjectArray> trustManagerArray(static_cast<jobjectArray>( env->CallObjectMethod(trustFactoryManager.get(), trustManagerFactoryGetTrustManagersMethod))); CHECK_JREF(env, trustManagerArray); java_local_ref<jobject> trustManager(env->GetObjectArrayElement(trustManagerArray.get(), 0)); CHECK_JREF(env, trustManager); // Validate certificate chain. java_local_ref<jstring> RSAString(env->NewStringUTF("RSA")); CHECK_JREF(env, RSAString); env->CallVoidMethod( trustManager.get(), X509TrustManagerCheckServerTrustedMethod, certsArray.get(), RSAString.get()); CHECK_JNI(env); // Verify hostname on certificate according to RFC 2818. java_local_ref<jobject> hostnameVerifier(env->NewObject( strictHostnameVerifierClass.get(), strictHostnameVerifierConstructorMethod)); CHECK_JREF(env, hostnameVerifier); java_local_ref<jstring> hostNameString(env->NewStringUTF(hostName.c_str())); CHECK_JREF(env, hostNameString); java_local_ref<jobject> cert(env->GetObjectArrayElement(certsArray.get(), 0)); CHECK_JREF(env, cert); env->CallVoidMethod( hostnameVerifier.get(), strictHostnameVerifierVerifyMethod, hostNameString.get(), cert.get()); CHECK_JNI(env); return true; }
SECStatus ConfigSecureServerWithNamedCert(PRFileDesc *fd, const char *certName, /*optional*/ ScopedCERTCertificate *certOut, /*optional*/ SSLKEAType *keaOut) { ScopedCERTCertificate cert(PK11_FindCertFromNickname(certName, nullptr)); if (!cert) { PrintPRError("PK11_FindCertFromNickname failed"); return SECFailure; } // If an intermediate certificate issued the server certificate (rather than // directly by a trust anchor), we want to send it along in the handshake so // we don't encounter unknown issuer errors when that's not what we're // testing. UniqueCERTCertificateList certList; ScopedCERTCertificate issuerCert( CERT_FindCertByName(CERT_GetDefaultCertDB(), &cert->derIssuer)); // If we can't find the issuer cert, continue without it. if (issuerCert) { // Sadly, CERTCertificateList does not have a CERT_NewCertificateList // utility function, so we must create it ourselves. This consists // of creating an arena, allocating space for the CERTCertificateList, // and then transferring ownership of the arena to that list. ScopedPLArenaPool arena(PORT_NewArena(DER_DEFAULT_CHUNKSIZE)); if (!arena) { PrintPRError("PORT_NewArena failed"); return SECFailure; } certList.reset(static_cast<CERTCertificateList*>( PORT_ArenaAlloc(arena.get(), sizeof(CERTCertificateList)))); if (!certList) { PrintPRError("PORT_ArenaAlloc failed"); return SECFailure; } certList->arena = arena.forget(); // We also have to manually copy the certificates we care about to the // list, because there aren't any utility functions for that either. certList->certs = reinterpret_cast<SECItem*>( PORT_ArenaAlloc(certList->arena, 2 * sizeof(SECItem))); if (SECITEM_CopyItem(certList->arena, certList->certs, &cert->derCert) != SECSuccess) { PrintPRError("SECITEM_CopyItem failed"); return SECFailure; } if (SECITEM_CopyItem(certList->arena, certList->certs + 1, &issuerCert->derCert) != SECSuccess) { PrintPRError("SECITEM_CopyItem failed"); return SECFailure; } certList->len = 2; } ScopedPK11SlotInfo slot(PK11_GetInternalKeySlot()); UniqueSECKEYPrivateKey key( PK11_FindKeyByDERCert(slot.get(), cert.get(), nullptr)); if (!key) { PrintPRError("PK11_FindKeyByDERCert failed"); return SECFailure; } SSLKEAType certKEA = NSS_FindCertKEAType(cert); if (SSL_ConfigSecureServerWithCertChain(fd, cert.get(), certList.get(), key.get(), certKEA) != SECSuccess) { PrintPRError("SSL_ConfigSecureServer failed"); return SECFailure; } if (certOut) { *certOut = cert.forget(); } if (keaOut) { *keaOut = certKEA; } return SECSuccess; }
bool SSLSocket::enableCrypto(bool activate /* = true */) { if (activate && !m_ssl_active) { double timeout = m_connect_timeout; bool blocked = m_is_blocked; if (!m_state_set) { if (m_client) { SSL_set_connect_state(m_handle); } else { SSL_set_accept_state(m_handle); } m_state_set = true; } if (m_client && setBlocking(false)) { m_is_blocked = false; } int n; bool retry = true; do { if (m_client) { struct timeval tvs, tve; struct timezone tz; gettimeofday(&tvs, &tz); n = SSL_connect(m_handle); gettimeofday(&tve, &tz); timeout -= (tve.tv_sec + (double) tve.tv_usec / 1000000) - (tvs.tv_sec + (double) tvs.tv_usec / 1000000); if (timeout < 0) { raise_warning("SSL: connection timeout"); return -1; } } else { n = SSL_accept(m_handle); } if (n <= 0) { retry = handleError(n, true); } else { break; } } while (retry); if (m_client && m_is_blocked != blocked && setBlocking(blocked)) { m_is_blocked = blocked; } if (n == 1) { X509 *peer_cert = SSL_get_peer_certificate(m_handle); if (!applyVerificationPolicy(peer_cert)) { SSL_shutdown(m_handle); } else { m_ssl_active = true; /* allow the script to capture the peer cert * and/or the certificate chain */ if (m_context["capture_peer_cert"].toBoolean()) { Object cert(new Certificate(peer_cert)); m_context.set("peer_certificate", cert); peer_cert = nullptr; } if (m_context["capture_peer_cert_chain"].toBoolean()) { Array arr; STACK_OF(X509) *chain = SSL_get_peer_cert_chain(m_handle); if (chain) { for (int i = 0; i < sk_X509_num(chain); i++) { X509 *mycert = X509_dup(sk_X509_value(chain, i)); arr.append(Object(new Certificate(mycert))); } } m_context.set("peer_certificate_chain", arr); } } if (peer_cert) { X509_free(peer_cert); } } else { n = errno == EAGAIN ? 0 : -1; } return n >= 0; } else if (!activate && m_ssl_active) { /* deactivate - common for server/client */ SSL_shutdown(m_handle); m_ssl_active = false; } return true; }
OSStatus SecIdentityCopyPreference( CFStringRef name, CSSM_KEYUSE keyUsage, CFArrayRef validIssuers, SecIdentityRef *identity) { // The original implementation of SecIdentityCopyPreference matches the exact string only. // That implementation has been moved to _SecIdentityCopyPreferenceMatchingName (above), // and this function is a wrapper which calls it, so that existing clients will get the // extended behavior of server domain matching for items that specify URLs. // (Note that behavior is unchanged if the specified name is not a URL.) BEGIN_SECAPI CFTypeRef val = (CFTypeRef)CFPreferencesCopyValue(CFSTR("LogIdentityPreferenceLookup"), CFSTR("com.apple.security"), kCFPreferencesCurrentUser, kCFPreferencesAnyHost); Boolean logging = false; if (val && CFGetTypeID(val) == CFBooleanGetTypeID()) { logging = CFBooleanGetValue((CFBooleanRef)val); CFRelease(val); } OSStatus status = errSecItemNotFound; CFArrayRef names = _SecIdentityCopyPossiblePaths(name); if (!names) { return status; } CFIndex idx, total = CFArrayGetCount(names); for (idx = 0; idx < total; idx++) { CFStringRef aName = (CFStringRef)CFArrayGetValueAtIndex(names, idx); try { status = _SecIdentityCopyPreferenceMatchingName(aName, keyUsage, validIssuers, identity); } catch (...) { status = errSecItemNotFound; } if (logging) { // get identity label CFStringRef labelString = NULL; if (!status && identity && *identity) { try { SecPointer<Certificate> cert(Identity::required(*identity)->certificate()); cert->inferLabel(false, &labelString); } catch (...) { labelString = NULL; }; } char *labelBuf = NULL; CFIndex labelBufSize = (labelString) ? CFStringGetLength(labelString) * 4 : 4; labelBuf = (char *)malloc(labelBufSize); if (!labelString || !CFStringGetCString(labelString, labelBuf, labelBufSize, kCFStringEncodingUTF8)) { labelBuf[0] = 0; } if (labelString) { CFRelease(labelString); } // get service name char *serviceBuf = NULL; CFIndex serviceBufSize = CFStringGetLength(aName) * 4; serviceBuf = (char *)malloc(serviceBufSize); if (!CFStringGetCString(aName, serviceBuf, serviceBufSize, kCFStringEncodingUTF8)) { serviceBuf[0] = 0; } syslog(LOG_NOTICE, "preferred identity: \"%s\" found for \"%s\"\n", labelBuf, serviceBuf); if (!status && name) { char *nameBuf = NULL; CFIndex nameBufSize = CFStringGetLength(name) * 4; nameBuf = (char *)malloc(nameBufSize); if (!CFStringGetCString(name, nameBuf, nameBufSize, kCFStringEncodingUTF8)) { nameBuf[0] = 0; } syslog(LOG_NOTICE, "lookup complete; will use: \"%s\" for \"%s\"\n", labelBuf, nameBuf); free(nameBuf); } free(labelBuf); free(serviceBuf); } if (status == errSecSuccess) { break; // match found } } CFRelease(names); return status; END_SECAPI }
nsresult Generate() { nsresult rv; // Get the key slot for generation later UniquePK11SlotInfo slot(PK11_GetInternalKeySlot()); if (!slot) { return mozilla::psm::GetXPCOMFromNSSError(PR_GetError()); } // Remove existing certs with this name (if any) rv = RemoveExisting(); if (NS_FAILED(rv)) { return rv; } // Generate a new cert NS_NAMED_LITERAL_CSTRING(commonNamePrefix, "CN="); nsAutoCString subjectNameStr(commonNamePrefix + mNickname); UniqueCERTName subjectName(CERT_AsciiToName(subjectNameStr.get())); if (!subjectName) { return mozilla::psm::GetXPCOMFromNSSError(PR_GetError()); } // Use the well-known NIST P-256 curve SECOidData* curveOidData = SECOID_FindOIDByTag(SEC_OID_SECG_EC_SECP256R1); if (!curveOidData) { return mozilla::psm::GetXPCOMFromNSSError(PR_GetError()); } // Get key params from the curve ScopedAutoSECItem keyParams(2 + curveOidData->oid.len); keyParams.data[0] = SEC_ASN1_OBJECT_ID; keyParams.data[1] = curveOidData->oid.len; memcpy(keyParams.data + 2, curveOidData->oid.data, curveOidData->oid.len); // Generate cert key pair SECKEYPublicKey* tempPublicKey; UniqueSECKEYPrivateKey privateKey( PK11_GenerateKeyPair(slot.get(), CKM_EC_KEY_PAIR_GEN, &keyParams, &tempPublicKey, true /* token */, true /* sensitive */, nullptr)); UniqueSECKEYPublicKey publicKey(tempPublicKey); tempPublicKey = nullptr; if (!privateKey || !publicKey) { return mozilla::psm::GetXPCOMFromNSSError(PR_GetError()); } // Create subject public key info and cert request UniqueCERTSubjectPublicKeyInfo spki( SECKEY_CreateSubjectPublicKeyInfo(publicKey.get())); if (!spki) { return mozilla::psm::GetXPCOMFromNSSError(PR_GetError()); } UniqueCERTCertificateRequest certRequest( CERT_CreateCertificateRequest(subjectName.get(), spki.get(), nullptr)); if (!certRequest) { return mozilla::psm::GetXPCOMFromNSSError(PR_GetError()); } // Valid from one day before to 1 year after static const PRTime oneDay = PRTime(PR_USEC_PER_SEC) * PRTime(60) // sec * PRTime(60) // min * PRTime(24); // hours PRTime now = PR_Now(); PRTime notBefore = now - oneDay; PRTime notAfter = now + (PRTime(365) * oneDay); UniqueCERTValidity validity(CERT_CreateValidity(notBefore, notAfter)); if (!validity) { return mozilla::psm::GetXPCOMFromNSSError(PR_GetError()); } // Generate random serial unsigned long serial; // This serial in principle could collide, but it's unlikely rv = MapSECStatus(PK11_GenerateRandomOnSlot( slot.get(), BitwiseCast<unsigned char*, unsigned long*>(&serial), sizeof(serial))); if (NS_FAILED(rv)) { return rv; } // Create the cert from these pieces UniqueCERTCertificate cert( CERT_CreateCertificate(serial, subjectName.get(), validity.get(), certRequest.get())); if (!cert) { return mozilla::psm::GetXPCOMFromNSSError(PR_GetError()); } // Update the cert version to X509v3 if (!cert->version.data) { return NS_ERROR_INVALID_POINTER; } *(cert->version.data) = SEC_CERTIFICATE_VERSION_3; cert->version.len = 1; // Set cert signature algorithm PLArenaPool* arena = cert->arena; if (!arena) { return NS_ERROR_INVALID_POINTER; } rv = MapSECStatus( SECOID_SetAlgorithmID(arena, &cert->signature, SEC_OID_ANSIX962_ECDSA_SHA256_SIGNATURE, 0)); if (NS_FAILED(rv)) { return rv; } // Encode and self-sign the cert UniqueSECItem certDER( SEC_ASN1EncodeItem(nullptr, nullptr, cert.get(), SEC_ASN1_GET(CERT_CertificateTemplate))); if (!certDER) { return mozilla::psm::GetXPCOMFromNSSError(PR_GetError()); } rv = MapSECStatus( SEC_DerSignData(arena, &cert->derCert, certDER->data, certDER->len, privateKey.get(), SEC_OID_ANSIX962_ECDSA_SHA256_SIGNATURE)); if (NS_FAILED(rv)) { return rv; } // Create a CERTCertificate from the signed data UniqueCERTCertificate certFromDER( CERT_NewTempCertificate(CERT_GetDefaultCertDB(), &cert->derCert, nullptr, true /* perm */, true /* copyDER */)); if (!certFromDER) { return mozilla::psm::GetXPCOMFromNSSError(PR_GetError()); } // Save the cert in the DB rv = MapSECStatus(PK11_ImportCert(slot.get(), certFromDER.get(), CK_INVALID_HANDLE, mNickname.get(), false /* unused */)); if (NS_FAILED(rv)) { return rv; } // We should now have cert in the DB, read it back in nsIX509Cert form return GetFromDB(); }
static OSStatus _SecIdentityAddPreferenceItemWithName( SecKeychainRef keychainRef, SecIdentityRef identityRef, CFStringRef idString, SecKeychainItemRef *itemRef) { // this is NOT exported, and called only from SecIdentityAddPreferenceItem (below), so no BEGIN/END macros here; // caller must handle exceptions if (!identityRef || !idString) return errSecParam; SecPointer<Certificate> cert(Identity::required(identityRef)->certificate()); Item item(kSecGenericPasswordItemClass, 'aapl', 0, NULL, false); sint32 keyUsage = 0; // determine the account attribute // // This attribute must be synthesized from certificate label + pref item type + key usage, // as only the account and service attributes can make a generic keychain item unique. // For 'iprf' type items (but not 'cprf'), we append a trailing space. This insures that // we can save a certificate preference if an identity preference already exists for the // given service name, and vice-versa. // If the key usage is 0 (i.e. the normal case), we omit the appended key usage string. // CFStringRef labelStr = nil; cert->inferLabel(false, &labelStr); if (!labelStr) { return errSecDataTooLarge; // data is "in a format which cannot be displayed" } CFIndex accountUTF8Len = CFStringGetMaximumSizeForEncoding(CFStringGetLength(labelStr), kCFStringEncodingUTF8) + 1; const char *templateStr = "%s [key usage 0x%X]"; const int keyUsageMaxStrLen = 8; accountUTF8Len += strlen(templateStr) + keyUsageMaxStrLen; char accountUTF8[accountUTF8Len]; if (!CFStringGetCString(labelStr, accountUTF8, accountUTF8Len-1, kCFStringEncodingUTF8)) accountUTF8[0] = (char)'\0'; if (keyUsage) snprintf(accountUTF8, accountUTF8Len-1, templateStr, accountUTF8, keyUsage); snprintf(accountUTF8, accountUTF8Len-1, "%s ", accountUTF8); CssmData account(const_cast<char *>(accountUTF8), strlen(accountUTF8)); CFRelease(labelStr); // service attribute (name provided by the caller) CFIndex serviceUTF8Len = CFStringGetMaximumSizeForEncoding(CFStringGetLength(idString), kCFStringEncodingUTF8) + 1;; char serviceUTF8[serviceUTF8Len]; if (!CFStringGetCString(idString, serviceUTF8, serviceUTF8Len-1, kCFStringEncodingUTF8)) serviceUTF8[0] = (char)'\0'; CssmData service(const_cast<char *>(serviceUTF8), strlen(serviceUTF8)); // set item attribute values item->setAttribute(Schema::attributeInfo(kSecServiceItemAttr), service); item->setAttribute(Schema::attributeInfo(kSecLabelItemAttr), service); item->setAttribute(Schema::attributeInfo(kSecTypeItemAttr), (FourCharCode)'iprf'); item->setAttribute(Schema::attributeInfo(kSecAccountItemAttr), account); item->setAttribute(Schema::attributeInfo(kSecScriptCodeItemAttr), keyUsage); // generic attribute (store persistent certificate reference) CFDataRef pItemRef = nil; OSStatus status = SecKeychainItemCreatePersistentReference((SecKeychainItemRef)cert->handle(), &pItemRef); if (!pItemRef) status = errSecInvalidItemRef; if (status) return status; const UInt8 *dataPtr = CFDataGetBytePtr(pItemRef); CFIndex dataLen = CFDataGetLength(pItemRef); CssmData pref(const_cast<void *>(reinterpret_cast<const void *>(dataPtr)), dataLen); item->setAttribute(Schema::attributeInfo(kSecGenericItemAttr), pref); CFRelease(pItemRef); Keychain keychain = nil; try { keychain = Keychain::optional(keychainRef); if (!keychain->exists()) MacOSError::throwMe(errSecNoSuchKeychain); // Might be deleted or not available at this time. } catch(...) { keychain = globals().storageManager.defaultKeychainUI(item); } try { keychain->add(item); } catch (const MacOSError &err) { if (err.osStatus() != errSecDuplicateItem) throw; // if item already exists, fall through to update } item->update(); if (itemRef) *itemRef = item->handle(); return status; }
bool Servatrice::initServer() { serverName = settings->value("server/name").toString(); serverId = settings->value("server/id", 0).toInt(); bool regServerOnly = settings->value("server/regonly", 0).toBool(); const QString authenticationMethodStr = settings->value("authentication/method").toString(); if (authenticationMethodStr == "sql") { authenticationMethod = AuthenticationSql; } else { if (regServerOnly) { qDebug() << "Registration only server enabled but no DB Connection : Error."; return false; } authenticationMethod = AuthenticationNone; } QString dbTypeStr = settings->value("database/type").toString(); if (dbTypeStr == "mysql") databaseType = DatabaseMySql; else databaseType = DatabaseNone; servatriceDatabaseInterface = new Servatrice_DatabaseInterface(-1, this); setDatabaseInterface(servatriceDatabaseInterface); if (databaseType != DatabaseNone) { settings->beginGroup("database"); dbPrefix = settings->value("prefix").toString(); servatriceDatabaseInterface->initDatabase("QMYSQL", settings->value("hostname").toString(), settings->value("database").toString(), settings->value("user").toString(), settings->value("password").toString()); settings->endGroup(); updateServerList(); qDebug() << "Clearing previous sessions..."; servatriceDatabaseInterface->clearSessionTables(); } const QString roomMethod = settings->value("rooms/method").toString(); if (roomMethod == "sql") { QSqlQuery query(servatriceDatabaseInterface->getDatabase()); query.prepare("select id, name, descr, auto_join, join_message from " + dbPrefix + "_rooms order by id asc"); servatriceDatabaseInterface->execSqlQuery(query); while (query.next()) { QSqlQuery query2(servatriceDatabaseInterface->getDatabase()); query2.prepare("select name from " + dbPrefix + "_rooms_gametypes where id_room = :id_room"); query2.bindValue(":id_room", query.value(0).toInt()); servatriceDatabaseInterface->execSqlQuery(query2); QStringList gameTypes; while (query2.next()) gameTypes.append(query2.value(0).toString()); addRoom(new Server_Room(query.value(0).toInt(), query.value(1).toString(), query.value(2).toString(), query.value(3).toInt(), query.value(4).toString(), gameTypes, this )); } } else { int size = settings->beginReadArray("rooms/roomlist"); for (int i = 0; i < size; ++i) { settings->setArrayIndex(i); QStringList gameTypes; int size2 = settings->beginReadArray("game_types"); for (int j = 0; j < size2; ++j) { settings->setArrayIndex(j); gameTypes.append(settings->value("name").toString()); } settings->endArray(); Server_Room *newRoom = new Server_Room( i, settings->value("name").toString(), settings->value("description").toString(), settings->value("autojoin").toBool(), settings->value("joinmessage").toString(), gameTypes, this ); addRoom(newRoom); } settings->endArray(); } updateLoginMessage(); maxGameInactivityTime = settings->value("game/max_game_inactivity_time").toInt(); maxPlayerInactivityTime = settings->value("game/max_player_inactivity_time").toInt(); maxUsersPerAddress = settings->value("security/max_users_per_address").toInt(); messageCountingInterval = settings->value("security/message_counting_interval").toInt(); maxMessageCountPerInterval = settings->value("security/max_message_count_per_interval").toInt(); maxMessageSizePerInterval = settings->value("security/max_message_size_per_interval").toInt(); maxGamesPerUser = settings->value("security/max_games_per_user").toInt(); try { if (settings->value("servernetwork/active", 0).toInt()) { qDebug() << "Connecting to ISL network."; const QString certFileName = settings->value("servernetwork/ssl_cert").toString(); const QString keyFileName = settings->value("servernetwork/ssl_key").toString(); qDebug() << "Loading certificate..."; QFile certFile(certFileName); if (!certFile.open(QIODevice::ReadOnly)) throw QString("Error opening certificate file: %1").arg(certFileName); QSslCertificate cert(&certFile); #if QT_VERSION < 0x050000 if (!cert.isValid()) throw(QString("Invalid certificate.")); #else const QDateTime currentTime = QDateTime::currentDateTime(); if(currentTime < cert.effectiveDate() || currentTime > cert.expiryDate() || cert.isBlacklisted()) throw(QString("Invalid certificate.")); #endif qDebug() << "Loading private key..."; QFile keyFile(keyFileName); if (!keyFile.open(QIODevice::ReadOnly)) throw QString("Error opening private key file: %1").arg(keyFileName); QSslKey key(&keyFile, QSsl::Rsa, QSsl::Pem, QSsl::PrivateKey); if (key.isNull()) throw QString("Invalid private key."); QMutableListIterator<ServerProperties> serverIterator(serverList); while (serverIterator.hasNext()) { const ServerProperties &prop = serverIterator.next(); if (prop.cert == cert) { serverIterator.remove(); continue; } QThread *thread = new QThread; thread->setObjectName("isl_" + QString::number(prop.id)); connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater())); IslInterface *interface = new IslInterface(prop.id, prop.hostname, prop.address.toString(), prop.controlPort, prop.cert, cert, key, this); interface->moveToThread(thread); connect(interface, SIGNAL(destroyed()), thread, SLOT(quit())); thread->start(); QMetaObject::invokeMethod(interface, "initClient", Qt::BlockingQueuedConnection); } const int networkPort = settings->value("servernetwork/port", 14747).toInt(); qDebug() << "Starting ISL server on port" << networkPort; islServer = new Servatrice_IslServer(this, cert, key, this); if (islServer->listen(QHostAddress::Any, networkPort)) qDebug() << "ISL server listening."; else throw QString("islServer->listen()"); } } catch (QString error) { qDebug() << "ERROR --" << error; return false; } pingClock = new QTimer(this); connect(pingClock, SIGNAL(timeout()), this, SIGNAL(pingClockTimeout())); pingClock->start(1000); int statusUpdateTime = settings->value("server/statusupdate").toInt(); statusUpdateClock = new QTimer(this); connect(statusUpdateClock, SIGNAL(timeout()), this, SLOT(statusUpdate())); if (statusUpdateTime != 0) { qDebug() << "Starting status update clock, interval " << statusUpdateTime << " ms"; statusUpdateClock->start(statusUpdateTime); } const int numberPools = settings->value("server/number_pools", 1).toInt(); gameServer = new Servatrice_GameServer(this, numberPools, servatriceDatabaseInterface->getDatabase(), this); gameServer->setMaxPendingConnections(1000); const int gamePort = settings->value("server/port", 4747).toInt(); qDebug() << "Starting server on port" << gamePort; if (gameServer->listen(QHostAddress::Any, gamePort)) qDebug() << "Server listening."; else { qDebug() << "gameServer->listen(): Error."; return false; } return true; }
void run(int argc, char* argv[], char* env[]) { U_TRACE(5, "Application::run(%d,%p,%p)", argc, argv, env) UApplication::run(argc, argv, env); U_SYSCALL_VOID_NO_PARAM(xmlInitParser); // init libxml LIBXML_TEST_VERSION // manage options num_args = (argc - optind); U_INTERNAL_DUMP("optind = %d num_args = %d", optind, num_args) if (UApplication::isOptions()) cfg_str = opt['c']; // manage file configuration if (cfg_str.empty()) cfg_str = U_STRING_FROM_CONSTANT("XAdES.ini"); // ---------------------------------------------------------------------------------------------------------------------------------- // XAdES signature - configuration parameters // ---------------------------------------------------------------------------------------------------------------------------------- // DigestAlgorithm md2 | md5 | sha | sha1 | sha224 | sha256 | sha384 | sha512 | mdc2 | ripmed160 // // SigningTime this property contains the time at which the signer claims to have performed the signing process (yes/no) // ClaimedRole this property contains claimed or certified roles assumed by the signer in creating the signature // // this property contains the indication of the purported place where the signer claims to have produced the signature // ------------------------------------------------------------------------------------------------------------------- // ProductionPlaceCity // ProductionPlaceStateOrProvince // ProductionPlacePostalCode // ProductionPlaceCountryName // ------------------------------------------------------------------------------------------------------------------- // // DataObjectFormatMimeType this property identifies the format of a signed data object (when electronic signatures // are not exchanged in a restricted context) to enable the presentation to the verifier or // use by the verifier (text, sound or video) in exactly the same way as intended by the signer // // CAStore // ArchiveTimeStamp the time-stamp token within this property covers the archive validation data // // SignatureTimeStamp the time-stamp token within this property covers the digital signature value element // Schema the pathname XML Schema of XAdES // ---------------------------------------------------------------------------------------------------------------------------------- cfg.UFile::setPath(cfg_str); UString x(U_CAPACITY); UServices::readEOF(STDIN_FILENO, x); if (x.empty()) U_ERROR("cannot read data from <stdin>"); (void) document.reserve(x.size()); UBase64::decode(x, document); if (document.empty()) U_ERROR("decoding data read failed"); // manage arguments... if ( U_DATA_URI && *U_DATA_URI == '\0') { U_ERROR("DATA_URI is mandatory"); } if ( U_X509 && *U_X509 == '\0') { U_ERROR("X509 is mandatory"); } if ( U_KEY_HANDLE && *U_KEY_HANDLE == '\0') { U_ERROR("KEY_HANDLE is mandatory"); } UCertificate cert(UString(U_X509)); if (cert.isValid() == false) U_ERROR("certificate not valid"); U_INTERNAL_DUMP("U_CA_STORE = %S", U_CA_STORE) xades_c = (U_CA_STORE != U_NULLPTR); digest_algorithm = getOptionValue(U_DIGEST_ALGORITHM, "DigestAlgorithm"); alg = u_dgst_get_algoritm(digest_algorithm.c_str()); if (alg == -1) U_ERROR("I can't find the digest algorithm for: %s", digest_algorithm.data()); signing_time = getOptionValue(U_SIGNING_TIME, "SigningTime").strtol(); claimed_role = getOptionValue(U_CLAIMED_ROLE, "ClaimedRole"); production_place_city = getOptionValue(U_PRODUCTION_PLACE_CITY, "ProductionPlaceCity"); production_place_state_or_province = getOptionValue(U_PRODUCTION_PLACE_STATE_OR_PROVINCE, "ProductionPlaceStateOrProvince"); production_place_postal_code = getOptionValue(U_PRODUCTION_PLACE_POSTAL_CODE, "ProductionPlacePostalCode"); production_place_country_name = getOptionValue(U_PRODUCTION_PLACE_COUNTRY_NAME, "ProductionPlaceCountryName"); data_object_format_mimetype = getOptionValue("", "DataObjectFormatMimeType"); if (xades_c == false) num_ca = 0; else { // XAdES-C // ------------------------------------------------------------------------------------------------------------- str_CApath = getOptionValue(U_CA_STORE, "CAStore"); signature_timestamp = getOptionValue(U_SIGNATURE_TIMESTAMP, "SignatureTimeStamp"); if (str_CApath.empty() || UServices::setupOpenSSLStore(U_NULLPTR, str_CApath.c_str()) == false) { U_ERROR("error on setting CA Store: %S", str_CApath.data()); } num_ca = cert.getSignerCertificates(vec_ca, U_NULLPTR, 0); if (UCertificate::verify_result == false) { UServices::setVerifyStatus(); U_ERROR("error on verifying the certificate: %.*s", u_buffer_len, u_buffer); } // ------------------------------------------------------------------------------------------------------------- } u_base64_max_columns = U_OPENSSL_BASE64_MAX_COLUMN; U_line_terminator_len = 2; UString modulus = cert.getModulus(), exponent = cert.getExponent(); X509IssuerName = cert.getIssuerForLDAP(), X509SubjectName = cert.getSubjectForLDAP(), X509Certificate = cert.getEncoded("DER"); X509SerialNumber = cert.getSerialNumber(); UString X509CertificateValue(U_CAPACITY), KeyInfo(U_CAPACITY); UBase64::encode(X509Certificate, X509CertificateValue); u_base64_max_columns = 0; KeyInfo.snprintf(U_CONSTANT_TO_PARAM(U_XMLDSIG_KEYINFO_TEMPLATE), U_STRING_TO_TRACE(modulus), U_STRING_TO_TRACE(exponent), U_STRING_TO_TRACE(X509SubjectName), U_STRING_TO_TRACE(X509IssuerName), X509SerialNumber, U_STRING_TO_TRACE(X509CertificateValue)); UString ObjectDigestValue(200U), Reference(U_CAPACITY), dataObjectFormat(U_CAPACITY), XMLDSIGReference(U_CAPACITY), XMLDSIGReferenceC14N(U_CAPACITY); // --------------------------------------------------------------------------------------------------------------- // check for OOffice or MS-Word document... // --------------------------------------------------------------------------------------------------------------- utility.handlerConfig(cfg); (void) utility.checkDocument(document, U_DATA_URI, true); // --------------------------------------------------------------------------------------------------------------- for (uint32_t i = 0, n = utility.vdocument.size(); i < n; ++i) { uri = utility.vuri[i]; to_digest = utility.vdocument[i]; // --------------------------------------------------------------------------------------------------------------- // 2. Compute the message digest of the text, m = Hash(C). // --------------------------------------------------------------------------------------------------------------- ObjectDigestValue.setEmpty(); UServices::generateDigest(alg, 0, to_digest, ObjectDigestValue, true); // --------------------------------------------------------------------------------------------------------------- Reference.snprintf(U_CONSTANT_TO_PARAM(U_XMLDSIG_REFERENCE_TEMPLATE), uri.c_str(), U_STRING_TO_TRACE(digest_algorithm), U_STRING_TO_TRACE(ObjectDigestValue)); XMLDSIGReference += Reference; XMLDSIGReferenceC14N += UXML2Document::xmlC14N(Reference); if (data_object_format_mimetype.empty() == false) { dataObjectFormat.snprintf(U_CONSTANT_TO_PARAM(U_XADES_DATA_OBJECT_FORMAT_TEMPLATE), uri.c_str(), U_STRING_TO_TRACE(data_object_format_mimetype)); DataObjectFormat += dataObjectFormat; } } setXAdESReference(); // XAdES management // --------------------------------------------------------------------------------------------------------------- // 3. Encapsulate the message digest in an XML <SignedInfo> element, SI, in canonicalized form. // --------------------------------------------------------------------------------------------------------------- UString SignedInfo(U_CONSTANT_SIZE(U_XMLDSIG_SIGNED_INFO_TEMPLATE) + XMLDSIGReference.size() + XAdESReference.size()); SignedInfo.snprintf(U_CONSTANT_TO_PARAM(U_XMLDSIG_SIGNED_INFO_TEMPLATE), U_STRING_TO_TRACE(digest_algorithm), U_STRING_TO_TRACE(XMLDSIGReference), U_STRING_TO_TRACE(XAdESReference)); UString to_sign = UXML2Document::xmlC14N(SignedInfo); // --------------------------------------------------------------------------------------------------------------- // --------------------------------------------------------------------------------------------------------------- // 4. Compute the RSA signatureValue of the canonicalized <SignedInfo> element, SV = RsaSign(Ks, SI). // --------------------------------------------------------------------------------------------------------------- UString SignatureValue(U_CAPACITY), signatureTimeStamp(U_CAPACITY), archiveTimeStamp(U_CAPACITY); u_base64_max_columns = U_OPENSSL_BASE64_MAX_COLUMN; ENGINE* e; # ifdef _MSWINDOWS_ e = UServices::loadEngine("HCSP", ENGINE_METHOD_RSA); x = U_KEY_HANDLE; # else e = U_NULLPTR; x = UFile::contentOf(UString(U_KEY_HANDLE)); if (x.empty() || (u_pkey = UServices::loadKey(x, U_NULLPTR, true, U_NULLPTR, e)) == U_NULLPTR) { U_ERROR("I can't load the private key: %S", U_KEY_HANDLE); } # ifdef HAVE_OPENSSL_98 if (cert.matchPrivateKey(u_pkey) == false) U_ERROR("the private key doesn't matches the public key of the certificate"); # endif x.clear(); # endif UString sign = UServices::getSignatureValue(alg, to_sign, x, UString::getStringNull(), true, e); u_base64_max_columns = 0; SignatureValue.snprintf(U_CONSTANT_TO_PARAM(U_XMLDSIG_SIGNATURE_VALUE_TEMPLATE), U_STRING_TO_TRACE(sign)); if (signature_timestamp.empty() == false) { to_digest = UXML2Document::xmlC14N(SignatureValue); UString token = getTimeStampToken(to_digest, signature_timestamp); signatureTimeStamp.snprintf(U_CONSTANT_TO_PARAM(U_XADES_SIGNATURE_TIMESTAMP_TEMPLATE), U_STRING_TO_TRACE(token)); } // XAdES-C // ------------------------------------------------------------------------------------------------------------- if (xades_c) setXAdESUnsignedSignatureProperties(); // ------------------------------------------------------------------------------------------------------------- (void) XAdESObject.reserve(U_CONSTANT_SIZE(U_XADES_TEMPLATE) + signedProperties.size() + unsignedSignatureProperties.size() + archiveTimeStamp.size() + signatureTimeStamp.size()); XAdESObject.snprintf(U_CONSTANT_TO_PARAM(U_XADES_TEMPLATE), U_STRING_TO_TRACE(signedProperties), U_STRING_TO_TRACE(unsignedSignatureProperties), U_STRING_TO_TRACE(archiveTimeStamp), U_STRING_TO_TRACE(signatureTimeStamp)); // --------------------------------------------------------------------------------------------------------------- // --------------------------------------------------------------------------------------------------------------- // 5. Compose the final XML document including the signatureValue, this time in non-canonicalized form. // --------------------------------------------------------------------------------------------------------------- UString output(U_CONSTANT_SIZE(U_XMLDSIG_TEMPLATE) + 8192U + SignedInfo.size() + SignatureValue.size() + XAdESObject.size()); if (utility.ooffice) { OpenDocumentStart = U_STRING_FROM_CONSTANT("<document-signatures xmlns=\"urn:oasis:names:tc:opendocument:xmlns:digitalsignature:1.0\">"); OpenDocumentEnd = U_STRING_FROM_CONSTANT("</document-signatures>"); } output.snprintf(U_CONSTANT_TO_PARAM(U_XMLDSIG_TEMPLATE), U_STRING_TO_TRACE(OpenDocumentStart), U_STRING_TO_TRACE(SignedInfo), U_STRING_TO_TRACE(SignatureValue), U_STRING_TO_TRACE(KeyInfo), U_STRING_TO_TRACE(XAdESObject), U_STRING_TO_TRACE(OpenDocumentEnd)); // --------------------------------------------------------------------------------------------------------------- // --------------------------------------------------------------------------------------------------------------- // check for OOffice or MS-Word document... // --------------------------------------------------------------------------------------------------------------- utility.outputDocument(output); // --------------------------------------------------------------------------------------------------------------- }
QStringList QCSP::containers( SslCertificate::KeyUsage usage ) { qWarning() << "Start enumerationg providers"; QHash<QString,QPair<QString,QString> > certs; HCRYPTPROV h = 0; DWORD index = 0, type = 0, size = 0; while( CryptEnumProvidersW( index, 0, 0, &type, 0, &size ) ) { QString provider( size / sizeof(wchar_t) - 1, 0 ); if( !CryptEnumProvidersW( index++, 0, 0, &type, LPWSTR(provider.data()), &size ) ) continue; qWarning() << "Found provider" << provider << "type" << type; if( type != PROV_RSA_FULL ) continue; // its broken and does not play well with pkcs11 if( provider.toLower().contains( "esteid" ) ) continue; qWarning() << "Acquiring provider" << provider << "context"; if( h ) CryptReleaseContext( h, 0 ); h = 0; if( !CryptAcquireContextW( &h, 0, LPCWSTR(provider.utf16()), type, CRYPT_SILENT ) ) continue; qWarning() << "Checking if provider" << provider << "is HW"; QByteArray imptype = QCSPPrivate::provParam( h, PP_IMPTYPE ); if( imptype.isEmpty() || !(imptype[0] & CRYPT_IMPL_HARDWARE) ) continue; qWarning() << "Enumerating provider " << provider << "containers"; QStringList containers; QByteArray container = QCSPPrivate::provParam( h, PP_ENUMCONTAINERS, CRYPT_FIRST ); while( !container.isEmpty() ) { containers << container; container = QCSPPrivate::provParam( h, PP_ENUMCONTAINERS, CRYPT_NEXT ); } qWarning() << "Provider" << provider << "containers" << containers; Q_FOREACH( const QString &container, containers ) { if( h ) CryptReleaseContext( h, 0 ); h = 0; qWarning() << "Acquiring provider" << provider << "container" << container << "context"; if( !CryptAcquireContextW( &h, LPCWSTR(container.utf16()), LPCWSTR(provider.utf16()), type, CRYPT_SILENT ) ) continue; qWarning() << "Geting provider" << provider << "container" << container << "key"; HCRYPTKEY key = 0; if( !CryptGetUserKey( h, usage == SslCertificate::NonRepudiation ? AT_SIGNATURE : AT_KEYEXCHANGE, &key ) ) continue; qWarning() << "Reading provider" << provider << "container" << container << "cert"; QSslCertificate cert( QCSPPrivate::keyParam( key, KP_CERTIFICATE, 0 ), QSsl::Der ); CryptDestroyKey( key ); if( cert.isNull() ) continue; qWarning() << "Adding provider" << provider << "container" << container << "list"; certs.insert( cert.subjectInfo( QSslCertificate::CommonName ), QPair<QString,QString>( provider, container ) ); } } if( h ) CryptReleaseContext( h, 0 ); qWarning() << "End enumerationg providers"; d->certs = certs; return d->certs.keys(); }
signed int main(signed int ac, char** av) { SSL_CTX* ctx(nullptr); SSL_METHOD* meth(nullptr); SSL* ssl(nullptr); signed long sflags(0); signed int sockfd(-1); signed int retval(-1); std::string host(""); std::string port(""); std::string key(""); std::string cert(""); std::string store(""); std::string root(""); ::SSL_library_init(); ::OpenSSL_add_all_algorithms(); ::SSL_load_error_strings(); sflags = ( SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_TLSv1 | SSL_OP_NO_TLSv1_1 | SSL_OP_CIPHER_SERVER_PREFERENCE | SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION ); if (7 != ac) { std::cerr << "Usage: " << av[0] << " <host> <port> <certificate> <key> <root certificate> <certificate store>" << std::endl; return EXIT_FAILURE; } host = av[1]; port = av[2]; cert = av[3]; key = av[4]; root = av[5]; store = av[6]; meth = const_cast< SSL_METHOD* >(::TLSv1_2_client_method()); ctx = ::SSL_CTX_new(meth); if (nullptr == meth) { ::ERR_print_errors_fp(stderr); return EXIT_FAILURE; } ::SSL_CTX_set_options(ctx, sflags); if (0 >= ::SSL_CTX_use_certificate_file(ctx, cert.c_str(), SSL_FILETYPE_PEM)) { ::ERR_print_errors_fp(stderr); return EXIT_FAILURE; } if (0 >= ::SSL_CTX_use_PrivateKey_file(ctx, key.c_str(), SSL_FILETYPE_PEM)) { ::ERR_print_errors_fp(stderr); return EXIT_FAILURE; } if (! ::SSL_CTX_check_private_key(ctx)) { std::cerr << "Private key does not match certificate" << std::endl; return EXIT_FAILURE; } if (! ::SSL_CTX_load_verify_locations(ctx, root.c_str(), store.c_str())) { std::cerr << "Load certificate store location failure" << std::endl; return EXIT_FAILURE; } ::SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, nullptr); //&verify_cb); ::SSL_CTX_set_verify_depth(ctx, 5); std::cout << "Connecting to: " << host << ":" << port << std::endl; sockfd = open_connection(host, port); if (0 > sockfd) return EXIT_FAILURE; ssl = SSL_new(ctx); ::SSL_set_fd(ssl, sockfd); do { retval = ::ERR_get_error(); if (0 != retval) std::cerr << "SSL ERR: " << ::ERR_reason_error_string(retval) << std::endl; } while (0 != retval); retval = ::SSL_connect(ssl); if (1 != retval) { std::cerr << "Error in SSL_connect()" << std::endl; ::ERR_print_errors_fp(stderr); } else { X509* ccert(::SSL_get_peer_certificate(ssl)); char* line(nullptr); char buf[4096] = {0}; signed int len(-1); struct in_addr ia; struct in6_addr i6a; std::vector< ip_addr_t > avec; std::vector< port_t > pvec; //message_t msg(OP_SCAN_STATUS, 0x4141414141414141); if (0 >= ::inet_pton(AF_INET, "127.0.0.0", &ia)) { std::cerr << "inet_pton() error: " << ::strerror(errno) << std::endl; return EXIT_FAILURE; } avec.push_back(ip_addr_t(ia, 24)); if (0 >= ::inet_pton(AF_INET, "192.0.0.0", &ia)) { std::cerr << "inet_pton() error: " << ::strerror(errno) << std::endl; return EXIT_FAILURE; } avec.push_back(ip_addr_t(ia, 8)); if (0 >= ::inet_pton(AF_INET6, "fe80:20c:29ff:feee:4b72::1", &i6a)) { std::cerr << "inet_pton() error: " << ::strerror(errno) << std::endl; return EXIT_FAILURE; } avec.push_back(ip_addr_t(i6a, 120)); if (0 >= ::inet_pton(AF_INET, "10.0.0.1", &ia)) { std::cerr << "inet_pton() error: " << ::strerror(errno) << std::endl; return EXIT_FAILURE; } avec.push_back(ip_addr_t(ia)); if (0 >= ::inet_pton(AF_INET6, "::1", &i6a)) { std::cerr << "inet_pton() error: " << ::strerror(errno) << std::endl; return EXIT_FAILURE; } avec.push_back(ip_addr_t(i6a)); pvec.push_back(port_t(PORT_PROTO_TCP, 80)); pvec.push_back(port_t(PORT_PROTO_TCP, 443)); pvec.push_back(port_t(PORT_PROTO_TCP, 143)); pvec.push_back(port_t(PORT_PROTO_TCP, 22)); pvec.push_back(port_t(PORT_PROTO_TCP, 139)); pvec.push_back(port_t(PORT_PROTO_TCP, 31336)); pvec.push_back(port_t(PORT_PROTO_TCP, 15)); message_t msg(avec, pvec); if (X509_V_OK != ::SSL_get_verify_result(ssl)) std::cout << "Certificate validation failed" << std::endl; else std::cout << "Certificate successfully validated" << std::endl; std::cout << "Connected with " << ::SSL_get_cipher(ssl) << " encryption." << std::endl; if (nullptr == ccert) { std::cerr << "ccert is nullptr" << std::endl; return EXIT_FAILURE; } line = ::X509_NAME_oneline(::X509_get_subject_name(ccert), 0, 0); std::cout << "Subject: " << line << std::endl; ::free(line); line = ::X509_NAME_oneline(::X509_get_issuer_name(ccert), 0, 0); std::cout << "Issuer: " << line << std::endl; ::free(line); std::cout << "Version: " << ::X509_get_version(ccert) << std::endl; ::X509_free(ccert); len = ::SSL_read(ssl, buf, sizeof(buf)); if (0 < len && 4096 > len) { buf[len] = 0; std::cout << "buf: " << buf << std::endl; } std::vector< uint8_t > d(msg.data()); ::SSL_write(ssl, d.data(), d.size()); } ::close(sockfd); ::SSL_CTX_free(ctx); return EXIT_SUCCESS; }