• Skip to content
  • Skip to link menu
KDE 4.4 API Reference
  • KDE API Reference
  • KDE Support
  • Sitemap
  • Contact Us
 

qca

qca_core.cpp

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2003-2008  Justin Karneges <justin@affinix.com>
00003  * Copyright (C) 2004,2005  Brad Hards <bradh@frogmouth.net>
00004  *
00005  * This library is free software; you can redistribute it and/or
00006  * modify it under the terms of the GNU Lesser General Public
00007  * License as published by the Free Software Foundation; either
00008  * version 2.1 of the License, or (at your option) any later version.
00009  *
00010  * This library is distributed in the hope that it will be useful,
00011  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013  * Lesser General Public License for more details.
00014  *
00015  * You should have received a copy of the GNU Lesser General Public
00016  * License along with this library; if not, write to the Free Software
00017  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
00018  * 02110-1301  USA
00019  *
00020  */
00021 
00022 #include "qca_core.h"
00023 
00024 #include "qca_plugin.h"
00025 #include "qca_textfilter.h"
00026 #include "qca_cert.h"
00027 #include "qca_keystore.h"
00028 #include "qcaprovider.h"
00029 
00030 // for qAddPostRoutine
00031 #include <QCoreApplication>
00032 
00033 #include <QMutex>
00034 #include <QSettings>
00035 #include <QVariantMap>
00036 #include <QWaitCondition>
00037 
00038 #ifdef Q_OS_UNIX
00039 # include <unistd.h>
00040 #endif
00041 
00042 int qcaVersion()
00043 {
00044     return QCA_VERSION;
00045 }
00046 
00047 namespace QCA {
00048 
00049 // from qca_tools
00050 bool botan_init(int prealloc, bool mmap);
00051 void botan_deinit();
00052 
00053 // from qca_default
00054 Provider *create_default_provider();
00055 
00056 //----------------------------------------------------------------------------
00057 // Global
00058 //----------------------------------------------------------------------------
00059 class Global
00060 {
00061 public:
00062     int refs;
00063     bool secmem;
00064     bool loaded;
00065     bool first_scan;
00066     QString app_name;
00067     QMutex name_mutex;
00068     ProviderManager *manager;
00069     QMutex scan_mutex;
00070     Random *rng;
00071     QMutex rng_mutex;
00072     Logger *logger;
00073     QVariantMap properties;
00074     QMutex prop_mutex;
00075     QMap<QString,QVariantMap> config;
00076     QMutex config_mutex;
00077     QMutex logger_mutex;
00078 
00079     Global()
00080     {
00081         refs = 0;
00082         secmem = false;
00083         loaded = false;
00084         first_scan = false;
00085         rng = 0;
00086         logger = 0;
00087         manager = new ProviderManager;
00088     }
00089 
00090     ~Global()
00091     {
00092         KeyStoreManager::shutdown();
00093         delete rng;
00094         rng = 0;
00095         delete manager;
00096         manager = 0;
00097         delete logger;
00098         logger = 0;
00099     }
00100 
00101     void ensure_loaded()
00102     {
00103         // probably we shouldn't overload scan mutex, or else rename it
00104         QMutexLocker locker(&scan_mutex);
00105         if(!loaded)
00106         {
00107             loaded = true;
00108             manager->setDefault(create_default_provider()); // manager owns it
00109         }
00110     }
00111 
00112     bool ensure_first_scan()
00113     {
00114         scan_mutex.lock();
00115         if(!first_scan)
00116         {
00117             first_scan = true;
00118             manager->scan();
00119             scan_mutex.unlock();
00120             return true;
00121         }
00122         scan_mutex.unlock();
00123         return false;
00124     }
00125 
00126     void scan()
00127     {
00128         scan_mutex.lock();
00129         first_scan = true;
00130         manager->scan();
00131         scan_mutex.unlock();
00132     }
00133 
00134     void ksm_scan()
00135     {
00136         KeyStoreManager::scan();
00137     }
00138 
00139     Logger *get_logger()
00140     {
00141         QMutexLocker locker(&logger_mutex);
00142         if(!logger)
00143         {
00144             logger = new Logger;
00145 
00146             // needed so deinit may delete the logger regardless
00147             //   of what thread the logger was created from
00148             logger->moveToThread(0);
00149         }
00150         return logger;
00151     }
00152 
00153     void unloadAllPlugins()
00154     {
00155         KeyStoreManager::shutdown();
00156 
00157         // if the global_rng was owned by a plugin, then delete it
00158         rng_mutex.lock();
00159         if(rng && (rng->provider() != manager->find("default")))
00160         {
00161             delete rng;
00162             rng = 0;
00163         }
00164         rng_mutex.unlock();
00165 
00166         manager->unloadAll();
00167     }
00168 };
00169 
00170 Q_GLOBAL_STATIC(QMutex, global_mutex)
00171 static Global *global = 0;
00172 
00173 static bool features_have(const QStringList &have, const QStringList &want)
00174 {
00175     foreach(const QString &i, want)
00176     {
00177         if(!have.contains(i))
00178             return false;
00179     }
00180     return true;
00181 }
00182 
00183 void init(MemoryMode mode, int prealloc)
00184 {
00185     QMutexLocker locker(global_mutex());
00186     if(global)
00187     {
00188         ++(global->refs);
00189         return;
00190     }
00191 
00192     bool allow_mmap_fallback = false;
00193     bool drop_root = false;
00194     if(mode == Practical)
00195     {
00196         allow_mmap_fallback = true;
00197         drop_root = true;
00198     }
00199     else if(mode == Locking)
00200         drop_root = true;
00201 
00202     bool secmem = botan_init(prealloc, allow_mmap_fallback);
00203 
00204     if(drop_root)
00205     {
00206 #ifdef Q_OS_UNIX
00207         setuid(getuid());
00208 #endif
00209     }
00210 
00211     global = new Global;
00212     global->secmem = secmem;
00213     ++(global->refs);
00214 
00215     // for maximum setuid safety, qca should be initialized before qapp:
00216     //
00217     //   int main(int argc, char **argv)
00218     //   {
00219     //       QCA::Initializer init;
00220     //       QCoreApplication app(argc, argv);
00221     //       return 0;
00222     //   }
00223     //
00224     // however, the above code has the unfortunate side-effect of causing
00225     // qapp to deinit before qca, which can cause problems with any
00226     // plugins that have active objects (notably KeyStore).  we'll use a
00227     // post routine to force qca to deinit first.
00228     qAddPostRoutine(deinit);
00229 }
00230 
00231 void init()
00232 {
00233     init(Practical, 64);
00234 }
00235 
00236 void deinit()
00237 {
00238     QMutexLocker locker(global_mutex());
00239     if(!global)
00240         return;
00241     --(global->refs);
00242     if(global->refs == 0)
00243     {
00244         delete global;
00245         global = 0;
00246         botan_deinit();
00247     }
00248 }
00249 
00250 static bool global_check()
00251 {
00252     Q_ASSERT(global);
00253     if(!global)
00254         return false;
00255     return true;
00256 }
00257 
00258 static bool global_check_load()
00259 {
00260     Q_ASSERT(global);
00261     if(!global)
00262         return false;
00263     global->ensure_loaded();
00264     return true;
00265 }
00266 
00267 QMutex *global_random_mutex()
00268 {
00269     return &global->rng_mutex;
00270 }
00271 
00272 Random *global_random()
00273 {
00274     if(!global->rng)
00275         global->rng = new Random;
00276     return global->rng;
00277 }
00278 
00279 bool haveSecureMemory()
00280 {
00281     if(!global_check())
00282         return false;
00283 
00284     return global->secmem;
00285 }
00286 
00287 bool haveSecureRandom()
00288 {
00289     if(!global_check_load())
00290         return false;
00291 
00292     QMutexLocker locker(global_random_mutex());
00293     if(global_random()->provider()->name() != "default")
00294         return true;
00295 
00296     return false;
00297 }
00298 
00299 bool isSupported(const QStringList &features, const QString &provider)
00300 {
00301     if(!global_check_load())
00302         return false;
00303 
00304     // single
00305     if(!provider.isEmpty())
00306     {
00307         Provider *p = global->manager->find(provider);
00308         if(!p)
00309         {
00310             // ok, try scanning for new stuff
00311             global->scan();
00312             p = global->manager->find(provider);
00313         }
00314 
00315         if(p && features_have(p->features(), features))
00316             return true;
00317     }
00318     // all
00319     else
00320     {
00321         if(features_have(global->manager->allFeatures(), features))
00322             return true;
00323 
00324         global->manager->appendDiagnosticText(QString("Scanning to find features: %1\n").arg(features.join(" ")));
00325 
00326         // ok, try scanning for new stuff
00327         global->scan();
00328 
00329         if(features_have(global->manager->allFeatures(), features))
00330             return true;
00331     }
00332     return false;
00333 }
00334 
00335 bool isSupported(const char *features, const QString &provider)
00336 {
00337     return isSupported(QString(features).split(',', QString::SkipEmptyParts), provider);
00338 }
00339 
00340 QStringList supportedFeatures()
00341 {
00342     if(!global_check_load())
00343         return QStringList();
00344 
00345     // query all features
00346     global->scan();
00347     return global->manager->allFeatures();
00348 }
00349 
00350 QStringList defaultFeatures()
00351 {
00352     if(!global_check_load())
00353         return QStringList();
00354 
00355     return global->manager->find("default")->features();
00356 }
00357 
00358 ProviderList providers()
00359 {
00360     if(!global_check_load())
00361         return ProviderList();
00362 
00363     global->ensure_first_scan();
00364 
00365     return global->manager->providers();
00366 }
00367 
00368 bool insertProvider(Provider *p, int priority)
00369 {
00370     if(!global_check_load())
00371         return false;
00372 
00373     global->ensure_first_scan();
00374 
00375     return global->manager->add(p, priority);
00376 }
00377 
00378 void setProviderPriority(const QString &name, int priority)
00379 {
00380     if(!global_check_load())
00381         return;
00382 
00383     global->ensure_first_scan();
00384 
00385     global->manager->changePriority(name, priority);
00386 }
00387 
00388 int providerPriority(const QString &name)
00389 {
00390     if(!global_check_load())
00391         return -1;
00392 
00393     global->ensure_first_scan();
00394 
00395     return global->manager->getPriority(name);
00396 }
00397 
00398 Provider *findProvider(const QString &name)
00399 {
00400     if(!global_check_load())
00401         return 0;
00402 
00403     global->ensure_first_scan();
00404 
00405     return global->manager->find(name);
00406 }
00407 
00408 Provider *defaultProvider()
00409 {
00410     if(!global_check_load())
00411         return 0;
00412 
00413     return global->manager->find("default");
00414 }
00415 
00416 void scanForPlugins()
00417 {
00418     if(!global_check_load())
00419         return;
00420 
00421     global->scan();
00422     global->ksm_scan();
00423 }
00424 
00425 void unloadAllPlugins()
00426 {
00427     if(!global_check_load())
00428         return;
00429 
00430     global->unloadAllPlugins();
00431 }
00432 
00433 QString pluginDiagnosticText()
00434 {
00435     if(!global_check_load())
00436         return QString();
00437 
00438     return global->manager->diagnosticText();
00439 }
00440 
00441 void clearPluginDiagnosticText()
00442 {
00443     if(!global_check_load())
00444         return;
00445 
00446     global->manager->clearDiagnosticText();
00447 }
00448 
00449 void appendPluginDiagnosticText(const QString &text)
00450 {
00451     if(!global_check_load())
00452         return;
00453 
00454     global->manager->appendDiagnosticText(text);
00455 }
00456 
00457 void setProperty(const QString &name, const QVariant &value)
00458 {
00459     if(!global_check_load())
00460         return;
00461 
00462     QMutexLocker locker(&global->prop_mutex);
00463 
00464     global->properties[name] = value;
00465 }
00466 
00467 QVariant getProperty(const QString &name)
00468 {
00469     if(!global_check_load())
00470         return QVariant();
00471 
00472     QMutexLocker locker(&global->prop_mutex);
00473 
00474     return global->properties.value(name);
00475 }
00476 
00477 static bool configIsValid(const QVariantMap &config)
00478 {
00479     if(!config.contains("formtype"))
00480         return false;
00481     QMapIterator<QString,QVariant> it(config);
00482     while(it.hasNext())
00483     {
00484         it.next();
00485         const QVariant &v = it.value();
00486         if(v.type() != QVariant::String && v.type() != QVariant::Int && v.type() != QVariant::Bool)
00487             return false;
00488     }
00489     return true;
00490 }
00491 
00492 static QVariantMap readConfig(const QString &name)
00493 {
00494     QSettings settings("Affinix", "QCA2");
00495     settings.beginGroup("ProviderConfig");
00496     QStringList providerNames = settings.value("providerNames").toStringList();
00497     if(!providerNames.contains(name))
00498         return QVariantMap();
00499 
00500     settings.beginGroup(name);
00501     QStringList keys = settings.childKeys();
00502     QVariantMap map;
00503     foreach(const QString &key, keys)
00504         map[key] = settings.value(key);
00505     settings.endGroup();
00506 
00507     if(!configIsValid(map))
00508         return QVariantMap();
00509     return map;
00510 }
00511 
00512 static bool writeConfig(const QString &name, const QVariantMap &config, bool systemWide = false)
00513 {
00514     QSettings settings(QSettings::NativeFormat, systemWide ? QSettings::SystemScope : QSettings::UserScope, "Affinix", "QCA2");
00515     settings.beginGroup("ProviderConfig");
00516 
00517     // version
00518     settings.setValue("version", 2);
00519 
00520     // add the entry if needed
00521     QStringList providerNames = settings.value("providerNames").toStringList();
00522     if(!providerNames.contains(name))
00523         providerNames += name;
00524     settings.setValue("providerNames", providerNames);
00525 
00526     settings.beginGroup(name);
00527     QMapIterator<QString,QVariant> it(config);
00528     while(it.hasNext())
00529     {
00530         it.next();
00531         settings.setValue(it.key(), it.value());
00532     }
00533     settings.endGroup();
00534 
00535     if(settings.status() == QSettings::NoError)
00536         return true;
00537     return false;
00538 }
00539 
00540 void setProviderConfig(const QString &name, const QVariantMap &config)
00541 {
00542     if(!global_check_load())
00543         return;
00544 
00545     if(!configIsValid(config))
00546         return;
00547 
00548     global->config_mutex.lock();
00549     global->config[name] = config;
00550     global->config_mutex.unlock();
00551 
00552     Provider *p = findProvider(name);
00553     if(p)
00554         p->configChanged(config);
00555 }
00556 
00557 QVariantMap getProviderConfig(const QString &name)
00558 {
00559     if(!global_check_load())
00560         return QVariantMap();
00561 
00562     QVariantMap conf;
00563 
00564     global->config_mutex.lock();
00565 
00566     // try loading from persistent storage
00567     conf = readConfig(name);
00568 
00569     // if not, load the one from memory
00570     if(conf.isEmpty())
00571         conf = global->config.value(name);
00572 
00573     global->config_mutex.unlock();
00574 
00575     // if provider doesn't exist or doesn't have a valid config form,
00576     //   use the config we loaded
00577     Provider *p = findProvider(name);
00578     if(!p)
00579         return conf;
00580     QVariantMap pconf = p->defaultConfig();
00581     if(!configIsValid(pconf))
00582         return conf;
00583 
00584     // if the config loaded was empty, use the provider's config
00585     if(conf.isEmpty())
00586         return pconf;
00587 
00588     // if the config formtype doesn't match the provider's formtype,
00589     //   then use the provider's
00590     if(pconf["formtype"] != conf["formtype"])
00591         return pconf;
00592 
00593     // otherwise, use the config loaded
00594     return conf;
00595 }
00596 
00597 void saveProviderConfig(const QString &name)
00598 {
00599     if(!global_check_load())
00600         return;
00601 
00602     QMutexLocker locker(&global->config_mutex);
00603 
00604     QVariantMap conf = global->config.value(name);
00605     if(conf.isEmpty())
00606         return;
00607 
00608     writeConfig(name, conf);
00609 }
00610 
00611 QVariantMap getProviderConfig_internal(Provider *p)
00612 {
00613     QVariantMap conf;
00614     QString name = p->name();
00615 
00616     global->config_mutex.lock();
00617 
00618     // try loading from persistent storage
00619     conf = readConfig(name);
00620 
00621     // if not, load the one from memory
00622     if(conf.isEmpty())
00623         conf = global->config.value(name);
00624 
00625     global->config_mutex.unlock();
00626 
00627     // if provider doesn't exist or doesn't have a valid config form,
00628     //   use the config we loaded
00629     QVariantMap pconf = p->defaultConfig();
00630     if(!configIsValid(pconf))
00631         return conf;
00632 
00633     // if the config loaded was empty, use the provider's config
00634     if(conf.isEmpty())
00635         return pconf;
00636 
00637     // if the config formtype doesn't match the provider's formtype,
00638     //   then use the provider's
00639     if(pconf["formtype"] != conf["formtype"])
00640         return pconf;
00641 
00642     // otherwise, use the config loaded
00643     return conf;
00644 }
00645 
00646 QString globalRandomProvider()
00647 {
00648     QMutexLocker locker(global_random_mutex());
00649     return global_random()->provider()->name();
00650 }
00651 
00652 void setGlobalRandomProvider(const QString &provider)
00653 {
00654     QMutexLocker locker(global_random_mutex());
00655     delete global->rng;
00656     global->rng = new Random(provider);
00657 }
00658 
00659 Logger *logger()
00660 {
00661     return global->get_logger();
00662 }
00663 
00664 bool haveSystemStore()
00665 {
00666     // ensure the system store is loaded
00667     KeyStoreManager::start("default");
00668     KeyStoreManager ksm;
00669     ksm.waitForBusyFinished();
00670 
00671     QStringList list = ksm.keyStores();
00672     for(int n = 0; n < list.count(); ++n)
00673     {
00674         KeyStore ks(list[n], &ksm);
00675         if(ks.type() == KeyStore::System && ks.holdsTrustedCertificates())
00676             return true;
00677     }
00678     return false;
00679 }
00680 
00681 CertificateCollection systemStore()
00682 {
00683     // ensure the system store is loaded
00684     KeyStoreManager::start("default");
00685     KeyStoreManager ksm;
00686     ksm.waitForBusyFinished();
00687 
00688     CertificateCollection col;
00689     QStringList list = ksm.keyStores();
00690     for(int n = 0; n < list.count(); ++n)
00691     {
00692         KeyStore ks(list[n], &ksm);
00693 
00694         // system store
00695         if(ks.type() == KeyStore::System && ks.holdsTrustedCertificates())
00696         {
00697             // extract contents
00698             QList<KeyStoreEntry> entries = ks.entryList();
00699             for(int i = 0; i < entries.count(); ++i)
00700             {
00701                 if(entries[i].type() == KeyStoreEntry::TypeCertificate)
00702                     col.addCertificate(entries[i].certificate());
00703                 else if(entries[i].type() == KeyStoreEntry::TypeCRL)
00704                     col.addCRL(entries[i].crl());
00705             }
00706             break;
00707         }
00708     }
00709     return col;
00710 }
00711 
00712 QString appName()
00713 {
00714     if(!global_check())
00715         return QString();
00716 
00717     QMutexLocker locker(&global->name_mutex);
00718 
00719     return global->app_name;
00720 }
00721 
00722 void setAppName(const QString &s)
00723 {
00724     if(!global_check())
00725         return;
00726 
00727     QMutexLocker locker(&global->name_mutex);
00728 
00729     global->app_name = s;
00730 }
00731 
00732 QString arrayToHex(const QByteArray &a)
00733 {
00734     return Hex().arrayToString(a);
00735 }
00736 
00737 QByteArray hexToArray(const QString &str)
00738 {
00739     return Hex().stringToArray(str).toByteArray();
00740 }
00741 
00742 static Provider *getProviderForType(const QString &type, const QString &provider)
00743 {
00744     Provider *p = 0;
00745     bool scanned = global->ensure_first_scan();
00746     if(!provider.isEmpty())
00747     {
00748         // try using specific provider
00749         p = global->manager->findFor(provider, type);
00750         if(!p && !scanned)
00751         {
00752             // maybe this provider is new, so scan and try again
00753             global->scan();
00754             scanned = true;
00755             p = global->manager->findFor(provider, type);
00756         }
00757     }
00758     if(!p)
00759     {
00760         // try using some other provider
00761         p = global->manager->findFor(QString(), type);
00762 
00763         // note: we used to rescan if no provider was found or if
00764         //   the only found provider was 'default'.  now we only
00765         //   rescan if no provider was found.  this optimizes lookups
00766         //   for features that are in the default provider (such as
00767         //   'sha1') when no other plugin is available.  the drawback
00768         //   is that if a plugin is installed later during runtime,
00769         //   then it won't be picked up without restarting the
00770         //   application or manually calling QCA::scanForPlugins.
00771         //if((!p || p->name() == "default") && !scanned)
00772         if(!p && !scanned)
00773         {
00774             // maybe there are new providers, so scan and try again
00775             //   before giving up or using default
00776             global->scan();
00777             scanned = true;
00778             p = global->manager->findFor(QString(), type);
00779         }
00780     }
00781 
00782     return p;
00783 }
00784 
00785 static inline Provider::Context *doCreateContext(Provider *p, const QString &type)
00786 {
00787     return p->createContext(type);
00788 }
00789 
00790 Provider::Context *getContext(const QString &type, const QString &provider)
00791 {
00792     if(!global_check_load())
00793         return 0;
00794 
00795     Provider *p;
00796     {
00797         p = getProviderForType(type, provider);
00798         if(!p)
00799             return 0;
00800     }
00801 
00802     return doCreateContext(p, type);
00803 }
00804 
00805 Provider::Context *getContext(const QString &type, Provider *_p)
00806 {
00807     if(!global_check_load())
00808         return 0;
00809 
00810     Provider *p;
00811     {
00812         p = global->manager->find(_p);
00813         if(!p)
00814             return 0;
00815     }
00816 
00817     return doCreateContext(p, type);
00818 }
00819 
00820 //----------------------------------------------------------------------------
00821 // Initializer
00822 //----------------------------------------------------------------------------
00823 Initializer::Initializer(MemoryMode m, int prealloc)
00824 {
00825     init(m, prealloc);
00826 }
00827 
00828 Initializer::~Initializer()
00829 {
00830     deinit();
00831 }
00832 
00833 //----------------------------------------------------------------------------
00834 // Provider
00835 //----------------------------------------------------------------------------
00836 Provider::~Provider()
00837 {
00838 }
00839 
00840 void Provider::init()
00841 {
00842 }
00843 
00844 void Provider::deinit()
00845 {
00846 }
00847 
00848 int Provider::version() const
00849 {
00850     return 0;
00851 }
00852 
00853 QString Provider::credit() const
00854 {
00855     return QString();
00856 }
00857 
00858 QVariantMap Provider::defaultConfig() const
00859 {
00860     return QVariantMap();
00861 }
00862 
00863 void Provider::configChanged(const QVariantMap &)
00864 {
00865 }
00866 
00867 Provider::Context::Context(Provider *parent, const QString &type)
00868 :QObject()
00869 {
00870     _provider = parent;
00871     _type = type;
00872 }
00873 
00874 Provider::Context::Context(const Context &from)
00875 :QObject()
00876 {
00877     _provider = from._provider;
00878     _type = from._type;
00879 }
00880 
00881 Provider::Context::~Context()
00882 {
00883 }
00884 
00885 Provider *Provider::Context::provider() const
00886 {
00887     return _provider;
00888 }
00889 
00890 QString Provider::Context::type() const
00891 {
00892     return _type;
00893 }
00894 
00895 bool Provider::Context::sameProvider(const Context *c) const
00896 {
00897     return (c->provider() == _provider);
00898 }
00899 
00900 //----------------------------------------------------------------------------
00901 // BasicContext
00902 //----------------------------------------------------------------------------
00903 BasicContext::BasicContext(Provider *parent, const QString &type)
00904 :Context(parent, type)
00905 {
00906     moveToThread(0); // no thread association
00907 }
00908 
00909 BasicContext::BasicContext(const BasicContext &from)
00910 :Context(from)
00911 {
00912     moveToThread(0); // no thread association
00913 }
00914 
00915 BasicContext::~BasicContext()
00916 {
00917 }
00918 
00919 //----------------------------------------------------------------------------
00920 // InfoContext
00921 //----------------------------------------------------------------------------
00922 QStringList InfoContext::supportedHashTypes() const
00923 {
00924     return QStringList();
00925 }
00926 
00927 QStringList InfoContext::supportedCipherTypes() const
00928 {
00929     return QStringList();
00930 }
00931 
00932 QStringList InfoContext::supportedMACTypes() const
00933 {
00934     return QStringList();
00935 }
00936 
00937 //----------------------------------------------------------------------------
00938 // PKeyBase
00939 //----------------------------------------------------------------------------
00940 PKeyBase::PKeyBase(Provider *p, const QString &type)
00941 :BasicContext(p, type)
00942 {
00943 }
00944 
00945 int PKeyBase::maximumEncryptSize(EncryptionAlgorithm) const
00946 {
00947     return 0;
00948 }
00949 
00950 SecureArray PKeyBase::encrypt(const SecureArray &, EncryptionAlgorithm)
00951 {
00952     return SecureArray();
00953 }
00954 
00955 bool PKeyBase::decrypt(const SecureArray &, SecureArray *, EncryptionAlgorithm)
00956 {
00957     return false;
00958 }
00959 
00960 void PKeyBase::startSign(SignatureAlgorithm, SignatureFormat)
00961 {
00962 }
00963 
00964 void PKeyBase::startVerify(SignatureAlgorithm, SignatureFormat)
00965 {
00966 }
00967 
00968 void PKeyBase::update(const MemoryRegion &)
00969 {
00970 }
00971 
00972 QByteArray PKeyBase::endSign()
00973 {
00974     return QByteArray();
00975 }
00976 
00977 bool PKeyBase::endVerify(const QByteArray &)
00978 {
00979     return false;
00980 }
00981 
00982 SymmetricKey PKeyBase::deriveKey(const PKeyBase &)
00983 {
00984     return SymmetricKey();
00985 }
00986 
00987 //----------------------------------------------------------------------------
00988 // PKeyContext
00989 //----------------------------------------------------------------------------
00990 QByteArray PKeyContext::publicToDER() const
00991 {
00992     return QByteArray();
00993 }
00994 
00995 QString PKeyContext::publicToPEM() const
00996 {
00997     return QString();
00998 }
00999 
01000 ConvertResult PKeyContext::publicFromDER(const QByteArray &)
01001 {
01002     return ErrorDecode;
01003 }
01004 
01005 ConvertResult PKeyContext::publicFromPEM(const QString &)
01006 {
01007     return ErrorDecode;
01008 }
01009 
01010 SecureArray PKeyContext::privateToDER(const SecureArray &, PBEAlgorithm) const
01011 {
01012     return SecureArray();
01013 }
01014 
01015 QString PKeyContext::privateToPEM(const SecureArray &, PBEAlgorithm) const
01016 {
01017     return QString();
01018 }
01019 
01020 ConvertResult PKeyContext::privateFromDER(const SecureArray &, const SecureArray &)
01021 {
01022     return ErrorDecode;
01023 }
01024 
01025 ConvertResult PKeyContext::privateFromPEM(const QString &, const SecureArray &)
01026 {
01027     return ErrorDecode;
01028 }
01029 
01030 //----------------------------------------------------------------------------
01031 // KeyStoreEntryContext
01032 //----------------------------------------------------------------------------
01033 bool KeyStoreEntryContext::isAvailable() const
01034 {
01035     return true;
01036 }
01037 
01038 KeyBundle KeyStoreEntryContext::keyBundle() const
01039 {
01040     return KeyBundle();
01041 }
01042 
01043 Certificate KeyStoreEntryContext::certificate() const
01044 {
01045     return Certificate();
01046 }
01047 
01048 CRL KeyStoreEntryContext::crl() const
01049 {
01050     return CRL();
01051 }
01052 
01053 PGPKey KeyStoreEntryContext::pgpSecretKey() const
01054 {
01055     return PGPKey();
01056 }
01057 
01058 PGPKey KeyStoreEntryContext::pgpPublicKey() const
01059 {
01060     return PGPKey();
01061 }
01062 
01063 bool KeyStoreEntryContext::ensureAccess()
01064 {
01065     return true;
01066 }
01067 
01068 //----------------------------------------------------------------------------
01069 // KeyStoreListContext
01070 //----------------------------------------------------------------------------
01071 void KeyStoreListContext::start()
01072 {
01073     QMetaObject::invokeMethod(this, "busyEnd", Qt::QueuedConnection);
01074 }
01075 
01076 void KeyStoreListContext::setUpdatesEnabled(bool)
01077 {
01078 }
01079 
01080 bool KeyStoreListContext::isReadOnly(int) const
01081 {
01082     return true;
01083 }
01084 
01085 KeyStoreEntryContext *KeyStoreListContext::entry(int id, const QString &entryId)
01086 {
01087     KeyStoreEntryContext *out = 0;
01088     QList<KeyStoreEntryContext*> list = entryList(id);
01089     for(int n = 0; n < list.count(); ++n)
01090     {
01091         if(list[n]->id() == entryId)
01092         {
01093             out = list.takeAt(n);
01094             break;
01095         }
01096     }
01097     qDeleteAll(list);
01098     return out;
01099 }
01100 
01101 KeyStoreEntryContext *KeyStoreListContext::entryPassive(const QString &serialized)
01102 {
01103     Q_UNUSED(serialized);
01104     return 0;
01105 }
01106 
01107 QString KeyStoreListContext::writeEntry(int, const KeyBundle &)
01108 {
01109     return QString();
01110 }
01111 
01112 QString KeyStoreListContext::writeEntry(int, const Certificate &)
01113 {
01114     return QString();
01115 }
01116 
01117 QString KeyStoreListContext::writeEntry(int, const CRL &)
01118 {
01119     return QString();
01120 }
01121 
01122 QString KeyStoreListContext::writeEntry(int, const PGPKey &)
01123 {
01124     return QString();
01125 }
01126 
01127 bool KeyStoreListContext::removeEntry(int, const QString &)
01128 {
01129     return false;
01130 }
01131 
01132 //----------------------------------------------------------------------------
01133 // TLSContext
01134 //----------------------------------------------------------------------------
01135 void TLSContext::setMTU(int)
01136 {
01137 }
01138 
01139 //----------------------------------------------------------------------------
01140 // MessageContext
01141 //----------------------------------------------------------------------------
01142 QString MessageContext::diagnosticText() const
01143 {
01144     return QString();
01145 }
01146 
01147 //----------------------------------------------------------------------------
01148 // SMSContext
01149 //----------------------------------------------------------------------------
01150 void SMSContext::setTrustedCertificates(const CertificateCollection &)
01151 {
01152 }
01153 
01154 void SMSContext::setUntrustedCertificates(const CertificateCollection &)
01155 {
01156 }
01157 
01158 void SMSContext::setPrivateKeys(const QList<SecureMessageKey> &)
01159 {
01160 }
01161 
01162 //----------------------------------------------------------------------------
01163 // BufferedComputation
01164 //----------------------------------------------------------------------------
01165 BufferedComputation::~BufferedComputation()
01166 {
01167 }
01168 
01169 MemoryRegion BufferedComputation::process(const MemoryRegion &a)
01170 {
01171     clear();
01172     update(a);
01173     return final();
01174 }
01175 
01176 //----------------------------------------------------------------------------
01177 // Filter
01178 //----------------------------------------------------------------------------
01179 Filter::~Filter()
01180 {
01181 }
01182 
01183 MemoryRegion Filter::process(const MemoryRegion &a)
01184 {
01185     clear();
01186     MemoryRegion buf = update(a);
01187     if(!ok())
01188         return MemoryRegion();
01189     MemoryRegion fin = final();
01190     if(!ok())
01191         return MemoryRegion();
01192     if(buf.isSecure() || fin.isSecure())
01193         return (SecureArray(buf) + SecureArray(fin));
01194     else
01195         return (buf.toByteArray() + fin.toByteArray());
01196 }
01197 
01198 //----------------------------------------------------------------------------
01199 // Algorithm
01200 //----------------------------------------------------------------------------
01201 class Algorithm::Private : public QSharedData
01202 {
01203 public:
01204     Provider::Context *c;
01205 
01206     Private(Provider::Context *context)
01207     {
01208         c = context;
01209         //printf("** [%p] Algorithm Created\n", c);
01210     }
01211 
01212     Private(const Private &from) : QSharedData(from)
01213     {
01214         c = from.c->clone();
01215         //printf("** [%p] Algorithm Copied (to [%p])\n", from.c, c);
01216     }
01217 
01218     ~Private()
01219     {
01220         //printf("** [%p] Algorithm Destroyed\n", c);
01221         delete c;
01222     }
01223 };
01224 
01225 Algorithm::Algorithm()
01226 {
01227 }
01228 
01229 Algorithm::Algorithm(const QString &type, const QString &provider)
01230 {
01231     change(type, provider);
01232 }
01233 
01234 Algorithm::Algorithm(const Algorithm &from)
01235 {
01236     *this = from;
01237 }
01238 
01239 Algorithm::~Algorithm()
01240 {
01241 }
01242 
01243 Algorithm & Algorithm::operator=(const Algorithm &from)
01244 {
01245     d = from.d;
01246     return *this;
01247 }
01248 
01249 QString Algorithm::type() const
01250 {
01251     if(d)
01252         return d->c->type();
01253     else
01254         return QString();
01255 }
01256 
01257 Provider *Algorithm::provider() const
01258 {
01259     if(d)
01260         return d->c->provider();
01261     else
01262         return 0;
01263 }
01264 
01265 Provider::Context *Algorithm::context()
01266 {
01267     if(d)
01268         return d->c;
01269     else
01270         return 0;
01271 }
01272 
01273 const Provider::Context *Algorithm::context() const
01274 {
01275     if(d)
01276         return d->c;
01277     else
01278         return 0;
01279 }
01280 
01281 void Algorithm::change(Provider::Context *c)
01282 {
01283     if(c)
01284         d = new Private(c);
01285     else
01286         d = 0;
01287 }
01288 
01289 void Algorithm::change(const QString &type, const QString &provider)
01290 {
01291     if(!type.isEmpty())
01292         change(getContext(type, provider));
01293     else
01294         change(0);
01295 }
01296 
01297 Provider::Context *Algorithm::takeContext()
01298 {
01299     if(d)
01300     {
01301         Provider::Context *c = d->c; // should cause a detach
01302         d->c = 0;
01303         d = 0;
01304         return c;
01305     }
01306     else
01307         return 0;
01308 }
01309 
01310 //----------------------------------------------------------------------------
01311 // SymmetricKey
01312 //----------------------------------------------------------------------------
01313 SymmetricKey::SymmetricKey()
01314 {
01315 }
01316 
01317 SymmetricKey::SymmetricKey(int size)
01318 {
01319     set(Random::randomArray(size));
01320 }
01321 
01322 SymmetricKey::SymmetricKey(const SecureArray &a)
01323 {
01324     set(a);
01325 }
01326 
01327 SymmetricKey::SymmetricKey(const QByteArray &a)
01328 {
01329     set(SecureArray(a));
01330 }
01331 
01332 /* from libgcrypt-1.2.0 */
01333 static unsigned char desWeakKeyTable[64][8] =
01334 {
01335     { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, /*w*/
01336     { 0x00, 0x00, 0x1e, 0x1e, 0x00, 0x00, 0x0e, 0x0e },
01337     { 0x00, 0x00, 0xe0, 0xe0, 0x00, 0x00, 0xf0, 0xf0 },
01338     { 0x00, 0x00, 0xfe, 0xfe, 0x00, 0x00, 0xfe, 0xfe },
01339     { 0x00, 0x1e, 0x00, 0x1e, 0x00, 0x0e, 0x00, 0x0e }, /*sw*/
01340     { 0x00, 0x1e, 0x1e, 0x00, 0x00, 0x0e, 0x0e, 0x00 },
01341     { 0x00, 0x1e, 0xe0, 0xfe, 0x00, 0x0e, 0xf0, 0xfe },
01342     { 0x00, 0x1e, 0xfe, 0xe0, 0x00, 0x0e, 0xfe, 0xf0 },
01343     { 0x00, 0xe0, 0x00, 0xe0, 0x00, 0xf0, 0x00, 0xf0 }, /*sw*/
01344     { 0x00, 0xe0, 0x1e, 0xfe, 0x00, 0xf0, 0x0e, 0xfe },
01345     { 0x00, 0xe0, 0xe0, 0x00, 0x00, 0xf0, 0xf0, 0x00 },
01346     { 0x00, 0xe0, 0xfe, 0x1e, 0x00, 0xf0, 0xfe, 0x0e },
01347     { 0x00, 0xfe, 0x00, 0xfe, 0x00, 0xfe, 0x00, 0xfe }, /*sw*/
01348     { 0x00, 0xfe, 0x1e, 0xe0, 0x00, 0xfe, 0x0e, 0xf0 },
01349     { 0x00, 0xfe, 0xe0, 0x1e, 0x00, 0xfe, 0xf0, 0x0e },
01350     { 0x00, 0xfe, 0xfe, 0x00, 0x00, 0xfe, 0xfe, 0x00 },
01351     { 0x1e, 0x00, 0x00, 0x1e, 0x0e, 0x00, 0x00, 0x0e },
01352     { 0x1e, 0x00, 0x1e, 0x00, 0x0e, 0x00, 0x0e, 0x00 }, /*sw*/
01353     { 0x1e, 0x00, 0xe0, 0xfe, 0x0e, 0x00, 0xf0, 0xfe },
01354     { 0x1e, 0x00, 0xfe, 0xe0, 0x0e, 0x00, 0xfe, 0xf0 },
01355     { 0x1e, 0x1e, 0x00, 0x00, 0x0e, 0x0e, 0x00, 0x00 },
01356     { 0x1e, 0x1e, 0x1e, 0x1e, 0x0e, 0x0e, 0x0e, 0x0e }, /*w*/
01357     { 0x1e, 0x1e, 0xe0, 0xe0, 0x0e, 0x0e, 0xf0, 0xf0 },
01358     { 0x1e, 0x1e, 0xfe, 0xfe, 0x0e, 0x0e, 0xfe, 0xfe },
01359     { 0x1e, 0xe0, 0x00, 0xfe, 0x0e, 0xf0, 0x00, 0xfe },
01360     { 0x1e, 0xe0, 0x1e, 0xe0, 0x0e, 0xf0, 0x0e, 0xf0 }, /*sw*/
01361     { 0x1e, 0xe0, 0xe0, 0x1e, 0x0e, 0xf0, 0xf0, 0x0e },
01362     { 0x1e, 0xe0, 0xfe, 0x00, 0x0e, 0xf0, 0xfe, 0x00 },
01363     { 0x1e, 0xfe, 0x00, 0xe0, 0x0e, 0xfe, 0x00, 0xf0 },
01364     { 0x1e, 0xfe, 0x1e, 0xfe, 0x0e, 0xfe, 0x0e, 0xfe }, /*sw*/
01365     { 0x1e, 0xfe, 0xe0, 0x00, 0x0e, 0xfe, 0xf0, 0x00 },
01366     { 0x1e, 0xfe, 0xfe, 0x1e, 0x0e, 0xfe, 0xfe, 0x0e },
01367     { 0xe0, 0x00, 0x00, 0xe0, 0xf0, 0x00, 0x00, 0xf0 },
01368     { 0xe0, 0x00, 0x1e, 0xfe, 0xf0, 0x00, 0x0e, 0xfe },
01369     { 0xe0, 0x00, 0xe0, 0x00, 0xf0, 0x00, 0xf0, 0x00 }, /*sw*/
01370     { 0xe0, 0x00, 0xfe, 0x1e, 0xf0, 0x00, 0xfe, 0x0e },
01371     { 0xe0, 0x1e, 0x00, 0xfe, 0xf0, 0x0e, 0x00, 0xfe },
01372     { 0xe0, 0x1e, 0x1e, 0xe0, 0xf0, 0x0e, 0x0e, 0xf0 },
01373     { 0xe0, 0x1e, 0xe0, 0x1e, 0xf0, 0x0e, 0xf0, 0x0e }, /*sw*/
01374     { 0xe0, 0x1e, 0xfe, 0x00, 0xf0, 0x0e, 0xfe, 0x00 },
01375     { 0xe0, 0xe0, 0x00, 0x00, 0xf0, 0xf0, 0x00, 0x00 },
01376     { 0xe0, 0xe0, 0x1e, 0x1e, 0xf0, 0xf0, 0x0e, 0x0e },
01377     { 0xe0, 0xe0, 0xe0, 0xe0, 0xf0, 0xf0, 0xf0, 0xf0 }, /*w*/
01378     { 0xe0, 0xe0, 0xfe, 0xfe, 0xf0, 0xf0, 0xfe, 0xfe },
01379     { 0xe0, 0xfe, 0x00, 0x1e, 0xf0, 0xfe, 0x00, 0x0e },
01380     { 0xe0, 0xfe, 0x1e, 0x00, 0xf0, 0xfe, 0x0e, 0x00 },
01381     { 0xe0, 0xfe, 0xe0, 0xfe, 0xf0, 0xfe, 0xf0, 0xfe }, /*sw*/
01382     { 0xe0, 0xfe, 0xfe, 0xe0, 0xf0, 0xfe, 0xfe, 0xf0 },
01383     { 0xfe, 0x00, 0x00, 0xfe, 0xfe, 0x00, 0x00, 0xfe },
01384     { 0xfe, 0x00, 0x1e, 0xe0, 0xfe, 0x00, 0x0e, 0xf0 },
01385     { 0xfe, 0x00, 0xe0, 0x1e, 0xfe, 0x00, 0xf0, 0x0e },
01386     { 0xfe, 0x00, 0xfe, 0x00, 0xfe, 0x00, 0xfe, 0x00 }, /*sw*/
01387     { 0xfe, 0x1e, 0x00, 0xe0, 0xfe, 0x0e, 0x00, 0xf0 },
01388     { 0xfe, 0x1e, 0x1e, 0xfe, 0xfe, 0x0e, 0x0e, 0xfe },
01389     { 0xfe, 0x1e, 0xe0, 0x00, 0xfe, 0x0e, 0xf0, 0x00 },
01390     { 0xfe, 0x1e, 0xfe, 0x1e, 0xfe, 0x0e, 0xfe, 0x0e }, /*sw*/
01391     { 0xfe, 0xe0, 0x00, 0x1e, 0xfe, 0xf0, 0x00, 0x0e },
01392     { 0xfe, 0xe0, 0x1e, 0x00, 0xfe, 0xf0, 0x0e, 0x00 },
01393     { 0xfe, 0xe0, 0xe0, 0xfe, 0xfe, 0xf0, 0xf0, 0xfe },
01394     { 0xfe, 0xe0, 0xfe, 0xe0, 0xfe, 0xf0, 0xfe, 0xf0 }, /*sw*/
01395     { 0xfe, 0xfe, 0x00, 0x00, 0xfe, 0xfe, 0x00, 0x00 },
01396     { 0xfe, 0xfe, 0x1e, 0x1e, 0xfe, 0xfe, 0x0e, 0x0e },
01397     { 0xfe, 0xfe, 0xe0, 0xe0, 0xfe, 0xfe, 0xf0, 0xf0 },
01398     { 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe }  /*w*/
01399 };
01400 
01401 bool SymmetricKey::isWeakDESKey()
01402 {
01403     if(size() != 8)
01404         return false; // dubious
01405     SecureArray workingCopy(8);
01406     // clear parity bits
01407     for(uint i = 0; i < 8; i++)
01408         workingCopy[i] = (data()[i]) & 0xfe;
01409 
01410     for(int n = 0; n < 64; n++)
01411     {
01412         if(memcmp(workingCopy.data(), desWeakKeyTable[n], 8) == 0)
01413             return true;
01414     }
01415     return false;
01416 }
01417 
01418 //----------------------------------------------------------------------------
01419 // InitializationVector
01420 //----------------------------------------------------------------------------
01421 InitializationVector::InitializationVector()
01422 {
01423 }
01424 
01425 InitializationVector::InitializationVector(int size)
01426 {
01427     set(Random::randomArray(size));
01428 }
01429 
01430 InitializationVector::InitializationVector(const SecureArray &a)
01431 {
01432     set(a);
01433 }
01434 
01435 InitializationVector::InitializationVector(const QByteArray &a)
01436 {
01437     set(SecureArray(a));
01438 }
01439 
01440 //----------------------------------------------------------------------------
01441 // Event
01442 //----------------------------------------------------------------------------
01443 class Event::Private : public QSharedData
01444 {
01445 public:
01446     Type type;
01447     Source source;
01448     PasswordStyle style;
01449     KeyStoreInfo ksi;
01450     KeyStoreEntry kse;
01451     QString fname;
01452     void *ptr;
01453 };
01454 
01455 Event::Event()
01456 {
01457 }
01458 
01459 Event::Event(const Event &from)
01460 :d(from.d)
01461 {
01462 }
01463 
01464 Event::~Event()
01465 {
01466 }
01467 
01468 Event & Event::operator=(const Event &from)
01469 {
01470     d = from.d;
01471     return *this;
01472 }
01473 
01474 bool Event::isNull() const
01475 {
01476     return (d ? false : true);
01477 }
01478 
01479 Event::Type Event::type() const
01480 {
01481     return d->type;
01482 }
01483 
01484 Event::Source Event::source() const
01485 {
01486     return d->source;
01487 }
01488 
01489 Event::PasswordStyle Event::passwordStyle() const
01490 {
01491     return d->style;
01492 }
01493 
01494 KeyStoreInfo Event::keyStoreInfo() const
01495 {
01496     return d->ksi;
01497 }
01498 
01499 KeyStoreEntry Event::keyStoreEntry() const
01500 {
01501     return d->kse;
01502 }
01503 
01504 QString Event::fileName() const
01505 {
01506     return d->fname;
01507 }
01508 
01509 void *Event::ptr() const
01510 {
01511     return d->ptr;
01512 }
01513 
01514 void Event::setPasswordKeyStore(PasswordStyle pstyle, const KeyStoreInfo &keyStoreInfo, const KeyStoreEntry &keyStoreEntry, void *ptr)
01515 {
01516     if(!d)
01517         d = new Private;
01518     d->type = Password;
01519     d->source = KeyStore;
01520     d->style = pstyle;
01521     d->ksi = keyStoreInfo;
01522     d->kse = keyStoreEntry;
01523     d->fname = QString();
01524     d->ptr = ptr;
01525 }
01526 
01527 void Event::setPasswordData(PasswordStyle pstyle, const QString &fileName, void *ptr)
01528 {
01529     if(!d)
01530         d = new Private;
01531     d->type = Password;
01532     d->source = Data;
01533     d->style = pstyle;
01534     d->ksi = KeyStoreInfo();
01535     d->kse = KeyStoreEntry();
01536     d->fname = fileName;
01537     d->ptr = ptr;
01538 }
01539 
01540 void Event::setToken(const KeyStoreInfo &keyStoreInfo, const KeyStoreEntry &keyStoreEntry, void *ptr)
01541 {
01542     if(!d)
01543         d = new Private;
01544     d->type = Token;
01545     d->source = KeyStore;
01546     d->style = StylePassword;
01547     d->ksi = keyStoreInfo;
01548     d->kse = keyStoreEntry;
01549     d->fname = QString();
01550     d->ptr = ptr;
01551 }
01552 
01553 //----------------------------------------------------------------------------
01554 // EventGlobal
01555 //----------------------------------------------------------------------------
01556 class HandlerBase : public QObject
01557 {
01558     Q_OBJECT
01559 public:
01560     HandlerBase(QObject *parent = 0) : QObject(parent)
01561     {
01562     }
01563 
01564 protected slots:
01565     virtual void ask(int id, const QCA::Event &e) = 0;
01566 };
01567 
01568 class AskerBase : public QObject
01569 {
01570     Q_OBJECT
01571 public:
01572     AskerBase(QObject *parent = 0) : QObject(parent)
01573     {
01574     }
01575 
01576     virtual void set_accepted(const SecureArray &password) = 0;
01577     virtual void set_rejected() = 0;
01578 };
01579 
01580 static void handler_add(HandlerBase *h, int pos = -1);
01581 static void handler_remove(HandlerBase *h);
01582 static void handler_accept(HandlerBase *h, int id, const SecureArray &password);
01583 static void handler_reject(HandlerBase *h, int id);
01584 static bool asker_ask(AskerBase *a, const Event &e);
01585 static void asker_cancel(AskerBase *a);
01586 
01587 Q_GLOBAL_STATIC(QMutex, g_event_mutex)
01588 
01589 class EventGlobal;
01590 static EventGlobal *g_event = 0;
01591 
01592 class EventGlobal
01593 {
01594 public:
01595     class HandlerItem
01596     {
01597     public:
01598         HandlerBase *h;
01599         QList<int> ids;
01600     };
01601 
01602     class AskerItem
01603     {
01604     public:
01605         AskerBase *a;
01606         int id;
01607         Event event;
01608         int handler_pos;
01609     };
01610 
01611     QList<HandlerItem> handlers;
01612     QList<AskerItem> askers;
01613 
01614     int next_id;
01615 
01616     EventGlobal()
01617     {
01618         qRegisterMetaType<Event>("QCA::Event");
01619         qRegisterMetaType<SecureArray>("QCA::SecureArray");
01620         next_id = 0;
01621     }
01622 
01623     int findHandlerItem(HandlerBase *h)
01624     {
01625         for(int n = 0; n < handlers.count(); ++n)
01626         {
01627             if(handlers[n].h == h)
01628                 return n;
01629         }
01630         return -1;
01631     }
01632 
01633     int findAskerItem(AskerBase *a)
01634     {
01635         for(int n = 0; n < askers.count(); ++n)
01636         {
01637             if(askers[n].a == a)
01638                 return n;
01639         }
01640         return -1;
01641     }
01642 
01643     int findAskerItemById(int id)
01644     {
01645         for(int n = 0; n < askers.count(); ++n)
01646         {
01647             if(askers[n].id == id)
01648                 return n;
01649         }
01650         return -1;
01651     }
01652 
01653     void ask(int asker_at)
01654     {
01655         AskerItem &i = askers[asker_at];
01656 
01657         g_event->handlers[i.handler_pos].ids += i.id;
01658         QMetaObject::invokeMethod(handlers[i.handler_pos].h, "ask",
01659             Qt::QueuedConnection, Q_ARG(int, i.id),
01660             Q_ARG(QCA::Event, i.event));
01661     }
01662 
01663     void reject(int asker_at)
01664     {
01665         AskerItem &i = askers[asker_at];
01666 
01667         // look for the next usable handler
01668         int pos = -1;
01669         for(int n = i.handler_pos + 1; n < g_event->handlers.count(); ++n)
01670         {
01671             // handler and asker can't be in the same thread
01672             //Q_ASSERT(g_event->handlers[n].h->thread() != i.a->thread());
01673             //if(g_event->handlers[n].h->thread() != i.a->thread())
01674             //{
01675                 pos = n;
01676                 break;
01677             //}
01678         }
01679 
01680         // if there is one, try it
01681         if(pos != -1)
01682         {
01683             i.handler_pos = pos;
01684             ask(asker_at);
01685         }
01686         // if not, send official reject
01687         else
01688         {
01689             AskerBase *asker = i.a;
01690             askers.removeAt(asker_at);
01691 
01692             asker->set_rejected();
01693         }
01694     }
01695 };
01696 
01697 void handler_add(HandlerBase *h, int pos)
01698 {
01699     QMutexLocker locker(g_event_mutex());
01700     if(!g_event)
01701         g_event = new EventGlobal;
01702 
01703     EventGlobal::HandlerItem i;
01704     i.h = h;
01705 
01706     if(pos != -1)
01707     {
01708         g_event->handlers.insert(pos, i);
01709 
01710         // adjust handler positions
01711         for(int n = 0; n < g_event->askers.count(); ++n)
01712         {
01713             if(g_event->askers[n].handler_pos >= pos)
01714                 g_event->askers[n].handler_pos++;
01715         }
01716     }
01717     else
01718         g_event->handlers += i;
01719 }
01720 
01721 void handler_remove(HandlerBase *h)
01722 {
01723     QMutexLocker locker(g_event_mutex());
01724     Q_ASSERT(g_event);
01725     if(!g_event)
01726         return;
01727     int at = g_event->findHandlerItem(h);
01728     Q_ASSERT(at != -1);
01729     if(at == -1)
01730         return;
01731 
01732     QList<int> ids = g_event->handlers[at].ids;
01733     g_event->handlers.removeAt(at);
01734 
01735     // adjust handler positions within askers
01736     for(int n = 0; n < g_event->askers.count(); ++n)
01737     {
01738         if(g_event->askers[n].handler_pos >= at)
01739             g_event->askers[n].handler_pos--;
01740     }
01741 
01742     // reject all askers
01743     foreach(int id, ids)
01744     {
01745         int asker_at = g_event->findAskerItemById(id);
01746         Q_ASSERT(asker_at != -1);
01747 
01748         g_event->reject(asker_at);
01749     }
01750 
01751     if(g_event->handlers.isEmpty())
01752     {
01753         delete g_event;
01754         g_event = 0;
01755     }
01756 }
01757 
01758 void handler_accept(HandlerBase *h, int id, const SecureArray &password)
01759 {
01760     QMutexLocker locker(g_event_mutex());
01761     Q_ASSERT(g_event);
01762     if(!g_event)
01763         return;
01764     int at = g_event->findHandlerItem(h);
01765     Q_ASSERT(at != -1);
01766     if(at == -1)
01767         return;
01768     int asker_at = g_event->findAskerItemById(id);
01769     Q_ASSERT(asker_at != -1);
01770     if(asker_at == -1)
01771         return;
01772 
01773     g_event->handlers[at].ids.removeAll(g_event->askers[asker_at].id);
01774 
01775     AskerBase *asker = g_event->askers[asker_at].a;
01776     asker->set_accepted(password);
01777 }
01778 
01779 void handler_reject(HandlerBase *h, int id)
01780 {
01781     QMutexLocker locker(g_event_mutex());
01782     Q_ASSERT(g_event);
01783     if(!g_event)
01784         return;
01785     int at = g_event->findHandlerItem(h);
01786     Q_ASSERT(at != -1);
01787     if(at == -1)
01788         return;
01789     int asker_at = g_event->findAskerItemById(id);
01790     Q_ASSERT(asker_at != -1);
01791     if(asker_at == -1)
01792         return;
01793 
01794     g_event->handlers[at].ids.removeAll(g_event->askers[asker_at].id);
01795 
01796     g_event->reject(asker_at);
01797 }
01798 
01799 bool asker_ask(AskerBase *a, const Event &e)
01800 {
01801     QMutexLocker locker(g_event_mutex());
01802     if(!g_event)
01803         return false;
01804 
01805     int pos = -1;
01806     for(int n = 0; n < g_event->handlers.count(); ++n)
01807     {
01808         // handler and asker can't be in the same thread
01809         //Q_ASSERT(g_event->handlers[n].h->thread() != a->thread());
01810         //if(g_event->handlers[n].h->thread() != a->thread())
01811         //{
01812             pos = n;
01813             break;
01814         //}
01815     }
01816     if(pos == -1)
01817         return false;
01818 
01819     EventGlobal::AskerItem i;
01820     i.a = a;
01821     i.id = g_event->next_id++;
01822     i.event = e;
01823     i.handler_pos = pos;
01824     g_event->askers += i;
01825     int asker_at = g_event->askers.count() - 1;
01826 
01827     g_event->ask(asker_at);
01828     return true;
01829 }
01830 
01831 void asker_cancel(AskerBase *a)
01832 {
01833     QMutexLocker locker(g_event_mutex());
01834     if(!g_event)
01835         return;
01836     int at = g_event->findAskerItem(a);
01837     if(at == -1)
01838         return;
01839 
01840     for(int n = 0; n < g_event->handlers.count(); ++n)
01841         g_event->handlers[n].ids.removeAll(g_event->askers[at].id);
01842 
01843     g_event->askers.removeAt(at);
01844 }
01845 
01846 //----------------------------------------------------------------------------
01847 // EventHandler
01848 //----------------------------------------------------------------------------
01849 class EventHandler::Private : public HandlerBase
01850 {
01851     Q_OBJECT
01852 public:
01853     EventHandler *q;
01854     bool started;
01855     QList<int> activeIds;
01856 
01857     Private(EventHandler *_q) : HandlerBase(_q), q(_q)
01858     {
01859         started = false;
01860     }
01861 
01862 public slots:
01863     virtual void ask(int id, const QCA::Event &e)
01864     {
01865         activeIds += id;
01866         emit q->eventReady(id, e);
01867     }
01868 };
01869 
01870 EventHandler::EventHandler(QObject *parent)
01871 :QObject(parent)
01872 {
01873     d = new Private(this);
01874 }
01875 
01876 EventHandler::~EventHandler()
01877 {
01878     if(d->started)
01879     {
01880         foreach(int id, d->activeIds)
01881             handler_reject(d, id);
01882 
01883         handler_remove(d);
01884     }
01885 
01886     delete d;
01887 }
01888 
01889 void EventHandler::start()
01890 {
01891     d->started = true;
01892     handler_add(d);
01893 }
01894 
01895 void EventHandler::submitPassword(int id, const SecureArray &password)
01896 {
01897     if(!d->activeIds.contains(id))
01898         return;
01899 
01900     d->activeIds.removeAll(id);
01901     handler_accept(d, id, password);
01902 }
01903 
01904 void EventHandler::tokenOkay(int id)
01905 {
01906     if(!d->activeIds.contains(id))
01907         return;
01908 
01909     d->activeIds.removeAll(id);
01910     handler_accept(d, id, SecureArray());
01911 }
01912 
01913 void EventHandler::reject(int id)
01914 {
01915     if(!d->activeIds.contains(id))
01916         return;
01917 
01918     d->activeIds.removeAll(id);
01919     handler_reject(d, id);
01920 }
01921 
01922 //----------------------------------------------------------------------------
01923 // PasswordAsker
01924 //----------------------------------------------------------------------------
01925 class AskerPrivate : public AskerBase
01926 {
01927     Q_OBJECT
01928 public:
01929     enum Type { Password, Token };
01930 
01931     Type type;
01932     PasswordAsker *passwordAsker;
01933     TokenAsker *tokenAsker;
01934 
01935     QMutex m;
01936     QWaitCondition w;
01937 
01938     bool accepted;
01939     SecureArray password;
01940     bool waiting;
01941     bool done;
01942 
01943     AskerPrivate(PasswordAsker *parent) : AskerBase(parent)
01944     {
01945         passwordAsker = parent;
01946         tokenAsker = 0;
01947         type = Password;
01948         accepted = false;
01949         waiting = false;
01950         done = true;
01951     }
01952 
01953     AskerPrivate(TokenAsker *parent) : AskerBase(parent)
01954     {
01955         passwordAsker = 0;
01956         tokenAsker = parent;
01957         type = Token;
01958         accepted = false;
01959         waiting = false;
01960         done = true;
01961     }
01962 
01963     void ask(const Event &e)
01964     {
01965         accepted = false;
01966         waiting = false;
01967         done = false;
01968         password.clear();
01969 
01970         if(!asker_ask(this, e))
01971         {
01972             done = true;
01973             QMetaObject::invokeMethod(this, "emitResponseReady", Qt::QueuedConnection);
01974         }
01975     }
01976 
01977     void cancel()
01978     {
01979         if(!done)
01980             asker_cancel(this);
01981     }
01982 
01983     virtual void set_accepted(const SecureArray &_password)
01984     {
01985         QMutexLocker locker(&m);
01986         accepted = true;
01987         password = _password;
01988         done = true;
01989         if(waiting)
01990             w.wakeOne();
01991         else
01992             QMetaObject::invokeMethod(this, "emitResponseReady", Qt::QueuedConnection);
01993     }
01994 
01995     virtual void set_rejected()
01996     {
01997         QMutexLocker locker(&m);
01998         done = true;
01999         if(waiting)
02000             w.wakeOne();
02001         else
02002             QMetaObject::invokeMethod(this, "emitResponseReady", Qt::QueuedConnection);
02003     }
02004 
02005     void waitForResponse()
02006     {
02007         QMutexLocker locker(&m);
02008         if(done)
02009             return;
02010         waiting = true;
02011         w.wait(&m);
02012         waiting = false;
02013     }
02014 
02015 public slots:
02016     virtual void emitResponseReady() = 0;
02017 };
02018 
02019 class PasswordAsker::Private : public AskerPrivate
02020 {
02021 public:
02022     Private(PasswordAsker *_q) : AskerPrivate(_q)
02023     {
02024     }
02025 
02026     virtual void emitResponseReady()
02027     {
02028         emit passwordAsker->responseReady();
02029     }
02030 };
02031 
02032 PasswordAsker::PasswordAsker(QObject *parent)
02033 :QObject(parent)
02034 {
02035     d = new Private(this);
02036 }
02037 
02038 PasswordAsker::~PasswordAsker()
02039 {
02040     delete d;
02041 }
02042 
02043 void PasswordAsker::ask(Event::PasswordStyle pstyle, const KeyStoreInfo &keyStoreInfo, const KeyStoreEntry &keyStoreEntry, void *ptr)
02044 {
02045     Event e;
02046     e.setPasswordKeyStore(pstyle, keyStoreInfo, keyStoreEntry, ptr);
02047     d->ask(e);
02048 }
02049 
02050 void PasswordAsker::ask(Event::PasswordStyle pstyle, const QString &fileName, void *ptr)
02051 {
02052     Event e;
02053     e.setPasswordData(pstyle, fileName, ptr);
02054     d->ask(e);
02055 }
02056 
02057 void PasswordAsker::cancel()
02058 {
02059     d->cancel();
02060 }
02061 
02062 void PasswordAsker::waitForResponse()
02063 {
02064     d->waitForResponse();
02065 }
02066 
02067 bool PasswordAsker::accepted() const
02068 {
02069     return d->accepted;
02070 }
02071 
02072 SecureArray PasswordAsker::password() const
02073 {
02074     return d->password;
02075 }
02076 
02077 //----------------------------------------------------------------------------
02078 // TokenAsker
02079 //----------------------------------------------------------------------------
02080 class TokenAsker::Private : public AskerPrivate
02081 {
02082 public:
02083     Private(TokenAsker *_q) : AskerPrivate(_q)
02084     {
02085     }
02086 
02087     virtual void emitResponseReady()
02088     {
02089         emit tokenAsker->responseReady();
02090     }
02091 };
02092 
02093 TokenAsker::TokenAsker(QObject *parent)
02094 :QObject(parent)
02095 {
02096     d = new Private(this);
02097 }
02098 
02099 TokenAsker::~TokenAsker()
02100 {
02101     delete d;
02102 }
02103 
02104 void TokenAsker::ask(const KeyStoreInfo &keyStoreInfo, const KeyStoreEntry &keyStoreEntry, void *ptr)
02105 {
02106     Event e;
02107     e.setToken(keyStoreInfo, keyStoreEntry, ptr);
02108     d->ask(e);
02109 }
02110 
02111 void TokenAsker::cancel()
02112 {
02113     d->cancel();
02114 }
02115 
02116 void TokenAsker::waitForResponse()
02117 {
02118     d->waitForResponse();
02119 }
02120 
02121 bool TokenAsker::accepted() const
02122 {
02123     return d->accepted;
02124 }
02125 
02126 }
02127 
02128 #include "qca_core.moc"

qca

Skip menu "qca"
  • Main Page
  • Modules
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

KDE Support

Skip menu "KDE Support"
  • akonadi
  • Decibel
  • grantlee
  • kdewin
  • phonon
  •     Backend
  • polkit-qt
  • qca
  • qimageblitz
  • soprano
  • strigi
  •     searchclient
  •     streamanalyzer
  •     streams
Generated for KDE Support by doxygen 1.5.9-20090814
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal