Changeset View
Changeset View
Standalone View
Standalone View
src/main.cpp
Show All 18 Lines | |||||
19 | 19 | | |||
20 | #include <sys/resource.h> | 20 | #include <sys/resource.h> | ||
21 | #include <memory> | 21 | #include <memory> | ||
22 | 22 | | |||
23 | #include <kwallet.h> | 23 | #include <kwallet.h> | ||
24 | #include <KPasswordDialog> | 24 | #include <KPasswordDialog> | ||
25 | #include <KAboutData> | 25 | #include <KAboutData> | ||
26 | #include <KLocalizedString> | 26 | #include <KLocalizedString> | ||
27 | #include <KMessageBox> | ||||
27 | 28 | | |||
28 | #include <QApplication> | 29 | #include <QApplication> | ||
29 | #include <QCommandLineParser> | 30 | #include <QCommandLineParser> | ||
30 | #include <QTextStream> | 31 | #include <QTextStream> | ||
31 | #include <QCommandLineOption> | 32 | #include <QCommandLineOption> | ||
33 | #include <QInputDialog> | ||||
32 | #include <QPointer> | 34 | #include <QPointer> | ||
33 | #include <QRegularExpression> | 35 | #include <QRegularExpression> | ||
34 | #include <QLoggingCategory> | 36 | #include <QLoggingCategory> | ||
35 | #include <QDesktopWidget> | 37 | #include <QDesktopWidget> | ||
36 | 38 | | |||
37 | Q_LOGGING_CATEGORY(LOG_KSSHASKPASS, "ksshaskpass") | 39 | Q_LOGGING_CATEGORY(LOG_KSSHASKPASS, "ksshaskpass") | ||
38 | 40 | | |||
41 | enum Type { | ||||
42 | TypePassword, | ||||
43 | TypeClearText, | ||||
44 | TypeConfirm, | ||||
fvogt: I'd prefer an enum instead of two booleans. | |||||
45 | }; | ||||
46 | | ||||
39 | // Try to understand what we're asked for by parsing the phrase. Unfortunately, sshaskpass interface does not | 47 | // Try to understand what we're asked for by parsing the phrase. Unfortunately, sshaskpass interface does not | ||
40 | // include any saner methods to pass the action or the name of the keyfile. Fortunately, at least Debian's ssh-add | 48 | // include any saner methods to pass the action or the name of the keyfile. Fortunately, openssh and git | ||
41 | // has no i18n, so this should work for all languages as long as the string is unchanged. | 49 | // has no i18n, so this should work for all languages as long as the string is unchanged. | ||
42 | static void parsePrompt(const QString &prompt, QString& keyFile, bool& wrongPassphrase) | 50 | static void parsePrompt(const QString &prompt, QString& identifier, bool& ignoreWallet, enum Type& type) | ||
43 | { | 51 | { | ||
44 | // Case 1: asking for passphrase for a certain keyfile for the first time => we should try a password from the wallet | 52 | QRegularExpressionMatch match; | ||
45 | QRegularExpression re1(QStringLiteral("^Enter passphrase for (.*?)( \\(will confirm each use\\))?: $")); | 53 | | ||
46 | QRegularExpressionMatch match1 = re1.match(prompt); | 54 | // openssh sshconnect2.c | ||
47 | if (match1.hasMatch()) { | 55 | // Case: password for authentication on remote ssh server | ||
48 | keyFile = match1.captured(1); | 56 | match = QRegularExpression(QStringLiteral("^(.*@.*)'s password( \\(JPAKE\\))?: $")).match(prompt); | ||
49 | wrongPassphrase = false; | 57 | if (match.hasMatch()) { | ||
58 | identifier = match.captured(1); | ||||
59 | type = TypePassword; | ||||
60 | ignoreWallet = false; | ||||
61 | return; | ||||
62 | } | ||||
63 | | ||||
64 | // openssh sshconnect2.c | ||||
65 | // Case: password change request | ||||
66 | match = QRegularExpression(QStringLiteral("^(Enter|Retype) (.*@.*)'s (old|new) password: $")).match(prompt); | ||||
67 | if (match.hasMatch()) { | ||||
68 | identifier = match.captured(2); | ||||
69 | type = TypePassword; | ||||
70 | ignoreWallet = true; | ||||
71 | return; | ||||
72 | } | ||||
73 | | ||||
74 | // openssh sshconnect2.c and sshconnect1.c | ||||
75 | // Case: asking for passphrase for a certain keyfile | ||||
76 | match = QRegularExpression(QStringLiteral("^Enter passphrase for( RSA)? key '(.*)': $")).match(prompt); | ||||
77 | if (match.hasMatch()) { | ||||
78 | identifier = match.captured(2); | ||||
79 | type = TypePassword; | ||||
80 | ignoreWallet = false; | ||||
50 | return; | 81 | return; | ||
51 | } | 82 | } | ||
52 | 83 | | |||
53 | // Case 2: re-asking for passphrase for a certain keyfile => probably we've tried a password from the wallet, no point | 84 | // openssh ssh-add.c | ||
85 | // Case: asking for passphrase for a certain keyfile for the first time => we should try a password from the wallet | ||||
86 | match = QRegularExpression(QStringLiteral("^Enter passphrase for (.*?)( \\(will confirm each use\\))?: $")).match(prompt); | ||||
87 | if (match.hasMatch()) { | ||||
88 | identifier = match.captured(1); | ||||
89 | type = TypePassword; | ||||
90 | ignoreWallet = false; | ||||
91 | return; | ||||
92 | } | ||||
93 | | ||||
94 | // openssh ssh-add.c | ||||
95 | // Case: re-asking for passphrase for a certain keyfile => probably we've tried a password from the wallet, no point | ||||
54 | // in trying it again | 96 | // in trying it again | ||
55 | QRegularExpression re2(QStringLiteral("^Bad passphrase, try again for (.*?)( \\(will confirm each use\\))?: $")); | 97 | match = QRegularExpression(QStringLiteral("^Bad passphrase, try again for (.*?)( \\(will confirm each use\\))?: $")).match(prompt); | ||
56 | QRegularExpressionMatch match2 = re2.match(prompt); | 98 | if (match.hasMatch()) { | ||
57 | if (match2.hasMatch()) { | 99 | identifier = match.captured(1); | ||
58 | keyFile = match2.captured(1); | 100 | type = TypePassword; | ||
59 | wrongPassphrase = true; | 101 | ignoreWallet = true; | ||
102 | return; | ||||
103 | } | ||||
104 | | ||||
105 | // openssh ssh-pkcs11.c | ||||
106 | // Case: asking for PIN for some token label | ||||
107 | match = QRegularExpression(QStringLiteral("Enter PIN for '(.*)': $")).match(prompt); | ||||
108 | if (match.hasMatch()) { | ||||
109 | identifier = match.captured(1); | ||||
110 | type = TypePassword; | ||||
111 | ignoreWallet = false; | ||||
112 | return; | ||||
113 | } | ||||
114 | | ||||
115 | // openssh mux.c | ||||
116 | match = QRegularExpression(QStringLiteral("^(Allow|Terminate) shared connection to (.*)\\? $")).match(prompt); | ||||
117 | if (match.hasMatch()) { | ||||
118 | identifier = match.captured(2); | ||||
119 | type = TypeConfirm; | ||||
120 | ignoreWallet = true; | ||||
121 | return; | ||||
122 | } | ||||
123 | | ||||
124 | // openssh mux.c | ||||
125 | match = QRegularExpression(QStringLiteral("^Open (.* on .*)?$")).match(prompt); | ||||
126 | if (match.hasMatch()) { | ||||
127 | identifier = match.captured(1); | ||||
128 | type = TypeConfirm; | ||||
129 | ignoreWallet = true; | ||||
130 | return; | ||||
131 | } | ||||
132 | | ||||
133 | // openssh mux.c | ||||
134 | match = QRegularExpression(QStringLiteral("^Allow forward to (.*:.*)\\? $")).match(prompt); | ||||
135 | if (match.hasMatch()) { | ||||
136 | identifier = match.captured(1); | ||||
137 | type = TypeConfirm; | ||||
138 | ignoreWallet = true; | ||||
139 | return; | ||||
140 | } | ||||
141 | | ||||
142 | // openssh mux.c | ||||
143 | match = QRegularExpression(QStringLiteral("^Disable further multiplexing on shared connection to (.*)? $")).match(prompt); | ||||
144 | if (match.hasMatch()) { | ||||
145 | identifier = match.captured(1); | ||||
146 | type = TypeConfirm; | ||||
147 | ignoreWallet = true; | ||||
148 | return; | ||||
149 | } | ||||
150 | | ||||
151 | // openssh ssh-agent.c | ||||
152 | match = QRegularExpression(QStringLiteral("^Allow use of key (.*)?\\nKey fingerprint .*\\.$")).match(prompt); | ||||
153 | if (match.hasMatch()) { | ||||
154 | identifier = match.captured(1); | ||||
155 | type = TypeConfirm; | ||||
156 | ignoreWallet = true; | ||||
157 | return; | ||||
158 | } | ||||
159 | | ||||
160 | // openssh sshconnect.c | ||||
161 | match = QRegularExpression(QStringLiteral("^Add key (.*) \\(.*\\) to agent\\?$")).match(prompt); | ||||
162 | if (match.hasMatch()) { | ||||
163 | identifier = match.captured(1); | ||||
164 | type = TypeConfirm; | ||||
165 | ignoreWallet = true; | ||||
166 | return; | ||||
167 | } | ||||
168 | | ||||
169 | // git imap-send.c | ||||
170 | // Case: asking for password by git imap-send | ||||
171 | match = QRegularExpression(QStringLiteral("^Password \\((.*@.*)\\): $")).match(prompt); | ||||
172 | if (match.hasMatch()) { | ||||
173 | identifier = match.captured(1); | ||||
174 | type = TypePassword; | ||||
175 | ignoreWallet = false; | ||||
176 | return; | ||||
177 | } | ||||
178 | | ||||
179 | // git credential.c | ||||
180 | // Case: asking for username by git without specifying any other information | ||||
181 | match = QRegularExpression(QStringLiteral("^Username: $")).match(prompt); | ||||
182 | if (match.hasMatch()) { | ||||
183 | identifier = QString(); | ||||
184 | type = TypeClearText; | ||||
185 | ignoreWallet = true; | ||||
186 | return; | ||||
187 | } | ||||
188 | | ||||
189 | // git credential.c | ||||
190 | // Case: asking for password by git without specifying any other information | ||||
191 | match = QRegularExpression(QStringLiteral("^Password: $")).match(prompt); | ||||
192 | if (match.hasMatch()) { | ||||
193 | identifier = QString(); | ||||
194 | type = TypePassword; | ||||
195 | ignoreWallet = true; | ||||
196 | return; | ||||
197 | } | ||||
198 | | ||||
199 | // git credential.c | ||||
200 | // Case: asking for username by git for some identifier | ||||
201 | match = QRegularExpression(QStringLiteral("^Username for '(.*)': $")).match(prompt); | ||||
202 | if (match.hasMatch()) { | ||||
203 | identifier = match.captured(1); | ||||
204 | type = TypeClearText; | ||||
205 | ignoreWallet = false; | ||||
206 | return; | ||||
207 | } | ||||
208 | | ||||
209 | // git credential.c | ||||
210 | // Case: asking for password by git for some identifier | ||||
211 | match = QRegularExpression(QStringLiteral("^Password for '(.*)': $")).match(prompt); | ||||
212 | if (match.hasMatch()) { | ||||
213 | identifier = match.captured(1); | ||||
214 | type = TypePassword; | ||||
215 | ignoreWallet = false; | ||||
60 | return; | 216 | return; | ||
61 | } | 217 | } | ||
62 | 218 | | |||
63 | // Case 3: password extraction from git, see bug 376228 | 219 | // Case: username extraction from git-lfs | ||
64 | QRegularExpression re3(QStringLiteral("^(Password|Username) for (.*?)[:] $")); | 220 | match = QRegularExpression(QStringLiteral("^Username for \"(.*?)\"$")).match(prompt); | ||
65 | QRegularExpressionMatch match3 = re3.match(prompt); | 221 | if (match.hasMatch()) { | ||
66 | if (match3.hasMatch()) { | 222 | identifier = match.captured(1); | ||
67 | keyFile = match3.captured(2); | 223 | type = TypeClearText; | ||
68 | wrongPassphrase = false; | 224 | ignoreWallet = false; | ||
69 | return; | 225 | return; | ||
70 | } | 226 | } | ||
71 | 227 | | |||
72 | // Case 3a: password extraction from git-lfs | 228 | // Case: password extraction from git-lfs | ||
73 | QRegularExpression re3a(QStringLiteral("^(Password|Username) for \"(.*?)\"$")); | 229 | match = QRegularExpression(QStringLiteral("^Password for \"(.*?)\"$")).match(prompt); | ||
74 | QRegularExpressionMatch match3a = re3a.match(prompt); | 230 | if (match.hasMatch()) { | ||
75 | if (match3a.hasMatch()) { | 231 | identifier = match.captured(1); | ||
76 | keyFile = match3a.captured(2); | 232 | type = TypePassword; | ||
77 | wrongPassphrase = false; | 233 | ignoreWallet = false; | ||
78 | return; | 234 | return; | ||
79 | } | 235 | } | ||
80 | 236 | | |||
81 | // Case 4: password extraction from mercurial, see bug 380085 | 237 | // Case: password extraction from mercurial, see bug 380085 | ||
82 | QRegularExpression re4(QStringLiteral("^(.*?)'s password: $")); | 238 | match = QRegularExpression(QStringLiteral("^(.*?)'s password: $")).match(prompt); | ||
83 | QRegularExpressionMatch match4 = re4.match(prompt); | 239 | if (match.hasMatch()) { | ||
84 | if (match4.hasMatch()) { | 240 | identifier = match.captured(1); | ||
85 | keyFile = match4.captured(1); | 241 | type = TypePassword; | ||
86 | wrongPassphrase = false; | 242 | ignoreWallet = false; | ||
87 | return; | 243 | return; | ||
88 | } | 244 | } | ||
89 | 245 | | |||
90 | // Nothing matched; either it was called by some sort of a script with a custom prompt (i.e. not ssh-add), or | 246 | // Nothing matched; either it was called by some sort of a script with a custom prompt (i.e. not ssh-add), or | ||
91 | // strings we're looking for were broken. Issue a warning and continue without keyFile. | 247 | // strings we're looking for were broken. Issue a warning and continue without identifier. | ||
92 | qCWarning(LOG_KSSHASKPASS) << "Unable to extract keyFile from phrase" << prompt; | 248 | qCWarning(LOG_KSSHASKPASS) << "Unable to parse phrase" << prompt; | ||
93 | } | 249 | } | ||
94 | 250 | | |||
95 | int main(int argc, char **argv) | 251 | int main(int argc, char **argv) | ||
96 | { | 252 | { | ||
97 | QApplication app(argc, argv); | 253 | QApplication app(argc, argv); | ||
98 | KLocalizedString::setApplicationDomain("ksshaskpass"); | 254 | KLocalizedString::setApplicationDomain("ksshaskpass"); | ||
99 | 255 | | |||
100 | //TODO update it. | 256 | //TODO update it. | ||
101 | KAboutData about( | 257 | KAboutData about( | ||
102 | QStringLiteral("ksshaskpass"), | 258 | QStringLiteral("ksshaskpass"), | ||
103 | i18n("Ksshaskpass"), | 259 | i18n("Ksshaskpass"), | ||
104 | QStringLiteral(PROJECT_VERSION), | 260 | QStringLiteral(PROJECT_VERSION), | ||
105 | i18n("KDE version of ssh-askpass"), | 261 | i18n("KDE version of ssh-askpass"), | ||
106 | KAboutLicense::GPL, | 262 | KAboutLicense::GPL, | ||
107 | i18n("(c) 2006 Hans van Leeuwen\n(c) 2008-2010 Armin Berres"), | 263 | i18n("(c) 2006 Hans van Leeuwen\n(c) 2008-2010 Armin Berres\n(c) 2013 Pali Rohár"), | ||
108 | i18n("Ksshaskpass allows you to interactively prompt users for a passphrase for ssh-add"), | 264 | i18n("Ksshaskpass allows you to interactively prompt users for a passphrase for ssh-add"), | ||
109 | QStringLiteral("http://www.kde-apps.org/content/show.php?action=content&content=50971"), | 265 | QStringLiteral("http://www.kde-apps.org/content/show.php?action=content&content=50971"), | ||
110 | QStringLiteral("armin@space-based.de") | 266 | QStringLiteral("armin@space-based.de") | ||
111 | ); | 267 | ); | ||
112 | 268 | | |||
113 | about.addAuthor(i18n("Armin Berres"), i18n("Current author"), QStringLiteral("armin@space-based.de")); | 269 | about.addAuthor(i18n("Armin Berres"), i18n("Current author"), QStringLiteral("armin@space-based.de")); | ||
114 | about.addAuthor(i18n("Hans van Leeuwen"), i18n("Original author"), QStringLiteral("hanz@hanz.nl")); | 270 | about.addAuthor(i18n("Hans van Leeuwen"), i18n("Original author"), QStringLiteral("hanz@hanz.nl")); | ||
271 | about.addAuthor(i18n("Pali Rohár"), i18n("Contributor"), QStringLiteral("pali.rohar@gmail.com")); | ||||
115 | about.addAuthor(i18n("Armin Berres"), i18n("Current author"), QStringLiteral("armin@space-based.de"), QString()); | 272 | about.addAuthor(i18n("Armin Berres"), i18n("Current author"), QStringLiteral("armin@space-based.de"), QString()); | ||
116 | about.addAuthor(i18n("Hans van Leeuwen"), i18n("Original author"), QStringLiteral("hanz@hanz.nl"), QString()); | 273 | about.addAuthor(i18n("Hans van Leeuwen"), i18n("Original author"), QStringLiteral("hanz@hanz.nl"), QString()); | ||
274 | about.addAuthor(i18n("Pali Rohár"), i18n("Contributor"), QStringLiteral("pali.rohar@gmail.com"), QString()); | ||||
117 | KAboutData::setApplicationData(about); | 275 | KAboutData::setApplicationData(about); | ||
118 | 276 | | |||
119 | QCommandLineParser parser; | 277 | QCommandLineParser parser; | ||
120 | about.setupCommandLine(&parser); | 278 | about.setupCommandLine(&parser); | ||
121 | parser.addOption(QCommandLineOption(QStringList() << QStringLiteral("+[prompt]"), i18nc("Name of a prompt for a password", "Prompt"))); | 279 | parser.addOption(QCommandLineOption(QStringList() << QStringLiteral("+[prompt]"), i18nc("Name of a prompt for a password", "Prompt"))); | ||
122 | 280 | | |||
123 | parser.process(app); | 281 | parser.process(app); | ||
124 | about.processCommandLine(&parser); | 282 | about.processCommandLine(&parser); | ||
125 | 283 | | |||
126 | const QString walletFolder = app.applicationName(); | 284 | const QString walletFolder = app.applicationName(); | ||
127 | QString dialog = i18n("Please enter passphrase"); // Default dialog text. | 285 | QString dialog = i18n("Please enter passphrase"); // Default dialog text. | ||
128 | QString keyFile; | 286 | QString identifier; | ||
129 | QString password; | 287 | QString item; | ||
130 | bool wrongPassphrase = false; | 288 | bool ignoreWallet = false; | ||
289 | enum Type type = TypePassword; | ||||
131 | 290 | | |||
132 | // Parse commandline arguments | 291 | // Parse commandline arguments | ||
133 | if (!parser.positionalArguments().isEmpty()) { | 292 | if (!parser.positionalArguments().isEmpty()) { | ||
134 | dialog = parser.positionalArguments().at(0); | 293 | dialog = parser.positionalArguments().at(0); | ||
135 | parsePrompt(dialog, keyFile, wrongPassphrase); | 294 | parsePrompt(dialog, identifier, ignoreWallet, type); | ||
136 | } | 295 | } | ||
137 | 296 | | |||
138 | // Open KWallet to see if a password was previously stored | 297 | // Open KWallet to see if an item was previously stored | ||
139 | WId winId = QApplication::desktop()->winId(); | 298 | WId winId = QApplication::desktop()->winId(); | ||
140 | std::auto_ptr<KWallet::Wallet> wallet(KWallet::Wallet::openWallet(KWallet::Wallet::NetworkWallet(), winId)); | 299 | std::auto_ptr<KWallet::Wallet> wallet(ignoreWallet ? 0 : KWallet::Wallet::openWallet(KWallet::Wallet::NetworkWallet(), winId)); | ||
141 | 300 | | |||
142 | if ((!wrongPassphrase) && (!keyFile.isNull()) && wallet.get() && wallet->hasFolder(walletFolder)) { | 301 | if ((!ignoreWallet) && (!identifier.isNull()) && wallet.get() && wallet->hasFolder(walletFolder)) { | ||
143 | wallet->setFolder(walletFolder); | 302 | wallet->setFolder(walletFolder); | ||
144 | 303 | | |||
145 | QString retrievedPass; | 304 | QString retrievedItem; | ||
146 | wallet->readPassword(keyFile, retrievedPass); | 305 | if (type != TypePassword) { | ||
147 | 306 | QByteArray retrievedBytes; | |||
148 | if (!retrievedPass.isEmpty()) { | 307 | wallet->readEntry(identifier, retrievedBytes); | ||
149 | password = retrievedPass; | 308 | retrievedItem = QString::fromUtf8(retrievedBytes); | ||
150 | } else { | 309 | } else { | ||
310 | wallet->readPassword(identifier, retrievedItem); | ||||
311 | } | ||||
312 | | ||||
313 | if (!retrievedItem.isEmpty()) { | ||||
314 | item = retrievedItem; | ||||
315 | } else if (type == TypePassword) { | ||||
151 | // There was a bug in previous versions of ksshaskpass that caused it to create keys with extra space | 316 | // There was a bug in previous versions of ksshaskpass that caused it to create keys with extra space | ||
152 | // appended to key file name. Try these keys too, and, if there's a match, ensure that it's properly | 317 | // appended to key file name. Try these keys too, and, if there's a match, ensure that it's properly | ||
153 | // replaced with proper one. | 318 | // replaced with proper one. | ||
154 | const QString keyFile2 = keyFile + QLatin1Char(' '); | 319 | const QString keyFile = identifier + QLatin1Char(' '); | ||
155 | wallet->readPassword(keyFile2, retrievedPass); | 320 | wallet->readPassword(keyFile, retrievedItem); | ||
156 | if (!retrievedPass.isEmpty()) { | 321 | if (!retrievedItem.isEmpty()) { | ||
157 | qCWarning(LOG_KSSHASKPASS) << "Detected legacy key for " << keyFile << ", enabling workaround"; | 322 | qCWarning(LOG_KSSHASKPASS) << "Detected legacy key for " << identifier << ", enabling workaround"; | ||
158 | password = retrievedPass; | 323 | item = retrievedItem; | ||
159 | wallet->renameEntry(keyFile2, keyFile); | 324 | wallet->renameEntry(keyFile, identifier); | ||
325 | } | ||||
160 | } | 326 | } | ||
161 | } | 327 | } | ||
328 | | ||||
329 | if (!item.isEmpty()) { | ||||
330 | QTextStream(stdout) << item; | ||||
Can you replace this if with if (!item.isEmpty()) { QTextStream(stdout) << item; return 0; } That way there's one layer of indentation less on the following code. fvogt: Can you replace this if with
```
if (!item.isEmpty()) {
QTextStream(stdout) << item… | |||||
331 | return 0; | ||||
Please use switch(type) { case TypeConfirm: { ...} ... } instead of an if..else if..else chain. fvogt: Please use `switch(type) { case TypeConfirm: { ...} ... }` instead of an if..else if..else… | |||||
162 | } | 332 | } | ||
163 | 333 | | |||
164 | // Password could not be retrieved from wallet. Open password dialog | 334 | // Item could not be retrieved from wallet. Open dialog | ||
165 | if (password.isEmpty()) { | 335 | switch (type) { | ||
336 | case TypeConfirm: { | ||||
337 | if (KMessageBox::questionYesNo(0, dialog, i18n("Ksshaskpass")) != KMessageBox::Yes) { | ||||
338 | // dialog has been canceled | ||||
339 | return 1; | ||||
340 | } | ||||
341 | item = QStringLiteral("yes\n"); | ||||
342 | break; | ||||
343 | } | ||||
344 | case TypeClearText: { | ||||
345 | bool ok = false; | ||||
346 | item = QInputDialog::getText(0, i18n("Ksshaskpass"), dialog, QLineEdit::Normal, QString(), &ok); | ||||
347 | if (!ok) { | ||||
348 | // dialog has been canceled | ||||
349 | return 1; | ||||
350 | } | ||||
351 | break; | ||||
352 | } | ||||
353 | case TypePassword: { | ||||
166 | // create the password dialog, but only show "Enable Keep" button, if the wallet is open | 354 | // create the password dialog, but only show "Enable Keep" button, if the wallet is open | ||
167 | KPasswordDialog::KPasswordDialogFlag flag(KPasswordDialog::NoFlags); | 355 | KPasswordDialog::KPasswordDialogFlag flag(KPasswordDialog::NoFlags); | ||
168 | if (wallet.get()) { | 356 | if (wallet.get()) { | ||
169 | flag = KPasswordDialog::ShowKeepPassword; | 357 | flag = KPasswordDialog::ShowKeepPassword; | ||
170 | } | 358 | } | ||
171 | QPointer<KPasswordDialog> kpd = new KPasswordDialog(nullptr, flag); | 359 | QPointer<KPasswordDialog> kpd = new KPasswordDialog(nullptr, flag); | ||
172 | 360 | | |||
173 | kpd->setPrompt(dialog); | 361 | kpd->setPrompt(dialog); | ||
174 | kpd->setWindowTitle(i18n("Ksshaskpass")); | 362 | kpd->setWindowTitle(i18n("Ksshaskpass")); | ||
175 | // We don't want to dump core when the password dialog is shown, because it could contain the entered password. | 363 | // We don't want to dump core when the password dialog is shown, because it could contain the entered password. | ||
176 | // KPasswordDialog::disableCoreDumps() seems to be gone in KDE 4 -- do it manually | 364 | // KPasswordDialog::disableCoreDumps() seems to be gone in KDE 4 -- do it manually | ||
177 | struct rlimit rlim; | 365 | struct rlimit rlim; | ||
178 | rlim.rlim_cur = rlim.rlim_max = 0; | 366 | rlim.rlim_cur = rlim.rlim_max = 0; | ||
179 | setrlimit(RLIMIT_CORE, &rlim); | 367 | setrlimit(RLIMIT_CORE, &rlim); | ||
180 | 368 | | |||
181 | if (kpd->exec() == QDialog::Accepted) { | 369 | if (kpd->exec() == QDialog::Accepted) { | ||
182 | password = kpd->password(); | 370 | item = kpd->password(); | ||
183 | // If "Enable Keep" is enabled, open/create a folder in KWallet and store the password. | 371 | // If "Enable Keep" is enabled, open/create a folder in KWallet and store the password. | ||
184 | if ((!keyFile.isNull()) && wallet.get() && kpd->keepPassword()) { | 372 | if ((!identifier.isNull()) && wallet.get() && kpd->keepPassword()) { | ||
185 | if (!wallet->hasFolder(walletFolder)) { | 373 | if (!wallet->hasFolder(walletFolder)) { | ||
186 | wallet->createFolder(walletFolder); | 374 | wallet->createFolder(walletFolder); | ||
187 | } | 375 | } | ||
188 | wallet->setFolder(walletFolder); | 376 | wallet->setFolder(walletFolder); | ||
189 | wallet->writePassword(keyFile, password); | 377 | wallet->writePassword(identifier, item); | ||
190 | } | 378 | } | ||
191 | } else { | 379 | } else { | ||
192 | // dialog has been canceled | 380 | // dialog has been canceled | ||
193 | return 1; | 381 | return 1; | ||
194 | } | 382 | } | ||
383 | break; | ||||
384 | } | ||||
195 | } | 385 | } | ||
196 | 386 | | |||
197 | QTextStream out(stdout); | 387 | QTextStream out(stdout); | ||
198 | out << password << "\n"; | 388 | out << item << "\n"; | ||
199 | return 0; | 389 | return 0; | ||
200 | } | 390 | } | ||
201 | 391 | |
I'd prefer an enum instead of two booleans.