File indexing completed on 2024-12-01 04:21:58
0001 /* 0002 * Copyright (C) 2003-2008 Justin Karneges <justin@affinix.com> 0003 * Copyright (C) 2004,2005 Brad Hards <bradh@frogmouth.net> 0004 * Copyright (C) 2014-2016 Ivan Romanov <drizt@land.ru> 0005 * 0006 * This library is free software; you can redistribute it and/or 0007 * modify it under the terms of the GNU Lesser General Public 0008 * License as published by the Free Software Foundation; either 0009 * version 2.1 of the License, or (at your option) any later version. 0010 * 0011 * This library is distributed in the hope that it will be useful, 0012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 0013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0014 * Lesser General Public License for more details. 0015 * 0016 * You should have received a copy of the GNU Lesser General Public 0017 * License along with this library; if not, write to the Free Software 0018 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 0019 * 02110-1301 USA 0020 * 0021 */ 0022 0023 #include "qca_core.h" 0024 0025 #include "qca_cert.h" 0026 #include "qca_keystore.h" 0027 #include "qca_plugin.h" 0028 #include "qca_textfilter.h" 0029 #include "qcaprovider.h" 0030 0031 // for qAddPostRoutine 0032 #include <QCoreApplication> 0033 0034 #include <QDir> 0035 #include <QMutex> 0036 #include <QSettings> 0037 #include <QVariantMap> 0038 #include <QWaitCondition> 0039 0040 #ifdef Q_OS_UNIX 0041 #include <unistd.h> 0042 #endif 0043 0044 int qcaVersion() 0045 { 0046 return QCA_VERSION; 0047 } 0048 0049 const char *qcaVersionStr() 0050 { 0051 return QCA_VERSION_STR; 0052 } 0053 0054 int qcaMajorVersion() 0055 { 0056 return QCA_MAJOR_VERSION; 0057 } 0058 0059 int qcaMinorVersion() 0060 { 0061 return QCA_MINOR_VERSION; 0062 } 0063 0064 int qcaPatchVersion() 0065 { 0066 return QCA_PATCH_VERSION; 0067 } 0068 0069 namespace QCA { 0070 0071 // from qca_tools 0072 bool botan_init(int prealloc, bool mmap); 0073 void botan_deinit(); 0074 0075 // from qca_default 0076 Provider *create_default_provider(); 0077 0078 //---------------------------------------------------------------------------- 0079 // Global 0080 //---------------------------------------------------------------------------- 0081 class Global 0082 { 0083 public: 0084 int refs; 0085 bool secmem; 0086 bool loaded; 0087 bool first_scan; 0088 QString app_name; 0089 QMutex name_mutex; 0090 ProviderManager *manager; 0091 QMutex scan_mutex; 0092 Random *rng; 0093 QMutex rng_mutex; 0094 Logger *logger; 0095 QVariantMap properties; 0096 QMutex prop_mutex; 0097 QMap<QString, QVariantMap> config; 0098 QMutex config_mutex; 0099 QMutex logger_mutex; 0100 0101 Global() 0102 { 0103 refs = 0; 0104 secmem = false; 0105 loaded = false; 0106 first_scan = false; 0107 rng = nullptr; 0108 logger = nullptr; 0109 manager = new ProviderManager; 0110 } 0111 0112 ~Global() 0113 { 0114 KeyStoreManager::shutdown(); 0115 delete rng; 0116 rng = nullptr; 0117 delete manager; 0118 manager = nullptr; 0119 delete logger; 0120 logger = nullptr; 0121 } 0122 0123 void ensure_loaded() 0124 { 0125 // probably we shouldn't overload scan mutex, or else rename it 0126 QMutexLocker locker(&scan_mutex); 0127 if (!loaded) { 0128 loaded = true; 0129 manager->setDefault(create_default_provider()); // manager owns it 0130 } 0131 } 0132 0133 bool ensure_first_scan() 0134 { 0135 scan_mutex.lock(); 0136 if (!first_scan) { 0137 first_scan = true; 0138 manager->scan(); 0139 scan_mutex.unlock(); 0140 return true; 0141 } 0142 scan_mutex.unlock(); 0143 return false; 0144 } 0145 0146 void scan() 0147 { 0148 scan_mutex.lock(); 0149 first_scan = true; 0150 manager->scan(); 0151 scan_mutex.unlock(); 0152 } 0153 0154 void ksm_scan() 0155 { 0156 KeyStoreManager::scan(); 0157 } 0158 0159 Logger *get_logger() 0160 { 0161 QMutexLocker locker(&logger_mutex); 0162 if (!logger) { 0163 logger = new Logger; 0164 0165 // needed so deinit may delete the logger regardless 0166 // of what thread the logger was created from 0167 logger->moveToThread(nullptr); 0168 } 0169 return logger; 0170 } 0171 0172 void unloadAllPlugins() 0173 { 0174 KeyStoreManager::shutdown(); 0175 0176 // if the global_rng was owned by a plugin, then delete it 0177 rng_mutex.lock(); 0178 if (rng && (rng->provider() != manager->find(QStringLiteral("default")))) { 0179 delete rng; 0180 rng = nullptr; 0181 } 0182 rng_mutex.unlock(); 0183 0184 manager->unloadAll(); 0185 } 0186 }; 0187 0188 Q_GLOBAL_STATIC(QMutex, global_mutex) 0189 static Global *global = nullptr; 0190 0191 static bool features_have(const QStringList &have, const QStringList &want) 0192 { 0193 foreach (const QString &i, want) { 0194 if (!have.contains(i)) 0195 return false; 0196 } 0197 return true; 0198 } 0199 0200 void init(MemoryMode mode, int prealloc) 0201 { 0202 QMutexLocker locker(global_mutex()); 0203 if (global) { 0204 ++(global->refs); 0205 return; 0206 } 0207 0208 bool allow_mmap_fallback = false; 0209 bool drop_root = false; 0210 if (mode == Practical) { 0211 allow_mmap_fallback = true; 0212 drop_root = true; 0213 } else if (mode == Locking) 0214 drop_root = true; 0215 0216 bool secmem = botan_init(prealloc, allow_mmap_fallback); 0217 0218 #if defined(Q_OS_UNIX) 0219 if ((geteuid() == 0) && drop_root) { 0220 setuid(getuid()); 0221 } 0222 #endif 0223 0224 global = new Global; 0225 global->secmem = secmem; 0226 ++(global->refs); 0227 0228 // for maximum setuid safety, qca should be initialized before qapp: 0229 // 0230 // int main(int argc, char **argv) 0231 // { 0232 // QCA::Initializer init; 0233 // QCoreApplication app(argc, argv); 0234 // return 0; 0235 // } 0236 // 0237 // however, the above code has the unfortunate side-effect of causing 0238 // qapp to deinit before qca, which can cause problems with any 0239 // plugins that have active objects (notably KeyStore). we'll use a 0240 // post routine to force qca to deinit first. 0241 qAddPostRoutine(deinit); 0242 } 0243 0244 void init() 0245 { 0246 init(Practical, 64); 0247 } 0248 0249 void deinit() 0250 { 0251 QMutexLocker locker(global_mutex()); 0252 if (!global) 0253 return; 0254 --(global->refs); 0255 if (global->refs == 0) { 0256 // In order to maintain symmetry with the init() function, remove the 0257 // post routine from QCoreApplication. This is needed in case when the 0258 // QCA library is unloaded before QCoreApplication instance completes: 0259 // QCoreApplication d-tor would try to execute the deinit() function, 0260 // which would no longer be there. 0261 // Note that this function is documented only in Qt 5.3 and later, but 0262 // it has been present since ancient times with the same semantics. 0263 qRemovePostRoutine(deinit); 0264 0265 delete global; 0266 global = nullptr; 0267 botan_deinit(); 0268 } 0269 } 0270 0271 static bool global_check() 0272 { 0273 Q_ASSERT(global); 0274 if (!global) 0275 return false; 0276 return true; 0277 } 0278 0279 static bool global_check_load() 0280 { 0281 Q_ASSERT(global); 0282 if (!global) 0283 return false; 0284 global->ensure_loaded(); 0285 return true; 0286 } 0287 0288 QMutex *global_random_mutex() 0289 { 0290 return &global->rng_mutex; 0291 } 0292 0293 Random *global_random() 0294 { 0295 if (!global->rng) 0296 global->rng = new Random; 0297 return global->rng; 0298 } 0299 0300 bool haveSecureMemory() 0301 { 0302 if (!global_check()) 0303 return false; 0304 0305 return global->secmem; 0306 } 0307 0308 bool haveSecureRandom() 0309 { 0310 if (!global_check_load()) 0311 return false; 0312 0313 QMutexLocker locker(global_random_mutex()); 0314 if (global_random()->provider()->name() != QLatin1String("default")) 0315 return true; 0316 0317 return false; 0318 } 0319 0320 bool isSupported(const QStringList &features, const QString &provider) 0321 { 0322 if (!global_check_load()) 0323 return false; 0324 0325 // single 0326 if (!provider.isEmpty()) { 0327 Provider *p = global->manager->find(provider); 0328 if (!p) { 0329 // ok, try scanning for new stuff 0330 global->scan(); 0331 p = global->manager->find(provider); 0332 } 0333 0334 if (p && features_have(p->features(), features)) 0335 return true; 0336 } 0337 // all 0338 else { 0339 if (features_have(global->manager->allFeatures(), features)) 0340 return true; 0341 0342 global->manager->appendDiagnosticText( 0343 QStringLiteral("Scanning to find features: %1\n").arg(features.join(QStringLiteral(" ")))); 0344 0345 // ok, try scanning for new stuff 0346 global->scan(); 0347 0348 if (features_have(global->manager->allFeatures(), features)) 0349 return true; 0350 } 0351 return false; 0352 } 0353 0354 bool isSupported(const char *features, const QString &provider) 0355 { 0356 return isSupported(QString::fromLatin1(features).split(QLatin1Char(','), Qt::SkipEmptyParts), provider); 0357 } 0358 0359 QStringList supportedFeatures() 0360 { 0361 if (!global_check_load()) 0362 return QStringList(); 0363 0364 // query all features 0365 global->scan(); 0366 return global->manager->allFeatures(); 0367 } 0368 0369 QStringList defaultFeatures() 0370 { 0371 if (!global_check_load()) 0372 return QStringList(); 0373 0374 return global->manager->find(QStringLiteral("default"))->features(); 0375 } 0376 0377 ProviderList providers() 0378 { 0379 if (!global_check_load()) 0380 return ProviderList(); 0381 0382 global->ensure_first_scan(); 0383 0384 return global->manager->providers(); 0385 } 0386 0387 bool insertProvider(Provider *p, int priority) 0388 { 0389 if (!global_check_load()) 0390 return false; 0391 0392 global->ensure_first_scan(); 0393 0394 return global->manager->add(p, priority); 0395 } 0396 0397 bool unloadProvider(const QString &name) 0398 { 0399 if (!global_check_load()) 0400 return false; 0401 0402 global->ensure_first_scan(); 0403 0404 return global->manager->unload(name); 0405 } 0406 0407 void setProviderPriority(const QString &name, int priority) 0408 { 0409 if (!global_check_load()) 0410 return; 0411 0412 global->ensure_first_scan(); 0413 0414 global->manager->changePriority(name, priority); 0415 } 0416 0417 int providerPriority(const QString &name) 0418 { 0419 if (!global_check_load()) 0420 return -1; 0421 0422 global->ensure_first_scan(); 0423 0424 return global->manager->getPriority(name); 0425 } 0426 0427 Provider *findProvider(const QString &name) 0428 { 0429 if (!global_check_load()) 0430 return nullptr; 0431 0432 global->ensure_first_scan(); 0433 0434 return global->manager->find(name); 0435 } 0436 0437 Provider *defaultProvider() 0438 { 0439 if (!global_check_load()) 0440 return nullptr; 0441 0442 return global->manager->find(QStringLiteral("default")); 0443 } 0444 0445 QStringList pluginPaths() 0446 { 0447 QStringList paths; 0448 #ifndef DEVELOPER_MODE 0449 const QByteArray qcaPluginPath = qgetenv("QCA_PLUGIN_PATH"); 0450 if (!qcaPluginPath.isEmpty()) { 0451 #ifdef Q_OS_WIN 0452 char pathSep(';'); 0453 #else 0454 char pathSep(':'); 0455 #endif 0456 foreach (const QByteArray &path, qcaPluginPath.split(pathSep)) { 0457 const QString canonicalPath = QDir(QFile::decodeName(path)).canonicalPath(); 0458 if (!canonicalPath.isEmpty()) 0459 paths << canonicalPath; 0460 } 0461 } 0462 paths += QCoreApplication::libraryPaths(); 0463 #endif 0464 // In developer mode load plugins only from buildtree. 0465 // In regular mode QCA_PLUGIN_PATH is path where plugins was installed 0466 paths << QDir(QStringLiteral(QCA_PLUGIN_PATH)).canonicalPath(); 0467 #ifndef DEVELOPER_MODE 0468 paths.removeDuplicates(); 0469 #endif 0470 // No empty strings 0471 paths.removeAll(QString()); 0472 return paths; 0473 } 0474 0475 void scanForPlugins() 0476 { 0477 if (!global_check_load()) 0478 return; 0479 0480 global->scan(); 0481 global->ksm_scan(); 0482 } 0483 0484 void unloadAllPlugins() 0485 { 0486 if (!global_check_load()) 0487 return; 0488 0489 global->unloadAllPlugins(); 0490 } 0491 0492 QString pluginDiagnosticText() 0493 { 0494 if (!global_check_load()) 0495 return QString(); 0496 0497 return global->manager->diagnosticText(); 0498 } 0499 0500 void clearPluginDiagnosticText() 0501 { 0502 if (!global_check_load()) 0503 return; 0504 0505 global->manager->clearDiagnosticText(); 0506 } 0507 0508 void appendPluginDiagnosticText(const QString &text) 0509 { 0510 if (!global_check_load()) 0511 return; 0512 0513 global->manager->appendDiagnosticText(text); 0514 } 0515 0516 void setProperty(const QString &name, const QVariant &value) 0517 { 0518 if (!global_check_load()) 0519 return; 0520 0521 QMutexLocker locker(&global->prop_mutex); 0522 0523 global->properties[name] = value; 0524 } 0525 0526 QVariant getProperty(const QString &name) 0527 { 0528 if (!global_check_load()) 0529 return QVariant(); 0530 0531 QMutexLocker locker(&global->prop_mutex); 0532 0533 return global->properties.value(name); 0534 } 0535 0536 static bool configIsValid(const QVariantMap &config) 0537 { 0538 if (!config.contains(QStringLiteral("formtype"))) 0539 return false; 0540 QMapIterator<QString, QVariant> it(config); 0541 while (it.hasNext()) { 0542 it.next(); 0543 const QVariant &v = it.value(); 0544 #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) 0545 if (v.typeId() != QMetaType::QString && v.typeId() != QMetaType::Int && v.typeId() != QMetaType::Bool) 0546 #else 0547 if (v.type() != QVariant::String && v.type() != QVariant::Int && v.type() != QVariant::Bool) 0548 0549 #endif 0550 return false; 0551 } 0552 return true; 0553 } 0554 0555 static QVariantMap readConfig(const QString &name) 0556 { 0557 QSettings settings(QStringLiteral("Affinix"), QStringLiteral("QCA2")); 0558 settings.beginGroup(QStringLiteral("ProviderConfig")); 0559 const QStringList providerNames = settings.value(QStringLiteral("providerNames")).toStringList(); 0560 if (!providerNames.contains(name)) 0561 return QVariantMap(); 0562 0563 settings.beginGroup(name); 0564 const QStringList keys = settings.childKeys(); 0565 QVariantMap map; 0566 foreach (const QString &key, keys) 0567 map[key] = settings.value(key); 0568 settings.endGroup(); 0569 0570 if (!configIsValid(map)) 0571 return QVariantMap(); 0572 return map; 0573 } 0574 0575 static bool writeConfig(const QString &name, const QVariantMap &config, bool systemWide = false) 0576 { 0577 QSettings settings(QSettings::NativeFormat, 0578 systemWide ? QSettings::SystemScope : QSettings::UserScope, 0579 QStringLiteral("Affinix"), 0580 QStringLiteral("QCA2")); 0581 settings.beginGroup(QStringLiteral("ProviderConfig")); 0582 0583 // version 0584 settings.setValue(QStringLiteral("version"), 2); 0585 0586 // add the entry if needed 0587 QStringList providerNames = settings.value(QStringLiteral("providerNames")).toStringList(); 0588 if (!providerNames.contains(name)) 0589 providerNames += name; 0590 settings.setValue(QStringLiteral("providerNames"), providerNames); 0591 0592 settings.beginGroup(name); 0593 QMapIterator<QString, QVariant> it(config); 0594 while (it.hasNext()) { 0595 it.next(); 0596 settings.setValue(it.key(), it.value()); 0597 } 0598 settings.endGroup(); 0599 0600 if (settings.status() == QSettings::NoError) 0601 return true; 0602 return false; 0603 } 0604 0605 void setProviderConfig(const QString &name, const QVariantMap &config) 0606 { 0607 if (!global_check_load()) 0608 return; 0609 0610 if (!configIsValid(config)) 0611 return; 0612 0613 global->config_mutex.lock(); 0614 global->config[name] = config; 0615 global->config_mutex.unlock(); 0616 0617 Provider *p = findProvider(name); 0618 if (p) 0619 p->configChanged(config); 0620 } 0621 0622 QVariantMap getProviderConfig(const QString &name) 0623 { 0624 if (!global_check_load()) 0625 return QVariantMap(); 0626 0627 QVariantMap conf; 0628 0629 global->config_mutex.lock(); 0630 0631 // try loading from persistent storage 0632 conf = readConfig(name); 0633 0634 // if not, load the one from memory 0635 if (conf.isEmpty()) 0636 conf = global->config.value(name); 0637 0638 global->config_mutex.unlock(); 0639 0640 // if provider doesn't exist or doesn't have a valid config form, 0641 // use the config we loaded 0642 Provider *p = findProvider(name); 0643 if (!p) 0644 return conf; 0645 const QVariantMap pconf = p->defaultConfig(); 0646 if (!configIsValid(pconf)) 0647 return conf; 0648 0649 // if the config loaded was empty, use the provider's config 0650 if (conf.isEmpty()) 0651 return pconf; 0652 0653 // if the config formtype doesn't match the provider's formtype, 0654 // then use the provider's 0655 if (pconf[QStringLiteral("formtype")] != conf[QStringLiteral("formtype")]) 0656 return pconf; 0657 0658 // otherwise, use the config loaded 0659 return conf; 0660 } 0661 0662 void saveProviderConfig(const QString &name) 0663 { 0664 if (!global_check_load()) 0665 return; 0666 0667 QMutexLocker locker(&global->config_mutex); 0668 0669 QVariantMap conf = global->config.value(name); 0670 if (conf.isEmpty()) 0671 return; 0672 0673 writeConfig(name, conf); 0674 } 0675 0676 QVariantMap getProviderConfig_internal(Provider *p) 0677 { 0678 QVariantMap conf; 0679 const QString name = p->name(); 0680 0681 global->config_mutex.lock(); 0682 0683 // try loading from persistent storage 0684 conf = readConfig(name); 0685 0686 // if not, load the one from memory 0687 if (conf.isEmpty()) 0688 conf = global->config.value(name); 0689 0690 global->config_mutex.unlock(); 0691 0692 // if provider doesn't exist or doesn't have a valid config form, 0693 // use the config we loaded 0694 const QVariantMap pconf = p->defaultConfig(); 0695 if (!configIsValid(pconf)) 0696 return conf; 0697 0698 // if the config loaded was empty, use the provider's config 0699 if (conf.isEmpty()) 0700 return pconf; 0701 0702 // if the config formtype doesn't match the provider's formtype, 0703 // then use the provider's 0704 if (pconf[QStringLiteral("formtype")] != conf[QStringLiteral("formtype")]) 0705 return pconf; 0706 0707 // otherwise, use the config loaded 0708 return conf; 0709 } 0710 0711 QString globalRandomProvider() 0712 { 0713 QMutexLocker locker(global_random_mutex()); 0714 return global_random()->provider()->name(); 0715 } 0716 0717 void setGlobalRandomProvider(const QString &provider) 0718 { 0719 QMutexLocker locker(global_random_mutex()); 0720 delete global->rng; 0721 global->rng = new Random(provider); 0722 } 0723 0724 Logger *logger() 0725 { 0726 return global->get_logger(); 0727 } 0728 0729 bool haveSystemStore() 0730 { 0731 // ensure the system store is loaded 0732 KeyStoreManager::start(QStringLiteral("default")); 0733 KeyStoreManager ksm; 0734 ksm.waitForBusyFinished(); 0735 0736 const QStringList list = ksm.keyStores(); 0737 for (int n = 0; n < list.count(); ++n) { 0738 KeyStore ks(list[n], &ksm); 0739 if (ks.type() == KeyStore::System && ks.holdsTrustedCertificates()) 0740 return true; 0741 } 0742 return false; 0743 } 0744 0745 CertificateCollection systemStore() 0746 { 0747 // ensure the system store is loaded 0748 KeyStoreManager::start(QStringLiteral("default")); 0749 KeyStoreManager ksm; 0750 ksm.waitForBusyFinished(); 0751 0752 CertificateCollection col; 0753 const QStringList list = ksm.keyStores(); 0754 for (int n = 0; n < list.count(); ++n) { 0755 KeyStore ks(list[n], &ksm); 0756 0757 // system store 0758 if (ks.type() == KeyStore::System && ks.holdsTrustedCertificates()) { 0759 // extract contents 0760 const QList<KeyStoreEntry> entries = ks.entryList(); 0761 for (int i = 0; i < entries.count(); ++i) { 0762 if (entries[i].type() == KeyStoreEntry::TypeCertificate) 0763 col.addCertificate(entries[i].certificate()); 0764 else if (entries[i].type() == KeyStoreEntry::TypeCRL) 0765 col.addCRL(entries[i].crl()); 0766 } 0767 break; 0768 } 0769 } 0770 return col; 0771 } 0772 0773 QString appName() 0774 { 0775 if (!global_check()) 0776 return QString(); 0777 0778 QMutexLocker locker(&global->name_mutex); 0779 0780 return global->app_name; 0781 } 0782 0783 void setAppName(const QString &s) 0784 { 0785 if (!global_check()) 0786 return; 0787 0788 QMutexLocker locker(&global->name_mutex); 0789 0790 global->app_name = s; 0791 } 0792 0793 QString arrayToHex(const QByteArray &a) 0794 { 0795 return Hex().arrayToString(a); 0796 } 0797 0798 QByteArray hexToArray(const QString &str) 0799 { 0800 return Hex().stringToArray(str).toByteArray(); 0801 } 0802 0803 QString arrayToBase64(const QByteArray &a) 0804 { 0805 return Base64().arrayToString(a); 0806 } 0807 0808 QByteArray base64ToArray(const QString &base64String) 0809 { 0810 return Base64().stringToArray(base64String).toByteArray(); 0811 } 0812 0813 static Provider *getProviderForType(const QString &type, const QString &provider) 0814 { 0815 Provider *p = nullptr; 0816 bool scanned = global->ensure_first_scan(); 0817 if (!provider.isEmpty()) { 0818 // try using specific provider 0819 p = global->manager->findFor(provider, type); 0820 if (!p && !scanned) { 0821 // maybe this provider is new, so scan and try again 0822 global->scan(); 0823 scanned = true; 0824 p = global->manager->findFor(provider, type); 0825 } 0826 } 0827 if (!p) { 0828 // try using some other provider 0829 p = global->manager->findFor(QString(), type); 0830 0831 // note: we used to rescan if no provider was found or if 0832 // the only found provider was 'default'. now we only 0833 // rescan if no provider was found. this optimizes lookups 0834 // for features that are in the default provider (such as 0835 // 'sha1') when no other plugin is available. the drawback 0836 // is that if a plugin is installed later during runtime, 0837 // then it won't be picked up without restarting the 0838 // application or manually calling QCA::scanForPlugins. 0839 // if((!p || p->name() == "default") && !scanned) 0840 if (!p && !scanned) { 0841 // maybe there are new providers, so scan and try again 0842 // before giving up or using default 0843 global->scan(); 0844 scanned = true; 0845 p = global->manager->findFor(QString(), type); 0846 } 0847 } 0848 0849 return p; 0850 } 0851 0852 static inline Provider::Context *doCreateContext(Provider *p, const QString &type) 0853 { 0854 return p->createContext(type); 0855 } 0856 0857 Provider::Context *getContext(const QString &type, const QString &provider) 0858 { 0859 if (!global_check_load()) 0860 return nullptr; 0861 0862 Provider *p; 0863 { 0864 p = getProviderForType(type, provider); 0865 if (!p) 0866 return nullptr; 0867 } 0868 0869 return doCreateContext(p, type); 0870 } 0871 0872 Provider::Context *getContext(const QString &type, Provider *_p) 0873 { 0874 if (!global_check_load()) 0875 return nullptr; 0876 0877 Provider *p; 0878 { 0879 p = global->manager->find(_p); 0880 if (!p) 0881 return nullptr; 0882 } 0883 0884 return doCreateContext(p, type); 0885 } 0886 0887 //---------------------------------------------------------------------------- 0888 // Initializer 0889 //---------------------------------------------------------------------------- 0890 Initializer::Initializer(MemoryMode m, int prealloc) 0891 { 0892 init(m, prealloc); 0893 } 0894 0895 Initializer::~Initializer() 0896 { 0897 deinit(); 0898 } 0899 0900 //---------------------------------------------------------------------------- 0901 // Provider 0902 //---------------------------------------------------------------------------- 0903 Provider::~Provider() 0904 { 0905 } 0906 0907 void Provider::init() 0908 { 0909 } 0910 0911 void Provider::deinit() 0912 { 0913 } 0914 0915 int Provider::version() const 0916 { 0917 return 0; 0918 } 0919 0920 QString Provider::credit() const 0921 { 0922 return QString(); 0923 } 0924 0925 QVariantMap Provider::defaultConfig() const 0926 { 0927 return QVariantMap(); 0928 } 0929 0930 void Provider::configChanged(const QVariantMap &) 0931 { 0932 } 0933 0934 Provider::Context::Context(Provider *parent, const QString &type) 0935 : QObject() 0936 { 0937 _provider = parent; 0938 _type = type; 0939 } 0940 0941 Provider::Context::Context(const Context &from) 0942 : QObject() 0943 { 0944 _provider = from._provider; 0945 _type = from._type; 0946 } 0947 0948 Provider::Context::~Context() 0949 { 0950 } 0951 0952 Provider *Provider::Context::provider() const 0953 { 0954 return _provider; 0955 } 0956 0957 QString Provider::Context::type() const 0958 { 0959 return _type; 0960 } 0961 0962 bool Provider::Context::sameProvider(const Context *c) const 0963 { 0964 return (c->provider() == _provider); 0965 } 0966 0967 //---------------------------------------------------------------------------- 0968 // BasicContext 0969 //---------------------------------------------------------------------------- 0970 BasicContext::BasicContext(Provider *parent, const QString &type) 0971 : Context(parent, type) 0972 { 0973 moveToThread(nullptr); // no thread association 0974 } 0975 0976 BasicContext::BasicContext(const BasicContext &from) 0977 : Context(from) 0978 { 0979 moveToThread(nullptr); // no thread association 0980 } 0981 0982 BasicContext::~BasicContext() 0983 { 0984 } 0985 0986 //---------------------------------------------------------------------------- 0987 // InfoContext 0988 //---------------------------------------------------------------------------- 0989 QStringList InfoContext::supportedHashTypes() const 0990 { 0991 return QStringList(); 0992 } 0993 0994 QStringList InfoContext::supportedCipherTypes() const 0995 { 0996 return QStringList(); 0997 } 0998 0999 QStringList InfoContext::supportedMACTypes() const 1000 { 1001 return QStringList(); 1002 } 1003 1004 //---------------------------------------------------------------------------- 1005 // PKeyBase 1006 //---------------------------------------------------------------------------- 1007 PKeyBase::PKeyBase(Provider *p, const QString &type) 1008 : BasicContext(p, type) 1009 { 1010 } 1011 1012 int PKeyBase::maximumEncryptSize(EncryptionAlgorithm) const 1013 { 1014 return 0; 1015 } 1016 1017 SecureArray PKeyBase::encrypt(const SecureArray &, EncryptionAlgorithm) 1018 { 1019 return SecureArray(); 1020 } 1021 1022 bool PKeyBase::decrypt(const SecureArray &, SecureArray *, EncryptionAlgorithm) 1023 { 1024 return false; 1025 } 1026 1027 void PKeyBase::startSign(SignatureAlgorithm, SignatureFormat) 1028 { 1029 } 1030 1031 void PKeyBase::startVerify(SignatureAlgorithm, SignatureFormat) 1032 { 1033 } 1034 1035 void PKeyBase::update(const MemoryRegion &) 1036 { 1037 } 1038 1039 QByteArray PKeyBase::endSign() 1040 { 1041 return QByteArray(); 1042 } 1043 1044 bool PKeyBase::endVerify(const QByteArray &) 1045 { 1046 return false; 1047 } 1048 1049 SymmetricKey PKeyBase::deriveKey(const PKeyBase &) 1050 { 1051 return SymmetricKey(); 1052 } 1053 1054 //---------------------------------------------------------------------------- 1055 // PKeyContext 1056 //---------------------------------------------------------------------------- 1057 QByteArray PKeyContext::publicToDER() const 1058 { 1059 return QByteArray(); 1060 } 1061 1062 QString PKeyContext::publicToPEM() const 1063 { 1064 return QString(); 1065 } 1066 1067 ConvertResult PKeyContext::publicFromDER(const QByteArray &) 1068 { 1069 return ErrorDecode; 1070 } 1071 1072 ConvertResult PKeyContext::publicFromPEM(const QString &) 1073 { 1074 return ErrorDecode; 1075 } 1076 1077 SecureArray PKeyContext::privateToDER(const SecureArray &, PBEAlgorithm) const 1078 { 1079 return SecureArray(); 1080 } 1081 1082 QString PKeyContext::privateToPEM(const SecureArray &, PBEAlgorithm) const 1083 { 1084 return QString(); 1085 } 1086 1087 ConvertResult PKeyContext::privateFromDER(const SecureArray &, const SecureArray &) 1088 { 1089 return ErrorDecode; 1090 } 1091 1092 ConvertResult PKeyContext::privateFromPEM(const QString &, const SecureArray &) 1093 { 1094 return ErrorDecode; 1095 } 1096 1097 //---------------------------------------------------------------------------- 1098 // KeyStoreEntryContext 1099 //---------------------------------------------------------------------------- 1100 bool KeyStoreEntryContext::isAvailable() const 1101 { 1102 return true; 1103 } 1104 1105 KeyBundle KeyStoreEntryContext::keyBundle() const 1106 { 1107 return KeyBundle(); 1108 } 1109 1110 Certificate KeyStoreEntryContext::certificate() const 1111 { 1112 return Certificate(); 1113 } 1114 1115 CRL KeyStoreEntryContext::crl() const 1116 { 1117 return CRL(); 1118 } 1119 1120 PGPKey KeyStoreEntryContext::pgpSecretKey() const 1121 { 1122 return PGPKey(); 1123 } 1124 1125 PGPKey KeyStoreEntryContext::pgpPublicKey() const 1126 { 1127 return PGPKey(); 1128 } 1129 1130 bool KeyStoreEntryContext::ensureAccess() 1131 { 1132 return true; 1133 } 1134 1135 //---------------------------------------------------------------------------- 1136 // KeyStoreListContext 1137 //---------------------------------------------------------------------------- 1138 void KeyStoreListContext::start() 1139 { 1140 QMetaObject::invokeMethod(this, "busyEnd", Qt::QueuedConnection); 1141 } 1142 1143 void KeyStoreListContext::setUpdatesEnabled(bool) 1144 { 1145 } 1146 1147 bool KeyStoreListContext::isReadOnly(int) const 1148 { 1149 return true; 1150 } 1151 1152 KeyStoreEntryContext *KeyStoreListContext::entry(int id, const QString &entryId) 1153 { 1154 KeyStoreEntryContext *out = nullptr; 1155 QList<KeyStoreEntryContext *> list = entryList(id); 1156 for (int n = 0; n < list.count(); ++n) { 1157 if (list[n]->id() == entryId) { 1158 out = list.takeAt(n); 1159 break; 1160 } 1161 } 1162 qDeleteAll(list); 1163 return out; 1164 } 1165 1166 KeyStoreEntryContext *KeyStoreListContext::entryPassive(const QString &serialized) 1167 { 1168 Q_UNUSED(serialized); 1169 return nullptr; 1170 } 1171 1172 QString KeyStoreListContext::writeEntry(int, const KeyBundle &) 1173 { 1174 return QString(); 1175 } 1176 1177 QString KeyStoreListContext::writeEntry(int, const Certificate &) 1178 { 1179 return QString(); 1180 } 1181 1182 QString KeyStoreListContext::writeEntry(int, const CRL &) 1183 { 1184 return QString(); 1185 } 1186 1187 QString KeyStoreListContext::writeEntry(int, const PGPKey &) 1188 { 1189 return QString(); 1190 } 1191 1192 bool KeyStoreListContext::removeEntry(int, const QString &) 1193 { 1194 return false; 1195 } 1196 1197 //---------------------------------------------------------------------------- 1198 // TLSContext 1199 //---------------------------------------------------------------------------- 1200 void TLSContext::setMTU(int) 1201 { 1202 } 1203 1204 //---------------------------------------------------------------------------- 1205 // MessageContext 1206 //---------------------------------------------------------------------------- 1207 QString MessageContext::diagnosticText() const 1208 { 1209 return QString(); 1210 } 1211 1212 //---------------------------------------------------------------------------- 1213 // SMSContext 1214 //---------------------------------------------------------------------------- 1215 void SMSContext::setTrustedCertificates(const CertificateCollection &) 1216 { 1217 } 1218 1219 void SMSContext::setUntrustedCertificates(const CertificateCollection &) 1220 { 1221 } 1222 1223 void SMSContext::setPrivateKeys(const QList<SecureMessageKey> &) 1224 { 1225 } 1226 1227 //---------------------------------------------------------------------------- 1228 // BufferedComputation 1229 //---------------------------------------------------------------------------- 1230 BufferedComputation::~BufferedComputation() 1231 { 1232 } 1233 1234 MemoryRegion BufferedComputation::process(const MemoryRegion &a) 1235 { 1236 clear(); 1237 update(a); 1238 return final(); 1239 } 1240 1241 //---------------------------------------------------------------------------- 1242 // Filter 1243 //---------------------------------------------------------------------------- 1244 Filter::~Filter() 1245 { 1246 } 1247 1248 MemoryRegion Filter::process(const MemoryRegion &a) 1249 { 1250 clear(); 1251 MemoryRegion buf = update(a); 1252 if (!ok()) 1253 return MemoryRegion(); 1254 const MemoryRegion fin = final(); 1255 if (!ok()) 1256 return MemoryRegion(); 1257 if (buf.isSecure() || fin.isSecure()) 1258 return (SecureArray(buf) + SecureArray(fin)); 1259 else 1260 return QByteArray(buf.toByteArray() + fin.toByteArray()); 1261 } 1262 1263 //---------------------------------------------------------------------------- 1264 // Algorithm 1265 //---------------------------------------------------------------------------- 1266 class Algorithm::Private : public QSharedData 1267 { 1268 public: 1269 Provider::Context *c; 1270 1271 Private(Provider::Context *context) 1272 { 1273 c = context; 1274 // printf("** [%p] Algorithm Created\n", c); 1275 } 1276 1277 Private(const Private &from) 1278 : QSharedData(from) 1279 { 1280 c = from.c->clone(); 1281 // printf("** [%p] Algorithm Copied (to [%p])\n", from.c, c); 1282 } 1283 1284 ~Private() 1285 { 1286 // printf("** [%p] Algorithm Destroyed\n", c); 1287 delete c; 1288 } 1289 }; 1290 1291 Algorithm::Algorithm() 1292 { 1293 } 1294 1295 Algorithm::Algorithm(const QString &type, const QString &provider) 1296 { 1297 change(type, provider); 1298 } 1299 1300 Algorithm::Algorithm(const Algorithm &from) 1301 { 1302 *this = from; 1303 } 1304 1305 Algorithm::~Algorithm() 1306 { 1307 } 1308 1309 Algorithm &Algorithm::operator=(const Algorithm &from) 1310 { 1311 d = from.d; 1312 return *this; 1313 } 1314 1315 QString Algorithm::type() const 1316 { 1317 if (d) 1318 return d->c->type(); 1319 else 1320 return QString(); 1321 } 1322 1323 Provider *Algorithm::provider() const 1324 { 1325 if (d) 1326 return d->c->provider(); 1327 else 1328 return nullptr; 1329 } 1330 1331 Provider::Context *Algorithm::context() 1332 { 1333 if (d) 1334 return d->c; 1335 else 1336 return nullptr; 1337 } 1338 1339 const Provider::Context *Algorithm::context() const 1340 { 1341 if (d) 1342 return d->c; 1343 else 1344 return nullptr; 1345 } 1346 1347 void Algorithm::change(Provider::Context *c) 1348 { 1349 if (c) 1350 d = new Private(c); 1351 else 1352 d = nullptr; 1353 } 1354 1355 void Algorithm::change(const QString &type, const QString &provider) 1356 { 1357 if (!type.isEmpty()) 1358 change(getContext(type, provider)); 1359 else 1360 change(nullptr); 1361 } 1362 1363 Provider::Context *Algorithm::takeContext() 1364 { 1365 if (d) { 1366 Provider::Context *c = d->c; // should cause a detach 1367 d->c = nullptr; 1368 d = nullptr; 1369 return c; 1370 } else 1371 return nullptr; 1372 } 1373 1374 //---------------------------------------------------------------------------- 1375 // SymmetricKey 1376 //---------------------------------------------------------------------------- 1377 SymmetricKey::SymmetricKey() 1378 { 1379 } 1380 1381 SymmetricKey::SymmetricKey(int size) 1382 { 1383 set(Random::randomArray(size)); 1384 } 1385 1386 SymmetricKey::SymmetricKey(const SecureArray &a) 1387 { 1388 set(a); 1389 } 1390 1391 SymmetricKey::SymmetricKey(const QByteArray &a) 1392 { 1393 set(SecureArray(a)); 1394 } 1395 1396 /* from libgcrypt-1.2.0 */ 1397 static const unsigned char desWeakKeyTable[64][8] = { 1398 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*w*/ 1399 {0x00, 0x00, 0x1e, 0x1e, 0x00, 0x00, 0x0e, 0x0e}, {0x00, 0x00, 0xe0, 0xe0, 0x00, 0x00, 0xf0, 0xf0}, 1400 {0x00, 0x00, 0xfe, 0xfe, 0x00, 0x00, 0xfe, 0xfe}, {0x00, 0x1e, 0x00, 0x1e, 0x00, 0x0e, 0x00, 0x0e}, /*sw*/ 1401 {0x00, 0x1e, 0x1e, 0x00, 0x00, 0x0e, 0x0e, 0x00}, {0x00, 0x1e, 0xe0, 0xfe, 0x00, 0x0e, 0xf0, 0xfe}, 1402 {0x00, 0x1e, 0xfe, 0xe0, 0x00, 0x0e, 0xfe, 0xf0}, {0x00, 0xe0, 0x00, 0xe0, 0x00, 0xf0, 0x00, 0xf0}, /*sw*/ 1403 {0x00, 0xe0, 0x1e, 0xfe, 0x00, 0xf0, 0x0e, 0xfe}, {0x00, 0xe0, 0xe0, 0x00, 0x00, 0xf0, 0xf0, 0x00}, 1404 {0x00, 0xe0, 0xfe, 0x1e, 0x00, 0xf0, 0xfe, 0x0e}, {0x00, 0xfe, 0x00, 0xfe, 0x00, 0xfe, 0x00, 0xfe}, /*sw*/ 1405 {0x00, 0xfe, 0x1e, 0xe0, 0x00, 0xfe, 0x0e, 0xf0}, {0x00, 0xfe, 0xe0, 0x1e, 0x00, 0xfe, 0xf0, 0x0e}, 1406 {0x00, 0xfe, 0xfe, 0x00, 0x00, 0xfe, 0xfe, 0x00}, {0x1e, 0x00, 0x00, 0x1e, 0x0e, 0x00, 0x00, 0x0e}, 1407 {0x1e, 0x00, 0x1e, 0x00, 0x0e, 0x00, 0x0e, 0x00}, /*sw*/ 1408 {0x1e, 0x00, 0xe0, 0xfe, 0x0e, 0x00, 0xf0, 0xfe}, {0x1e, 0x00, 0xfe, 0xe0, 0x0e, 0x00, 0xfe, 0xf0}, 1409 {0x1e, 0x1e, 0x00, 0x00, 0x0e, 0x0e, 0x00, 0x00}, {0x1e, 0x1e, 0x1e, 0x1e, 0x0e, 0x0e, 0x0e, 0x0e}, /*w*/ 1410 {0x1e, 0x1e, 0xe0, 0xe0, 0x0e, 0x0e, 0xf0, 0xf0}, {0x1e, 0x1e, 0xfe, 0xfe, 0x0e, 0x0e, 0xfe, 0xfe}, 1411 {0x1e, 0xe0, 0x00, 0xfe, 0x0e, 0xf0, 0x00, 0xfe}, {0x1e, 0xe0, 0x1e, 0xe0, 0x0e, 0xf0, 0x0e, 0xf0}, /*sw*/ 1412 {0x1e, 0xe0, 0xe0, 0x1e, 0x0e, 0xf0, 0xf0, 0x0e}, {0x1e, 0xe0, 0xfe, 0x00, 0x0e, 0xf0, 0xfe, 0x00}, 1413 {0x1e, 0xfe, 0x00, 0xe0, 0x0e, 0xfe, 0x00, 0xf0}, {0x1e, 0xfe, 0x1e, 0xfe, 0x0e, 0xfe, 0x0e, 0xfe}, /*sw*/ 1414 {0x1e, 0xfe, 0xe0, 0x00, 0x0e, 0xfe, 0xf0, 0x00}, {0x1e, 0xfe, 0xfe, 0x1e, 0x0e, 0xfe, 0xfe, 0x0e}, 1415 {0xe0, 0x00, 0x00, 0xe0, 0xf0, 0x00, 0x00, 0xf0}, {0xe0, 0x00, 0x1e, 0xfe, 0xf0, 0x00, 0x0e, 0xfe}, 1416 {0xe0, 0x00, 0xe0, 0x00, 0xf0, 0x00, 0xf0, 0x00}, /*sw*/ 1417 {0xe0, 0x00, 0xfe, 0x1e, 0xf0, 0x00, 0xfe, 0x0e}, {0xe0, 0x1e, 0x00, 0xfe, 0xf0, 0x0e, 0x00, 0xfe}, 1418 {0xe0, 0x1e, 0x1e, 0xe0, 0xf0, 0x0e, 0x0e, 0xf0}, {0xe0, 0x1e, 0xe0, 0x1e, 0xf0, 0x0e, 0xf0, 0x0e}, /*sw*/ 1419 {0xe0, 0x1e, 0xfe, 0x00, 0xf0, 0x0e, 0xfe, 0x00}, {0xe0, 0xe0, 0x00, 0x00, 0xf0, 0xf0, 0x00, 0x00}, 1420 {0xe0, 0xe0, 0x1e, 0x1e, 0xf0, 0xf0, 0x0e, 0x0e}, {0xe0, 0xe0, 0xe0, 0xe0, 0xf0, 0xf0, 0xf0, 0xf0}, /*w*/ 1421 {0xe0, 0xe0, 0xfe, 0xfe, 0xf0, 0xf0, 0xfe, 0xfe}, {0xe0, 0xfe, 0x00, 0x1e, 0xf0, 0xfe, 0x00, 0x0e}, 1422 {0xe0, 0xfe, 0x1e, 0x00, 0xf0, 0xfe, 0x0e, 0x00}, {0xe0, 0xfe, 0xe0, 0xfe, 0xf0, 0xfe, 0xf0, 0xfe}, /*sw*/ 1423 {0xe0, 0xfe, 0xfe, 0xe0, 0xf0, 0xfe, 0xfe, 0xf0}, {0xfe, 0x00, 0x00, 0xfe, 0xfe, 0x00, 0x00, 0xfe}, 1424 {0xfe, 0x00, 0x1e, 0xe0, 0xfe, 0x00, 0x0e, 0xf0}, {0xfe, 0x00, 0xe0, 0x1e, 0xfe, 0x00, 0xf0, 0x0e}, 1425 {0xfe, 0x00, 0xfe, 0x00, 0xfe, 0x00, 0xfe, 0x00}, /*sw*/ 1426 {0xfe, 0x1e, 0x00, 0xe0, 0xfe, 0x0e, 0x00, 0xf0}, {0xfe, 0x1e, 0x1e, 0xfe, 0xfe, 0x0e, 0x0e, 0xfe}, 1427 {0xfe, 0x1e, 0xe0, 0x00, 0xfe, 0x0e, 0xf0, 0x00}, {0xfe, 0x1e, 0xfe, 0x1e, 0xfe, 0x0e, 0xfe, 0x0e}, /*sw*/ 1428 {0xfe, 0xe0, 0x00, 0x1e, 0xfe, 0xf0, 0x00, 0x0e}, {0xfe, 0xe0, 0x1e, 0x00, 0xfe, 0xf0, 0x0e, 0x00}, 1429 {0xfe, 0xe0, 0xe0, 0xfe, 0xfe, 0xf0, 0xf0, 0xfe}, {0xfe, 0xe0, 0xfe, 0xe0, 0xfe, 0xf0, 0xfe, 0xf0}, /*sw*/ 1430 {0xfe, 0xfe, 0x00, 0x00, 0xfe, 0xfe, 0x00, 0x00}, {0xfe, 0xfe, 0x1e, 0x1e, 0xfe, 0xfe, 0x0e, 0x0e}, 1431 {0xfe, 0xfe, 0xe0, 0xe0, 0xfe, 0xfe, 0xf0, 0xf0}, {0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe} /*w*/ 1432 }; 1433 1434 bool SymmetricKey::isWeakDESKey() 1435 { 1436 if (size() != 8) 1437 return false; // dubious 1438 SecureArray workingCopy(8); 1439 // clear parity bits 1440 for (uint i = 0; i < 8; i++) 1441 workingCopy[i] = (data()[i]) & 0xfe; 1442 1443 for (auto n : desWeakKeyTable) { 1444 if (memcmp(workingCopy.data(), n, 8) == 0) 1445 return true; 1446 } 1447 return false; 1448 } 1449 1450 //---------------------------------------------------------------------------- 1451 // InitializationVector 1452 //---------------------------------------------------------------------------- 1453 InitializationVector::InitializationVector() 1454 { 1455 } 1456 1457 InitializationVector::InitializationVector(int size) 1458 { 1459 set(Random::randomArray(size)); 1460 } 1461 1462 InitializationVector::InitializationVector(const SecureArray &a) 1463 { 1464 set(a); 1465 } 1466 1467 InitializationVector::InitializationVector(const QByteArray &a) 1468 { 1469 set(SecureArray(a)); 1470 } 1471 1472 //---------------------------------------------------------------------------- 1473 // AuthTag 1474 //---------------------------------------------------------------------------- 1475 AuthTag::AuthTag() 1476 { 1477 } 1478 1479 AuthTag::AuthTag(int size) 1480 { 1481 resize(size); 1482 } 1483 1484 AuthTag::AuthTag(const SecureArray &a) 1485 { 1486 set(a); 1487 } 1488 1489 AuthTag::AuthTag(const QByteArray &a) 1490 { 1491 set(SecureArray(a)); 1492 } 1493 1494 //---------------------------------------------------------------------------- 1495 // Event 1496 //---------------------------------------------------------------------------- 1497 class Event::Private : public QSharedData 1498 { 1499 public: 1500 Type type; 1501 Source source; 1502 PasswordStyle style; 1503 KeyStoreInfo ksi; 1504 KeyStoreEntry kse; 1505 QString fname; 1506 void *ptr; 1507 }; 1508 1509 Event::Event() 1510 { 1511 } 1512 1513 Event::Event(const Event &from) 1514 : d(from.d) 1515 { 1516 } 1517 1518 Event::~Event() 1519 { 1520 } 1521 1522 Event &Event::operator=(const Event &from) 1523 { 1524 d = from.d; 1525 return *this; 1526 } 1527 1528 bool Event::isNull() const 1529 { 1530 return (d ? false : true); 1531 } 1532 1533 Event::Type Event::type() const 1534 { 1535 return d->type; 1536 } 1537 1538 Event::Source Event::source() const 1539 { 1540 return d->source; 1541 } 1542 1543 Event::PasswordStyle Event::passwordStyle() const 1544 { 1545 return d->style; 1546 } 1547 1548 KeyStoreInfo Event::keyStoreInfo() const 1549 { 1550 return d->ksi; 1551 } 1552 1553 KeyStoreEntry Event::keyStoreEntry() const 1554 { 1555 return d->kse; 1556 } 1557 1558 QString Event::fileName() const 1559 { 1560 return d->fname; 1561 } 1562 1563 void *Event::ptr() const 1564 { 1565 return d->ptr; 1566 } 1567 1568 void Event::setPasswordKeyStore(PasswordStyle pstyle, 1569 const KeyStoreInfo &keyStoreInfo, 1570 const KeyStoreEntry &keyStoreEntry, 1571 void *ptr) 1572 { 1573 if (!d) 1574 d = new Private; 1575 d->type = Password; 1576 d->source = KeyStore; 1577 d->style = pstyle; 1578 d->ksi = keyStoreInfo; 1579 d->kse = keyStoreEntry; 1580 d->fname = QString(); 1581 d->ptr = ptr; 1582 } 1583 1584 void Event::setPasswordData(PasswordStyle pstyle, const QString &fileName, void *ptr) 1585 { 1586 if (!d) 1587 d = new Private; 1588 d->type = Password; 1589 d->source = Data; 1590 d->style = pstyle; 1591 d->ksi = KeyStoreInfo(); 1592 d->kse = KeyStoreEntry(); 1593 d->fname = fileName; 1594 d->ptr = ptr; 1595 } 1596 1597 void Event::setToken(const KeyStoreInfo &keyStoreInfo, const KeyStoreEntry &keyStoreEntry, void *ptr) 1598 { 1599 if (!d) 1600 d = new Private; 1601 d->type = Token; 1602 d->source = KeyStore; 1603 d->style = StylePassword; 1604 d->ksi = keyStoreInfo; 1605 d->kse = keyStoreEntry; 1606 d->fname = QString(); 1607 d->ptr = ptr; 1608 } 1609 1610 //---------------------------------------------------------------------------- 1611 // EventGlobal 1612 //---------------------------------------------------------------------------- 1613 class HandlerBase : public QObject 1614 { 1615 Q_OBJECT 1616 public: 1617 HandlerBase(QObject *parent = nullptr) 1618 : QObject(parent) 1619 { 1620 } 1621 1622 protected Q_SLOTS: 1623 virtual void ask(int id, const QCA::Event &e) = 0; 1624 }; 1625 1626 class AskerBase : public QObject 1627 { 1628 Q_OBJECT 1629 public: 1630 AskerBase(QObject *parent = nullptr) 1631 : QObject(parent) 1632 { 1633 } 1634 1635 virtual void set_accepted(const SecureArray &password) = 0; 1636 virtual void set_rejected() = 0; 1637 }; 1638 1639 static void handler_add(HandlerBase *h, int pos = -1); 1640 static void handler_remove(HandlerBase *h); 1641 static void handler_accept(HandlerBase *h, int id, const SecureArray &password); 1642 static void handler_reject(HandlerBase *h, int id); 1643 static bool asker_ask(AskerBase *a, const Event &e); 1644 static void asker_cancel(AskerBase *a); 1645 1646 Q_GLOBAL_STATIC(QMutex, g_event_mutex) 1647 1648 class EventGlobal; 1649 static EventGlobal *g_event = nullptr; 1650 1651 class EventGlobal 1652 { 1653 public: 1654 class HandlerItem 1655 { 1656 public: 1657 HandlerBase *h; 1658 QList<int> ids; 1659 }; 1660 1661 class AskerItem 1662 { 1663 public: 1664 AskerBase *a; 1665 int id; 1666 Event event; 1667 int handler_pos; 1668 }; 1669 1670 QList<HandlerItem> handlers; 1671 QList<AskerItem> askers; 1672 1673 int next_id; 1674 1675 EventGlobal() 1676 { 1677 qRegisterMetaType<Event>("QCA::Event"); 1678 qRegisterMetaType<SecureArray>("QCA::SecureArray"); 1679 next_id = 0; 1680 } 1681 1682 int findHandlerItem(HandlerBase *h) 1683 { 1684 for (int n = 0; n < handlers.count(); ++n) { 1685 if (handlers[n].h == h) 1686 return n; 1687 } 1688 return -1; 1689 } 1690 1691 int findAskerItem(AskerBase *a) 1692 { 1693 for (int n = 0; n < askers.count(); ++n) { 1694 if (askers[n].a == a) 1695 return n; 1696 } 1697 return -1; 1698 } 1699 1700 int findAskerItemById(int id) 1701 { 1702 for (int n = 0; n < askers.count(); ++n) { 1703 if (askers[n].id == id) 1704 return n; 1705 } 1706 return -1; 1707 } 1708 1709 void ask(int asker_at) 1710 { 1711 AskerItem &i = askers[asker_at]; 1712 1713 g_event->handlers[i.handler_pos].ids += i.id; 1714 QMetaObject::invokeMethod( 1715 handlers[i.handler_pos].h, "ask", Qt::QueuedConnection, Q_ARG(int, i.id), Q_ARG(QCA::Event, i.event)); 1716 } 1717 1718 void reject(int asker_at) 1719 { 1720 AskerItem &i = askers[asker_at]; 1721 1722 // look for the next usable handler 1723 int pos = -1; 1724 for (int n = i.handler_pos + 1; n < g_event->handlers.count(); ++n) { 1725 // handler and asker can't be in the same thread 1726 // Q_ASSERT(g_event->handlers[n].h->thread() != i.a->thread()); 1727 // if(g_event->handlers[n].h->thread() != i.a->thread()) 1728 //{ 1729 pos = n; 1730 break; 1731 //} 1732 } 1733 1734 // if there is one, try it 1735 if (pos != -1) { 1736 i.handler_pos = pos; 1737 ask(asker_at); 1738 } 1739 // if not, send official reject 1740 else { 1741 AskerBase *asker = i.a; 1742 askers.removeAt(asker_at); 1743 1744 asker->set_rejected(); 1745 } 1746 } 1747 }; 1748 1749 void handler_add(HandlerBase *h, int pos) 1750 { 1751 QMutexLocker locker(g_event_mutex()); 1752 if (!g_event) 1753 g_event = new EventGlobal; 1754 1755 EventGlobal::HandlerItem i; 1756 i.h = h; 1757 1758 if (pos != -1) { 1759 g_event->handlers.insert(pos, i); 1760 1761 // adjust handler positions 1762 for (int n = 0; n < g_event->askers.count(); ++n) { 1763 if (g_event->askers[n].handler_pos >= pos) 1764 g_event->askers[n].handler_pos++; 1765 } 1766 } else 1767 g_event->handlers += i; 1768 } 1769 1770 void handler_remove(HandlerBase *h) 1771 { 1772 QMutexLocker locker(g_event_mutex()); 1773 Q_ASSERT(g_event); 1774 if (!g_event) 1775 return; 1776 int at = g_event->findHandlerItem(h); 1777 Q_ASSERT(at != -1); 1778 if (at == -1) 1779 return; 1780 1781 const QList<int> ids = g_event->handlers[at].ids; 1782 g_event->handlers.removeAt(at); 1783 1784 // adjust handler positions within askers 1785 for (int n = 0; n < g_event->askers.count(); ++n) { 1786 if (g_event->askers[n].handler_pos >= at) 1787 g_event->askers[n].handler_pos--; 1788 } 1789 1790 // reject all askers 1791 foreach (int id, ids) { 1792 int asker_at = g_event->findAskerItemById(id); 1793 Q_ASSERT(asker_at != -1); 1794 1795 g_event->reject(asker_at); 1796 } 1797 1798 if (g_event->handlers.isEmpty()) { 1799 delete g_event; 1800 g_event = nullptr; 1801 } 1802 } 1803 1804 void handler_accept(HandlerBase *h, int id, const SecureArray &password) 1805 { 1806 QMutexLocker locker(g_event_mutex()); 1807 Q_ASSERT(g_event); 1808 if (!g_event) 1809 return; 1810 int at = g_event->findHandlerItem(h); 1811 Q_ASSERT(at != -1); 1812 if (at == -1) 1813 return; 1814 int asker_at = g_event->findAskerItemById(id); 1815 Q_ASSERT(asker_at != -1); 1816 if (asker_at == -1) 1817 return; 1818 1819 g_event->handlers[at].ids.removeAll(g_event->askers[asker_at].id); 1820 1821 AskerBase *asker = g_event->askers[asker_at].a; 1822 asker->set_accepted(password); 1823 } 1824 1825 void handler_reject(HandlerBase *h, int id) 1826 { 1827 QMutexLocker locker(g_event_mutex()); 1828 Q_ASSERT(g_event); 1829 if (!g_event) 1830 return; 1831 int at = g_event->findHandlerItem(h); 1832 Q_ASSERT(at != -1); 1833 if (at == -1) 1834 return; 1835 int asker_at = g_event->findAskerItemById(id); 1836 Q_ASSERT(asker_at != -1); 1837 if (asker_at == -1) 1838 return; 1839 1840 g_event->handlers[at].ids.removeAll(g_event->askers[asker_at].id); 1841 1842 g_event->reject(asker_at); 1843 } 1844 1845 bool asker_ask(AskerBase *a, const Event &e) 1846 { 1847 QMutexLocker locker(g_event_mutex()); 1848 if (!g_event) 1849 return false; 1850 1851 int pos = -1; 1852 for (int n = 0; n < g_event->handlers.count(); ++n) { 1853 // handler and asker can't be in the same thread 1854 // Q_ASSERT(g_event->handlers[n].h->thread() != a->thread()); 1855 // if(g_event->handlers[n].h->thread() != a->thread()) 1856 //{ 1857 pos = n; 1858 break; 1859 //} 1860 } 1861 if (pos == -1) 1862 return false; 1863 1864 EventGlobal::AskerItem i; 1865 i.a = a; 1866 i.id = g_event->next_id++; 1867 i.event = e; 1868 i.handler_pos = pos; 1869 g_event->askers += i; 1870 const int asker_at = g_event->askers.count() - 1; 1871 1872 g_event->ask(asker_at); 1873 return true; 1874 } 1875 1876 void asker_cancel(AskerBase *a) 1877 { 1878 QMutexLocker locker(g_event_mutex()); 1879 if (!g_event) 1880 return; 1881 int at = g_event->findAskerItem(a); 1882 if (at == -1) 1883 return; 1884 1885 for (int n = 0; n < g_event->handlers.count(); ++n) 1886 g_event->handlers[n].ids.removeAll(g_event->askers[at].id); 1887 1888 g_event->askers.removeAt(at); 1889 } 1890 1891 //---------------------------------------------------------------------------- 1892 // EventHandler 1893 //---------------------------------------------------------------------------- 1894 class EventHandler::Private : public HandlerBase 1895 { 1896 Q_OBJECT 1897 public: 1898 EventHandler *q; 1899 bool started; 1900 QList<int> activeIds; 1901 1902 Private(EventHandler *_q) 1903 : HandlerBase(_q) 1904 , q(_q) 1905 { 1906 started = false; 1907 } 1908 1909 public Q_SLOTS: 1910 void ask(int id, const QCA::Event &e) override 1911 { 1912 activeIds += id; 1913 emit q->eventReady(id, e); 1914 } 1915 }; 1916 1917 EventHandler::EventHandler(QObject *parent) 1918 : QObject(parent) 1919 { 1920 d = new Private(this); 1921 } 1922 1923 EventHandler::~EventHandler() 1924 { 1925 if (d->started) { 1926 foreach (int id, d->activeIds) 1927 handler_reject(d, id); 1928 1929 handler_remove(d); 1930 } 1931 1932 delete d; 1933 } 1934 1935 void EventHandler::start() 1936 { 1937 d->started = true; 1938 handler_add(d); 1939 } 1940 1941 void EventHandler::submitPassword(int id, const SecureArray &password) 1942 { 1943 if (!d->activeIds.contains(id)) 1944 return; 1945 1946 d->activeIds.removeAll(id); 1947 handler_accept(d, id, password); 1948 } 1949 1950 void EventHandler::tokenOkay(int id) 1951 { 1952 if (!d->activeIds.contains(id)) 1953 return; 1954 1955 d->activeIds.removeAll(id); 1956 handler_accept(d, id, SecureArray()); 1957 } 1958 1959 void EventHandler::reject(int id) 1960 { 1961 if (!d->activeIds.contains(id)) 1962 return; 1963 1964 d->activeIds.removeAll(id); 1965 handler_reject(d, id); 1966 } 1967 1968 //---------------------------------------------------------------------------- 1969 // PasswordAsker 1970 //---------------------------------------------------------------------------- 1971 class AskerPrivate : public AskerBase 1972 { 1973 Q_OBJECT 1974 public: 1975 enum Type 1976 { 1977 Password, 1978 Token 1979 }; 1980 1981 Type type; 1982 PasswordAsker *passwordAsker; 1983 TokenAsker *tokenAsker; 1984 1985 QMutex m; 1986 QWaitCondition w; 1987 1988 bool accepted; 1989 SecureArray password; 1990 bool waiting; 1991 bool done; 1992 1993 AskerPrivate(PasswordAsker *parent) 1994 : AskerBase(parent) 1995 { 1996 passwordAsker = parent; 1997 tokenAsker = nullptr; 1998 type = Password; 1999 accepted = false; 2000 waiting = false; 2001 done = true; 2002 } 2003 2004 AskerPrivate(TokenAsker *parent) 2005 : AskerBase(parent) 2006 { 2007 passwordAsker = nullptr; 2008 tokenAsker = parent; 2009 type = Token; 2010 accepted = false; 2011 waiting = false; 2012 done = true; 2013 } 2014 2015 void ask(const Event &e) 2016 { 2017 accepted = false; 2018 waiting = false; 2019 done = false; 2020 password.clear(); 2021 2022 if (!asker_ask(this, e)) { 2023 done = true; 2024 QMetaObject::invokeMethod(this, "emitResponseReady", Qt::QueuedConnection); 2025 } 2026 } 2027 2028 void cancel() 2029 { 2030 if (!done) 2031 asker_cancel(this); 2032 } 2033 2034 void set_accepted(const SecureArray &_password) override 2035 { 2036 QMutexLocker locker(&m); 2037 accepted = true; 2038 password = _password; 2039 done = true; 2040 if (waiting) 2041 w.wakeOne(); 2042 else 2043 QMetaObject::invokeMethod(this, "emitResponseReady", Qt::QueuedConnection); 2044 } 2045 2046 void set_rejected() override 2047 { 2048 QMutexLocker locker(&m); 2049 done = true; 2050 if (waiting) 2051 w.wakeOne(); 2052 else 2053 QMetaObject::invokeMethod(this, "emitResponseReady", Qt::QueuedConnection); 2054 } 2055 2056 void waitForResponse() 2057 { 2058 QMutexLocker locker(&m); 2059 if (done) 2060 return; 2061 waiting = true; 2062 w.wait(&m); 2063 waiting = false; 2064 } 2065 2066 public Q_SLOTS: 2067 virtual void emitResponseReady() = 0; 2068 }; 2069 2070 class PasswordAsker::Private : public AskerPrivate 2071 { 2072 Q_OBJECT 2073 public: 2074 Private(PasswordAsker *_q) 2075 : AskerPrivate(_q) 2076 { 2077 } 2078 2079 void emitResponseReady() override 2080 { 2081 emit passwordAsker->responseReady(); 2082 } 2083 }; 2084 2085 PasswordAsker::PasswordAsker(QObject *parent) 2086 : QObject(parent) 2087 { 2088 d = new Private(this); 2089 } 2090 2091 PasswordAsker::~PasswordAsker() 2092 { 2093 delete d; 2094 } 2095 2096 void PasswordAsker::ask(Event::PasswordStyle pstyle, 2097 const KeyStoreInfo &keyStoreInfo, 2098 const KeyStoreEntry &keyStoreEntry, 2099 void *ptr) 2100 { 2101 Event e; 2102 e.setPasswordKeyStore(pstyle, keyStoreInfo, keyStoreEntry, ptr); 2103 d->ask(e); 2104 } 2105 2106 void PasswordAsker::ask(Event::PasswordStyle pstyle, const QString &fileName, void *ptr) 2107 { 2108 Event e; 2109 e.setPasswordData(pstyle, fileName, ptr); 2110 d->ask(e); 2111 } 2112 2113 void PasswordAsker::cancel() 2114 { 2115 d->cancel(); 2116 } 2117 2118 void PasswordAsker::waitForResponse() 2119 { 2120 d->waitForResponse(); 2121 } 2122 2123 bool PasswordAsker::accepted() const 2124 { 2125 return d->accepted; 2126 } 2127 2128 SecureArray PasswordAsker::password() const 2129 { 2130 return d->password; 2131 } 2132 2133 //---------------------------------------------------------------------------- 2134 // TokenAsker 2135 //---------------------------------------------------------------------------- 2136 class TokenAsker::Private : public AskerPrivate 2137 { 2138 Q_OBJECT 2139 public: 2140 Private(TokenAsker *_q) 2141 : AskerPrivate(_q) 2142 { 2143 } 2144 2145 void emitResponseReady() override 2146 { 2147 emit tokenAsker->responseReady(); 2148 } 2149 }; 2150 2151 TokenAsker::TokenAsker(QObject *parent) 2152 : QObject(parent) 2153 { 2154 d = new Private(this); 2155 } 2156 2157 TokenAsker::~TokenAsker() 2158 { 2159 delete d; 2160 } 2161 2162 void TokenAsker::ask(const KeyStoreInfo &keyStoreInfo, const KeyStoreEntry &keyStoreEntry, void *ptr) 2163 { 2164 Event e; 2165 e.setToken(keyStoreInfo, keyStoreEntry, ptr); 2166 d->ask(e); 2167 } 2168 2169 void TokenAsker::cancel() 2170 { 2171 d->cancel(); 2172 } 2173 2174 void TokenAsker::waitForResponse() 2175 { 2176 d->waitForResponse(); 2177 } 2178 2179 bool TokenAsker::accepted() const 2180 { 2181 return d->accepted; 2182 } 2183 2184 } 2185 2186 #include "qca_core.moc"