QtPass 2.0.0
Developer documentation
Loading...
Searching...
No Matches
RealPass Class Reference

Implementation of Pass that wraps the 'pass' command-line tool. More...

#include <realpass.h>

Inheritance diagram for RealPass:
Collaboration diagram for RealPass:

Classes

struct  LinkCommit
struct  InsertRecord

Public Member Functions

 RealPass ()
 Construct a RealPass instance.
 ~RealPass () override
 Destructor; lets the search workers wind down.
void GitInit () override
 Initialize Git repository in password store.
void GitPull () override
 Pull changes from remote.
void GitPull_b () override
 Pull with rebase.
void GitPush () override
 Push changes to remote.
void Show (QString file) override
 Show decrypted password.
void Insert (QString file, QString newValue, bool overwrite) override
 Insert new password.
void Remove (QString file, bool isDir) override
 Remove an entry or folder with pass rm.
void Init (QString path, const QList< UserInfo > &users) override
 Initialize password store.
void Move (const QString src, const QString dest, const bool force) override
 Move password file or directory.
void Copy (const QString src, const QString dest, const bool force) override
 Copy password file or directory.
void Grep (QString pattern, bool caseInsensitive) override
 Search all password content by GPG-decrypting each real .gpg file, as ImitatePass does.
Public Member Functions inherited from Pass
 Pass ()
 Construct a Pass instance.
void init (const AppSettings &settings)
 Initialize the Pass instance with a settings snapshot.
auto insertsPending () const -> int
 How many inserts have started queueing but not yet reported.
virtual auto generatePassword (unsigned int length, const QString &charset) -> QString
 Generate random password.
void GenerateGPGKeys (QString batch)
 Generate GPG keys using batch script.
auto listKeys (QStringList keystrings, bool secret=false) -> QList< UserInfo >
 List GPG keys matching patterns.
auto listKeys (const QString &keystring="", bool secret=false) -> QList< UserInfo >
 List GPG keys.
void updateEnv ()
 Update environment for subprocesses.
auto recipientsForEditing (const QString &dir, const QString &passStore) -> RecipientsForEditing
 The recipients a dialog may preselect for editing the list of dir.
auto isIdle () const -> bool
 Whether no gpg, git or pass of this backend runs or waits.

Protected Member Functions

void finished (int id, int exitCode, const QString &out, const QString &err) override
 Finish a process; a linked-folder removal commit (GIT_COMMIT, which RealPass uses for nothing else) is judged by finishLinkCommit().
Protected Member Functions inherited from Pass
auto storeEnvironment () const -> QProcessEnvironment
 The environment QtPass runs the store's processes in.
auto withCurrentGitPin (QProcessEnvironment base) const -> QProcessEnvironment
 base with GIT_DIR and GIT_WORK_TREE as the store is now (Util::gitStoreVariables()), not as it was at updateEnv(): a .git that appeared or changed hands since then is judged when Git runs.
auto refuseSkippedGpgId (const QString &file, bool signing, const QString &except=QString()) -> bool
 With signing on, refuse to encrypt file when the lookup passed over its folder's own list (skippedGpgId()): the parent's list is not what was signed for it.
auto verifySignedList (const GpgIdSigner &signer, const QString &gpgIdFile, QByteArray *contents, QString *why) const -> bool
 Whether gpgIdFile is a signed list QtPass accepts: its signature verifies (GpgIdSigner::verifyFile()), and it is current and bound to the folder it lies in (GpgIdGeneration::accept()), so an older authentic list put back, or one signed for another folder, is refused.
void queueShow (const QString &file)
 Remember what a Show() asked for, so its completion can say so.
void queueInsert ()
 Count one insert that has started queueing but not yet reported.
auto refuseLinkedPath (const QString &path, LinkScope scope=LinkScope::EntryAndParents, PathSpelling spelling=PathSpelling::Configured) -> bool
 Refuse an operation on something that is, or lies behind, a symbolic link or NTFS junction inside the store.
auto refuseFolderOutsideStore (const QString &folder, QString *relative=nullptr) -> bool
 Refuse recipients for a folder outside the store, as pass refuses a path with .. in it.
