1 | /* |
2 | Copyright (C) 2007 Brad Hards <bradh@frogmouth.net> |
3 | |
4 | Permission is hereby granted, free of charge, to any person obtaining a copy |
5 | of this software and associated documentation files (the "Software"), to deal |
6 | in the Software without restriction, including without limitation the rights |
7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
8 | copies of the Software, and to permit persons to whom the Software is |
9 | furnished to do so, subject to the following conditions: |
10 | |
11 | The above copyright notice and this permission notice shall be included in |
12 | all copies or substantial portions of the Software. |
13 | |
14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
16 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
17 | AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN |
18 | AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN |
19 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
20 | */ |
21 | |
22 | // QtCrypto has the declarations for all of QCA |
23 | #include <QtCrypto> |
24 | |
25 | #include <QCoreApplication> |
26 | |
27 | #include <iostream> |
28 | |
29 | #ifdef QT_STATICPLUGIN |
30 | #include "import_plugins.h" |
31 | #endif |
32 | |
33 | /** |
34 | We need a class on the client side to handle password requests. |
35 | */ |
36 | class ClientPassphraseHandler : public QObject |
37 | { |
38 | Q_OBJECT |
39 | public: |
40 | ClientPassphraseHandler(QObject *parent = nullptr) |
41 | : QObject(parent) |
42 | { |
43 | // When the PasswordAsker or TokenAsker needs to interact |
44 | // with the user, it raises a signal. We connect that to a |
45 | // local slot to get the required information. |
46 | connect(sender: &m_handler, signal: &QCA::EventHandler::eventReady, context: this, slot: &ClientPassphraseHandler::my_eventReady); |
47 | |
48 | // Now that we are set up, we can start the EventHandler. Nothing |
49 | // will happen if you don't call this method. |
50 | m_handler.start(); |
51 | } |
52 | |
53 | private Q_SLOTS: |
54 | // This slot gets called when the provider needs a token inserted, |
55 | // or to get a passphrase / password / PIN. |
56 | void my_eventReady(int id, const QCA::Event &event) |
57 | { |
58 | // We can sanity check the event |
59 | if (event.isNull()) { |
60 | return; |
61 | } |
62 | |
63 | // Events can be associated with a a keystore or a file/bytearray |
64 | // You can tell which by looking at the Source |
65 | if (event.source() == QCA::Event::KeyStore) { |
66 | std::cout << "Event is associated with a key store operation" << std::endl; |
67 | } else if (event.source() == QCA::Event::Data) { |
68 | std::cout << "Event is associated with a file or some other data" << std::endl; |
69 | // if the event comes from a file type operation, you can get the |
70 | // name / label using fileName() |
71 | std::cout << " Filename: " << qPrintable(event.fileName()) << std::endl; |
72 | } else { |
73 | std::cout << "Unexpected Source for Event" << std::endl; |
74 | } |
75 | |
76 | // There are different kinds of events. |
77 | if (event.type() == QCA::Event::Token) { |
78 | // You would typically ask the user to insert the token here |
79 | std::cout << "Request for token" << std::endl; |
80 | // we just fake it for this demo. |
81 | m_handler.tokenOkay(id); |
82 | // you could use m_handler.reject( id ) to refuse the token request |
83 | |
84 | } else if (event.type() == QCA::Event::Password) { |
85 | std::cout << "Request for password, passphrase or PIN" << std::endl; |
86 | // and within the Password type, we have a few different styles. |
87 | if (event.passwordStyle() == QCA::Event::StylePassword) { |
88 | std::cout << " [Password request]" << std::endl; |
89 | } else if (event.passwordStyle() == QCA::Event::StylePassphrase) { |
90 | std::cout << " [Passphrase request]" << std::endl; |
91 | } else if (event.passwordStyle() == QCA::Event::StylePIN) { |
92 | std::cout << " [PIN request]" << std::endl; |
93 | } else { |
94 | std::cout << " [unexpect request style]" << std::endl; |
95 | } |
96 | // You would typically request the password/PIN/passphrase. |
97 | // again, we just fake it. |
98 | m_handler.submitPassword(id, password: QCA::SecureArray("hello" )); |
99 | |
100 | } else { |
101 | std::cout << "Unexpected event type" << std::endl; |
102 | } |
103 | } |
104 | |
105 | private: |
106 | QCA::EventHandler m_handler; |
107 | }; |
108 | |
109 | void asker_procedure(); |
110 | |
111 | class AskerThread : public QThread |
112 | { |
113 | Q_OBJECT |
114 | protected: |
115 | void run() override |
116 | { |
117 | asker_procedure(); |
118 | } |
119 | }; |
120 | |
121 | int main(int argc, char **argv) |
122 | { |
123 | // the Initializer object sets things up, and |
124 | // also does cleanup when it goes out of scope |
125 | QCA::Initializer init; |
126 | |
127 | QCoreApplication exampleApp(argc, argv); |
128 | |
129 | ClientPassphraseHandler cph; |
130 | |
131 | // handler and asker cannot occur in the same thread |
132 | AskerThread askerThread; |
133 | QObject::connect(sender: &askerThread, signal: &AskerThread::finished, context: &exampleApp, slot: &QCoreApplication::quit); |
134 | askerThread.start(); |
135 | |
136 | exampleApp.exec(); |
137 | return 0; |
138 | } |
139 | |
140 | void asker_procedure() |
141 | { |
142 | QCA::PasswordAsker pwAsker; |
143 | |
144 | pwAsker.ask(pstyle: QCA::Event::StylePassword, QStringLiteral("foo.tmp" ), ptr: nullptr); |
145 | |
146 | pwAsker.waitForResponse(); |
147 | |
148 | std::cout << "Password was: " << pwAsker.password().toByteArray().data() << std::endl; |
149 | |
150 | std::cout << std::endl << "Now do token:" << std::endl; |
151 | |
152 | QCA::TokenAsker tokenAsker; |
153 | |
154 | tokenAsker.ask( |
155 | keyStoreInfo: QCA::KeyStoreInfo(QCA::KeyStore::SmartCard, QStringLiteral("Token Id" ), QStringLiteral("Token Name" )), |
156 | keyStoreEntry: QCA::KeyStoreEntry(), |
157 | ptr: nullptr); |
158 | |
159 | tokenAsker.waitForResponse(); |
160 | |
161 | if (tokenAsker.accepted()) { |
162 | std::cout << "Token was accepted" << std::endl; |
163 | } else { |
164 | std::cout << "Token was not accepted" << std::endl; |
165 | } |
166 | } |
167 | |
168 | #include "eventhandlerdemo.moc" |
169 | |