summaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
Diffstat (limited to 'tests')
-rw-r--r--tests/openpgp/Makefile.am4
-rwxr-xr-xtests/openpgp/export.test110
-rw-r--r--tests/openpgp/fake-pinentry.c216
3 files changed, 314 insertions, 16 deletions
diff --git a/tests/openpgp/Makefile.am b/tests/openpgp/Makefile.am
index bab0b7d..bb1047d 100644
--- a/tests/openpgp/Makefile.am
+++ b/tests/openpgp/Makefile.am
@@ -57,6 +57,7 @@ TESTS = version.test mds.test \
import.test ecc.test 4gb-packet.test \
$(sqlite3_dependent_tests) \
gpgtar.test use-exact-key.test default-key.test \
+ export.test \
finish.test
@@ -123,7 +124,8 @@ CLEANFILES = prepared.stamp x y yy z out err $(data_files) \
*.test.log gpg_dearmor gpg.conf gpg-agent.conf S.gpg-agent \
pubring.gpg pubring.gpg~ pubring.kbx pubring.kbx~ \
secring.gpg pubring.pkr secring.skr \
- gnupg-test.stop random_seed gpg-agent.log tofu.db
+ gnupg-test.stop random_seed gpg-agent.log tofu.db \
+ passphrases
clean-local:
-rm -rf private-keys-v1.d openpgp-revocs.d tofu.d gpgtar.d
diff --git a/tests/openpgp/export.test b/tests/openpgp/export.test
new file mode 100755
index 0000000..9776760
--- /dev/null
+++ b/tests/openpgp/export.test
@@ -0,0 +1,110 @@
+#!/bin/sh
+
+. $srcdir/defs.inc || exit 3
+
+check_exported_public_key()
+{
+ $GPG --list-packets $1 >$1.packets
+ grep '^:public key packet:' $1.packets >/dev/null
+ grep "^ keyid: .*$KEY$" $1.packets >/dev/null
+ grep '^:user ID packet:' $1.packets >/dev/null
+ grep "^:signature packet:.*keyid.*$KEY" $1.packets >/dev/null
+ rm $1.packets
+}
+
+check_armored_public_key()
+{
+ grep '^-----BEGIN PGP PUBLIC KEY BLOCK-----$' $1 >/dev/null
+ grep '^-----END PGP PUBLIC KEY BLOCK-----$' $1 >/dev/null
+ check_exported_public_key $1
+}
+
+check_exported_private_key()
+{
+ $GPG --list-packets $1 >$1.packets
+ grep '^:secret key packet:' $1.packets >/dev/null
+ grep "^ keyid: .*$KEY$" $1.packets >/dev/null
+ grep '^:user ID packet:' $1.packets >/dev/null
+ grep "^:signature packet:.*keyid.*$KEY" $1.packets >/dev/null
+ rm $1.packets
+}
+
+check_armored_private_key()
+{
+ grep '^-----BEGIN PGP PRIVATE KEY BLOCK-----$' $1 >/dev/null
+ grep '^-----END PGP PRIVATE KEY BLOCK-----$' $1 >/dev/null
+ check_exported_private_key $1
+}
+
+logfile="`pwd`/pinentry.log"
+ppfile="`pwd`/passphrases"
+rm -f -- $logfile $ppfile
+touch $ppfile
+
+prepare_passphrase()
+{
+ echo $* >>$ppfile
+}
+
+prepare_passphrase_confirm()
+{
+ echo "fake-entry being started to CONFIRM the weak phrase" >>$ppfile
+}
+
+assert_passphrases_consumed()
+{
+ if test -s $ppfile; then
+ echo "Expected $ppfile to be empty, but these are enqueued:" >&2
+ cat "$ppfile" >&2
+ exit 1
+ fi
+ rm -f -- $logfile
+}
+
+export PINENTRY_USER_DATA="--logfile=$logfile --passphrasefile=$ppfile"
+
+info "Checking key export."
+for KEY in D74C5F22 C40FDECF ECABF51D
+do
+ progress $KEY
+
+ $GPG --export $KEY >$KEY.public
+ check_exported_public_key $KEY.public
+ rm $KEY.public
+
+ $GPG --armor --export $KEY >$KEY.public
+ check_armored_public_key $KEY.public
+ rm $KEY.public
+
+ # test without --armor:
+
+ if [ $KEY = D74C5F22 ]; then
+ # Key D74C5F22 is protected by a passphrase. Prepare this
+ # one. Currently, GnuPG does not ask for an export passphrase
+ # in this case.
+ prepare_passphrase "$usrpass1"
+ fi
+
+ $GPG --export-secret-keys $KEY >$KEY.private
+ check_exported_private_key $KEY.private
+ rm $KEY.private
+
+ assert_passphrases_consumed
+
+ # test with --armor:
+
+ if [ $KEY = D74C5F22 ]; then
+ # Key D74C5F22 is protected by a passphrase. Prepare this
+ # one. Currently, GnuPG does not ask for an export passphrase
+ # in this case.
+ prepare_passphrase "$usrpass1"
+ fi
+
+ $GPG --armor --export-secret-keys $KEY >$KEY.private
+ check_armored_private_key $KEY.private
+ rm $KEY.private
+
+ assert_passphrases_consumed
+done
+
+progress_end
diff --git a/tests/openpgp/fake-pinentry.c b/tests/openpgp/fake-pinentry.c
index b8aa848..a651726 100644
--- a/tests/openpgp/fake-pinentry.c
+++ b/tests/openpgp/fake-pinentry.c
@@ -21,30 +21,208 @@
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
+#include <stdarg.h>
+
+FILE *log_stream;
+
+int
+reply (const char *fmt, ...)
+{
+ int result;
+ va_list ap;
+
+ if (log_stream)
+ {
+ fprintf (log_stream, "> ");
+ va_start (ap, fmt);
+ vfprintf (log_stream, fmt, ap);
+ va_end (ap);
+ }
+ va_start (ap, fmt);
+ result = vprintf (fmt, ap);
+ va_end (ap);
+
+ return result;
+}
+
+/* Return the first line from FNAME, removing it from the file. */
+char *
+get_passphrase (const char *fname)
+{
+ char *passphrase = NULL;
+ size_t fname_len;
+ char *fname_new;
+ FILE *source, *sink;
+ char linebuf[80];
+
+ fname_len = strlen (fname);
+ fname_new = malloc (fname_len + 5);
+ if (fname_new == NULL)
+ {
+ perror ("malloc");
+ exit (1);
+ }
+ snprintf (fname_new, fname_len + 5, "%s.new", fname);
+
+ source = fopen (fname, "r");
+ if (! source)
+ {
+ perror (fname);
+ exit (1);
+ }
+
+ sink = fopen (fname_new, "w");
+ if (! sink)
+ {
+ perror (fname_new);
+ exit (1);
+ }
+
+ while (fgets (linebuf, sizeof linebuf, source))
+ {
+ linebuf[sizeof linebuf - 1] = 0;
+ if (passphrase == NULL)
+ {
+ passphrase = strdup (linebuf);
+ if (passphrase == NULL)
+ {
+ perror ("strdup");
+ exit (1);
+ }
+ }
+ else
+ fputs (linebuf, sink);
+ }
+
+ if (ferror (source))
+ {
+ perror (fname);
+ exit (1);
+ }
+
+ if (ferror (sink))
+ {
+ perror (fname_new);
+ exit (1);
+ }
+
+ fclose (source);
+ fclose (sink);
+ rename (fname_new, fname);
+ return passphrase;
+}
+
+
+#define spacep(p) (*(p) == ' ' || *(p) == '\t')
+
+/* Skip over options in LINE.
+
+ Blanks after the options are also removed. Options are indicated
+ by two leading dashes followed by a string consisting of non-space
+ characters. The special option "--" indicates an explicit end of
+ options; all what follows will not be considered an option. The
+ first no-option string also indicates the end of option parsing. */
+char *
+skip_options (const char *line)
+{
+ while (spacep (line))
+ line++;
+ while (*line == '-' && line[1] == '-')
+ {
+ while (*line && !spacep (line))
+ line++;
+ while (spacep (line))
+ line++;
+ }
+ return (char*) line;
+}
+
+
+/* Return a pointer to the argument of the option with NAME. If such
+ an option is not given, NULL is returned. */
+char *
+option_value (const char *line, const char *name)
+{
+ char *s;
+ int n = strlen (name);
+
+ s = strstr (line, name);
+ if (s && s >= skip_options (line))
+ return NULL;
+ if (s && (s == line || spacep (s-1))
+ && s[n] && (spacep (s+n) || s[n] == '='))
+ {
+ s += n + 1;
+ s += strspn (s, " ");
+ if (*s && !spacep(s))
+ return s;
+ }
+ return NULL;
+}
int
main (int argc, char **argv)
{
- static char *passphrase;
- char *p;
+ char *args;
+ char *logfile;
+ char *passphrasefile;
+ char *passphrase;
+ /* We get our options via PINENTRY_USER_DATA. */
(void) argc, (void) argv;
setvbuf (stdin, NULL, _IOLBF, BUFSIZ);
setvbuf (stdout, NULL, _IOLBF, BUFSIZ);
- if (!passphrase)
+ args = getenv ("PINENTRY_USER_DATA");
+ if (! args)
+ args = "";
+
+ logfile = option_value (args, "--logfile");
+ if (logfile)
+ {
+ char *p = logfile, more;
+ while (*p && ! spacep (p))
+ p++;
+ more = !! *p;
+ *p = 0;
+ args = more ? p+1 : p;
+
+ log_stream = fopen (logfile, "a");
+ if (! log_stream)
+ {
+ perror (logfile);
+ return 1;
+ }
+ }
+
+ passphrasefile = option_value (args, "--passphrasefile");
+ if (passphrasefile)
{
- passphrase = getenv ("PINENTRY_USER_DATA");
- if (!passphrase)
- passphrase = "";
- for (p=passphrase; *p; p++)
- if (*p == '\r' || *p == '\n')
- *p = '.';
- printf ("# Passphrase='%s'\n", passphrase);
+ char *p = passphrasefile, more;
+ while (*p && ! spacep (p))
+ p++;
+ more = !! *p;
+ *p = 0;
+ args = more ? p+1 : p;
+
+ passphrase = get_passphrase (passphrasefile);
+ if (! passphrase)
+ {
+ reply ("# Passphrasefile '%s' is empty. Terminating.\n",
+ passphrasefile);
+ return 1;
+ }
+
+ p = passphrase + strlen (passphrase) - 1;
+ if (*p == '\n')
+ *p = 0;
}
+ else
+ passphrase = skip_options (args);
- printf ("OK - what's up?\n");
+ reply ("# fake-pinentry started. Passphrase='%s'.\n", passphrase);
+ reply ("OK - what's up?\n");
while (! feof (stdin))
{
@@ -53,15 +231,23 @@ main (int argc, char **argv)
if (fgets (buffer, sizeof buffer, stdin) == NULL)
break;
+ if (log_stream)
+ fprintf (log_stream, "< %s", buffer);
+
if (strncmp (buffer, "GETPIN", 6) == 0)
- printf ("D %s\nOK\n", passphrase);
+ reply ("D %s\n", passphrase);
else if (strncmp (buffer, "BYE", 3) == 0)
{
- printf ("OK\n");
+ reply ("OK\n");
break;
}
- else
- printf ("OK\n");
+
+ reply ("OK\n");
}
+
+ reply ("# Connection terminated.\n");
+ if (log_stream)
+ fclose (log_stream);
+
return 0;
}