auto refuseUnfinishedGitOperation () -> bool
 Refuse to change the store while git is mid-rebase, -merge, -cherry-pick or -revert.
auto unfinishedGitOperationReason () -> QString
 The unfinished git operation in progress in the store, if any.
auto refusePendingPull () -> bool
 Refuse a store change while a Git pull is still queued or running.
void executeWrapper (PROCESS id, const QString &app, const QStringList &args, bool readStdout=true, bool readStderr=true)
 Execute external wrapper command.
auto generateRandomPassword (const QString &charset, unsigned int length) -> QString
 Generate random password from charset.
auto boundedRandom (quint32 bound) -> quint32
 Generate random number in range.
void setEnvVar (const QString &name, const QString &value)
 Set or remove an environment variable.
void executeWrapper (PROCESS id, const QString &app, const QStringList &args, QString input, bool readStdout, bool readStderr)
 Execute wrapper with input.
virtual void beforeExecute (PROCESS id)
 Hook invoked just before a wrapped command is dispatched.

Private Member Functions

void finishLinkCommit (const LinkCommit &commit, const QString &out, const QString &err)
 Judge a queued linked-folder removal commit by what is left staged in the store it ran in: pass git exits 0 whatever git did.
void executePass (PROCESS id, const QStringList &args, QString input=QString(), bool readStdout=true, bool readStderr=true)
 Execute pass command with arguments.
void passMoveOrCopy (PROCESS id, const QString &subcommand, const QString &src, const QString &dest, bool force)
 Shared implementation of Move and Copy via pass mv/pass cp.
auto passName (const QString &path, bool stripGpg) const -> QString
 path as pass names it: relative to the store, without the .gpg pass appends itself.
auto insertWritten (const QString &err) const -> bool override
 Whether the failed pass insert wrote its entry before its git step failed. pass does not say, so: the entry's bytes differ from what they were when that insert started to run (a new entry appeared, or an existing one was rewritten), and pass did not say that the encryption broke off (gpg can leave a partial file behind then).
auto refuseUnverifiedList (const QString &file) -> bool
 With signing on, refuse to have pass encrypt file when the signed list it would use is not one QtPass accepts: its folder's own list was passed over, the signature does not verify, or the list is older than one this device accepted or signed for another folder.
auto storeGit (const QStringList &args, QString *out) -> bool override
 Run a git command in the store through pass git, blocking.
