File indexing completed on 2024-09-08 04:18:39
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"