Page MenuHome GnuPG

No OneTemporary

diff --git a/autotests/testenvs/README.md b/autotests/testenvs/README.md
index 98be461..cadfa95 100644
--- a/autotests/testenvs/README.md
+++ b/autotests/testenvs/README.md
@@ -1,198 +1,199 @@
# Testenvs
This folder contains scripts to generate testdata for `gpgpass`
and to setup/start `gpgpass` in various isolated test environments.
The test environments are generated by `reset.sh` in three stages:
1. `./templates/certs.sh`: certs for multiple users with gnupg home folders
2. `./templates/stores.sh`: password stores for users (uses certs)
3. `./templates/envs.sh`: gpgpass testing environments (copies certs/stores/templates)
The certs/stores/envs are generated in `./templates/`.
The generated envs are copied to `./envs` on `reset.sh`.
Requirements:
- `pass` (used to generate store entries)
- `tmux` (optional, used for the start script)
## Usage
1. Setup: `./reset.sh` (initial generation of certs/stores/envs)
2. Testing:
- Start gpgpass:
`./envs/ENV/USER/gpgpass`, e.g.
- `./envs/main/alice/gpgpass`
- `./envs/user/bob/gpgpass`
- `./envs/setup/charlie/gpgpass`
- Load shell environment (to use pass/gpg):
`source ./envs/ENV/USER/store-STORE.sh`, e.g.
- `source ./envs/main/alice/store-team.sh`
- `source ./envs/user/bob/store-user.sh`
- `source ./envs/empty/charlie/store-empty.sh`
- Start gpgpass and all stores in a tmux session
(adds global tmux shortcuts, see below!):
`./start.sh [ENV [USER]]`, e.g.
- `./start.sh` (main, alice)
- `./start.sh team` (alice)
- `./start.sh template bob`
3. Reset:
- `./reset.sh`: reset test data
- `./reset.sh envs`: regenerates envs
- `./reset.sh stores`: regenerates stores/envs
- `./reset.sh certs|all`: regenerates certs/stores/envs
**start.sh**
- Alt+#: switch to window #
- Alt(+Shift)+Tab: switch to next/previous window
- Alt+r: reset the testdata (executes `./reset.sh`, restarts gpgpass)
- Alt+q: kill the session
*Note: for a custom build dir path, set `export GPGPASS_BUILD_DIR=<path>`*
## Environments
**Users (Main Cert)**
- alice: `alice.default.1`
- bob: `bob.default.1`
- charlie: `charlie.default.1`
**Envs**
- main: main test environment with most test cases included (`./envs/main`)
- certs: user
- stores: team, user, empty, template
- configs: shortcuts
- team: multiple users with one shared store (`./envs/team`)
- certs: user
- stores: team
- configs: shortcuts
- user: single user with one user store (`./envs/user`)
- certs: user
- stores: user
- configs: shortcuts
- setup: initial cert setup state with certs but no stores (`./envs/setup`)
- certs: user
- stores: new
- configs: none
- clean: initial cert setup state with no certs/stores (`./envs/clean`)
- certs: empty
- stores: new
- configs: none
- empty: single empty store (`./envs/empty`)
- certs: user
- stores: empty
- configs: shortcuts
- template: custom template preset matching the testdata (`./envs/template`)
- certs: user
- stores: template
- configs: template, shortcuts
**Certs (GnuPG home directories)**
- user: contains user sec/pub certs, other pub certs (`./envs/ENV/USER/gnupg`):
- empty: generated on start (`./tmp/gpgpass/certs/ENV/USER`)
**Cert Types**
- default: valid cert without passphrase (default cert)
- protected: valid cert with passphrase "protected"
- userids: multiple user ids
- unsigned: no userids signed
- somesigned: some userids signed
- revuserids: some userids revoked
- subkeys: subkeys for all usages
- noexpire: no expire date
- expired: expired cert
- revoked: revoked cert
- disabled: disabled cert
- missing: missing cert
- trust-: trust value `undefined`
- trustn: trust value `never`
- trustm: trust value `marginal`
- trustf: trust value `full`
**Stores (Entries)**
- user: private store for a single user (`./envs/ENV/USER/store-user`)
- fields: basic entries in root folder
- empty: empty folders and entries with/without one or multiple newlines, touched files
- chars: folders/entries with special chars, caret, c, utf, binary
+ - sort: folders/entries to test sort order
- urls: tests for the url parser
- long: long words/passwords (also qr code tests), many lines, etc
- tree: tests for width/length of the entry tree
- symlinks: linked folders/files, recursion, outside of store root
- conflict: conflicting folder names (.gpg-id, entry.gpg, etc)
- gpgid: .gpg-id files with different content
- certs: folders encrypted for each user encryption key
- team: shared store for all users (`./envs/ENV/store-team`)
- entry: basic entries in root folder, encrypted for all user main certs
- without: folders for each user excluded
- certs: folders encrypted for each encryption key + all main certs
- template: store with test entries for the template parser (`./envs/ENV/USER/store-template`)
- basic: entry with all key/value pairs defined in template config
- colons: colons and spaces
- long: long key/value
- chars: special chars as keys
- urls: urls as keys
- empty: generated on start (`./tmp/gpgpass/stores/ENV/USER`)
- new: default store path for new stores (`./envs/ENV/USER/store-new`)
**Configs**
- template: custom template (`./templates/files/gpgpassrc-template.txt`)
- shortcuts: custom shortcuts (`./templates/files/gpgpassui.rc-shortcuts.txt`)
- none: no initial config
## Development
**Certs**
- `./templates/certs.sh`: cert generation script, generates `./templates/certs/`
- `./templates/certs/all`: gnupghome with all sec/pub certs in initial valid/trusted/enabled state,
needed to encrypt with revoked/expired/missing/disabled certs, copied to `./envs/ENV/all`
- Exports for convenience
- `./templates/certs/USER/export/USER.TYPE.NUM.*`: all user sec/pub/rev certs
- `./templates/certs/USER/certs.*.txt`: key list
- Can be generated in any folder, e.g. `./templates/certs.sh /tmp/certs`
**Stores**
- `./templates/stores.sh`: store generation script, generates `./templates/stores/`
- Can be generated in any folder, e.g. `./templates/stores.sh /tmp/stores`
**Entries**
- `./templates/entries/STORE/*.sh`: entry generation scripts, generates entries in stores
- To add new entries, just add/adjust a `.sh` script (filename should match the name in the tree)
- During generation the gnupghome folder is set to `./templates/certs/all`
(all certs in usable state)
- `./templates/utils.sh` is sourced in all entry scripts and defines
- reusable dummy content, e.g. `loremipsum`, `longWord`, `longUrl`, etc.
- helper functions for scripting, e.g.
```
getUids
getUids alice
getIds
getIds bob
pubKeyids
pubFprs
pubFprs charlie
pubFpr alice.default.1
subFpr "<keyid>"
encKeyids alice.subkeys
encKeyids alice | getGrip
echo "<fingerprint>" | getName
pubFprs alice | getEmail
```
**Configs**
- `./templates/files/*`: config and start script files copied into the envs
**Envs**
- `./templates/envs.sh`: envs generation script, generates `./templates/envs`
- Can be generated in any folder, e.g. `./templates/envs.sh /tmp/envs`
**Todo**
- scripts
- use getopt (used by pass, too)
- scale args/config (n users, n certs)
- certs
- photo
- smartcard
- ambiguous userid
- symmetric key
- envs
- executables missing (gpg, pass)
- many stores
diff --git a/autotests/testenvs/templates/entries/template/chars.sh b/autotests/testenvs/templates/entries/template/chars.sh
index 8aa7e8c..b3b1c20 100755
--- a/autotests/testenvs/templates/entries/template/chars.sh
+++ b/autotests/testenvs/templates/entries/template/chars.sh
@@ -1,13 +1,13 @@
#!/usr/bin/env bash
# special chars as keys
set -eu
source "$(dirname "$0")/../../utils.sh"
# special chars
set -o noglob
cat <<EOF | pass insert -mf chars > /dev/null
password
-$(for char in $charsBasic; do echo "$char: value"; done)
+$(for char in $charsSpecial; do echo "$char: value"; done)
EOF
set +o noglob
diff --git a/autotests/testenvs/templates/entries/user/chars.sh b/autotests/testenvs/templates/entries/user/chars.sh
index 117597c..a224331 100755
--- a/autotests/testenvs/templates/entries/user/chars.sh
+++ b/autotests/testenvs/templates/entries/user/chars.sh
@@ -1,58 +1,58 @@
#!/usr/bin/env bash
# folders/entries with special chars, caret, c, utf, binary
set -eu
source "$(dirname "$0")/../../utils.sh"
# fields: basic
-cat <<EOF | pass insert -mf chars/basic > /dev/null
-$charsBasic
-login: $charsBasic
-URL: $charsBasic
-$charsBasic
+cat <<EOF | pass insert -mf chars/special > /dev/null
+$charsSpecial
+login: $charsSpecial
+URL: $charsSpecial
+$charsSpecial
EOF
# fields: caret
cat <<EOF | pass insert -mf chars/control_caret > /dev/null
$charsCaret
login: $charsCaret
URL: $charsCaret
$charsCaret
EOF
# fields: c
cat <<EOF | pass insert -mf chars/control_c > /dev/null
$charsC
login: $charsC
URL: $charsC
$charsC
EOF
# fields: utf
cat <<EOF | pass insert -mf chars/control_utf > /dev/null
$charsUtf
login: $charsUtf
URL: $charsUtf
$charsUtf
EOF
# fields: binary
entries=10
for i in $(seq -f "%05g" 1 $entries); do
head /dev/urandom | pass insert -ef "chars/binary/password_$i" > /dev/null
cat <<EOF | pass insert -mf "chars/binary/full_$i" > /dev/null 2>&1
$(head /dev/urandom | tr -d '\0')
login: $(head -c 100 /dev/urandom | tr -d '\0')
URL: $(head -c 100 /dev/urandom | tr -d '\0')
$(head /dev/urandom | tr -d '\0')
EOF
done
# paths: spaces
echo "password" | pass insert -ef "chars/folder with spaces/entry with spaces" > /dev/null
# paths: special chars
-echo "password" | pass insert -ef "chars/paths/${charsBasic//\//}/${charsBasic//\//}" > /dev/null
+echo "password" | pass insert -ef "chars/paths/${charsSpecial//\//}/${charsSpecial//\//}" > /dev/null
echo "password" | pass insert -ef "chars/paths/$charsCaret/$charsCaret" > /dev/null
echo "password" | pass insert -ef "chars/paths/$charsC/$charsC" > /dev/null
echo "password" | pass insert -ef "chars/paths/$charsUtf/$charsUtf" > /dev/null
diff --git a/autotests/testenvs/templates/entries/user/sort.sh b/autotests/testenvs/templates/entries/user/sort.sh
new file mode 100755
index 0000000..c2e8123
--- /dev/null
+++ b/autotests/testenvs/templates/entries/user/sort.sh
@@ -0,0 +1,13 @@
+#!/usr/bin/env bash
+# folders/entries to test sort order
+
+set -eu
+source "$(dirname "$0")/../../utils.sh"
+
+chars="${charsLower%f*} ${charsUpper%F*} ${charsNum%6*} + - # ! ? ("
+
+# folders/entries with some chars
+for char in $chars; do
+ mkdir -p "$PASSWORD_STORE_DIR/sort/$char"
+ echo "password" | pass insert -ef "sort/$char" > /dev/null
+done
diff --git a/autotests/testenvs/templates/utils.sh b/autotests/testenvs/templates/utils.sh
index 41e35ab..5901e71 100644
--- a/autotests/testenvs/templates/utils.sh
+++ b/autotests/testenvs/templates/utils.sh
@@ -1,140 +1,143 @@
#!/usr/bin/env bash
#
# Helpful functions and shared variables:
# - definition of main paths for other scripts
# - functions to generate and get specific cert data via gpg
# - content variables for pass entries
#
# Usage: source utils.sh
# paths
templatesDir="$(dirname "$(readlink -vf "${BASH_SOURCE:-"$0"}")")"
certsDir="$templatesDir/certs"
storesDir="$templatesDir/stores"
filesDir="$templatesDir/files"
entriesDir="$templatesDir/entries"
testDir="$(dirname "$templatesDir")"
envsDir="$testDir/envs"
logDir="$testDir/logs"
mkdir -p "$logDir"
# variables
users=
[ -d "$certsDir" ] && users="$(ls --ignore all "$certsDir"/ | xargs)"
newline='
'
# --- GPG ---------------------------------------------------------------------
# gpg wrapper for batch mode
GPG () { # <args>
gpg --expert --batch --yes \
--no-auto-check-trustdb \
--pinentry-mode loopback \
--passphrase "${passphrase:-}" \
--logger-file "$logDir/gpg.log" \
"$@"
}
# parse gpg key list with awk
parseKeys () { # <filter> [<search> ...]
local filter="$1"; shift
GPG --list-keys --with-colons --with-keygrip "$@" | awk "BEGIN {FS=\":\"} $filter"
}
# generate userid:
# 'User Type NumPad[suffix] <user.type.num[suffix]@gnupg.test> (type)'
genUid () { # <user> <type> <num> [<suffix>]
local user="$1" type="$2" num="$3" suffix="${4:-}"
local name= email= comment= userid=
name="${user^} ${type^} $(printf %02d $num)${suffix}"
email="${user}.${type}.${num}${suffix}@gnupg.test"
comment="$type"
userid="$name <$email> ($comment)"
echo $userid
}
# function wrapper to add an optional batch mode via pipe (one execution per line).
# ensures unique results, errors on multiple results for one execution.
# used as syntax sugar for the helper functions below, e.g.
#
# $ getEmail alice.default
# alice.default.1@gnupg.test
#
# $ pubFprs alice | getEmail
# alice.default.1@gnupg.test
# alice.disabled.1@gnupg.test
# ...
#
# note: will hang, if neither args or stdin is given (waits for stdin input).
pick () { # <function> <args> -OR- <args1>\n<args2> | <function>
local func="$1"; shift; local args="$@"
# choose args or stdin
echo "${args:-$(cat)}" | while read args; do
result="$($func "$args")"
# multiline
if echo "$result" | sed 1d | grep -q .; then case $func in
# for userid based information: take first userid
getUids|getNames|getEmails) result=${result%%"$newline"*} ;;
# error otherwise
*) echo -e "\nERROR! results for '$func $args' not unique:\n$result" >&2; return 1
esac fi
# result
if echo "$result" | grep -q .; then # no empty lines
echo "$result"
fi
done
}
# get fingerprints
pubFprs () { parseKeys '/^pub/ {getline; print $10}' "$@"; }
pubFpr () { pick pubFprs "$@"; }
subFprs () { parseKeys '/^sub/ {getline; print $10}' "$@"; }
_subFpr () { parseKeys '/^sub/ {if (index($5, "'$@'")) {getline; print $10}}' "$@"; }
subFpr () { pick _subFpr "$@"; }
# get keyids
pubKeyids () { parseKeys '/^pub/ {print $5}' "$@"; }
pubKeyid () { pick pubKeyids "$@"; }
subKeyids () { parseKeys '/^sub/ {print $5}' "$@"; }
subKeyid () { pick subKeyids "$@"; }
sigKeyids () { parseKeys '/^sub/ {if ($12 == "s") print $5}' "$@"; }
sigKeyid () { pick sigKeyids "$@"; }
encKeyids () { parseKeys '/^sub/ {if ($12 == "e") print $5}' "$@"; }
encKeyid () { pick encKeyids "$@"; }
autKeyids () { parseKeys '/^sub/ {if ($12 == "a") print $5}' "$@"; }
autKeyid () { pick autKeyids "$@"; }
# get keygrips
getGrips () { parseKeys '/^fpr/ {getline; print $10}' "$@"; }
_getGrip () { parseKeys '/^fpr/ {if (index($10, "'$@'")) {getline; print $10}}' "$@"; }
getGrip () { pick _getGrip "$@"; }
# get userids
getUids () { parseKeys '/^uid/ {print $10}' "$@"; }
getUid () { pick getUids "$@"; }
getNames () { parseKeys '/^uid/ {$0=$10; FS="[<>]"; $0=$0; print $1; FS=":"}' "$@"; }
getName () { pick getNames "$@"; }
getEmails () { parseKeys '/^uid/ {$0=$10; FS="[<>]"; $0=$0; print $2; FS=":"}' "$@"; }
getEmail () { pick getEmails "$@"; }
# get testids (local part of email in test certs without suffix, deduplicated)
getIds () { parseKeys '/^uid/ {FS="[<>]"; $0=$10; FS="[+@]"; $0=$2; print $1; FS=":"}' "$@" | sort -u; }
getId () { pick getIds "$@"; }
# --- CONTENT -----------------------------------------------------------------
# content
loremipsum="dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec quam felis, ultricies nec, pellentesque eu, pretium quis, sem. Nulla consequat massa quis enim. Donec pede justo, fringilla vel, aliquet nec, vulputate eget, arcu. In enim justo, rhoncus ut, imperdiet a, venenatis vitae, justo. Nullam dictum felis eu pede mollis pretium. Integer tincidunt. Cras dapibus. Vivamus elementum semper nisi. Aenean vulputate eleifend tellus. Aenean leo ligula, porttitor eu, consequat vitae, eleifend ac, enim. Aliquam lorem ante, dapibus in, viverra quis, feugiat a, tellus. Phasellus viverra nulla ut metus varius laoreet. Quisque rutrum. Aenean imperdiet. Etiam ultricies nisi vel augue. Curabitur ullamcorper ultricies nisi. Nam eget dui. Etiam rhoncus. Maecenas tempus, tellus eget condimentum rhoncus, sem quam semper libero, sit amet adipiscing sem neque sed ipsum. Nam quam nunc, blandit vel, luctus pulvinar, hendrerit id, lorem. Maecenas nec odio et ante tincidunt tempus. Donec vitae sapien ut libero venenatis faucibus. Nullam quis ante. Etiam sit amet orci eget eros faucibus tincidunt. Duis leo. Sed fringilla mauris sit amet nibh. Donec sodales sagittis magna. Sed consequat, leo eget bibendum sodales, augue velit cursus nunc,"
longWord="abcdefghijklmnopqrstuvwxyz01234567890abcdefghijklmnopqrstuvwxyz01234567890abcdefghijklmnopqrstuvwxyz01234567890abcdefghijklmnopqrstuvwxyz01234567890abcdefghijklmnopqrstuvwxyz01234567890abcdefghijklmnopqrstuvwxyz01234567890abcdefghijklmnopqrstuvwxyz01234567890abcdefghijklmnopqrstuvwxyz01234567890abcdefghijklmnopqrstuvwxyz01234567890abcdefghijklmnopqrstuvwxyz01234567890abcdefghijklmnopqrstuvwxyz01234567890abcdefghijklmnopqrstuvwxyz01234567890abcdefghijklmnopqrstuvwxyz01234567890"
longUrl="https://dev.gnpugp.org/some/very/long/path/with/some-long-name-of-some-product-copy-and-pasted-from-your-favourite-online-store?with=many&query=strings&also=with&very=long&obfuscated=code&matching=the&lenght=of&real=urls&like=1234567890abcdefghijklmnopqrstuvwxyz1234567890abcdefghijklmnopqrstuvwxyz1234567890abcdefghijklmnopqrstuvwxyz1234567890abcdefghijklmnopqrstuvwxyz1234567890abcdefghijklmnopqrstuvwxyz1234567890abcdefghijklmnopqrstuvwxyz1234567890abcdefghijklmnopqrstuvwxyz1234567890abcdefghijklmnopqrstuvwxyz1234567890abcdefghijklmnopqrstuvwxyz"
-# special chars
-charsBasic="~ ! @ # $ % ^ & * ( - _ + = { } ] [ | \` , . / ? ; : ' \" < > \n \t"
+# chars
+charsLower="a b c d e f g h i j k l m n o p q r s t u v w x y z"
+charsUpper="A B C D E F G H I J K L M N O P Q R S T U V W X Y Z"
+charsNum="1 2 3 4 5 6 7 8 9 0"
+charsSpecial="~ ! @ # $ % ^ & * ( - _ + = { } ] [ | \` , . / ? ; : ' \" < > \n \t"
charsCaret="^A ^B ^C ^D ^E ^F ^G ^H ^I ^J ^K ^L ^M ^N ^O ^P ^Q ^R ^S ^T ^U ^V ^W ^X ^Y ^Z ^@ ^[ ^\ \^ ]^ ^_ ^?"
charsC="\0 \a \b \t \n \v \f \r \\0 \\a \\b \\t \\n \\v \\f \\r \\\0 \\\\0"
charsUtf="\u00 \\u00 \u0000 \\u0000 \U00 \\U00 \U0000 \\U0000 0x00 0x0000"

File Metadata

Mime Type
text/x-diff
Expires
Fri, Dec 5, 5:09 AM (11 h, 21 m)
Storage Engine
local-disk
Storage Format
Raw Data
Storage Handle
0a/fe/5b9120d335a87d0ea6d2717892e3

Event Timeline