auto refuseUnverifiedTree (const QString &dir, bool onlyListsWithin, const QString &except=QString()) -> bool
 For a folder pass is about to re-encrypt in a move or copy: refuse when the signed list of one of its entries (every one pass's walk takes, hidden ones included) is not one QtPass accepts where it lies now (as refuseUnverifiedList()).
auto listSigner () -> GpgIdSigner
 The verifier for signed lists, gpg in the store's environment.
auto refuseList (const QString &file, const GpgIdSigner &signer, QSet< QString > &verified, const QString &within=QString(), const QString &except=QString()) -> bool
 The checks of refuseUnverifiedList() for file's nearest list, once per list.
void onDequeuing (int id, bool completes)
 The executor is about to run (or drop) its next item: for an insert, take its entry from m_insertQueue and fingerprint it now, not when it was queued, so an earlier queued save of the same entry counts as "before". Kept in m_insertPending for that insert's own completion.

Static Private Member Functions

static auto entryFingerprint (const QString &path) -> QByteArray
 A SHA-256 of the regular file path (opened without following a link or blocking on a FIFO).

Private Attributes

NativeGrep m_grep
QQueue< LinkCommit > m_linkCommits
QQueue< QString > m_insertQueue
 The entries of the queued inserts, oldest first.
QQueue< InsertRecord > m_insertPending
InsertRecord m_insertDone
 The insert whose completion is being handled.

Additional Inherited Members

Signals inherited from Pass
void idle ()
 Nothing of the store's runs or waits any more (isIdle()).
void startingExecuteWrapper ()
 Emitted each time a queued process is about to start, and by the refusals that go on to emit processErrorExit().
void statusMsg (const QString &msg, int timeout)
 Progress or a non-fatal problem worth a line in the status bar ("Creating backup commit", "Git pull failed: ...").
void critical (const QString &title, const QString &message)
 Something went wrong that the user has to be told about in a dialog, such as a refused path or a failed backup commit.
void processErrorExit (int exitCode, const QString &err)
 An operation ended in failure: its process exited non-zero, could not be started or crashed, or the operation was refused.
void finishedAnyWithPid (const QString &out, const QString &err, Enums::PROCESS pid)
 A process of any kind finished successfully and its output cannot contain a secret.
void finishedGitInit (const QString &out, const QString &err)
 git init in the store succeeded; the store is a repository now and the tree is re-read.
void finishedGitPull (const QString &out, const QString &err)
 git pull succeeded; entries may have changed on disk.
void finishedGitPush (const QString &out, const QString &err)
 git push succeeded.
void finishedShow (const QString &out, const QString &file)
 Emitted when a Show() succeeds.
void finishedInsert (const QString &out, const QString &err)
 An Insert() succeeded: the entry is in the store and, with Git in use, committed.
void finishedRemove (const QString &out, const QString &err)
 A Remove() succeeded; the entry or folder is gone from the store.
void finishedInit (const QString &out, const QString &err)
 An Init() succeeded: the folder's .gpg-id holds the new recipient list.
void finishedMove (const QString &out, const QString &err)
 A Move() succeeded; the entry or folder is under its new name.
void finishedCopy (const QString &out, const QString &err)
 A Copy() succeeded; the copy exists beside the original.
void finishedGenerateGPGKeys (const QString &out, const QString &err)
 GenerateGPGKeys() succeeded; the new key pair is in the keyring.
void generateGPGKeysFailed (const QString &err)
 Emitted when GPG key generation fails, alongside the generic processErrorExit(); lets the keygen dialog react to its own failure only, not to any other command failing meanwhile.
void insertFailed (const QString &err, bool written)
 Emitted when an Insert() fails through a queued command, before the generic processErrorExit(): the process exited non-zero, crashed or could not be started, or the entry could not be put in place afterwards. Lets the password dialog keep what was typed and say why, without reacting to any other command failing meanwhile. An insert refused before anything is queued does not emit it.
void finishedGrep (const QList< QPair< QString, QStringList > > &results)
 The newest Grep() is over; an empty list means no entry matched.
Static Public Member Functions inherited from Pass
static bool gpgSupportsEd25519 (const QString &gpgExecutable={})
 Check if GPG supports Ed25519 encryption.
static QString getDefaultKeyTemplate (const QString &gpgExecutable={})
 Get default key template for new GPG keys.
static auto maxOutputArgs () -> QStringList
 The gpg options that enforce kMaxPlaintextBytes.
static auto resolveGpgconfCommand (const QString &gpgPath) -> ResolvedGpgconfCommand
 Resolve the gpgconf command to kill agents.
static auto getGpgIdPath (const QString &for_file, const QString &passStore) -> QString
 Get .gpg-id file path for a password file.
static auto skippedGpgId (const QString &forFile, const QString &passStore, QString *recordError=nullptr) -> std::optional< QString >
 The folder list getGpgIdPath() passed over on its way up to the one it returns, if it passed one over that a signed store must not.
static auto getRecipientList (const QString &for_file, const QString &passStore) -> QStringList
 Get list of recipients for a password file.
static auto parseRecipients (const QByteArray &contents, const QString &sourceName) -> QStringList
 Parse the contents of a .gpg-id: one recipient per line, # starts a comment, unusable lines are logged and skipped.
static auto loggableArgs (const QStringList &args) -> QStringList
 The arguments as they may appear in the debug log: the value of --passphrase and friends, and otpauth URIs, are replaced.
static auto seedGpgIdFile (const QString &newDir, const QString &passStore) -> bool
 Seed a new folder's .gpg-id from the recipients it inherits.
Static Public Attributes inherited from Pass
static constexpr qint64 kMaxPlaintextBytes = 64LL * 1024 * 1024
 Most bytes of plaintext a gpg decryption may produce.
Protected Types inherited from Pass
enum class  LinkScope { EntryAndParents , ParentsOnly }
 What refuseLinkedPath() judges. More...
enum class  PathSpelling { Configured , PlacedByCaller }
 How a path handed to refuseLinkedPath() is spelled. More...
using PROCESS = Enums::PROCESS
 Alias for Enums::PROCESS used throughout this class.
Protected Attributes inherited from Pass
AppSettings m_settings
 Application settings snapshot injected at init() time.
Executor exec
 Internal command executor for queuing and running subprocesses.

Detailed Description

Implementation of Pass that wraps the 'pass' command-line tool.

RealPass delegates all password store operations to the external 'pass' utility. It provides a Qt-native interface while handling:

  • Git integration (init, pull, push)
  • Password CRUD (show, insert, remove, move, copy)
  • OTP generation
  • Store initialization with GPG keys

This is the primary implementation when 'pass' is available on the system.

Definition at line 32 of file realpass.h.

Constructor & Destructor Documentation

◆ RealPass()

RealPass::RealPass ( )

Construct a RealPass instance.

Definition at line 36 of file realpass.cpp.

Here is the call graph for this function:
Here is the caller graph for this function:

◆ ~RealPass()

RealPass::~RealPass ( )
override

Destructor; lets the search workers wind down.

Definition at line 41 of file realpass.cpp.

Here is the call graph for this function:

Member Function Documentation

◆ Copy()

void RealPass::Copy ( const QString src,
const QString dest,
const bool force )
overridevirtual

Copy password file or directory.

Parameters
srcSource path.
destDestination path.
forceOverwrite existing.

Implements Pass.

Definition at line 430 of file realpass.cpp.

Here is the call graph for this function:

◆ entryFingerprint()

auto RealPass::entryFingerprint ( const QString & path) -> QByteArray
staticprivate

A SHA-256 of the regular file path (opened without following a link or blocking on a FIFO).

Parameters
pathThe entry's file.
Returns
The hash; empty when path is no readable regular file.

Definition at line 243 of file realpass.cpp.

Here is the call graph for this function:
Here is the caller graph for this function:

◆ executePass()

void RealPass::executePass ( PROCESS id,
const QStringList & args,
QString input = QString(),
bool readStdout = true,
bool readStderr = true )
private

Execute pass command with arguments.

Parameters
idProcess identifier.
argsCommand arguments.
inputInput to pass to stdin.
readStdoutCapture stdout.
readStderrCapture stderr.

Definition at line 511 of file realpass.cpp.

Here is the call graph for this function:
Here is the caller graph for this function:

◆ finished()

void RealPass::finished ( int id,
int exitCode,
const QString & out,
const QString & err )
overrideprotectedvirtual

Finish a process; a linked-folder removal commit (GIT_COMMIT, which RealPass uses for nothing else) is judged by finishLinkCommit().

Parameters
idProcess identifier.
exitCodeExit code.
outStandard output.
errStandard error.

Reimplemented from Pass.

Definition at line 334 of file realpass.cpp.

Here is the call graph for this function:

◆ finishLinkCommit()

void RealPass::finishLinkCommit ( const LinkCommit & commit,
const QString & out,
const QString & err )
private

Judge a queued linked-folder removal commit by what is left staged in the store it ran in: pass git exits 0 whatever git did.

Parameters
commitThe folder and the store it was queued for.
outThe commit's standard output.
errThe commit's standard error.

Definition at line 350 of file realpass.cpp.

Here is the call graph for this function:
Here is the caller graph for this function:

◆ GitInit()

void RealPass::GitInit ( )
overridevirtual

Initialize Git repository in password store.

Implements Pass.

Definition at line 43 of file realpass.cpp.

Here is the call graph for this function:

◆ GitPull()

void RealPass::GitPull ( )
overridevirtual

Pull changes from remote.

Implements Pass.

Definition at line 53 of file realpass.cpp.

Here is the call graph for this function:

◆ GitPull_b()

void RealPass::GitPull_b ( )
overridevirtual

Pull with rebase.

Implements Pass.

Definition at line 45 of file realpass.cpp.

Here is the call graph for this function:

◆ GitPush()

void RealPass::GitPush ( )
overridevirtual

Push changes to remote.

Implements Pass.

Definition at line 55 of file realpass.cpp.

Here is the call graph for this function:

◆ Grep()

void RealPass::Grep ( QString pattern,
bool caseInsensitive )
overridevirtual

Search all password content by GPG-decrypting each real .gpg file, as ImitatePass does.

Not pass grep: that enumerates with find -L, which follows a link out of the store and decrypts what it finds there. Same pattern semantics as ImitatePass::Grep (QRegularExpression).

Parameters
patternSearch pattern (QRegularExpression).
caseInsensitivetrue for case-insensitive search.

Implements Pass.

Definition at line 500 of file realpass.cpp.

Here is the call graph for this function:

◆ Init()

void RealPass::Init ( QString path,
const QList< UserInfo > & users )
overridevirtual

Initialize password store.

Parameters
pathStore root path.
usersGPG recipients.

Implements Pass.

Definition at line 377 of file realpass.cpp.

Here is the call graph for this function:

◆ Insert()

void RealPass::Insert ( QString file,
QString newValue,
bool overwrite )
overridevirtual

Insert new password.

Parameters
filePath to password file.
newValuePassword content.
overwritetrue to overwrite existing.

Implements Pass.

Definition at line 190 of file realpass.cpp.

Here is the call graph for this function:

◆ insertWritten()

auto RealPass::insertWritten ( const QString & err) const -> bool
nodiscardoverrideprivatevirtual

Whether the failed pass insert wrote its entry before its git step failed. pass does not say, so: the entry's bytes differ from what they were when that insert started to run (a new entry appeared, or an existing one was rewritten), and pass did not say that the encryption broke off (gpg can leave a partial file behind then).

Parameters
errWhat pass reported on stderr.
Returns
true when the entry was written.

Reimplemented from Pass.

Definition at line 225 of file realpass.cpp.

Here is the call graph for this function:

◆ listSigner()

auto RealPass::listSigner ( ) -> GpgIdSigner
private

The verifier for signed lists, gpg in the store's environment.

Returns
A GpgIdSigner with the configured signing keys.

Definition at line 66 of file realpass.cpp.

Here is the call graph for this function:
Here is the caller graph for this function:

◆ Move()

void RealPass::Move ( const QString src,
const QString dest,
const bool force )
overridevirtual

Move password file or directory.

Parameters
srcSource path.
destDestination path.
forceOverwrite existing.

Implements Pass.

Definition at line 426 of file realpass.cpp.

Here is the call graph for this function:

◆ onDequeuing()

void RealPass::onDequeuing ( int id,
bool completes )
private

The executor is about to run (or drop) its next item: for an insert, take its entry from m_insertQueue and fingerprint it now, not when it was queued, so an earlier queued save of the same entry counts as "before". Kept in m_insertPending for that insert's own completion.

Parameters
idThe item's process id.
completesWhether a completion follows (not for a dropped one).

Definition at line 215 of file realpass.cpp.

Here is the call graph for this function:
Here is the caller graph for this function:

◆ passMoveOrCopy()

void RealPass::passMoveOrCopy ( PROCESS id,
const QString & subcommand,
const QString & src,
const QString & dest,
bool force )
private

Shared implementation of Move and Copy via pass mv/pass cp.

Parameters
idProcess id (PASS_MOVE or PASS_COPY).
subcommandThe pass subcommand, "mv" or "cp".
srcSource path.
destDestination path.
forceOverwrite an existing destination; without it a file-onto-file request is a no-op (pass would otherwise force).

Definition at line 444 of file realpass.cpp.

Here is the call graph for this function:
Here is the caller graph for this function:

◆ passName()

auto RealPass::passName ( const QString & path,
bool stripGpg ) const -> QString
private

path as pass names it: relative to the store, without the .gpg pass appends itself.

Parameters
pathThe file or folder, absolute or relative to the working directory.
stripGpgWhether to drop a trailing .gpg.
Returns
The store-relative name.

Definition at line 434 of file realpass.cpp.

Here is the call graph for this function:
Here is the caller graph for this function:

◆ refuseList()

auto RealPass::refuseList ( const QString & file,
const GpgIdSigner & signer,
QSet< QString > & verified,
const QString & within = QString(),
const QString & except = QString() ) -> bool
private

The checks of refuseUnverifiedList() for file's nearest list, once per list.

Parameters
fileThe entry.
signerThe verifier.
verifiedThe lists already found good; extended.
withinWhen set, only a list under this folder (absolute, cleaned, with a trailing "/") is verified; the skipped-list check applies regardless.
exceptA list about to be written, neither verified nor refused for being missing.
Returns
Whether it was refused (and the user told).

Definition at line 77 of file realpass.cpp.

Here is the call graph for this function:
Here is the caller graph for this function:

◆ refuseUnverifiedList()

auto RealPass::refuseUnverifiedList ( const QString & file) -> bool
private

With signing on, refuse to have pass encrypt file when the signed list it would use is not one QtPass accepts: its folder's own list was passed over, the signature does not verify, or the list is older than one this device accepted or signed for another folder.

Parameters
fileThe entry (or the place a move or copy writes to).
Returns
Whether it was refused (and the user told).

Definition at line 106 of file realpass.cpp.

Here is the call graph for this function:
Here is the caller graph for this function:

◆ refuseUnverifiedTree()

auto RealPass::refuseUnverifiedTree ( const QString & dir,
bool onlyListsWithin,
const QString & except = QString() ) -> bool
private

For a folder pass is about to re-encrypt in a move or copy: refuse when the signed list of one of its entries (every one pass's walk takes, hidden ones included) is not one QtPass accepts where it lies now (as refuseUnverifiedList()).

Parameters
dirThe folder moved or copied, or the existing folder written into. Each of its folders' lists counts, used by an entry yet or not: a copy merges into a folder of the same name, so lists on either side meet the other side's entries.
onlyListsWithinWhether only lists inside dir count: for the folder that moves, whose entries get the destination's list in place of any list above it.
exceptA list about to be written (pass init's own), neither verified nor refused for being missing.
Returns
Whether it was refused (and the user told).

Definition at line 141 of file realpass.cpp.

Here is the call graph for this function:
Here is the caller graph for this function:

◆ Remove()

void RealPass::Remove ( QString file,
bool isDir )
overridevirtual

Remove an entry or folder with pass rm.

A folder that is a link is unlinked here instead, without deleting its target; that removal is committed only when Git is enabled and the tracking lookup and index removal both report success.

Parameters
fileStore-relative entry path, without .gpg for a password file.
isDirtrue to remove a directory; false to remove a password file.

Implements Pass.

Definition at line 255 of file realpass.cpp.

Here is the call graph for this function:

◆ Show()

void RealPass::Show ( QString file)
overridevirtual

Show decrypted password.

Parameters
filePath to password file.

Implements Pass.

Definition at line 57 of file realpass.cpp.

Here is the call graph for this function:

◆ storeGit()

auto RealPass::storeGit ( const QStringList & args,
QString * out ) -> bool
overrideprivatevirtual

Run a git command in the store through pass git, blocking.

Parameters
argsThe git arguments (without git).
outReceives stdout; may be null.
Returns
true when pass git ran and exited 0 (git on).

Reimplemented from Pass.

Definition at line 178 of file realpass.cpp.

Here is the call graph for this function:

Member Data Documentation

◆ m_grep

NativeGrep RealPass::m_grep
private

The store's own search: pass grep runs find -L, which follows a link out of the store and decrypts what it finds there.

Definition at line 35 of file realpass.h.

◆ m_insertDone

InsertRecord RealPass::m_insertDone
private

The insert whose completion is being handled.

Definition at line 193 of file realpass.h.

◆ m_insertPending

QQueue<InsertRecord> RealPass::m_insertPending
private

The inserts that left the queue and have yet to complete, in the order their completions come: a failed start's error is posted, and the next insert may start before it arrives.

Definition at line 191 of file realpass.h.

◆ m_insertQueue

QQueue<QString> RealPass::m_insertQueue
private

The entries of the queued inserts, oldest first.

Definition at line 187 of file realpass.h.

◆ m_linkCommits

QQueue<LinkCommit> RealPass::m_linkCommits
private

Queued linked-folder removal commits (as GIT_COMMIT), oldest first; finished() judges each.

Definition at line 47 of file realpass.h.


The documentation for this class was generated from the following files: