Warning, file /utilities/kgpg/transactions/kgpgtransaction.h was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).
0001 /* 0002 SPDX-FileCopyrightText: 2008-2022 Rolf Eike Beer <kde@opensource.sf-tec.de> 0003 SPDX-License-Identifier: GPL-2.0-or-later 0004 */ 0005 0006 #ifndef KGPGTRANSACTION_H 0007 #define KGPGTRANSACTION_H 0008 0009 #include <QObject> 0010 #include <QString> 0011 #include <QStringList> 0012 0013 class GPGProc; 0014 class KGpgSignTransactionHelper; 0015 class KGpgTransactionPrivate; 0016 class QByteArray; 0017 class QUrl; 0018 0019 /** 0020 * @brief Process one GnuPG operation 0021 * 0022 * This class encapsulates one GnuPG operation. It will care for all 0023 * interaction with the gpg process. Everything you have to care about 0024 * is to set up the object properly, call start() and catch the done signal. 0025 * 0026 * This is an abstract base class for specific operations that implements 0027 * the basic I/O loop, the process setup and interaction and some convenience 0028 * members to set extra arguments for the process. 0029 * 0030 * If you want to add a new operation create a child class that implements 0031 * nextLine(). Usually you also need a constructor that takes some information 0032 * like the id of the key to modify. 0033 * 0034 * @author Rolf Eike Beer 0035 */ 0036 class KGpgTransaction: public QObject { 0037 Q_OBJECT 0038 0039 friend class KGpgTransactionPrivate; 0040 friend class KGpgSignTransactionHelper; 0041 0042 Q_DISABLE_COPY(KGpgTransaction) 0043 0044 public: 0045 /** 0046 * @brief return codes common to many transactions 0047 * 0048 * Every transaction may define additional return codes, which 0049 * should start at TS_COMMON_END + 1. 0050 */ 0051 enum ts_transaction { 0052 TS_OK = 0, ///< everything went fine 0053 TS_BAD_PASSPHRASE = 1, ///< the passphrase was not correct 0054 TS_MSG_SEQUENCE = 2, ///< unexpected sequence of GnuPG messages 0055 TS_USER_ABORTED = 3, ///< the user aborted the transaction 0056 TS_INVALID_EMAIL = 4, ///< the given email address is invalid 0057 TS_INPUT_PROCESS_ERROR = 5, ///< the connected input process returned an error 0058 TS_COMMON_END = 100 ///< placeholder for return values of derived classes 0059 }; 0060 /** 0061 * @brief result codes for GnuPG boolean questions 0062 * 0063 * These are the possible answers to a boolean question of a GnuPG process. 0064 */ 0065 enum ts_boolanswer { 0066 BA_UNKNOWN = 0, ///< the question is not supported (this is an error) 0067 BA_YES = 1, ///< answer "YES" 0068 BA_NO = 2 ///< answer "NO" 0069 }; 0070 /** 0071 * @brief the known hints sent by GnuPG 0072 */ 0073 enum ts_hintType { 0074 HT_KEYEXPIRED, ///< key is expired 0075 HT_SIGEXPIRED, ///< deprecated by GnuPG 0076 HT_NOSECKEY, ///< secret key not available 0077 HT_ENCTO, ///< message is encrypted for this key 0078 HT_PINENTRY_LAUNCHED ///< pinentry was launched 0079 }; 0080 0081 /** 0082 * @brief KGpgTransaction constructor 0083 */ 0084 explicit KGpgTransaction(QObject *parent = nullptr, const bool allowChaining = false); 0085 /** 0086 * @brief KGpgTransaction destructor 0087 */ 0088 ~KGpgTransaction() override; 0089 0090 /** 0091 * @brief Start the operation. 0092 */ 0093 void start(); 0094 0095 /** 0096 * @brief sets the home directory of GnuPG called for this transaction 0097 */ 0098 void setGnuPGHome(const QString &home); 0099 0100 /** 0101 * @brief blocks until the transaction is complete 0102 * @return the result of the transaction like done() would 0103 * @retval TS_USER_ABORTED the timeout expired 0104 * 0105 * If this transaction has another transaction set as input then 0106 * it would wait for those transaction to finish first. The msecs 0107 * argument is used as limit for both transactions then so you 0108 * can end up waiting twice the given time (or longer if you have 0109 * more transactions chained). 0110 */ 0111 int waitForFinished(const int msecs = -1); 0112 0113 /** 0114 * @brief return description of this transaction 0115 * @return string used to describe what's going on 0116 * 0117 * This is especially useful when using this transaction from a KJob. 0118 */ 0119 const QString &getDescription() const; 0120 0121 /** 0122 * @brief connect the standard input of this transaction to another process 0123 * 0124 * Once the input process is connected this transaction will not emit 0125 * the done signal until the input process sends the done signal. 0126 * 0127 * The basic idea is that when an input transaction is set you only need 0128 * to care about this transaction. The other transaction is automatically 0129 * started when this one is started and is destroyed when this one is. 0130 */ 0131 void setInputTransaction(KGpgTransaction *ta); 0132 0133 /** 0134 * @brief tell the process the standard input is no longer connected 0135 * 0136 * If you had connected an input process you need to tell the transaction 0137 * once this input process is gone. Otherwise you will not get a done 0138 * signal from this transaction as it will wait for the finished signal 0139 * from the process that will never come. 0140 */ 0141 void clearInputTransaction(); 0142 0143 /** 0144 * @brief check if another transaction will sent input to this 0145 */ 0146 bool hasInputTransaction() const; 0147 0148 /** 0149 * @brief abort this operation as soon as possible 0150 */ 0151 void kill(); 0152 0153 /** 0154 * @brief add a command line argument to gpg process 0155 * @param arg new argument 0156 * @returns the position of the new argument 0157 * 0158 * This is a convenience function that allows adding one additional 0159 * argument to the command line of the process. This must be called 0160 * before start() is called. Usually you will call this from your 0161 * constructor. 0162 */ 0163 int addArgument(const QString &arg); 0164 /** 0165 * @brief insert an argument at the given position 0166 * @param pos position to insert at 0167 * @param arg new argument 0168 */ 0169 void insertArgument(const int pos, const QString &arg); 0170 /** 0171 * @brief insert arguments at the given position 0172 * @param pos position to insert at 0173 * @param args new arguments 0174 */ 0175 void insertArguments(const int pos, const QStringList &args); 0176 0177 Q_SIGNALS: 0178 /** 0179 * @brief Emitted when the operation was completed. 0180 * @param result return status of the transaction 0181 * 0182 * @see ts_transaction for the common status codes. Each transaction 0183 * may define additional status codes. 0184 */ 0185 void done(int result); 0186 0187 /** 0188 * @brief emits textual status information 0189 * @param msg the status message 0190 */ 0191 void statusMessage(const QString &msg); 0192 0193 /** 0194 * @brief emits procentual status information 0195 * @param processedAmount how much of the job is done 0196 * @param totalAmount how much needs to be done to complete this job 0197 */ 0198 void infoProgress(qulonglong processedAmount, qulonglong totalAmount); 0199 0200 protected: 0201 /** 0202 * @brief Called before the gpg process is started. 0203 * @return true if the process should be started 0204 * 0205 * You may reimplement this member if you need to do some special 0206 * operations before the process is started. The command line of the 0207 * process may be modified for the last time here. 0208 * 0209 * When you notice that some values passed are invalid or the 0210 * transaction does not need to be run for some other reason you should 0211 * call setSuccess() to set the return value and return false. In this 0212 * case the process is not started but the value is immediately 0213 * returned. 0214 */ 0215 virtual bool preStart(); 0216 /** 0217 * @brief Called when the gpg process is up and running. 0218 * 0219 * This functions is connected to the started() signal of the gpg process. 0220 */ 0221 virtual void postStart(); 0222 /** 0223 * @brief Called for every line the gpg process writes. 0224 * @param line the input from the process 0225 * @return true if "quit" should be sent to process 0226 * 0227 * You need to implement this member to get a usable subclass. 0228 * 0229 * When this function returns true "quit" is written to the process. 0230 */ 0231 virtual bool nextLine(const QString &line) = 0; 0232 /** 0233 * @brief Called for every boolean question GnuPG answers 0234 * @param line the question GnuPG asked 0235 * @return what to answer GnuPG 0236 * 0237 * This is called instead of nextLine() if the line contains a boolean 0238 * question. Returning BA_UNKNOWN will cancel the current transaction 0239 * and will set the transaction result to TS_MSG_SEQUENCE. 0240 * 0241 * The default implementation will answer BA_UNKNOWN to every question. 0242 */ 0243 virtual ts_boolanswer boolQuestion(const QString &line); 0244 0245 /** 0246 * @brief called when GnuPG asks for confirmation for overwriting a file 0247 * @param currentFile fill in the current filename for the user dialog 0248 * @return what to answer to GnuPG 0249 * @retval BA_YES file will be overwritten, @p currentFile is ignored 0250 * @retval BA_NO file will not be overwritten, if @p currentFile is given this will automatically be provided as alternative to GnuPG 0251 * @retval BA_UNKNOWN ask the user for a choice or abort, @p currentFile is provided to the user as a hint about the original filename, if @p currentFile is empty the transaction is aborted 0252 * 0253 * The default implementation will just return BA_UNKNOWN without setting 0254 * a filename, causing a sequence error. 0255 */ 0256 virtual ts_boolanswer confirmOverwrite(QUrl ¤tFile); 0257 0258 /** 0259 * @brief Called for a set of hint messages 0260 * 0261 * @param hint the hint type given by GnuPG 0262 * @param args the arguments given to the hint 0263 * @return if the hint was parsed correctly 0264 * @retval true everything is fine 0265 * @retval false something went wrong (e.g. syntax error) 0266 * 0267 * The default implementation will do nothing but checking for some 0268 * argument counts. Override this and handle all interesting hints 0269 * yourself. Don't forget to call the default implementation at the end. 0270 */ 0271 virtual bool hintLine(const ts_hintType hint, const QString &args); 0272 /** 0273 * @brief Called when the gpg process finishes. 0274 * 0275 * You may reimplement this member if you need to do some special 0276 * operations after process completion. The provided one simply 0277 * does nothing which should be enough for most cases. 0278 */ 0279 virtual void finish(); 0280 /** 0281 * @brief called when the user entered a new passphrase 0282 * 0283 * This is called after askNewPassphrase() was called, the user has 0284 * entered a new passphrase and it was sent to the GnuPG process. 0285 * 0286 * The default implementation does nothing. 0287 */ 0288 virtual void newPassphraseEntered(); 0289 /** 0290 * @brief set the description returned in getDescription() 0291 * @param description the new description of this transaction 0292 */ 0293 void setDescription(const QString &description); 0294 0295 /** 0296 * @brief wait until the input transaction has finished 0297 */ 0298 void waitForInputTransaction(); 0299 0300 /** 0301 * @brief notify of an unexpected line 0302 * 0303 * This will print out the line to the console to ease debugging. 0304 */ 0305 void unexpectedLine(const QString &line); 0306 0307 /** 0308 * @brief called when GnuPG asks for a passphrase 0309 * @return if the processing should continue 0310 * @retval true processing should continue 0311 * @retval false an error occurred, transaction should be aborted 0312 * 0313 * This allows a transaction to implement special handling for 0314 * passphrases, e.g. when both old and new passphrase must be 0315 * requested when changing it. The default implementation will just 0316 * call askPassphrase(). 0317 */ 0318 virtual bool passphraseRequested(); 0319 0320 /** 0321 * @brief called when GnuPG accepted the passphrase 0322 * @return if the input channel to GnuPG should be closed 0323 * @retval true close the input channel of the GnuPG process 0324 * @retval false keep the GnuPG input channel open 0325 * 0326 * This allows a transaction to handle passphrase success in a 0327 * special way. The default implementation will just return true. 0328 */ 0329 virtual bool passphraseReceived(); 0330 0331 private: 0332 KGpgTransactionPrivate* const d; 0333 0334 protected: 0335 /** 0336 * @brief Ask user for passphrase and send it to gpg process. 0337 * 0338 * If the gpg process asks for a new passphrase this function will do 0339 * all necessary steps for you: ask the user for the passphrase and write 0340 * it to the gpg process. If the passphrase is wrong the user is prompted 0341 * again for the correct passphrase. If the user aborts the passphrase 0342 * entry the gpg process will be killed and the transaction result will 0343 * be set to TS_USER_ABORTED. 0344 * 0345 * This is virtual so the tests can provide an alternate implementation. 0346 * 0347 * @see askPassphrase 0348 */ 0349 virtual void askNewPassphrase(const QString &text); 0350 0351 /** 0352 * @brief get the success value that will be returned with the done signal 0353 */ 0354 int getSuccess() const; 0355 /** 0356 * @brief set the success value that will be returned with the done signal 0357 * @param v the new success value 0358 * 0359 * You should use 0 as success value. Other values can be defined as needed. 0360 */ 0361 void setSuccess(const int v); 0362 0363 /** 0364 * @brief add a userid hint 0365 * @param txt userid description 0366 * 0367 * Before GnuPG asks for a passphrase it usually sends out a hint message 0368 * for which key the passphrase will be needed. There may be several hint 0369 * messages, e.g. if a text was encrypted with multiple keys. 0370 */ 0371 void addIdHint(QString txt); 0372 /** 0373 * @brief get string of all userid hints 0374 * @returns concatenation of all ids previously added with addIdHint(). 0375 */ 0376 QString getIdHints() const; 0377 0378 /** 0379 * @brief get a reference to the gpg process object 0380 * @returns gpg process object 0381 * 0382 * This returns a reference to the gpg process object used internally. 0383 * In case you need to do some special things (e.g. changing the output 0384 * mode) you can modify this object. 0385 * 0386 * Usually you will not need this. 0387 * 0388 * @warning Never free this object! 0389 */ 0390 GPGProc *getProcess(); 0391 /** 0392 * @brief add command line arguments to gpg process 0393 * @param args new arguments 0394 * 0395 * This is a convenience function that allows adding additional 0396 * arguments to the command line of the process. This must be called 0397 * before start() is called. 0398 */ 0399 void addArguments(const QStringList &args); 0400 0401 /** 0402 * @brief replace the argument at the given position 0403 * @param pos position of old argument 0404 * @param arg new argument 0405 */ 0406 void replaceArgument(const int pos, const QString &arg); 0407 /** 0408 * @brief make sure the reference to a specific argument is kept up to date 0409 * @param ref the value where the position is stored 0410 * 0411 * You might want to keep the position of a specific argument to 0412 * later be able to repace it easily. In that case put it into 0413 * this function too so every time someone mofifies the argument 0414 * list (especially by insertArgument() and insertArguments()) 0415 * this reference will be kept up to date. 0416 */ 0417 void addArgumentRef(int *ref); 0418 /** 0419 * @brief write data to standard input of gpg process 0420 * @param a data to write 0421 * @param lf if line feed should be appended to message 0422 * 0423 * Use this function to interact with the gpg process. A carriage 0424 * return is appended to the data automatically. Usually you will 0425 * call this function from nextLine(). 0426 */ 0427 void write(const QByteArray &a, const bool lf = true); 0428 /** 0429 * @brief write data to standard input of gpg process 0430 * @param i data to write 0431 * 0432 * @overload 0433 */ 0434 void write(const int i); 0435 /** 0436 * @brief ask user for passphrase 0437 * @param message message to display to the user. If message is empty 0438 * "Enter passphrase for [UID]" will be used. 0439 * @return true if the authorization was successful 0440 * 0441 * This function handles user authorization for key operations. It will 0442 * take care to display the message asking the user for the passphrase 0443 * and the number of tries left. 0444 */ 0445 bool askPassphrase(const QString &message = QString()); 0446 0447 /** 0448 * @brief set the fingerprints that are expected for this transaction 0449 * 0450 * This will skip any KEY_CONSIDERED messages from GnuPG that contain 0451 * any of the given fingerprints. 0452 */ 0453 void setExpectedFingerprints(const QStringList &fingerprints); 0454 }; 0455 0456 #endif // KGPGTRANSACTION_H