File indexing completed on 2024-04-28 04:43:38

0001 /*
0002  Copyright (C) 2007 Brad Hards <bradh@frogmouth.net>
0003 
0004  Permission is hereby granted, free of charge, to any person obtaining a copy
0005  of this software and associated documentation files (the "Software"), to deal
0006  in the Software without restriction, including without limitation the rights
0007  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
0008  copies of the Software, and to permit persons to whom the Software is
0009  furnished to do so, subject to the following conditions:
0010 
0011  The above copyright notice and this permission notice shall be included in
0012  all copies or substantial portions of the Software.
0013 
0014  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
0015  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
0016  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
0017  AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
0018  AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
0019  CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
0020 */
0021 
0022 // QtCrypto has the declarations for all of QCA
0023 #include <QtCrypto>
0024 
0025 #include <QCoreApplication>
0026 
0027 #include <iostream>
0028 
0029 #ifdef QT_STATICPLUGIN
0030 #include "import_plugins.h"
0031 #endif
0032 
0033 /**
0034    We need a class on the client side to handle password requests.
0035 */
0036 class ClientPassphraseHandler : public QObject
0037 {
0038     Q_OBJECT
0039 public:
0040     ClientPassphraseHandler(QObject *parent = nullptr)
0041         : QObject(parent)
0042     {
0043         // When the PasswordAsker or TokenAsker needs to interact
0044         // with the user, it raises a signal. We connect that to a
0045         // local slot to get the required information.
0046         connect(&m_handler, &QCA::EventHandler::eventReady, this, &ClientPassphraseHandler::my_eventReady);
0047 
0048         // Now that we are set up, we can start the EventHandler. Nothing
0049         // will happen if you don't call this method.
0050         m_handler.start();
0051     }
0052 
0053 private Q_SLOTS:
0054     // This slot gets called when the provider needs a token inserted,
0055     // or to get a passphrase / password / PIN.
0056     void my_eventReady(int id, const QCA::Event &event)
0057     {
0058         // We can sanity check the event
0059         if (event.isNull()) {
0060             return;
0061         }
0062 
0063         // Events can be associated with a a keystore or a file/bytearray
0064         // You can tell which by looking at the Source
0065         if (event.source() == QCA::Event::KeyStore) {
0066             std::cout << "Event is associated with a key store operation" << std::endl;
0067         } else if (event.source() == QCA::Event::Data) {
0068             std::cout << "Event is associated with a file or some other data" << std::endl;
0069             // if the event comes from a file type operation, you can get the
0070             // name / label using fileName()
0071             std::cout << "   Filename: " << qPrintable(event.fileName()) << std::endl;
0072         } else {
0073             std::cout << "Unexpected Source for Event" << std::endl;
0074         }
0075 
0076         // There are different kinds of events.
0077         if (event.type() == QCA::Event::Token) {
0078             // You would typically ask the user to insert the token here
0079             std::cout << "Request for token" << std::endl;
0080             // we just fake it for this demo.
0081             m_handler.tokenOkay(id);
0082             // you could use m_handler.reject( id ) to refuse the token request
0083 
0084         } else if (event.type() == QCA::Event::Password) {
0085             std::cout << "Request for password, passphrase or PIN" << std::endl;
0086             // and within the Password type, we have a few different styles.
0087             if (event.passwordStyle() == QCA::Event::StylePassword) {
0088                 std::cout << "   [Password request]" << std::endl;
0089             } else if (event.passwordStyle() == QCA::Event::StylePassphrase) {
0090                 std::cout << "   [Passphrase request]" << std::endl;
0091             } else if (event.passwordStyle() == QCA::Event::StylePIN) {
0092                 std::cout << "   [PIN request]" << std::endl;
0093             } else {
0094                 std::cout << "   [unexpect request style]" << std::endl;
0095             }
0096             // You would typically request the password/PIN/passphrase.
0097             // again, we just fake it.
0098             m_handler.submitPassword(id, QCA::SecureArray("hello"));
0099 
0100         } else {
0101             std::cout << "Unexpected event type" << std::endl;
0102         }
0103     }
0104 
0105 private:
0106     QCA::EventHandler m_handler;
0107 };
0108 
0109 void asker_procedure();
0110 
0111 class AskerThread : public QThread
0112 {
0113     Q_OBJECT
0114 protected:
0115     void run() override
0116     {
0117         asker_procedure();
0118     }
0119 };
0120 
0121 int main(int argc, char **argv)
0122 {
0123     // the Initializer object sets things up, and
0124     // also does cleanup when it goes out of scope
0125     QCA::Initializer init;
0126 
0127     QCoreApplication exampleApp(argc, argv);
0128 
0129     ClientPassphraseHandler cph;
0130 
0131     // handler and asker cannot occur in the same thread
0132     AskerThread askerThread;
0133     QObject::connect(&askerThread, &AskerThread::finished, &exampleApp, &QCoreApplication::quit);
0134     askerThread.start();
0135 
0136     exampleApp.exec();
0137     return 0;
0138 }
0139 
0140 void asker_procedure()
0141 {
0142     QCA::PasswordAsker pwAsker;
0143 
0144     pwAsker.ask(QCA::Event::StylePassword, QStringLiteral("foo.tmp"), nullptr);
0145 
0146     pwAsker.waitForResponse();
0147 
0148     std::cout << "Password was: " << pwAsker.password().toByteArray().data() << std::endl;
0149 
0150     std::cout << std::endl << "Now do token:" << std::endl;
0151 
0152     QCA::TokenAsker tokenAsker;
0153 
0154     tokenAsker.ask(
0155         QCA::KeyStoreInfo(QCA::KeyStore::SmartCard, QStringLiteral("Token Id"), QStringLiteral("Token Name")),
0156         QCA::KeyStoreEntry(),
0157         nullptr);
0158 
0159     tokenAsker.waitForResponse();
0160 
0161     if (tokenAsker.accepted()) {
0162         std::cout << "Token was accepted" << std::endl;
0163     } else {
0164         std::cout << "Token was not accepted" << std::endl;
0165     }
0166 }
0167 
0168 #include "eventhandlerdemo.moc"