From adec130f20e374ae0d8f615f45916e27771a0278 Mon Sep 17 00:00:00 2001 From: Daniel Kahn Gillmor Date: Sat, 21 Feb 2009 18:06:45 -0500 Subject: fixing stupid internal version number synchronization. --- src/share/common | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/share/common b/src/share/common index 5e0cb6a..a21d803 100644 --- a/src/share/common +++ b/src/share/common @@ -21,7 +21,7 @@ SYSCONFIGDIR=${MONKEYSPHERE_SYSCONFIGDIR:-"/etc/monkeysphere"} export SYSCONFIGDIR # monkeysphere version -VERSION=0.23~pre +VERSION=0.23 # default log level LOG_LEVEL="INFO" -- cgit v1.2.3 From 3492507e7dc279be4e6c703733d8a174d0204d91 Mon Sep 17 00:00:00 2001 From: Daniel Kahn Gillmor Date: Sat, 21 Feb 2009 18:28:20 -0500 Subject: preparing for stupid brown paper bag 0.23.1 release. --- packaging/debian/changelog | 7 +++++++ src/share/common | 2 +- website/download.mdwn | 36 ++++++++++++++++++------------------ website/news/release-0.23.1-1.mdwn | 12 ++++++++++++ 4 files changed, 38 insertions(+), 19 deletions(-) create mode 100644 website/news/release-0.23.1-1.mdwn (limited to 'src') diff --git a/packaging/debian/changelog b/packaging/debian/changelog index 50a7071..96b719b 100644 --- a/packaging/debian/changelog +++ b/packaging/debian/changelog @@ -1,3 +1,10 @@ +monkeysphere (0.23.1-1) unstable; urgency=low + + * New Upstrem "Brown Paper Bag" Release: + - adjusts internal version numbers + + -- Daniel Kahn Gillmor Sat, 21 Feb 2009 18:09:47 -0500 + monkeysphere (0.23-1) unstable; urgency=low "The Golden Bezoar Release" diff --git a/src/share/common b/src/share/common index a21d803..0c26a91 100644 --- a/src/share/common +++ b/src/share/common @@ -21,7 +21,7 @@ SYSCONFIGDIR=${MONKEYSPHERE_SYSCONFIGDIR:-"/etc/monkeysphere"} export SYSCONFIGDIR # monkeysphere version -VERSION=0.23 +VERSION=0.23.1 # default log level LOG_LEVEL="INFO" diff --git a/website/download.mdwn b/website/download.mdwn index cc050a0..db25be6 100644 --- a/website/download.mdwn +++ b/website/download.mdwn @@ -77,38 +77,38 @@ For those that would like to download the source directly, [the source is available](/community) via [git](http://git.or.cz/). The [latest -tarball](http://archive.monkeysphere.info/debian/pool/monkeysphere/m/monkeysphere/monkeysphere_0.23.orig.tar.gz) +tarball](http://archive.monkeysphere.info/debian/pool/monkeysphere/m/monkeysphere/monkeysphere_0.23.1.orig.tar.gz) is also available, and has these checksums:
 -----BEGIN PGP SIGNED MESSAGE-----
 Hash: SHA1
 
-checksums for the monkeysphere 0.23 release:
+checksums for the monkeysphere 0.23.1 release:
 
 MD5:
-2c3e985884ecf7a5f53825f9034932a3  monkeysphere_0.23.orig.tar.gz
+9ab4a35052b41d6468a4ab4758fd23b2  monkeysphere_0.23.1.orig.tar.gz
 
 SHA1:
-6f03b9d813d48479c86623c7facf634d72da2cb0  monkeysphere_0.23.orig.tar.gz
+1e3004505b5c2cda98194d1241f76303b154aac6  monkeysphere_0.23.1.orig.tar.gz
 
 SHA256:
-7854d9c358b684c2b292b4f3470780d2c7e069466bd228885d6a246e0bd1abde  monkeysphere_0.23.orig.tar.gz
+998b8f8f0c498aa7d58eed6519c23ab9808cb8b622f97f8aa47865b718024d6c  monkeysphere_0.23.1.orig.tar.gz
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v1.4.9 (GNU/Linux)
 
-iQIVAwUBSaCGXxjmZ/HrivMUAQKIUhAAs/b+2z+cKkcP3bwfD8ItW377rXY3+ZrV
-pomzhzSuSk52gYxa6QBQ7rgYdWac996VRTSxR14yEM8iLyqxaBpvbvOJCgqv0B51
-VHJiosV8nVqjUXdrOa2iRFqPF3+zaINjsIgJSB5aKCjT6d2sxlYoe5OpIU1JD/yN
-E/ypvO8v3xNZ7V2YU858H2UhT0J2kMmnYPrprgoqgebWrVke/tnQLnGew/A9leel
-ZEWVhWaN+RO6n/obxxKbRHT2cAp2CW/qccFGAf80XB//i7yTD5KxlK1Ls0nLT43H
-3MQPZZsOTKFZsMfOD9Y46CN5ZDm/e3SnGhi7UgW2xDP4QhGihUVYputYHr4lvboA
-uoO2g7JT2MltsuyxFMacscf9tx9cgF80ndHTBUxqDtlh/aK1xlC4tPSwSgQwuKwy
-JabvCz3fwiQbZc08OhB/5DhuDPORhQk2CJJ7HGrN1Sc2Cde0x667rQjI/ckrUC0Y
-PIqXUp8trB+p85tQSSuWJEgxVbNRZ4hVftvNvLECKv7fd0bVdNeVvV57H5ieJ8FR
-adPVaASkhF+pL122t3qC/vSbUi956Hk3pKMT9+05vLnfzYM78A6j1jA4pTvlEzaC
-WWdvL2BvARlhw5OUz4gomCpw5ZSxWjsnF6SHte85UmmunZpmE67/udyvcPqMNzjA
-vG61wNXtmqA=
-=JqmC
+iQIVAwUBSaCKiRjmZ/HrivMUAQLA3A//Tn5R4TI//yPF6T0+swIHH9VnYhFIjitV
+pzm0aWQ/MfygAm24S64edudva6Mgnm5GsDmHzv9Kg0n12+NtCc+VTIH56aMwKO9J
+riT2BalxTny0UaMeIU2gsJP0H5GuEbFWknFMcKGwIKhEuiDKgF/QJNJKNNokBL55
+rivnxKrBKy5f2o2th+RxopA2jzVfUNKWtPlJz52vYyMGn7qkWdWY6zhm48PvHt1P
+9cR3Llzu6uQflVk/PaMZmsW/q8WFEp/9Igsws1GTac4XPl0N5FFwdYmOZRLwu2sF
+k5y7sdH+tZt+sKKuMYTloulj7nq27Zi3THrlqUuanvibWPVLiBTdnIV47fg17YsO
+Pr4UTeOEIxKRsJXTwYhFmToxrO5ehRo7DcPU4Y6+YaaNnneMdR8ZF0FbNmvpkLrU
+wYoT6nkCn/81Wde7G0bc2Lo6RlXPEhRfACQuLkokv2+bbzcsWn16s4TLIJLBi9Ev
+XQ4we8zp16h1wWSssXOk19iEDFIMcJ7lrc37ItEbdmOXdlyG6FlDZWWo9vyR8LDH
+AXEqjSNm0T2o1OjUwmUWSws+Y3cyhNlYMpAtq3u67qkMCBW3zEH4GhDvG6kcvt32
+NizDUn8ClMR4m7znlR3eNlnavYVMETuUutHeGq0lB2N008kbT2S+Ciz539ady7sg
+s2QqAl6xNzo=
+=JCyh
 -----END PGP SIGNATURE-----
 
diff --git a/website/news/release-0.23.1-1.mdwn b/website/news/release-0.23.1-1.mdwn new file mode 100644 index 0000000..79b3c05 --- /dev/null +++ b/website/news/release-0.23.1-1.mdwn @@ -0,0 +1,12 @@ +[[meta title="Monkeysphere 0.23.1-1 released!"]] + +Monkeysphere 0.23.1-1 has been released. + +Notes from the changelog: + +
+  * New Upstrem "Brown Paper Bag" Release:
+   - adjusts internal version numbers
+
+ +[[Download]] it now! -- cgit v1.2.3 From 224f87f09060a10519440dc8660a57b82cb0ba58 Mon Sep 17 00:00:00 2001 From: Daniel Kahn Gillmor Date: Sat, 21 Feb 2009 20:31:16 -0500 Subject: fix syntax error in m-a diagnostics. --- src/share/ma/diagnostics | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/share/ma/diagnostics b/src/share/ma/diagnostics index 8fc4b31..d9df9eb 100644 --- a/src/share/ma/diagnostics +++ b/src/share/ma/diagnostics @@ -103,7 +103,7 @@ fi # make sure that at least one identity certifier exists echo echo "Checking for Identity Certifiers..." -if ! monkeysphere-authentication list-identity-certifiers | egrep -q '^[A-F0-9]{40}:' then +if ! monkeysphere-authentication list-identity-certifiers | egrep -q '^[A-F0-9]{40}:' ; then echo "! No Identity Certifiers found!" echo " - Recommendation: once you know who should be able to certify the identities of connecting users, you should add their key, with: -- cgit v1.2.3 From bf3e2e6ecafbab7e80124ea4ba2bda61ee4423e9 Mon Sep 17 00:00:00 2001 From: Daniel Kahn Gillmor Date: Sat, 21 Feb 2009 20:33:01 -0500 Subject: added some FIXMEs to transitions/0.23, concerning host keys that were originally created with an expiration date. --- src/transitions/0.23 | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/transitions/0.23 b/src/transitions/0.23 index f09dfff..dead788 100755 --- a/src/transitions/0.23 +++ b/src/transitions/0.23 @@ -143,12 +143,24 @@ if [ -d "$SYSDATADIR"/gnupg-host ] ; then if [ -s "$SYSDATADIR"/ssh_host_rsa_key ] || \ GNUPGHOME="$SYSDATADIR"/gnupg-host gpg --no-permission-warning --with-colons --list-secret-keys | grep -q '^sec:' ; then + FPR=$(GNUPGHOME="$SYSDATADIR"/gnupg-host gpg --no-permission-warning --with-colons --fixed-list-mode --list-secret-keys --fingerprint | awk -F: '/^fpr:/{ print $10 }' ) + # create host home mkdir -p "${MHDATADIR}" chmod 0700 "${MHDATADIR}" log "importing host key from old monkeysphere installation\n" - GNUPGHOME="$SYSDATADIR"/gnupg-host gpg --no-permission-warning --export-secret-keys | \ + +# export from the pubring as well as the that new (non-expired) +# self-sigs are available, otherwise the secret key import may fail + +# FIXME: turns out the secret key import fails anyway, stupidly :( + +# FIXME: if all self-sigs are expired, then the secret key import may +# fail anyway. How should we deal with that? + + (GNUPGHOME="$SYSDATADIR"/gnupg-host gpg --no-permission-warning --export-secret-keys && \ + GNUPGHOME="$SYSDATADIR"/gnupg-host gpg --no-permission-warning --export $FPR) | \ GNUPGHOME="$MHDATADIR" gpg --quiet --no-tty --import monkeysphere-host update-gpg-pub-file -- cgit v1.2.3 From 687e4c47929c53e8da032a58a884cb6a2c1098f6 Mon Sep 17 00:00:00 2001 From: Daniel Kahn Gillmor Date: Sat, 21 Feb 2009 20:34:26 -0500 Subject: reverse sense of test for valid identity certifiers in m-a diagnostics. --- src/share/ma/diagnostics | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/share/ma/diagnostics b/src/share/ma/diagnostics index d9df9eb..0caf8d2 100644 --- a/src/share/ma/diagnostics +++ b/src/share/ma/diagnostics @@ -103,7 +103,7 @@ fi # make sure that at least one identity certifier exists echo echo "Checking for Identity Certifiers..." -if ! monkeysphere-authentication list-identity-certifiers | egrep -q '^[A-F0-9]{40}:' ; then +if monkeysphere-authentication list-identity-certifiers | egrep -q '^[A-F0-9]{40}:' ; then echo "! No Identity Certifiers found!" echo " - Recommendation: once you know who should be able to certify the identities of connecting users, you should add their key, with: -- cgit v1.2.3 From e71c7bb4dff26178f714cd0fcdbb3058effa4066 Mon Sep 17 00:00:00 2001 From: Jameson Graef Rollins Date: Sun, 22 Feb 2009 12:07:34 -0500 Subject: Fix how version number is saved/retrieved. Version is now stored in VERSION file, which is created in the tarball target. This is then installed at /usr/share/monkeysphere/VERSION, and cat'ed when the version number is requested by the front-end ui. No more manual setting of version number required (to avoid future problems, aka "0.23.1"). This system is also more flexible, as the VERSION file could potentially hold more info than just the release number. --- Makefile | 2 ++ packaging/debian/changelog | 7 +++++++ src/monkeysphere | 2 +- src/monkeysphere-authentication | 2 +- src/monkeysphere-host | 2 +- src/share/common | 8 +++++--- tests/basic | 16 ---------------- utils/preparing-release | 3 --- 8 files changed, 17 insertions(+), 25 deletions(-) (limited to 'src') diff --git a/Makefile b/Makefile index 71df92b..0284a8a 100755 --- a/Makefile +++ b/Makefile @@ -24,6 +24,7 @@ tarball: clean mkdir -p monkeysphere-$(MONKEYSPHERE_VERSION)/doc ln -s ../../website/getting-started-user.mdwn ../../website/getting-started-admin.mdwn ../../doc/TODO ../../doc/MonkeySpec monkeysphere-$(MONKEYSPHERE_VERSION)/doc ln -s ../COPYING ../etc ../Makefile ../man ../src ../tests monkeysphere-$(MONKEYSPHERE_VERSION) + echo $(MONKEYSPHERE_VERSION) > monkeysphere-$(MONKEYSPHERE_VERSION)/VERSION tar -ch --exclude='*~' monkeysphere-$(MONKEYSPHERE_VERSION) | gzip -n > monkeysphere_$(MONKEYSPHERE_VERSION).orig.tar.gz rm -rf monkeysphere-$(MONKEYSPHERE_VERSION) @@ -50,6 +51,7 @@ install: all installman mkdir -p $(DESTDIR)$(PREFIX)/share/monkeysphere/m $(DESTDIR)$(PREFIX)/share/monkeysphere/mh $(DESTDIR)$(PREFIX)/share/monkeysphere/ma $(DESTDIR)$(PREFIX)/share/monkeysphere/transitions mkdir -p $(DESTDIR)$(ETCPREFIX)/etc/monkeysphere mkdir -p $(DESTDIR)$(PREFIX)/share/doc/monkeysphere + install -m 0644 VERSION $(DESTDIR)$(PREFIX)/share/monkeysphere install src/monkeysphere src/keytrans/openpgp2ssh src/keytrans/pem2openpgp $(DESTDIR)$(PREFIX)/bin install src/monkeysphere-host src/monkeysphere-authentication $(DESTDIR)$(PREFIX)/sbin install -m 0644 src/share/common $(DESTDIR)$(PREFIX)/share/monkeysphere diff --git a/packaging/debian/changelog b/packaging/debian/changelog index 96b719b..58a80a3 100644 --- a/packaging/debian/changelog +++ b/packaging/debian/changelog @@ -1,3 +1,10 @@ +monkeysphere (0.24~pre-1) UNRELEASED; urgency=low + + * New upstream release: + - Fixed how version information is stored/retrieved. + + -- Jameson Graef Rollins Sun, 22 Feb 2009 12:02:06 -0500 + monkeysphere (0.23.1-1) unstable; urgency=low * New Upstrem "Brown Paper Bag" Release: diff --git a/src/monkeysphere b/src/monkeysphere index 371983f..6db4827 100755 --- a/src/monkeysphere +++ b/src/monkeysphere @@ -239,7 +239,7 @@ case $COMMAND in ;; 'version'|'v') - echo "$VERSION" + version ;; '--help'|'help'|'-h'|'h'|'?') diff --git a/src/monkeysphere-authentication b/src/monkeysphere-authentication index 497470d..c009653 100755 --- a/src/monkeysphere-authentication +++ b/src/monkeysphere-authentication @@ -199,7 +199,7 @@ case $COMMAND in ;; 'version'|'v') - echo "$VERSION" + version ;; '--help'|'help'|'-h'|'h'|'?') diff --git a/src/monkeysphere-host b/src/monkeysphere-host index 1b0de0c..c454354 100755 --- a/src/monkeysphere-host +++ b/src/monkeysphere-host @@ -315,7 +315,7 @@ case $COMMAND in ;; 'version'|'v') - echo "$VERSION" + version ;; '--help'|'help'|'-h'|'h'|'?') diff --git a/src/share/common b/src/share/common index 0c26a91..b2dcd35 100644 --- a/src/share/common +++ b/src/share/common @@ -20,9 +20,6 @@ SYSCONFIGDIR=${MONKEYSPHERE_SYSCONFIGDIR:-"/etc/monkeysphere"} export SYSCONFIGDIR -# monkeysphere version -VERSION=0.23.1 - # default log level LOG_LEVEL="INFO" @@ -41,6 +38,11 @@ PROMPT="true" ######################################################################## ### UTILITY FUNCTIONS +# output version info +version() { + cat "${SYSSHAREDIR}/VERSION" +} + # failure function. exits with code 255, unless specified otherwise. failure() { [ "$1" ] && echo "$1" >&2 diff --git a/tests/basic b/tests/basic index 9308e21..b1fe9ed 100755 --- a/tests/basic +++ b/tests/basic @@ -138,22 +138,6 @@ export SOCKET="$TEMPDIR"/ssh-socket # *anything* with any running X11 session. export DISPLAY=monkeys -## make sure that the version number matches the debian changelog -## (don't bother if this is being run from the tests). - -if [ -f "$TESTDIR"/../packaging/debian/changelog ]; then - echo - echo "##################################################" - echo "### checking version string match..." - repver=$(monkeysphere version) - debver=$(head -n1 "$TESTDIR"/../packaging/debian/changelog | sed 's/.*(\([^-]*\)-.*/\1/') - if [ "$repver" = "$debver" ] ; then - echo "Versions match!" - else - printf "reported version string (%s) does not match debian changelog (%s)\n" "$repver" "$debver" - exit 1 - fi -fi ###################################################################### ### CONFIGURE ENVIRONMENTS diff --git a/utils/preparing-release b/utils/preparing-release index 3c7ded5..dd9d224 100644 --- a/utils/preparing-release +++ b/utils/preparing-release @@ -3,9 +3,6 @@ * make sure that packaging/debian/changelog has a reasonable version number. - * make sure that src/share/common contains the upstream part of that - version number in the VERSION= line - * make tarball * make releasenote -- cgit v1.2.3 From be6cca8523345c6a3a3e8cddce7d8954a2bf5a54 Mon Sep 17 00:00:00 2001 From: Jameson Graef Rollins Date: Sun, 22 Feb 2009 12:16:32 -0500 Subject: fix some return code setting stuf that was no longer being used, and change name of return code variable in update_users, since all-caps variables should be reserved for global vars. --- src/monkeysphere-authentication | 5 ----- src/monkeysphere-host | 5 ----- src/share/ma/update_users | 9 ++++----- 3 files changed, 4 insertions(+), 15 deletions(-) (limited to 'src') diff --git a/src/monkeysphere-authentication b/src/monkeysphere-authentication index c009653..c5c48d5 100755 --- a/src/monkeysphere-authentication +++ b/src/monkeysphere-authentication @@ -42,9 +42,6 @@ DATE=$(date -u '+%FT%T') # unset some environment variables that could screw things up unset GREP_OPTIONS -# default return code -RETURN=0 - ######################################################################## # FUNCTIONS ######################################################################## @@ -211,5 +208,3 @@ case $COMMAND in Type '$PGRM help' for usage." ;; esac - -exit "$RETURN" diff --git a/src/monkeysphere-host b/src/monkeysphere-host index c454354..5e7a931 100755 --- a/src/monkeysphere-host +++ b/src/monkeysphere-host @@ -41,9 +41,6 @@ DATE=$(date -u '+%FT%T') # unset some environment variables that could screw things up unset GREP_OPTIONS -# default return code -RETURN=0 - ######################################################################## # FUNCTIONS ######################################################################## @@ -327,5 +324,3 @@ case $COMMAND in Type '$PGRM help' for usage." ;; esac - -exit "$RETURN" diff --git a/src/share/ma/update_users b/src/share/ma/update_users index bfefc31..c180b56 100644 --- a/src/share/ma/update_users +++ b/src/share/ma/update_users @@ -13,6 +13,7 @@ update_users() { +local returnCode=0 local unames local uname local authorizedKeysDir @@ -26,8 +27,6 @@ else unames=$(getent passwd | cut -d: -f1) fi -RETURN=0 - # set mode MODE="authorized_keys" @@ -94,7 +93,7 @@ for uname in $unames ; do # process authorized_user_ids file, as monkeysphere user su_monkeysphere_user \ ". ${SYSSHAREDIR}/common; process_authorized_user_ids $TMP_AUTHORIZED_USER_IDS" \ - || RETURN="$?" + || returnCode="$?" else log debug "not processing authorized_user_ids." fi @@ -141,7 +140,7 @@ for uname in $unames ; do log error "Failed to install authorized_keys for '$uname'!" rm -f "${authorizedKeysDir}/${uname}" # indicate that there has been a failure: - RETURN=1 + returnCode=1 } else rm -f "${authorizedKeysDir}/${uname}" @@ -154,5 +153,5 @@ for uname in $unames ; do rm -rf "$TMPLOC" done -return $RETURN +return $returnCode } -- cgit v1.2.3 From 5ebbfc2d643fbee80b5d53a7b326fd12d9202caa Mon Sep 17 00:00:00 2001 From: Daniel Kahn Gillmor Date: Sun, 22 Feb 2009 17:10:31 -0500 Subject: really really fix m-a diagnostics checking of identity certifiers. --- src/share/ma/diagnostics | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/share/ma/diagnostics b/src/share/ma/diagnostics index 0caf8d2..913a53d 100644 --- a/src/share/ma/diagnostics +++ b/src/share/ma/diagnostics @@ -103,7 +103,7 @@ fi # make sure that at least one identity certifier exists echo echo "Checking for Identity Certifiers..." -if monkeysphere-authentication list-identity-certifiers | egrep -q '^[A-F0-9]{40}:' ; then +if !( monkeysphere-authentication list-identity-certifiers | egrep -q '^[A-F0-9]{40}:' ) ; then echo "! No Identity Certifiers found!" echo " - Recommendation: once you know who should be able to certify the identities of connecting users, you should add their key, with: -- cgit v1.2.3 From 47b5e916b2a84a378ec08b3b03531f9a8ccc062b Mon Sep 17 00:00:00 2001 From: Daniel Kahn Gillmor Date: Sun, 22 Feb 2009 17:56:30 -0500 Subject: egrep -q terminates at the first match. m-a list-identity-certifiers chokes if it cannot write to stdout. Because we are setting pipefail, this causes the pipeline checking for any certifiers to return untrue. solution? do not use -q, and send the output to /dev/null --- src/share/ma/diagnostics | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/share/ma/diagnostics b/src/share/ma/diagnostics index 913a53d..8eca586 100644 --- a/src/share/ma/diagnostics +++ b/src/share/ma/diagnostics @@ -103,7 +103,7 @@ fi # make sure that at least one identity certifier exists echo echo "Checking for Identity Certifiers..." -if !( monkeysphere-authentication list-identity-certifiers | egrep -q '^[A-F0-9]{40}:' ) ; then +if ! ( monkeysphere-authentication list-identity-certifiers | egrep '^[A-F0-9]{40}:' >/dev/null ) ; then echo "! No Identity Certifiers found!" echo " - Recommendation: once you know who should be able to certify the identities of connecting users, you should add their key, with: -- cgit v1.2.3 From 90e182fac0303b6a5a9c9da92446b366b2bdadd7 Mon Sep 17 00:00:00 2001 From: Daniel Kahn Gillmor Date: Sat, 28 Feb 2009 12:46:51 -0500 Subject: transition script should ensure that the (old, deprecated) monkeysphere-server.conf gets renamed to monkeysphere-authentication.conf --- src/transitions/0.23 | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'src') diff --git a/src/transitions/0.23 b/src/transitions/0.23 index dead788..67d1f63 100755 --- a/src/transitions/0.23 +++ b/src/transitions/0.23 @@ -21,6 +21,7 @@ set -e SYSDATADIR=${MONKEYSPHERE_SYSDATADIR:-"/var/lib/monkeysphere"} +SYSCONFIGDIR=${MONKEYSPHERE_SYSCONFIGDIR:-"/etc/monkeysphere"} MADATADIR="${SYSDATADIR}/authentication" MHDATADIR="${SYSDATADIR}/host" @@ -43,6 +44,13 @@ is_domain_name() { printf "%s" "$1" | egrep -q '^[[:alnum:]][[:alnum:]-.]*[[:alnum:]]$' } + +# move the old server conf file to be the authentication conf file +if [ -f "$SYSCONFIGDIR"/monkeysphere-server.conf -a \ + ! -f "$SYSCONFIGDIR"/monkeysphere-authentication.conf ] ; then + mv "$SYSCONFIGDIR"/monkeysphere-server.conf "$SYSCONFIGDIR"/monkeysphere-authentication.conf +fi + # run the authentication setup (this is also the first chance to bail # if 0.23 is not fully-installed, because m-a did not exist before # 0.23) -- cgit v1.2.3 From 7f7a83939b6a457bb5a92462ea94057a43e60b16 Mon Sep 17 00:00:00 2001 From: Daniel Kahn Gillmor Date: Sat, 28 Feb 2009 13:30:29 -0500 Subject: made transitions/0.23 a little bit more resilient; made it so that running again after a failure is not fooled by the previous failure into thinking that the transition is done. --- src/transitions/0.23 | 26 +++++++++++++++++++------- 1 file changed, 19 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/transitions/0.23 b/src/transitions/0.23 index 67d1f63..b0c967a 100755 --- a/src/transitions/0.23 +++ b/src/transitions/0.23 @@ -154,8 +154,9 @@ if [ -d "$SYSDATADIR"/gnupg-host ] ; then FPR=$(GNUPGHOME="$SYSDATADIR"/gnupg-host gpg --no-permission-warning --with-colons --fixed-list-mode --list-secret-keys --fingerprint | awk -F: '/^fpr:/{ print $10 }' ) # create host home - mkdir -p "${MHDATADIR}" - chmod 0700 "${MHDATADIR}" + mkdir -p $(dirname "$MHDATADIR") + NEWDATADIR=$(mktemp -d "${MHDATADIR}.XXXXXX") + chmod 0700 "${NEWDATADIR}" log "importing host key from old monkeysphere installation\n" @@ -167,10 +168,20 @@ if [ -d "$SYSDATADIR"/gnupg-host ] ; then # FIXME: if all self-sigs are expired, then the secret key import may # fail anyway. How should we deal with that? - (GNUPGHOME="$SYSDATADIR"/gnupg-host gpg --no-permission-warning --export-secret-keys && \ - GNUPGHOME="$SYSDATADIR"/gnupg-host gpg --no-permission-warning --export $FPR) | \ - GNUPGHOME="$MHDATADIR" gpg --quiet --no-tty --import - + if (GNUPGHOME="$SYSDATADIR"/gnupg-host gpg --no-permission-warning --export-secret-keys && \ + GNUPGHOME="$SYSDATADIR"/gnupg-host gpg --no-permission-warning --export "$FPR") | \ + GNUPGHOME="$NEWDATADIR" gpg --quiet --no-tty --import ; then + : we are in good shape! + else + if ! GNUPGHOME="$NEWDATADIR" gpg --list-secret-key >/dev/null ; then + log "The old host key (%s) was not imported properly.\n" "$FPR" + exit 1 + fi + fi + + # if we get here cleanly, then we're OK to move forward: + mv "$NEWDATADIR" "$MHDATADIR" + monkeysphere-host update-gpg-pub-file else log "No host key found in old monkeysphere install; not importing any host key.\n" @@ -192,7 +203,8 @@ fi if [ -d "${SYSDATADIR}/gnupg-authentication" ] ; then GNUPGHOME="${SYSDATADIR}/gnupg-authentication" gpg --no-permission-warning --export | \ - monkeysphere-authentication gpg-cmd --import + monkeysphere-authentication gpg-cmd --import || \ + log "No OpenPGP certificates imported into monkeysphere-authentication trust sphere.\n" mkdir -p "$STASHDIR" chmod 0700 "$STASHDIR" -- cgit v1.2.3 From e83267c80493b9279bd35e8adf91963d0ec6f0b6 Mon Sep 17 00:00:00 2001 From: Daniel Kahn Gillmor Date: Sat, 28 Feb 2009 14:00:07 -0500 Subject: functionalize the bulk of pem2openpgp. --- src/keytrans/pem2openpgp | 329 +++++++++++++++++++++++++---------------------- 1 file changed, 172 insertions(+), 157 deletions(-) (limited to 'src') diff --git a/src/keytrans/pem2openpgp b/src/keytrans/pem2openpgp index 2631da6..3492361 100755 --- a/src/keytrans/pem2openpgp +++ b/src/keytrans/pem2openpgp @@ -32,12 +32,6 @@ use MIME::Base64; ## make sure all length() and substr() calls use bytes only: use bytes; -my $uid = shift; - -# FIXME: fail if there is no given user ID; or should we default to -# hostname_long() from Sys::Hostname::Long ? - - my $old_format_packet_lengths = { one => 0, two => 1, four => 2, @@ -348,172 +342,193 @@ sub fingerprint { } -my $rsa; -if (defined $ENV{PEM2OPENPGP_NEWKEY}) { - $rsa = Crypt::OpenSSL::RSA->generate_key($ENV{PEM2OPENPGP_NEWKEY}); -} else { - # we're just not dealing with newline business right now. slurp in - # the whole file. - undef $/; - $rsa = Crypt::OpenSSL::RSA->new_private_key(); -} +# FIXME: handle DSA keys as well! +sub pem2openpgp { + my $rsa = shift; + my $uid = shift; + my $args = shift; -$rsa->use_sha1_hash(); + $rsa->use_sha1_hash(); -# see page 22 of RFC 4880 for why i think this is the right padding -# choice to use: -$rsa->use_pkcs1_padding(); + # see page 22 of RFC 4880 for why i think this is the right padding + # choice to use: + $rsa->use_pkcs1_padding(); -if (! $rsa->check_key()) { - die "key does not check"; -} + if (! $rsa->check_key()) { + die "key does not check"; + } -my $version = pack('C', 4); -# strong assertion of identity: -my $sigtype = pack('C', $sig_types->{positive_certification}); -# RSA -my $pubkey_algo = pack('C', $asym_algos->{rsa}); -# SHA1 -my $hash_algo = pack('C', $digests->{sha1}); - -# FIXME: i'm worried about generating a bazillion new OpenPGP -# certificates from the same key, which could easily happen if you run -# this script more than once against the same key (because the -# timestamps will differ). How can we prevent this? - -# this environment variable (if set) overrides the current time, to -# be able to create a standard key? If we read the key from a file -# instead of stdin, should we use the creation time on the file? -my $timestamp = 0; -if (defined $ENV{PEM2OPENPGP_TIMESTAMP}) { - $timestamp = ($ENV{PEM2OPENPGP_TIMESTAMP} + 0); -} else { - $timestamp = time(); -} + my $version = pack('C', 4); + # strong assertion of identity: + my $sigtype = pack('C', $sig_types->{positive_certification}); + # RSA + my $pubkey_algo = pack('C', $asym_algos->{rsa}); + # SHA1 + my $hash_algo = pack('C', $digests->{sha1}); + + # FIXME: i'm worried about generating a bazillion new OpenPGP + # certificates from the same key, which could easily happen if you run + # this script more than once against the same key (because the + # timestamps will differ). How can we prevent this? + + # this environment variable (if set) overrides the current time, to + # be able to create a standard key? If we read the key from a file + # instead of stdin, should we use the creation time on the file? + my $timestamp = 0; + if (defined $args->{timestamp}) { + $timestamp = ($args->{timestamp} + 0); + } else { + $timestamp = time(); + } -my $creation_time_packet = pack('CCN', 5, $subpacket_types->{sig_creation_time}, $timestamp); + my $creation_time_packet = pack('CCN', 5, $subpacket_types->{sig_creation_time}, $timestamp); -my $flags = 0; -if (! defined $ENV{PEM2OPENPGP_USAGE_FLAGS}) { - $flags = $usage_flags->{certify}; -} else { - my @ff = split(",", $ENV{PEM2OPENPGP_USAGE_FLAGS}); - foreach my $f (@ff) { - if (! defined $usage_flags->{$f}) { - die "No such flag $f"; + my $flags = 0; + if (! defined $args->{usage_flags}) { + $flags = $usage_flags->{certify}; + } else { + my @ff = split(",", $args->{usage_flags}); + foreach my $f (@ff) { + if (! defined $usage_flags->{$f}) { + die "No such flag $f"; + } + $flags |= $usage_flags->{$f}; } - $flags |= $usage_flags->{$f}; } + + my $usage_packet = pack('CCC', 2, $subpacket_types->{usage_flags}, $flags); + + + # how should we determine how far off to set the expiration date? + # default is no expiration. Specify the timestamp in seconds from the + # key creation. + my $expiration_packet = ''; + if (defined $args->{expiration}) { + my $expires_in = $args->{expiration} + 0; + $expiration_packet = pack('CCN', 5, $subpacket_types->{key_expiration_time}, $expires_in); + } + + + # prefer AES-256, AES-192, AES-128, CAST5, 3DES: + my $pref_sym_algos = pack('CCCCCCC', 6, $subpacket_types->{preferred_cipher}, + $ciphers->{aes256}, + $ciphers->{aes192}, + $ciphers->{aes128}, + $ciphers->{cast5}, + $ciphers->{tripledes} + ); + + # prefer SHA-1, SHA-256, RIPE-MD/160 + my $pref_hash_algos = pack('CCCCC', 4, $subpacket_types->{preferred_digest}, + $digests->{sha1}, + $digests->{sha256}, + $digests->{ripemd160} + ); + + # prefer ZLIB, BZip2, ZIP + my $pref_zip_algos = pack('CCCCC', 4, $subpacket_types->{preferred_compression}, + $zips->{zlib}, + $zips->{bzip2}, + $zips->{zip} + ); + + # we support the MDC feature: + my $feature_subpacket = pack('CCC', 2, $subpacket_types->{features}, + $features->{mdc}); + + # keyserver preference: only owner modify (???): + my $keyserver_pref = pack('CCC', 2, $subpacket_types->{keyserver_prefs}, + $keyserver_prefs->{nomodify}); + + my $subpackets_to_be_hashed = + $creation_time_packet. + $usage_packet. + $expiration_packet. + $pref_sym_algos. + $pref_hash_algos. + $pref_zip_algos. + $feature_subpacket. + $keyserver_pref; + + my $subpacket_octets = pack('n', length($subpackets_to_be_hashed)); + + my $sig_data_to_be_hashed = + $version. + $sigtype. + $pubkey_algo. + $hash_algo. + $subpacket_octets. + $subpackets_to_be_hashed; + + my $pubkey = make_rsa_pub_key_body($rsa, $timestamp); + my $seckey = make_rsa_sec_key_body($rsa, $timestamp); + + # this is for signing. it needs to be an old-style header with a + # 2-packet octet count. + + my $key_data = make_packet($packet_types->{pubkey}, $pubkey, {'packet_length'=>2}); + + # take the last 8 bytes of the fingerprint as the keyid: + my $keyid = substr(fingerprint($rsa, $timestamp), 20 - 8, 8); + + # the v4 signature trailer is: + + # version number, literal 0xff, and then a 4-byte count of the + # signature data itself. + my $trailer = pack('CCN', 4, 0xff, length($sig_data_to_be_hashed)); + + my $uid_data = + pack('CN', 0xb4, length($uid)). + $uid; + + my $datatosign = + $key_data. + $uid_data. + $sig_data_to_be_hashed. + $trailer; + + my $data_hash = Digest::SHA1::sha1_hex($datatosign); + + my $issuer_packet = pack('CCa8', 9, $subpacket_types->{issuer}, $keyid); + + my $sig = Crypt::OpenSSL::Bignum->new_from_bin($rsa->sign($datatosign)); + + my $sig_body = + $sig_data_to_be_hashed. + pack('n', length($issuer_packet)). + $issuer_packet. + pack('n', hex(substr($data_hash, 0, 4))). + mpi_pack($sig); + + return + make_packet($packet_types->{seckey}, $seckey). + make_packet($packet_types->{uid}, $uid). + make_packet($packet_types->{sig}, $sig_body); } -my $usage_packet = pack('CCC', 2, $subpacket_types->{usage_flags}, $flags); +my $rsa; +if (defined $ENV{PEM2OPENPGP_NEWKEY}) { + $rsa = Crypt::OpenSSL::RSA->generate_key($ENV{PEM2OPENPGP_NEWKEY}); +} else { + # slurp in the entire stdin: + undef $/; + my $stdin = ; -# how should we determine how far off to set the expiration date? -# default is no expiration. Specify the timestamp in seconds from the -# key creation. -my $expiration_packet = ''; -if (defined $ENV{PEM2OPENPGP_EXPIRATION}) { - my $expires_in = $ENV{PEM2OPENPGP_EXPIRATION} + 0; - $expiration_packet = pack('CCN', 5, $subpacket_types->{key_expiration_time}, $expires_in); + $rsa = Crypt::OpenSSL::RSA->new_private_key($stdin); } +my $uid = shift; -# prefer AES-256, AES-192, AES-128, CAST5, 3DES: -my $pref_sym_algos = pack('CCCCCCC', 6, $subpacket_types->{preferred_cipher}, - $ciphers->{aes256}, - $ciphers->{aes192}, - $ciphers->{aes128}, - $ciphers->{cast5}, - $ciphers->{tripledes} - ); - -# prefer SHA-1, SHA-256, RIPE-MD/160 -my $pref_hash_algos = pack('CCCCC', 4, $subpacket_types->{preferred_digest}, - $digests->{sha1}, - $digests->{sha256}, - $digests->{ripemd160} - ); - -# prefer ZLIB, BZip2, ZIP -my $pref_zip_algos = pack('CCCCC', 4, $subpacket_types->{preferred_compression}, - $zips->{zlib}, - $zips->{bzip2}, - $zips->{zip} - ); - -# we support the MDC feature: -my $feature_subpacket = pack('CCC', 2, $subpacket_types->{features}, - $features->{mdc}); - -# keyserver preference: only owner modify (???): -my $keyserver_pref = pack('CCC', 2, $subpacket_types->{keyserver_prefs}, - $keyserver_prefs->{nomodify}); - -my $subpackets_to_be_hashed = - $creation_time_packet. - $usage_packet. - $expiration_packet. - $pref_sym_algos. - $pref_hash_algos. - $pref_zip_algos. - $feature_subpacket. - $keyserver_pref; - -my $subpacket_octets = pack('n', length($subpackets_to_be_hashed)); - -my $sig_data_to_be_hashed = - $version. - $sigtype. - $pubkey_algo. - $hash_algo. - $subpacket_octets. - $subpackets_to_be_hashed; - -my $pubkey = make_rsa_pub_key_body($rsa, $timestamp); -my $seckey = make_rsa_sec_key_body($rsa, $timestamp); - -# this is for signing. it needs to be an old-style header with a -# 2-packet octet count. - -my $key_data = make_packet($packet_types->{pubkey}, $pubkey, {'packet_length'=>2}); - -# take the last 8 bytes of the fingerprint as the keyid: -my $keyid = substr(fingerprint($rsa, $timestamp), 20 - 8, 8); - -# the v4 signature trailer is: - -# version number, literal 0xff, and then a 4-byte count of the -# signature data itself. -my $trailer = pack('CCN', 4, 0xff, length($sig_data_to_be_hashed)); - -my $uid_data = - pack('CN', 0xb4, length($uid)). - $uid; - -my $datatosign = - $key_data. - $uid_data. - $sig_data_to_be_hashed. - $trailer; - -my $data_hash = Digest::SHA1::sha1_hex($datatosign); - -my $issuer_packet = pack('CCa8', 9, $subpacket_types->{issuer}, $keyid); - -my $sig = Crypt::OpenSSL::Bignum->new_from_bin($rsa->sign($datatosign)); - -my $sig_body = - $sig_data_to_be_hashed. - pack('n', length($issuer_packet)). - $issuer_packet. - pack('n', hex(substr($data_hash, 0, 4))). - mpi_pack($sig); - -print - make_packet($packet_types->{seckey}, $seckey). - make_packet($packet_types->{uid}, $uid). - make_packet($packet_types->{sig}, $sig_body); +# FIXME: fail if there is no given user ID; or should we default to +# hostname_long() from Sys::Hostname::Long ? +print pem2openpgp($rsa, + $uid, + { timestamp => $ENV{PEM2OPENPGP_TIMESTAMP}, + expiration => $ENV{PEM2OPENPGP_EXPIRATION}, + usage_flags => $ENV{PEM2OPENPGP_USAGE_FLAGS}, + } + ); -- cgit v1.2.3 From b08a2e207f22000b494fc1aabe413bea5eb8f7d5 Mon Sep 17 00:00:00 2001 From: Daniel Kahn Gillmor Date: Sat, 28 Feb 2009 14:08:41 -0500 Subject: rewrite stdin slurping to match example in perldoc -f unpack. --- src/keytrans/pem2openpgp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/keytrans/pem2openpgp b/src/keytrans/pem2openpgp index 3492361..4e6ebe7 100755 --- a/src/keytrans/pem2openpgp +++ b/src/keytrans/pem2openpgp @@ -509,12 +509,14 @@ sub pem2openpgp { my $rsa; +my $stdin; if (defined $ENV{PEM2OPENPGP_NEWKEY}) { $rsa = Crypt::OpenSSL::RSA->generate_key($ENV{PEM2OPENPGP_NEWKEY}); } else { - # slurp in the entire stdin: - undef $/; - my $stdin = ; + $stdin = do { + local $/; # slurp! + ; + }; $rsa = Crypt::OpenSSL::RSA->new_private_key($stdin); } -- cgit v1.2.3 From 3cc809546f716f93be416f2f3edd9e06ea17a547 Mon Sep 17 00:00:00 2001 From: Daniel Kahn Gillmor Date: Sat, 28 Feb 2009 14:22:22 -0500 Subject: make pem2openpgp closer to a generic keytrans so that we can reuse it for the openpgp2ssh replacement. --- src/keytrans/pem2openpgp | 55 ++++++++++++++++++++++++++++++------------------ 1 file changed, 34 insertions(+), 21 deletions(-) (limited to 'src') diff --git a/src/keytrans/pem2openpgp b/src/keytrans/pem2openpgp index 4e6ebe7..4dda6ca 100755 --- a/src/keytrans/pem2openpgp +++ b/src/keytrans/pem2openpgp @@ -23,6 +23,7 @@ use strict; use warnings; +use File::Basename; use Crypt::OpenSSL::RSA; use Crypt::OpenSSL::Bignum; use Crypt::OpenSSL::Bignum::CTX; @@ -508,29 +509,41 @@ sub pem2openpgp { } -my $rsa; -my $stdin; -if (defined $ENV{PEM2OPENPGP_NEWKEY}) { - $rsa = Crypt::OpenSSL::RSA->generate_key($ENV{PEM2OPENPGP_NEWKEY}); -} else { - $stdin = do { - local $/; # slurp! - ; - }; +for (basename($0)) { + if (/^pem2openpgp$/) { - $rsa = Crypt::OpenSSL::RSA->new_private_key($stdin); -} + my $rsa; + my $stdin; + if (defined $ENV{PEM2OPENPGP_NEWKEY}) { + $rsa = Crypt::OpenSSL::RSA->generate_key($ENV{PEM2OPENPGP_NEWKEY}); + } else { + $stdin = do { + local $/; # slurp! + ; + }; + + $rsa = Crypt::OpenSSL::RSA->new_private_key($stdin); + } -my $uid = shift; + my $uid = shift; -# FIXME: fail if there is no given user ID; or should we default to -# hostname_long() from Sys::Hostname::Long ? + # FIXME: fail if there is no given user ID; or should we default to + # hostname_long() from Sys::Hostname::Long ? -print pem2openpgp($rsa, - $uid, - { timestamp => $ENV{PEM2OPENPGP_TIMESTAMP}, - expiration => $ENV{PEM2OPENPGP_EXPIRATION}, - usage_flags => $ENV{PEM2OPENPGP_USAGE_FLAGS}, - } - ); + print pem2openpgp($rsa, + $uid, + { timestamp => $ENV{PEM2OPENPGP_TIMESTAMP}, + expiration => $ENV{PEM2OPENPGP_EXPIRATION}, + usage_flags => $ENV{PEM2OPENPGP_USAGE_FLAGS}, + } + ); + } + elsif (/^openpgp2ssh$/) { + print STDERR "woo\n"; + } + else { + print STDERR "Unrecognized keytrans call.\n"; + die 1; + } +} -- cgit v1.2.3 From 375c864f9b89cb8f8923dfcb7a9ba2e783a244da Mon Sep 17 00:00:00 2001 From: Daniel Kahn Gillmor Date: Sat, 28 Feb 2009 15:55:10 -0500 Subject: start to make an openpgp2ssh implementation within pem2openpgp. --- src/keytrans/pem2openpgp | 45 ++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 44 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/keytrans/pem2openpgp b/src/keytrans/pem2openpgp index 4dda6ca..9b7d8f6 100755 --- a/src/keytrans/pem2openpgp +++ b/src/keytrans/pem2openpgp @@ -509,6 +509,45 @@ sub pem2openpgp { } + + +sub openpgp2ssh { + my $instr = shift; + my $fpr = shift; + + my $packettag; + read($instr, $packettag, 1); + $packettag = ord($packettag); + + my $packetlen; + if ( ! (0x80 & $packettag)) { + print STDERR "This is not an OpenPGP packet"; + exit 1; + } + if (0x40 & $packettag) { + print STDERR "This is a new-style packet header"; + $tag = (0x3f & $packettag); + } else { + print STDERR "This is an old-style packet header"; + $lentype = 0x03 & $packettag; + $tag = (0x3c & $packettag ) >> 2; + if ($lentype == 0) { + read($instr, $packetlen, 1); + $packetlen = unpack('%C', $packetlen); + } elsif ($lentype == 1) { + read($instr, $packetlen, 2); + $packetlen = unpack('%S', $packetlen); + } elsif ($lentype == 2) { + read($instr, $packetlen, 4); + $packetlen = unpack('%L', $packetlen); + } + } + printf(STDERR, "Packet is %d long\n", $packetlen); + + print $packettag; +} + + for (basename($0)) { if (/^pem2openpgp$/) { @@ -539,7 +578,11 @@ for (basename($0)) { ); } elsif (/^openpgp2ssh$/) { - print STDERR "woo\n"; + my $fpr = shift; + my $instream; + open($instream,'-'); + binmode($instream, ":bytes"); + openpgp2ssh($instream, $fpr); } else { print STDERR "Unrecognized keytrans call.\n"; -- cgit v1.2.3 From 21062dd622620dd44001858bd9cb4116ac978529 Mon Sep 17 00:00:00 2001 From: Daniel Kahn Gillmor Date: Sat, 28 Feb 2009 17:17:13 -0500 Subject: successfully parsing out the packets in pem2openpgp keytrans operation. --- src/keytrans/pem2openpgp | 92 +++++++++++++++++++++++++++++++++--------------- 1 file changed, 64 insertions(+), 28 deletions(-) (limited to 'src') diff --git a/src/keytrans/pem2openpgp b/src/keytrans/pem2openpgp index 9b7d8f6..94fd3c8 100755 --- a/src/keytrans/pem2openpgp +++ b/src/keytrans/pem2openpgp @@ -516,41 +516,78 @@ sub openpgp2ssh { my $fpr = shift; my $packettag; - read($instr, $packettag, 1); - $packettag = ord($packettag); + my $dummy; + my $tag; - my $packetlen; - if ( ! (0x80 & $packettag)) { - print STDERR "This is not an OpenPGP packet"; - exit 1; - } - if (0x40 & $packettag) { - print STDERR "This is a new-style packet header"; - $tag = (0x3f & $packettag); - } else { - print STDERR "This is an old-style packet header"; - $lentype = 0x03 & $packettag; - $tag = (0x3c & $packettag ) >> 2; - if ($lentype == 0) { - read($instr, $packetlen, 1); - $packetlen = unpack('%C', $packetlen); - } elsif ($lentype == 1) { - read($instr, $packetlen, 2); - $packetlen = unpack('%S', $packetlen); - } elsif ($lentype == 2) { - read($instr, $packetlen, 4); - $packetlen = unpack('%L', $packetlen); + while (! eof($instr)) { + read($instr, $packettag, 1); + $packettag = ord($packettag); + + my $packetlen; + if ( ! (0x80 & $packettag)) { + die "This is not an OpenPGP packet\n"; + } + if (0x40 & $packettag) { + print STDERR "This is a new-style packet header\n"; + $tag = (0x3f & $packettag); + my $nextlen = 0; + read($instr, $nextlen, 1); + $nextlen = ord($nextlen); + if ($nextlen < 192) { + $packetlen = $nextlen; + } elsif ($nextlen < 224) { + my $newoct; + read($instr, $newoct, 1); + $newoct = ord($newoct); + $packetlen = (($nextlen - 192) << 8) + ($newoct) + 192; + } elsif ($nextlen == 255) { + read($instr, $nextlen, 4); + $packetlen = unpack('%L', $nextlen); + } else { + # packet length is undefined. + } + } else { + my $lentype; + print STDERR "This is an old-style packet header\n"; + $lentype = 0x03 & $packettag; + $tag = ( 0x3c & $packettag ) >> 2; + if ($lentype == 0) { + read($instr, $packetlen, 1) or die "could not read packet length\n"; + $packetlen = unpack('C', $packetlen); + } elsif ($lentype == 1) { + read($instr, $packetlen, 2) or die "could not read packet length\n"; + $packetlen = unpack('n', $packetlen); + } elsif ($lentype == 2) { + read($instr, $packetlen, 4) or die "could not read packet length\n"; + $packetlen = unpack('N', $packetlen); + } else { + # packet length is undefined. + } + } + + if (! defined($packetlen)) { + die "Undefined packet lengths are not supported.\n"; + } + printf(STDERR "Packet is %d long\n", $packetlen); + + if ($tag == $packet_types->{pubkey} || + $tag == $packet_types->{pub_subkey} || + $tag == $packet_types->{seckey} || + $tag == $packet_types->{sec_subkey}) { + printf(STDERR "Packet type %d\n", $tag); + read($instr, $dummy, $packetlen) or die "Could not seek!\n"; + } else { + printf(STDERR "We do not care about this packet.\n"); + read($instr, $dummy, $packetlen) or die "Could not seek!\n"; } } - printf(STDERR, "Packet is %d long\n", $packetlen); - print $packettag; + print $tag; } for (basename($0)) { if (/^pem2openpgp$/) { - my $rsa; my $stdin; if (defined $ENV{PEM2OPENPGP_NEWKEY}) { @@ -585,8 +622,7 @@ for (basename($0)) { openpgp2ssh($instream, $fpr); } else { - print STDERR "Unrecognized keytrans call.\n"; - die 1; + die "Unrecognized keytrans call.\n"; } } -- cgit v1.2.3 From 2e2299e705d1e67d170137bd499f1ffa511a60a7 Mon Sep 17 00:00:00 2001 From: Daniel Kahn Gillmor Date: Sat, 28 Feb 2009 17:55:40 -0500 Subject: calculating and emitting key fingerprints in openpgp2ssh rewrite. --- src/keytrans/pem2openpgp | 61 +++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 52 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/keytrans/pem2openpgp b/src/keytrans/pem2openpgp index 94fd3c8..ae7c91f 100755 --- a/src/keytrans/pem2openpgp +++ b/src/keytrans/pem2openpgp @@ -288,6 +288,20 @@ sub mpi_pack { return pack('n', $mpilen).$val; } +# pull an OpenPGP-specified MPI off of a given stream. +sub read_mpi { + my $instr = shift; + + my $bitlen; + read($instr, $bitlen, 2) or die "could not read MPI length.\n"; + $bitlen = unpack('n', $bitlen); + + my $ret; + read($instr, $ret, ($bitlen + 7)/8) or die "could not read MPI body.\n"; + return Crypt::OpenSSL::Bignum->new_from_bin($ret); +} + + # FIXME: genericize these to accept either RSA or DSA keys: sub make_rsa_pub_key_body { my $key = shift; @@ -509,8 +523,6 @@ sub pem2openpgp { } - - sub openpgp2ssh { my $instr = shift; my $fpr = shift; @@ -528,7 +540,6 @@ sub openpgp2ssh { die "This is not an OpenPGP packet\n"; } if (0x40 & $packettag) { - print STDERR "This is a new-style packet header\n"; $tag = (0x3f & $packettag); my $nextlen = 0; read($instr, $nextlen, 1); @@ -542,13 +553,12 @@ sub openpgp2ssh { $packetlen = (($nextlen - 192) << 8) + ($newoct) + 192; } elsif ($nextlen == 255) { read($instr, $nextlen, 4); - $packetlen = unpack('%L', $nextlen); + $packetlen = unpack('N', $nextlen); } else { # packet length is undefined. } } else { my $lentype; - print STDERR "This is an old-style packet header\n"; $lentype = 0x03 & $packettag; $tag = ( 0x3c & $packettag ) >> 2; if ($lentype == 0) { @@ -568,17 +578,50 @@ sub openpgp2ssh { if (! defined($packetlen)) { die "Undefined packet lengths are not supported.\n"; } - printf(STDERR "Packet is %d long\n", $packetlen); if ($tag == $packet_types->{pubkey} || $tag == $packet_types->{pub_subkey} || $tag == $packet_types->{seckey} || $tag == $packet_types->{sec_subkey}) { printf(STDERR "Packet type %d\n", $tag); - read($instr, $dummy, $packetlen) or die "Could not seek!\n"; + + my $ver; + read($instr, $ver, 1) or die "could not read key version\n"; + $ver = ord($ver); + if ($ver != 4) { + printf(STDERR "We only work with version 4 keys. This key appears to be version $ver.\n"); + read($instr, $dummy, $packetlen - 1) or die "Could not skip past this packet.\n"; + } else { + + my $timestamp; + read($instr, $timestamp, 4) or die "could not read key timestamp.\n"; + $timestamp = unpack('N', $timestamp); + + my $algo; + read($instr, $algo, 1) or die "could not read key algorithm.\n"; + $algo = ord($algo); + if ($algo != $asym_algos->{rsa}) { + printf(STDERR "We only support RSA keys (this key used algorithm %d).\n", $algo); + read($instr, $dummy, $packetlen - 6) or die "Could not skip past this packet.\n"; + } else { + ## we have an RSA key. + my $modulus = read_mpi($instr); + my $exponent = read_mpi($instr); + + my $pubkey = Crypt::OpenSSL::RSA->new_key_from_parameters($modulus, $exponent); + my $foundfpr = fingerprint($pubkey, $timestamp); + + printf(STDERR "key fpr: %s\n", Crypt::OpenSSL::Bignum->new_from_bin($foundfpr)->to_hex()); + + if ($tag == $packet_types->{seckey} || + $tag == $packet_types->{sec_subkey}) { + die "Cannot deal with secret keys yet!\n"; + } + + } + } } else { - printf(STDERR "We do not care about this packet.\n"); - read($instr, $dummy, $packetlen) or die "Could not seek!\n"; + read($instr, $dummy, $packetlen) or die "Could not skip past this packet!\n"; } } -- cgit v1.2.3 From b62cb24951ccb9026fa9c2d660398be094a8b62f Mon Sep 17 00:00:00 2001 From: Daniel Kahn Gillmor Date: Sat, 28 Feb 2009 18:54:38 -0500 Subject: further perl-only openpgp2ssh work. public keys are now translated. --- src/keytrans/pem2openpgp | 62 ++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 55 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/keytrans/pem2openpgp b/src/keytrans/pem2openpgp index ae7c91f..40188c7 100755 --- a/src/keytrans/pem2openpgp +++ b/src/keytrans/pem2openpgp @@ -288,7 +288,38 @@ sub mpi_pack { return pack('n', $mpilen).$val; } -# pull an OpenPGP-specified MPI off of a given stream. +# takes a Crypt::OpenSSL::Bignum, returns an MPI packed in preparation +# for an OpenSSH-style public key format. see: +# http://marc.info/?l=openssh-unix-dev&m=121866301718839&w=2 +sub openssh_mpi_pack { + my $num = shift; + + my $val = $num->to_bin(); + my $mpilen = length($val); + + my $ret = pack('N', $mpilen); + + # if the first bit of the leading byte is high, we should include a + # 0 byte: + if (ord($val) & 0x80) { + $ret = pack('NC', $mpilen+1, 0); + } + + return $ret.$val; +} + +sub openssh_pubkey_pack { + my $key = shift; + + my ($modulus, $exponent) = $key->get_key_parameters(); + + return openssh_mpi_pack(Crypt::OpenSSL::Bignum->new_from_bin("ssh-rsa")). + openssh_mpi_pack($exponent). + openssh_mpi_pack($modulus); + } + +# pull an OpenPGP-specified MPI off of a given stream, returning it as +# a Crypt::OpenSSL::Bignum. sub read_mpi { my $instr = shift; @@ -527,10 +558,18 @@ sub openpgp2ssh { my $instr = shift; my $fpr = shift; + if (defined $fpr) { + if (length($fpr) < 8) { + die "We need at least 8 hex digits of fingerprint.\n"; + } + } + my $packettag; my $dummy; my $tag; + my $key; + while (! eof($instr)) { read($instr, $packettag, 1); $packettag = ord($packettag); @@ -583,8 +622,6 @@ sub openpgp2ssh { $tag == $packet_types->{pub_subkey} || $tag == $packet_types->{seckey} || $tag == $packet_types->{sec_subkey}) { - printf(STDERR "Packet type %d\n", $tag); - my $ver; read($instr, $ver, 1) or die "could not read key version\n"; $ver = ord($ver); @@ -610,8 +647,17 @@ sub openpgp2ssh { my $pubkey = Crypt::OpenSSL::RSA->new_key_from_parameters($modulus, $exponent); my $foundfpr = fingerprint($pubkey, $timestamp); - - printf(STDERR "key fpr: %s\n", Crypt::OpenSSL::Bignum->new_from_bin($foundfpr)->to_hex()); + + my $foundfprstr = Crypt::OpenSSL::Bignum->new_from_bin($foundfpr)->to_hex(); + + # is this a match? + if ((!defined($fpr)) || + (substr($foundfprstr, -1 * length($fpr)) eq $fpr)) { + if (defined($key)) { + die "Found two matching keys.\n"; + } + $key = $pubkey; + } if ($tag == $packet_types->{seckey} || $tag == $packet_types->{sec_subkey}) { @@ -625,7 +671,9 @@ sub openpgp2ssh { } } - print $tag; + if (defined($key)) { + return "ssh-rsa ".encode_base64(openssh_pubkey_pack($key), ''); + } } @@ -662,7 +710,7 @@ for (basename($0)) { my $instream; open($instream,'-'); binmode($instream, ":bytes"); - openpgp2ssh($instream, $fpr); + print openpgp2ssh($instream, $fpr); } else { die "Unrecognized keytrans call.\n"; -- cgit v1.2.3 From 2f91cf1747c882c9db1e8cde2ed00e5d909ff122 Mon Sep 17 00:00:00 2001 From: Daniel Kahn Gillmor Date: Sat, 28 Feb 2009 20:27:30 -0500 Subject: outputting secret key material now with perl-only openpgp2ssh. --- src/keytrans/pem2openpgp | 76 ++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 64 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/src/keytrans/pem2openpgp b/src/keytrans/pem2openpgp index 40188c7..37b372a 100755 --- a/src/keytrans/pem2openpgp +++ b/src/keytrans/pem2openpgp @@ -316,19 +316,23 @@ sub openssh_pubkey_pack { return openssh_mpi_pack(Crypt::OpenSSL::Bignum->new_from_bin("ssh-rsa")). openssh_mpi_pack($exponent). openssh_mpi_pack($modulus); - } +} # pull an OpenPGP-specified MPI off of a given stream, returning it as # a Crypt::OpenSSL::Bignum. sub read_mpi { my $instr = shift; + my $readtally = shift; my $bitlen; read($instr, $bitlen, 2) or die "could not read MPI length.\n"; $bitlen = unpack('n', $bitlen); + $$readtally += 2; + my $bytestoread = ($bitlen + 7)/8; my $ret; - read($instr, $ret, ($bitlen + 7)/8) or die "could not read MPI body.\n"; + read($instr, $ret, $bytestoread) or die "could not read MPI body.\n"; + $$readtally += $bytestoread; return Crypt::OpenSSL::Bignum->new_from_bin($ret); } @@ -562,6 +566,7 @@ sub openpgp2ssh { if (length($fpr) < 8) { die "We need at least 8 hex digits of fingerprint.\n"; } + $fpr = uc($fpr); } my $packettag; @@ -623,27 +628,32 @@ sub openpgp2ssh { $tag == $packet_types->{seckey} || $tag == $packet_types->{sec_subkey}) { my $ver; + my $readbytes = 0; read($instr, $ver, 1) or die "could not read key version\n"; + $readbytes += 1; $ver = ord($ver); + if ($ver != 4) { - printf(STDERR "We only work with version 4 keys. This key appears to be version $ver.\n"); - read($instr, $dummy, $packetlen - 1) or die "Could not skip past this packet.\n"; + printf(STDERR "We only work with version 4 keys. This key appears to be version %s.\n", $ver); + read($instr, $dummy, $packetlen - $readbytes) or die "Could not skip past this packet.\n"; } else { my $timestamp; read($instr, $timestamp, 4) or die "could not read key timestamp.\n"; + $readbytes += 4; $timestamp = unpack('N', $timestamp); my $algo; read($instr, $algo, 1) or die "could not read key algorithm.\n"; + $readbytes += 1; $algo = ord($algo); if ($algo != $asym_algos->{rsa}) { printf(STDERR "We only support RSA keys (this key used algorithm %d).\n", $algo); - read($instr, $dummy, $packetlen - 6) or die "Could not skip past this packet.\n"; + read($instr, $dummy, $packetlen - $readbytes) or die "Could not skip past this packet.\n"; } else { ## we have an RSA key. - my $modulus = read_mpi($instr); - my $exponent = read_mpi($instr); + my $modulus = read_mpi($instr, \$readbytes); + my $exponent = read_mpi($instr, \$readbytes); my $pubkey = Crypt::OpenSSL::RSA->new_key_from_parameters($modulus, $exponent); my $foundfpr = fingerprint($pubkey, $timestamp); @@ -661,7 +671,42 @@ sub openpgp2ssh { if ($tag == $packet_types->{seckey} || $tag == $packet_types->{sec_subkey}) { - die "Cannot deal with secret keys yet!\n"; + if (!defined($key)) { # we don't think the public part of + # this key matches + read($instr, $dummy, $packetlen - $readbytes) or die "Could not skip past this packet.\n"; + } else { + my $s2k; + read($instr, $s2k, 1) or die "Could not read S2K octet.\n"; + $readbytes += 1; + $s2k = ord($s2k); + if ($s2k == 0) { + # secret material is unencrypted + # see http://tools.ietf.org/html/rfc4880#section-5.5.3 + my $d = read_mpi($instr, \$readbytes); + my $p = read_mpi($instr, \$readbytes); + my $q = read_mpi($instr, \$readbytes); + my $u = read_mpi($instr, \$readbytes); + + my $checksum; + read($instr, $checksum, 2) or die "Could not read checksum of secret key material.\n"; + $readbytes += 2; + $checksum = unpack('n', $checksum); + + # FIXME: compare with the checksum! how? the data is + # gone into the Crypt::OpenSSL::Bignum + + $key = Crypt::OpenSSL::RSA->new_key_from_parameters($modulus, + $exponent, + $d, + $p, + $q); + + $key->check_key() or die "Secret key is not a valid RSA key.\n"; + } else { + print(STDERR "We cannot handle encrypted secret keys. Skipping!\n") ; + read($instr, $dummy, $packetlen - $readbytes) or die "Could not skip past this packet.\n"; + } + } } } @@ -671,9 +716,7 @@ sub openpgp2ssh { } } - if (defined($key)) { - return "ssh-rsa ".encode_base64(openssh_pubkey_pack($key), ''); - } + return $key; } @@ -710,7 +753,16 @@ for (basename($0)) { my $instream; open($instream,'-'); binmode($instream, ":bytes"); - print openpgp2ssh($instream, $fpr); + my $key = openpgp2ssh($instream, $fpr); + if (defined($key)) { + if ($key->is_private()) { + print $key->get_private_key_string(); + } else { + print "ssh-rsa ".encode_base64(openssh_pubkey_pack($key), '')."\n"; + } + } else { + die "No matching key found.\n"; + } } else { die "Unrecognized keytrans call.\n"; -- cgit v1.2.3 From a4375ee022de3c6ac6b3be371e1372bb8d720bb3 Mon Sep 17 00:00:00 2001 From: Daniel Kahn Gillmor Date: Sat, 28 Feb 2009 20:36:46 -0500 Subject: test for presence of User ID in pem2openpgp. --- src/keytrans/pem2openpgp | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/keytrans/pem2openpgp b/src/keytrans/pem2openpgp index 37b372a..73becfe 100755 --- a/src/keytrans/pem2openpgp +++ b/src/keytrans/pem2openpgp @@ -724,6 +724,14 @@ for (basename($0)) { if (/^pem2openpgp$/) { my $rsa; my $stdin; + + my $uid = shift; + defined($uid) or die "You must specify a user ID string.\n"; + + # FIXME: fail if there is no given user ID; or should we default to + # hostname_long() from Sys::Hostname::Long ? + + if (defined $ENV{PEM2OPENPGP_NEWKEY}) { $rsa = Crypt::OpenSSL::RSA->generate_key($ENV{PEM2OPENPGP_NEWKEY}); } else { @@ -735,11 +743,6 @@ for (basename($0)) { $rsa = Crypt::OpenSSL::RSA->new_private_key($stdin); } - my $uid = shift; - - # FIXME: fail if there is no given user ID; or should we default to - # hostname_long() from Sys::Hostname::Long ? - print pem2openpgp($rsa, $uid, { timestamp => $ENV{PEM2OPENPGP_TIMESTAMP}, -- cgit v1.2.3 From 620e3d1021993760ef7572ed9e5d6bf9f033b91e Mon Sep 17 00:00:00 2001 From: Jameson Graef Rollins Date: Sat, 28 Feb 2009 20:56:18 -0500 Subject: openpgp2ssh in ms-host show-key function takes the host gpg key from the temporary gpghome, instead of from the saved ssh_host_key_rsa.pub.gpg key file. --- src/monkeysphere-host | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/monkeysphere-host b/src/monkeysphere-host index 5e7a931..9e4a8c4 100755 --- a/src/monkeysphere-host +++ b/src/monkeysphere-host @@ -174,7 +174,7 @@ show_key() { # create the ssh key TMPSSH="$GNUPGHOME"/ssh_host_key_rsa_pub - openpgp2ssh <"$HOST_KEY_FILE" 2>/dev/null >"$TMPSSH" + gpg --export | openpgp2ssh 2>/dev/null >"$TMPSSH" # get the gpg fingerprint HOST_FINGERPRINT=$(gpg --quiet --list-keys --with-colons --with-fingerprint \ -- cgit v1.2.3 From 207272adad58f4ee86f961367e56fd478c754b39 Mon Sep 17 00:00:00 2001 From: Daniel Kahn Gillmor Date: Sun, 1 Mar 2009 03:24:20 -0500 Subject: fix rounding issue. Thanks, Richard K Darst! --- src/keytrans/pem2openpgp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/keytrans/pem2openpgp b/src/keytrans/pem2openpgp index 73becfe..8bf17fb 100755 --- a/src/keytrans/pem2openpgp +++ b/src/keytrans/pem2openpgp @@ -29,6 +29,7 @@ use Crypt::OpenSSL::Bignum; use Crypt::OpenSSL::Bignum::CTX; use Digest::SHA1; use MIME::Base64; +use POSIX; ## make sure all length() and substr() calls use bytes only: use bytes; @@ -329,7 +330,7 @@ sub read_mpi { $bitlen = unpack('n', $bitlen); $$readtally += 2; - my $bytestoread = ($bitlen + 7)/8; + my $bytestoread = POSIX::floor(($bitlen + 7)/8); my $ret; read($instr, $ret, $bytestoread) or die "could not read MPI body.\n"; $$readtally += $bytestoread; -- cgit v1.2.3 From ef9a47ba86dbd16bbff44cc01e5a2485823bbbdd Mon Sep 17 00:00:00 2001 From: Daniel Kahn Gillmor Date: Sun, 1 Mar 2009 04:03:57 -0500 Subject: removed test_gnu_dummy_s2k_extension(); no longer necessary --- src/share/common | 46 ----------------------------------------- src/share/m/subkey_to_ssh_agent | 8 ------- 2 files changed, 54 deletions(-) (limited to 'src') diff --git a/src/share/common b/src/share/common index b2dcd35..a9d23b2 100644 --- a/src/share/common +++ b/src/share/common @@ -336,52 +336,6 @@ passphrase_prompt() { fi } -test_gnu_dummy_s2k_extension() { - -# this block contains a demonstration private key that has had the -# primary key stripped out using the GNU S2K extension known as -# "gnu-dummy" (see /usr/share/doc/gnupg/DETAILS.gz). The subkey is -# present in cleartext, however. - -# openpgp2ssh will be able to deal with this based on whether the -# local copy of GnuTLS contains read_s2k support that can handle it. - -# read up on that here: - -# http://lists.gnu.org/archive/html/gnutls-devel/2008-08/msg00005.html - -echo " ------BEGIN PGP PRIVATE KEY BLOCK----- -Version: GnuPG v1.4.9 (GNU/Linux) - -lQCVBEO3YdABBACRqqEnucag4+vyZny2M67Pai5+5suIRRvY+Ly8Ms5MvgCi3EVV -xT05O/+0ShiRaf+QicCOFrhbU9PZzzU+seEvkeW2UCu4dQfILkmj+HBEIltGnHr3 -G0yegHj5pnqrcezERURf2e17gGFWX91cXB9Cm721FPXczuKraphKwCA9PwARAQAB -/gNlAkdOVQG0OURlbW9uc3RyYXRpb24gS2V5IGZvciBTMksgR05VIGV4dGVuc2lv -biAxMDAxIC0tIGdudS1kdW1teYi8BBMBAgAmBQJDt2HQAhsDBQkB4TOABgsJCAcD -AgQVAggDBBYCAwECHgECF4AACgkQQZUwSa4UDezTOQP/TMQXUVrWzHYZGopoPZ2+ -ZS3qddiznBHsgb7MGYg1KlTiVJSroDUBCHIUJvdQKZV9zrzrFl47D07x6hGyUPHV -aZXvuITW8t1o5MMHkCy3pmJ2KgfDvdUxrBvLfgPMICA4c6zA0mWquee43syEW9NY -g3q61iPlQwD1J1kX1wlimLCdAdgEQ7dh0AEEANAwa63zlQbuy1Meliy8otwiOa+a -mH6pxxUgUNggjyjO5qx+rl25mMjvGIRX4/L1QwIBXJBVi3SgvJW1COZxZqBYqj9U -8HVT07mWKFEDf0rZLeUE2jTm16cF9fcW4DQhW+sfYm+hi2sY3HeMuwlUBK9KHfW2 -+bGeDzVZ4pqfUEudABEBAAEAA/0bemib+wxub9IyVFUp7nPobjQC83qxLSNzrGI/ -RHzgu/5CQi4tfLOnwbcQsLELfker2hYnjsLrT9PURqK4F7udrWEoZ1I1LymOtLG/ -4tNZ7Mnul3wRC2tCn7FKx8sGJwGh/3li8vZ6ALVJAyOia5TZ/buX0+QZzt6+hPKk -7MU1WQIA4bUBjtrsqDwro94DvPj3/jBnMZbXr6WZIItLNeVDUcM8oHL807Am97K1 -ueO/f6v1sGAHG6lVPTmtekqPSTWBfwIA7CGFvEyvSALfB8NUa6jtk27NCiw0csql -kuhCmwXGMVOiryKEfegkIahf2bAd/gnWHPrpWp7bUE20v8YoW22I4wIAhnm5Wr5Q -Sy7EHDUxmJm5TzadFp9gq08qNzHBpXSYXXJ3JuWcL1/awUqp3tE1I6zZ0hZ38Ia6 -SdBMN88idnhDPqPoiKUEGAECAA8FAkO3YdACGyAFCQHhM4AACgkQQZUwSa4UDezm -vQP/ZhK+2ly9oI2z7ZcNC/BJRch0/ybQ3haahII8pXXmOThpZohr/LUgoWgCZdXg -vP6yiszNk2tIs8KphCAw7Lw/qzDC2hEORjWO4f46qk73RAgSqG/GyzI4ltWiDhqn -vnQCFl3+QFSe4zinqykHnLwGPMXv428d/ZjkIc2ju8dRsn4= -=CR5w ------END PGP PRIVATE KEY BLOCK----- -" | openpgp2ssh 4129E89D17C1D591 >/dev/null 2>/dev/null - -} - # remove all lines with specified string from specified file remove_line() { local file diff --git a/src/share/m/subkey_to_ssh_agent b/src/share/m/subkey_to_ssh_agent index 4ce14f8..ec596bd 100644 --- a/src/share/m/subkey_to_ssh_agent +++ b/src/share/m/subkey_to_ssh_agent @@ -26,14 +26,6 @@ subkey_to_ssh_agent() { local publine local kname - if ! test_gnu_dummy_s2k_extension ; then - failure "Your version of GnuTLS does not seem capable of using with gpg's exported subkeys. -You may want to consider patching or upgrading to GnuTLS 2.6 or later. - -For more details, see: - http://lists.gnu.org/archive/html/gnutls-devel/2008-08/msg00005.html" - fi - # if there's no agent running, don't bother: if [ -z "$SSH_AUTH_SOCK" ] || ! which ssh-add >/dev/null ; then failure "No ssh-agent available." -- cgit v1.2.3 From 2c427b22f6a780cbf0d4e22fce26071727e985a1 Mon Sep 17 00:00:00 2001 From: Daniel Kahn Gillmor Date: Sun, 1 Mar 2009 11:45:38 -0500 Subject: transition to the perl-based keytrans implementation. --- Makefile | 12 +- src/keytrans/Makefile | 15 - src/keytrans/gnutls-helpers.c | 466 ------------------------- src/keytrans/gnutls-helpers.h | 89 ----- src/keytrans/openpgp2ssh.c | 507 --------------------------- src/keytrans/pem2openpgp | 775 ------------------------------------------ src/openpgp2ssh | 1 + src/pem2openpgp | 1 + src/share/keytrans | 775 ++++++++++++++++++++++++++++++++++++++++++ 9 files changed, 783 insertions(+), 1858 deletions(-) delete mode 100644 src/keytrans/Makefile delete mode 100644 src/keytrans/gnutls-helpers.c delete mode 100644 src/keytrans/gnutls-helpers.h delete mode 100644 src/keytrans/openpgp2ssh.c delete mode 100755 src/keytrans/pem2openpgp create mode 120000 src/openpgp2ssh create mode 120000 src/pem2openpgp create mode 100755 src/share/keytrans (limited to 'src') diff --git a/Makefile b/Makefile index 0284a8a..2c6077e 100755 --- a/Makefile +++ b/Makefile @@ -14,10 +14,8 @@ ETCSUFFIX ?= PREFIX ?= /usr MANPREFIX ?= $(PREFIX)/share/man -all: keytrans - -keytrans: - $(MAKE) -C src/keytrans +# nothing actually needs to be built now. +all: tarball: clean rm -rf monkeysphere-$(MONKEYSPHERE_VERSION) @@ -40,7 +38,6 @@ freebsd-distinfo: ./utils/build-freebsd-distinfo clean: - $(MAKE) -C src/keytrans clean # clean up old monkeysphere packages lying around as well. rm -f monkeysphere_* @@ -52,9 +49,12 @@ install: all installman mkdir -p $(DESTDIR)$(ETCPREFIX)/etc/monkeysphere mkdir -p $(DESTDIR)$(PREFIX)/share/doc/monkeysphere install -m 0644 VERSION $(DESTDIR)$(PREFIX)/share/monkeysphere - install src/monkeysphere src/keytrans/openpgp2ssh src/keytrans/pem2openpgp $(DESTDIR)$(PREFIX)/bin + install src/monkeysphere $(DESTDIR)$(PREFIX)/bin install src/monkeysphere-host src/monkeysphere-authentication $(DESTDIR)$(PREFIX)/sbin install -m 0644 src/share/common $(DESTDIR)$(PREFIX)/share/monkeysphere + install -m 0755 src/share/keytrans $(DESTDIR)$(PREFIX)/share/monkeysphere + ln -s ../share/monkeysphere/keytrans $(DESTDIR)$(PREFIX)/bin/pem2openpgp + ln -s ../share/monkeysphere/keytrans $(DESTDIR)$(PREFIX)/bin/openpgp2ssh install -m 0744 src/transitions/* $(DESTDIR)$(PREFIX)/share/monkeysphere/transitions install -m 0644 src/transitions/README.txt $(DESTDIR)$(PREFIX)/share/monkeysphere/transitions install -m 0644 src/share/m/* $(DESTDIR)$(PREFIX)/share/monkeysphere/m diff --git a/src/keytrans/Makefile b/src/keytrans/Makefile deleted file mode 100644 index 4d54be7..0000000 --- a/src/keytrans/Makefile +++ /dev/null @@ -1,15 +0,0 @@ -CFLAGS=`libgnutls-config --libs --cflags` -g -Wall --pedantic -CC=gcc - -all: openpgp2ssh - -openpgp2ssh: openpgp2ssh.c gnutls-helpers.o - $(CC) $(CFLAGS) -o openpgp2ssh openpgp2ssh.c gnutls-helpers.o - -.c.o: - $(CC) $(CFLAGS) -c $< - -clean: - rm -f openpgp2ssh *.o - -.PHONY: clean all diff --git a/src/keytrans/gnutls-helpers.c b/src/keytrans/gnutls-helpers.c deleted file mode 100644 index 8d8ec17..0000000 --- a/src/keytrans/gnutls-helpers.c +++ /dev/null @@ -1,466 +0,0 @@ -/* Author: Daniel Kahn Gillmor */ -/* Date: Fri, 04 Apr 2008 19:31:16 -0400 */ -/* License: GPL v3 or later */ - -#include "gnutls-helpers.h" -/* for htonl() */ -#include - -/* for setlocale() */ -#include - -/* for isalnum() */ -#include - -/* for exit() */ -#include - -#include - -/* higher levels allow more frivolous error messages through. - this is set with the MONKEYSPHERE_DEBUG variable */ -static int loglevel = 0; - -void err(int level, const char* fmt, ...) { - va_list ap; - if (level > loglevel) - return; - va_start(ap, fmt); - vfprintf(stderr, fmt, ap); - va_end(ap); - fflush(stderr); -} - -void logfunc(int level, const char* string) { - fprintf(stderr, "GnuTLS Logging (%d): %s\n", level, string); -} - -void init_keyid(gnutls_openpgp_keyid_t keyid) { - memset(keyid, 'x', sizeof(gnutls_openpgp_keyid_t)); -} - - - -void make_keyid_printable(printable_keyid out, gnutls_openpgp_keyid_t keyid) -{ - assert(sizeof(out) >= 2*sizeof(keyid)); - hex_print_data((char*)out, (const unsigned char*)keyid, sizeof(keyid)); -} - -/* you must have twice as many bytes in the out buffer as in the in buffer */ -void hex_print_data(char* out, const unsigned char* in, size_t incount) -{ - static const char hex[16] = "0123456789ABCDEF"; - unsigned int inix = 0, outix = 0; - - while (inix < incount) { - out[outix] = hex[(in[inix] >> 4) & 0x0f]; - out[outix + 1] = hex[in[inix] & 0x0f]; - inix++; - outix += 2; - } -} - -unsigned char hex2bin(unsigned char x) { - if ((x >= '0') && (x <= '9')) - return x - '0'; - if ((x >= 'A') && (x <= 'F')) - return 10 + x - 'A'; - if ((x >= 'a') && (x <= 'f')) - return 10 + x - 'a'; - return 0xff; -} - -void collapse_printable_keyid(gnutls_openpgp_keyid_t out, printable_keyid in) { - unsigned int pkix = 0, outkix = 0; - while (pkix < sizeof(printable_keyid)) { - unsigned hi = hex2bin(in[pkix]); - unsigned lo = hex2bin(in[pkix + 1]); - if (hi == 0xff) { - err(0, "character '%c' is not a hex char\n", in[pkix]); - exit(1); - } - if (lo == 0xff) { - err(0, "character '%c' is not a hex char\n", in[pkix + 1]); - exit(1); - } - out[outkix] = lo | (hi << 4); - - pkix += 2; - outkix++; - } -} - -unsigned int hexstring2bin(unsigned char* out, const char* in) { - unsigned int pkix = 0, outkix = 0; - int hi = 0; /* which nybble is it? */ - - while (in[pkix]) { - unsigned char z = hex2bin(in[pkix]); - if (z != 0xff) { - if (!hi) { - if (out) out[outkix] = (z << 4); - hi = 1; - } else { - if (out) out[outkix] |= z; - hi = 0; - outkix++; - } - pkix++; - } - } - return outkix*8 + (hi ? 4 : 0); -} - -int convert_string_to_keyid(gnutls_openpgp_keyid_t out, const char* str) { - printable_keyid p; - int ret; - - ret = convert_string_to_printable_keyid(p, str); - if (ret == 0) - collapse_printable_keyid(out, p); - return ret; -} -int convert_string_to_printable_keyid(printable_keyid pkeyid, const char* str) { - int arglen, x; - arglen = 0; - x = 0; - while ((arglen <= sizeof(printable_keyid)) && - (str[x] != '\0')) { - if (isxdigit(str[x])) { - if (arglen == sizeof(printable_keyid)) { - err(0, "There are more than %d hex digits in the keyid '%s'\n", sizeof(printable_keyid), str); - return 1; - } - pkeyid[arglen] = str[x]; - arglen++; - } - x++; - } - - if (arglen != sizeof(printable_keyid)) { - err(0, "Keyid '%s' is not %d hex digits in length\n", str, sizeof(printable_keyid)); - return 1; - } - return 0; -} - - - -int init_gnutls() { - const char* version = NULL; - const char* debug_string = NULL; - int ret; - - if (debug_string = getenv("MONKEYSPHERE_DEBUG"), debug_string) { - loglevel = atoi(debug_string); - } - - if (ret = gnutls_global_init(), ret) { - err(0, "Failed to do gnutls_global_init() (error: %d)\n", ret); - return 1; - } - - version = gnutls_check_version(NULL); - - if (version) - err(1, "gnutls version: %s\n", version); - else { - err(0, "no gnutls version found!\n"); - return 1; - } - - gnutls_global_set_log_function(logfunc); - - gnutls_global_set_log_level(loglevel); - err(1, "set log level to %d\n", loglevel); - - return 0; -} - -void init_datum(gnutls_datum_t* d) { - d->data = NULL; - d->size = 0; -} -void copy_datum(gnutls_datum_t* dest, const gnutls_datum_t* src) { - dest->data = gnutls_realloc(dest->data, src->size); - dest->size = src->size; - memcpy(dest->data, src->data, src->size); -} -int compare_data(const gnutls_datum_t* a, const gnutls_datum_t* b) { - if (a->size > b->size) { - err(0,"a is larger\n"); - return 1; - } - if (a->size < b->size) { - err(0,"b is larger\n"); - return -1; - } - return memcmp(a->data, b->data, a->size); -} -void free_datum(gnutls_datum_t* d) { - gnutls_free(d->data); - d->data = NULL; - d->size = 0; -} - -/* read the passed-in string, store in a single datum */ -int set_datum_string(gnutls_datum_t* d, const char* s) { - unsigned int x = strlen(s)+1; - unsigned char* c = NULL; - - c = gnutls_realloc(d->data, x); - if (NULL == c) - return -1; - d->data = c; - d->size = x; - memcpy(d->data, s, x); - return 0; -} - -/* read the passed-in file descriptor until EOF, store in a single - datum */ -int set_datum_fd(gnutls_datum_t* d, int fd) { - unsigned int bufsize = 1024; - unsigned int len = 0; - - FILE* f = fdopen(fd, "r"); - if (bufsize > d->size) { - bufsize = 1024; - d->data = gnutls_realloc(d->data, bufsize); - if (d->data == NULL) { - err(0,"out of memory!\n"); - return -1; - } - d->size = bufsize; - } else { - bufsize = d->size; - } - f = fdopen(fd, "r"); - if (NULL == f) { - err(0,"could not fdopen FD %d\n", fd); - } - clearerr(f); - while (!feof(f) && !ferror(f)) { - if (len == bufsize) { - /* allocate more space by doubling: */ - bufsize *= 2; - d->data = gnutls_realloc(d->data, bufsize); - if (d->data == NULL) { - err(0,"out of memory!\n"); - return -1; - }; - d->size = bufsize; - } - len += fread(d->data + len, 1, bufsize - len, f); - /* err(0,"read %d bytes\n", len); */ - } - if (ferror(f)) { - err(0,"Error reading from fd %d (error: %d) (error: %d '%s')\n", fd, ferror(f), errno, strerror(errno)); - return -1; - } - - /* touch up buffer size to match reality: */ - d->data = gnutls_realloc(d->data, len); - d->size = len; - return 0; -} - -/* read the file indicated (by name) in the fname parameter. store - its entire contents in a single datum. */ -int set_datum_file(gnutls_datum_t* d, const char* fname) { - struct stat sbuf; - unsigned char* c = NULL; - FILE* file = NULL; - size_t x = 0; - - if (0 != stat(fname, &sbuf)) { - err(0,"failed to stat '%s'\n", fname); - return -1; - } - - c = gnutls_realloc(d->data, sbuf.st_size); - if (NULL == c) { - err(0,"failed to allocate %d bytes for '%s'\n", sbuf.st_size, fname); - return -1; - } - - d->data = c; - d->size = sbuf.st_size; - file = fopen(fname, "r"); - if (NULL == file) { - err(0,"failed to open '%s' for reading\n", fname); - return -1; - } - - x = fread(d->data, d->size, 1, file); - if (x != 1) { - err(0,"tried to read %d bytes, read %d instead from '%s'\n", d->size, x, fname); - fclose(file); - return -1; - } - fclose(file); - return 0; -} - -int write_datum_fd(int fd, const gnutls_datum_t* d) { - if (d->size != write(fd, d->data, d->size)) { - err(0,"failed to write body of datum.\n"); - return -1; - } - return 0; -} - - -int write_datum_fd_with_length(int fd, const gnutls_datum_t* d) { - uint32_t len; - int looks_negative = (d->data[0] & 0x80); - unsigned char zero = 0; - - /* if the first bit is 1, then the datum will appear negative in the - MPI encoding style used by OpenSSH. In that case, we'll increase - the length by one, and dump out one more byte */ - - if (looks_negative) { - len = htonl(d->size + 1); - } else { - len = htonl(d->size); - } - if (write(fd, &len, sizeof(len)) != sizeof(len)) { - err(0,"failed to write size of datum.\n"); - return -2; - } - if (looks_negative) { - if (write(fd, &zero, 1) != 1) { - err(0,"failed to write padding byte for MPI.\n"); - return -2; - } - } - return write_datum_fd(fd, d); -} - -int write_data_fd_with_length(int fd, const gnutls_datum_t** d, unsigned int num) { - unsigned int i; - int ret; - - for (i = 0; i < num; i++) - if (ret = write_datum_fd_with_length(fd, d[i]), ret != 0) - return ret; - - return 0; -} - - -int datum_from_string(gnutls_datum_t* d, const char* str) { - d->size = strlen(str); - d->data = gnutls_realloc(d->data, d->size); - if (d->data == 0) - return ENOMEM; - memcpy(d->data, str, d->size); - return 0; -} - - -int create_writing_pipe(pid_t* pid, const char* path, char* const argv[]) { - int p[2]; - int ret; - - if (pid == NULL) { - err(0,"bad pointer passed to create_writing_pipe()\n"); - return -1; - } - - if (ret = pipe(p), ret == -1) { - err(0,"failed to create a pipe (error: %d \"%s\")\n", errno, strerror(errno)); - return -1; - } - - *pid = fork(); - if (*pid == -1) { - err(0,"Failed to fork (error: %d \"%s\")\n", errno, strerror(errno)); - return -1; - } - if (*pid == 0) { /* this is the child */ - close(p[1]); /* close unused write end */ - - if (0 != dup2(p[0], 0)) { /* map the reading end into stdin */ - err(0,"Failed to transfer reading file descriptor to stdin (error: %d \"%s\")\n", errno, strerror(errno)); - exit(1); - } - execvp(path, argv); - err(0,"exec %s failed (error: %d \"%s\")\n", path, errno, strerror(errno)); - /* close the open file descriptors */ - close(p[0]); - close(0); - - exit(1); - } else { /* this is the parent */ - close(p[0]); /* close unused read end */ - return p[1]; - } -} - -int validate_ssh_host_userid(const char* userid) { - char* oldlocale = setlocale(LC_ALL, "C"); - - /* choke if userid does not match the expected format - ("ssh://fully.qualified.domain.name") */ - if (strncmp("ssh://", userid, strlen("ssh://")) != 0) { - err(0,"The user ID should start with ssh:// for a host key\n"); - goto fail; - } - /* so that isalnum will work properly */ - userid += strlen("ssh://"); - while (0 != (*userid)) { - if (!isalnum(*userid)) { - err(0,"label did not start with a letter or a digit! (%s)\n", userid); - goto fail; - } - userid++; - while (isalnum(*userid) || ('-' == (*userid))) - userid++; - if (('.' == (*userid)) || (0 == (*userid))) { /* clean end of label: - check last char - isalnum */ - if (!isalnum(*(userid - 1))) { - err(0,"label did not end with a letter or a digit!\n"); - goto fail; - } - if ('.' == (*userid)) /* advance to the start of the next label */ - userid++; - } else { - err(0,"invalid character in domain name: %c\n", *userid); - goto fail; - } - } - /* ensure that the last character is valid: */ - if (!isalnum(*(userid - 1))) { - err(0,"hostname did not end with a letter or a digit!\n"); - goto fail; - } - /* FIXME: fqdn's can be unicode now, thanks to RFC 3490 -- how do we - make sure that we've got an OK string? */ - - return 0; - - fail: - setlocale(LC_ALL, oldlocale); - return 1; -} - -/* http://tools.ietf.org/html/rfc4880#section-5.5.2 */ -size_t get_openpgp_mpi_size(gnutls_datum_t* d) { - return 2 + d->size; -} - -int write_openpgp_mpi_to_fd(int fd, gnutls_datum_t* d) { - uint16_t x; - - x = d->size * 8; - x = htons(x); - - write(fd, &x, sizeof(x)); - write(fd, d->data, d->size); - - return 0; -} diff --git a/src/keytrans/gnutls-helpers.h b/src/keytrans/gnutls-helpers.h deleted file mode 100644 index bf54af0..0000000 --- a/src/keytrans/gnutls-helpers.h +++ /dev/null @@ -1,89 +0,0 @@ -/* Author: Daniel Kahn Gillmor */ -/* Date: Fri, 04 Apr 2008 19:31:16 -0400 */ -/* License: GPL v3 or later */ - - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* Functions to help dealing with GnuTLS for monkeysphere key - translation projects: */ - -/* set everything up, including logging levels. Return 0 on - success */ -int init_gnutls(); - -/* logging and output functions: */ - -void err(int level, const char* fmt, ...); -void logfunc(int level, const char* string); - -/* basic datum manipulations: */ - -void init_datum(gnutls_datum_t* d); -void copy_datum(gnutls_datum_t* dest, const gnutls_datum_t* src); -int compare_data(const gnutls_datum_t* a, const gnutls_datum_t* b); -void free_datum(gnutls_datum_t* d); -int write_datum_fd(int fd, const gnutls_datum_t* d); -int write_datum_fd_with_length(int fd, const gnutls_datum_t* d); -int write_data_fd_with_length(int fd, const gnutls_datum_t** d, unsigned int num); - -/* set up a datum from a null-terminated string */ -int datum_from_string(gnutls_datum_t* d, const char* str); - -/* keyid manipulations: */ -typedef unsigned char printable_keyid[16]; - -void init_keyid(gnutls_openpgp_keyid_t keyid); -void make_keyid_printable(printable_keyid out, gnutls_openpgp_keyid_t keyid); -void collapse_printable_keyid(gnutls_openpgp_keyid_t out, printable_keyid in); -int convert_string_to_keyid(gnutls_openpgp_keyid_t out, const char* str); -int convert_string_to_printable_keyid(printable_keyid out, const char* str); - -/* you must have twice as many bytes in the out buffer as in the in buffer */ -void hex_print_data(char* out, const unsigned char* in, size_t incount); - -/* expects a null-terminated string as in, containing an even number - of hexadecimal characters. - - returns length in *bits* of raw data as output. - - the out buffer must be at least half as long as in to hold the - output. if out is NULL, no output will be generated, but the - length will still be returned. -*/ -unsigned int hexstring2bin(unsigned char* out, const char* in); - -/* functions to get data into datum objects: */ - -/* read the passed-in string, store in a single datum */ -int set_datum_string(gnutls_datum_t* d, const char* s); - -/* read the passed-in file descriptor until EOF, store in a single - datum */ -int set_datum_fd(gnutls_datum_t* d, int fd); - -/* read the file indicated (by name) in the fname parameter. store - its entire contents in a single datum. */ -int set_datum_file(gnutls_datum_t* d, const char* fname); - -/* set up file descriptor pipe for writing (child process pid gets - stored in pid, fd is returned)*/ -int create_writing_pipe(pid_t* pid, const char* path, char* const argv[]); - -/* return 0 if userid matches the monkeysphere spec for ssh host user IDs */ -int validate_ssh_host_userid(const char* userid); - -/* how many bytes will it take to write out this datum in OpenPGP MPI form? */ -size_t get_openpgp_mpi_size(gnutls_datum_t* d); - -/* write the MPI stored in gnutls_datum_t to file descriptor fd: */ -int write_openpgp_mpi_to_fd(int fd, gnutls_datum_t* d); diff --git a/src/keytrans/openpgp2ssh.c b/src/keytrans/openpgp2ssh.c deleted file mode 100644 index f16eac5..0000000 --- a/src/keytrans/openpgp2ssh.c +++ /dev/null @@ -1,507 +0,0 @@ -#include "gnutls-helpers.h" - -#include -#include - -/* for waitpid() */ -#include -#include - -/* - Author: Daniel Kahn Gillmor - Date: 2008-06-12 13:47:41-0400 - License: GPL v3 or later - - monkeysphere key translator: execute this with an OpenPGP key on - stdin, (please indicate the specific keyid that you want as the - first argument if there are subkeys). At the moment, only public - keys and passphraseless secret keys work. - - For secret keys, it will spit out a PEM-encoded version of the key - on stdout, which can be fed into ssh-add like this: - - gpg --export-secret-keys $KEYID | openpgp2ssh $KEYID | ssh-add -c /dev/stdin - - For public keys, it will spit out a single line of text that can - (with some massaging) be used in an openssh known_hosts or - authorized_keys file. For example: - - echo server.example.org $(gpg --export $KEYID | openpgp2ssh $KEYID) >> ~/.ssh/known_hosts - - Requirements: I've only built this so far with GnuTLS v2.3.x. - GnuTLS 2.2.x does not contain the appropriate functionality. - - */ - - -/* FIXME: keyid should be const as well */ -int convert_private_pgp_to_x509(gnutls_x509_privkey_t* output, const gnutls_openpgp_privkey_t* pgp_privkey, const unsigned char* keyfpr, unsigned int fprlen) { - gnutls_datum_t m, e, d, p, q, u, g, y, x; - gnutls_pk_algorithm_t pgp_algo; - unsigned int pgp_bits; - int ret; - int subkeyidx; - int subkeycount; - int found = 0; - unsigned char fingerprint[20]; - size_t fingerprint_length = sizeof(fingerprint); - - init_datum(&m); - init_datum(&e); - init_datum(&d); - init_datum(&p); - init_datum(&q); - init_datum(&u); - init_datum(&g); - init_datum(&y); - init_datum(&x); - - subkeycount = gnutls_openpgp_privkey_get_subkey_count(*pgp_privkey); - if (subkeycount < 0) { - err(0,"Could not determine subkey count (got value %d)\n", subkeycount); - return 1; - } - - if ((keyfpr == NULL) && - (subkeycount > 0)) { - err(0,"No key identifier passed in, but there were %d keys to choose from\n", subkeycount + 1); - return 1; - } - - if (keyfpr != NULL) { - ret = gnutls_openpgp_privkey_get_fingerprint(*pgp_privkey, fingerprint, &fingerprint_length); - if (ret) { - err(0,"Could not get fingerprint (error: %d)\n", ret); - return 1; - } - if (fprlen > fingerprint_length) { - err(0, "Requested key identifier is longer than computed fingerprint\n"); - return 1; - } - if (fingerprint_length > fprlen) { - err(0, "Only comparing last %d bits of key fingerprint\n", fprlen*8); - } - } - if ((keyfpr == NULL) || (memcmp(fingerprint + (fingerprint_length - fprlen), keyfpr, fprlen) == 0)) { - /* we want to export the primary key: */ - err(0,"exporting primary key\n"); - - /* FIXME: this is almost identical to the block below for subkeys. - This clumsiness seems inherent in the gnutls OpenPGP API, - though. ugh. */ - pgp_algo = gnutls_openpgp_privkey_get_pk_algorithm(*pgp_privkey, &pgp_bits); - if (pgp_algo < 0) { - err(0, "failed to get OpenPGP key algorithm (error: %d)\n", pgp_algo); - return 1; - } - if (pgp_algo == GNUTLS_PK_RSA) { - err(0,"OpenPGP RSA Key, with %d bits\n", pgp_bits); - ret = gnutls_openpgp_privkey_export_rsa_raw(*pgp_privkey, &m, &e, &d, &p, &q, &u); - if (GNUTLS_E_SUCCESS != ret) { - err(0, "failed to export RSA key parameters (error: %d)\n", ret); - return 1; - } - - } else if (pgp_algo == GNUTLS_PK_DSA) { - err(0,"OpenPGP DSA Key, with %d bits\n", pgp_bits); - ret = gnutls_openpgp_privkey_export_dsa_raw(*pgp_privkey, &p, &q, &g, &y, &x); - if (GNUTLS_E_SUCCESS != ret) { - err(0,"failed to export DSA key parameters (error: %d)\n", ret); - return 1; - } - } - found = 1; - } else { - /* lets trawl through the subkeys until we find the one we want: */ - for (subkeyidx = 0; (subkeyidx < subkeycount) && !found; subkeyidx++) { - ret = gnutls_openpgp_privkey_get_subkey_fingerprint(*pgp_privkey, subkeyidx, fingerprint, &fingerprint_length); - if (ret) { - err(0,"Could not get fingerprint of subkey with index %d (error: %d)\n", subkeyidx, ret); - return 1; - } - if (fprlen > fingerprint_length) { - err(0, "Requested key identifier is longer than computed fingerprint\n"); - return 1; - } - if (fingerprint_length > fprlen) { - err(1, "Only comparing last %d bits of key fingerprint\n", fprlen*8); - } - if (memcmp(fingerprint + (fingerprint_length - fprlen), keyfpr, fprlen) == 0) { - err(0,"exporting subkey index %d\n", subkeyidx); - - /* FIXME: this is almost identical to the block above for the - primary key. */ - pgp_algo = gnutls_openpgp_privkey_get_subkey_pk_algorithm(*pgp_privkey, subkeyidx, &pgp_bits); - if (pgp_algo < 0) { - err(0,"failed to get the algorithm of the OpenPGP public key (error: %d)\n", pgp_algo); - return pgp_algo; - } else if (pgp_algo == GNUTLS_PK_RSA) { - err(0,"OpenPGP RSA key, with %d bits\n", pgp_bits); - ret = gnutls_openpgp_privkey_export_subkey_rsa_raw(*pgp_privkey, subkeyidx, &m, &e, &d, &p, &q, &u); - if (GNUTLS_E_SUCCESS != ret) { - err(0,"failed to export RSA key parameters (error: %d)\n", ret); - return 1; - } - } else if (pgp_algo == GNUTLS_PK_DSA) { - err(0,"OpenPGP DSA Key, with %d bits\n", pgp_bits); - ret = gnutls_openpgp_privkey_export_subkey_dsa_raw(*pgp_privkey, subkeyidx, &p, &q, &g, &y, &x); - if (GNUTLS_E_SUCCESS != ret) { - err(0,"failed to export DSA key parameters (error: %d)\n", ret); - return 1; - } - } - found = 1; - } - } - } - - if (!found) { - err(0,"Could not find key in input\n"); - return 1; - } - - if (pgp_algo == GNUTLS_PK_RSA) { - ret = gnutls_x509_privkey_import_rsa_raw (*output, &m, &e, &d, &p, &q, &u); - if (GNUTLS_E_SUCCESS != ret) { - err(0, "failed to import RSA key parameters (error: %d)\n", ret); - return 1; - } - } else if (pgp_algo == GNUTLS_PK_DSA) { - ret = gnutls_x509_privkey_import_dsa_raw (*output, &p, &q, &g, &y, &x); - if (GNUTLS_E_SUCCESS != ret) { - err(0,"failed to import DSA key parameters (error: %d)\n", ret); - return 1; - } - } else { - err(0,"OpenPGP Key was not RSA or DSA -- can't deal! (actual algorithm was: %d)\n", pgp_algo); - return 1; - } - - ret = gnutls_x509_privkey_fix(*output); - if (ret != 0) { - err(0,"failed to fix up the private key in X.509 format (error: %d)\n", ret); - return 1; - } - - return 0; -} - -/* FIXME: keyid should be const also */ -int emit_public_openssh_from_pgp(const gnutls_openpgp_crt_t* pgp_crt, const unsigned char* keyfpr, size_t fprlen) { - int ret; - int subkeyidx; - int subkeycount; - int found = 0; - gnutls_datum_t m, e, p, q, g, y, algolabel; - unsigned int bits; - gnutls_pk_algorithm_t algo; - const gnutls_datum_t* all[5]; - const char* algoname; - int mpicount; - /* output_data must be at least 2 chars longer than the maximum possible - algorithm name: */ - char output_data[20]; - - unsigned char fingerprint[20]; - size_t fingerprint_length = sizeof(fingerprint); - - /* variables for the output conversion: */ - int pipestatus; - int pipefd, child_pid; - char* const b64args[] = {"sh", "-c", "base64 | tr -c -d '[A-Za-z0-9=+/]'", NULL}; - - init_datum(&m); - init_datum(&e); - init_datum(&p); - init_datum(&q); - init_datum(&g); - init_datum(&algolabel); - - - /* figure out if we've got the right thing: */ - subkeycount = gnutls_openpgp_crt_get_subkey_count(*pgp_crt); - if (subkeycount < 0) { - err(0,"Could not determine subkey count (got value %d)\n", subkeycount); - return 1; - } - - if ((keyfpr == NULL) && - (subkeycount > 0)) { - err(0,"No key identifier passed in, but there were %d keys to choose from\n", subkeycount + 1); - return 1; - } - - if (keyfpr != NULL) { - ret = gnutls_openpgp_crt_get_fingerprint(*pgp_crt, fingerprint, &fingerprint_length); - if (ret) { - err(0,"Could not get key fingerprint (error: %d)\n", ret); - return 1; - } - if (fprlen > fingerprint_length) { - err(0, "Requested key identifier is longer than computed fingerprint\n"); - return 1; - } - if (fingerprint_length > fprlen) { - err(0, "Only comparing last %d bits of key fingerprint\n", fprlen*8); - } - } - if ((keyfpr == NULL) || (memcmp(fingerprint + (fingerprint_length - fprlen), keyfpr, fprlen) == 0)) { - /* we want to export the primary key: */ - err(0,"exporting primary key\n"); - - /* FIXME: this is almost identical to the block below for subkeys. - This clumsiness seems inherent in the gnutls OpenPGP API, - though. ugh. */ - algo = gnutls_openpgp_crt_get_pk_algorithm(*pgp_crt, &bits); - if (algo < 0) { - err(0,"failed to get the algorithm of the OpenPGP public key (error: %d)\n", algo); - return algo; - } else if (algo == GNUTLS_PK_RSA) { - err(0,"OpenPGP RSA certificate, with %d bits\n", bits); - ret = gnutls_openpgp_crt_get_pk_rsa_raw(*pgp_crt, &m, &e); - if (GNUTLS_E_SUCCESS != ret) { - err(0,"failed to export RSA certificate parameters (error: %d)\n", ret); - return 1; - } - } else if (algo == GNUTLS_PK_DSA) { - err(0,"OpenPGP DSA certificate, with %d bits\n", bits); - ret = gnutls_openpgp_crt_get_pk_dsa_raw(*pgp_crt, &p, &q, &g, &y); - if (GNUTLS_E_SUCCESS != ret) { - err(0,"failed to export DSA certificate parameters (error: %d)\n", ret); - return 1; - } - } - found = 1; - - } else { - /* lets trawl through the subkeys until we find the one we want: */ - for (subkeyidx = 0; (subkeyidx < subkeycount) && !found; subkeyidx++) { - ret = gnutls_openpgp_crt_get_subkey_fingerprint(*pgp_crt, subkeyidx, fingerprint, &fingerprint_length); - if (ret) { - err(0,"Could not get fingerprint of subkey with index %d (error: %d)\n", subkeyidx, ret); - return 1; - } - if (fprlen > fingerprint_length) { - err(0, "Requested key identifier is longer than computed fingerprint\n"); - return 1; - } - if (fingerprint_length > fprlen) { - err(1, "Only comparing last %d bits of key fingerprint\n", fprlen*8); - } - if (memcmp(fingerprint + (fingerprint_length - fprlen), keyfpr, fprlen) == 0) { - err(0,"exporting subkey index %d\n", subkeyidx); - - /* FIXME: this is almost identical to the block above for the - primary key. */ - algo = gnutls_openpgp_crt_get_subkey_pk_algorithm(*pgp_crt, subkeyidx, &bits); - if (algo < 0) { - err(0,"failed to get the algorithm of the OpenPGP public key (error: %d)\n", algo); - return algo; - } else if (algo == GNUTLS_PK_RSA) { - err(0,"OpenPGP RSA certificate, with %d bits\n", bits); - ret = gnutls_openpgp_crt_get_subkey_pk_rsa_raw(*pgp_crt, subkeyidx, &m, &e); - if (GNUTLS_E_SUCCESS != ret) { - err(0,"failed to export RSA certificate parameters (error: %d)\n", ret); - return 1; - } - } else if (algo == GNUTLS_PK_DSA) { - err(0,"OpenPGP DSA certificate, with %d bits\n", bits); - ret = gnutls_openpgp_crt_get_subkey_pk_dsa_raw(*pgp_crt, subkeyidx, &p, &q, &g, &y); - if (GNUTLS_E_SUCCESS != ret) { - err(0,"failed to export DSA certificate parameters (error: %d)\n", ret); - return 1; - } - } - found = 1; - - } - } - } - - if (!found) { - err(0,"Could not find key in input\n"); - return 1; - } - - /* if we made it this far, we've got MPIs, and we've got the - algorithm, so we just need to emit the info */ - if (algo == GNUTLS_PK_RSA) { - algoname = "ssh-rsa"; - mpicount = 3; - - all[0] = &algolabel; - all[1] = &e; - all[2] = &m; - } else if (algo == GNUTLS_PK_DSA) { - algoname = "ssh-dss"; - mpicount = 5; - - all[0] = &algolabel; - all[1] = &p; - all[2] = &q; - all[3] = &g; - all[4] = &y; - } else { - err(0,"Key algorithm was neither DSA nor RSA (it was %d). Can't deal. Sorry!\n", algo); - return 1; - } - - if (ret = datum_from_string(&algolabel, algoname), ret) { - err(0,"couldn't label string (error: %d)\n", ret); - return ret; - } - - snprintf(output_data, sizeof(output_data), "%s ", algoname); - - pipefd = create_writing_pipe(&child_pid, b64args[0], b64args); - if (pipefd < 0) { - err(0,"failed to create a writing pipe (returned %d)\n", pipefd); - return pipefd; - } - - write(1, output_data, strlen(output_data)); - - if (0 != write_data_fd_with_length(pipefd, all, mpicount)) { - err(0,"was not able to write out RSA key data\n"); - return 1; - } - close(pipefd); - if (child_pid != waitpid(child_pid, &pipestatus, 0)) { - err(0,"could not wait for child process to return for some reason.\n"); - return 1; - } - if (pipestatus != 0) { - err(0,"base64 pipe died with return code %d\n", pipestatus); - return pipestatus; - } - - write(1, "\n", 1); - - return 0; -} - -int main(int argc, char* argv[]) { - gnutls_datum_t data; - int ret = 0; - gnutls_x509_privkey_t x509_privkey; - gnutls_openpgp_privkey_t pgp_privkey; - gnutls_openpgp_crt_t pgp_crt; - - char output_data[10240]; - size_t ods = sizeof(output_data); - - unsigned char * fingerprint = NULL; - size_t fpr_size; - char * prettyfpr = NULL; - - init_gnutls(); - - /* figure out what key we should be looking for: */ - if (argv[1] != NULL) { - if (strlen(argv[1]) > 81) { - /* safety check to avoid some sort of wacky overflow situation: - there's no reason that the key id should be longer than twice - a sane fingerprint (one byte between chars, and then another - two at the beginning and end) */ - err(0, "Key identifier is way too long. Please use at most 40 hex digits.\n"); - return 1; - } - - fpr_size = hexstring2bin(NULL, argv[1]); - if (fpr_size > 40*4) { - err(0, "Key identifier is longer than 40 hex digits\n"); - return 1; - } - /* since fpr_size is initially in bits: */ - if (fpr_size % 8 != 0) { - err(0, "Please provide an even number of hex digits for the key identifier\n"); - return 1; - } - fpr_size /= 8; - - fingerprint = malloc(sizeof(unsigned char) * fpr_size); - bzero(fingerprint, sizeof(unsigned char) * fpr_size); - hexstring2bin(fingerprint, argv[1]); - - prettyfpr = malloc(sizeof(unsigned char)*fpr_size*2 + 1); - if (prettyfpr != NULL) { - hex_print_data(prettyfpr, fingerprint, fpr_size); - prettyfpr[sizeof(unsigned char)*fpr_size*2] = '\0'; - err(1, "searching for key with fingerprint '%s'\n", prettyfpr); - free(prettyfpr); - } - - if (fpr_size < 4) { - err(0, "You MUST provide at least 8 hex digits in any key identifier\n"); - return 1; - } - if (fpr_size < 8) - err(0, "You should provide at least 16 hex digits in any key identifier (proceeding with %d digits anyway)\n", fpr_size*2); - - } - - - init_datum(&data); - - /* slurp in the key from stdin */ - if (ret = set_datum_fd(&data, 0), ret) { - err(0,"didn't read file descriptor 0\n"); - return 1; - } - - - if (ret = gnutls_openpgp_privkey_init(&pgp_privkey), ret) { - err(0,"Failed to initialized OpenPGP private key (error: %d)\n", ret); - return 1; - } - /* check whether it's a private key or a public key, by trying them: */ - if ((gnutls_openpgp_privkey_import(pgp_privkey, &data, GNUTLS_OPENPGP_FMT_RAW, NULL, 0) == 0) || - (gnutls_openpgp_privkey_import(pgp_privkey, &data, GNUTLS_OPENPGP_FMT_BASE64, NULL, 0) == 0)) { - /* we're dealing with a private key */ - err(0,"Translating private key\n"); - if (ret = gnutls_x509_privkey_init(&x509_privkey), ret) { - err(0,"Failed to initialize X.509 private key for output (error: %d)\n", ret); - return 1; - } - - ret = convert_private_pgp_to_x509(&x509_privkey, &pgp_privkey, fingerprint, fpr_size); - - gnutls_openpgp_privkey_deinit(pgp_privkey); - if (ret) - return ret; - - ret = gnutls_x509_privkey_export (x509_privkey, - GNUTLS_X509_FMT_PEM, - output_data, - &ods); - if (ret == 0) { - write(1, output_data, ods); - } - gnutls_x509_privkey_deinit(x509_privkey); - - } else { - if (ret = gnutls_openpgp_crt_init(&pgp_crt), ret) { - err(0,"Failed to initialized OpenPGP certificate (error: %d)\n", ret); - return 1; - } - - if ((gnutls_openpgp_crt_import(pgp_crt, &data, GNUTLS_OPENPGP_FMT_RAW) == 0) || - (gnutls_openpgp_crt_import(pgp_crt, &data, GNUTLS_OPENPGP_FMT_BASE64) == 0)) { - /* we're dealing with a public key */ - err(0,"Translating public key\n"); - - ret = emit_public_openssh_from_pgp(&pgp_crt, fingerprint, fpr_size); - if (ret != 0) - return ret; - - } else { - /* we have no idea what kind of key this is at all anyway! */ - err(0,"Input does not contain any form of OpenPGP key I recognize.\n"); - return 1; - } - } - - gnutls_global_deinit(); - free(fingerprint); - return 0; -} diff --git a/src/keytrans/pem2openpgp b/src/keytrans/pem2openpgp deleted file mode 100755 index 8bf17fb..0000000 --- a/src/keytrans/pem2openpgp +++ /dev/null @@ -1,775 +0,0 @@ -#!/usr/bin/perl -w -T - -# pem2openpgp: take a PEM-encoded RSA private-key on standard input, a -# User ID as the first argument, and generate an OpenPGP secret key -# and certificate from it. - -# WARNING: the secret key material *will* appear on stdout (albeit in -# OpenPGP form) -- if you redirect stdout to a file, make sure the -# permissions on that file are appropriately locked down! - -# Usage: - -# pem2openpgp 'ssh://'$(hostname -f) < /etc/ssh/ssh_host_rsa_key | gpg --import - -# Authors: -# Jameson Rollins -# Daniel Kahn Gillmor - -# Started on: 2009-01-07 02:01:19-0500 - -# License: GPL v3 or later (we may need to adjust this given that this -# connects to OpenSSL via perl) - -use strict; -use warnings; -use File::Basename; -use Crypt::OpenSSL::RSA; -use Crypt::OpenSSL::Bignum; -use Crypt::OpenSSL::Bignum::CTX; -use Digest::SHA1; -use MIME::Base64; -use POSIX; - -## make sure all length() and substr() calls use bytes only: -use bytes; - -my $old_format_packet_lengths = { one => 0, - two => 1, - four => 2, - indeterminate => 3, -}; - -# see RFC 4880 section 9.1 (ignoring deprecated algorithms for now) -my $asym_algos = { rsa => 1, - elgamal => 16, - dsa => 17, - }; - -# see RFC 4880 section 9.2 -my $ciphers = { plaintext => 0, - idea => 1, - tripledes => 2, - cast5 => 3, - blowfish => 4, - aes128 => 7, - aes192 => 8, - aes256 => 9, - twofish => 10, - }; - -# see RFC 4880 section 9.3 -my $zips = { uncompressed => 0, - zip => 1, - zlib => 2, - bzip2 => 3, - }; - -# see RFC 4880 section 9.4 -my $digests = { md5 => 1, - sha1 => 2, - ripemd160 => 3, - sha256 => 8, - sha384 => 9, - sha512 => 10, - sha224 => 11, - }; - -# see RFC 4880 section 5.2.3.21 -my $usage_flags = { certify => 0x01, - sign => 0x02, - encrypt_comms => 0x04, - encrypt_storage => 0x08, - encrypt => 0x0c, ## both comms and storage - split => 0x10, # the private key is split via secret sharing - authenticate => 0x20, - shared => 0x80, # more than one person holds the entire private key - }; - -# see RFC 4880 section 4.3 -my $packet_types = { pubkey_enc_session => 1, - sig => 2, - symkey_enc_session => 3, - onepass_sig => 4, - seckey => 5, - pubkey => 6, - sec_subkey => 7, - compressed_data => 8, - symenc_data => 9, - marker => 10, - literal => 11, - trust => 12, - uid => 13, - pub_subkey => 14, - uat => 17, - symenc_w_integrity => 18, - mdc => 19, - }; - -# see RFC 4880 section 5.2.1 -my $sig_types = { binary_doc => 0x00, - text_doc => 0x01, - standalone => 0x02, - generic_certification => 0x10, - persona_certification => 0x11, - casual_certification => 0x12, - positive_certification => 0x13, - subkey_binding => 0x18, - primary_key_binding => 0x19, - key_signature => 0x1f, - key_revocation => 0x20, - subkey_revocation => 0x28, - certification_revocation => 0x30, - timestamp => 0x40, - thirdparty => 0x50, - }; - - -# see RFC 4880 section 5.2.3.1 -my $subpacket_types = { sig_creation_time => 2, - sig_expiration_time => 3, - exportable => 4, - trust_sig => 5, - regex => 6, - revocable => 7, - key_expiration_time => 9, - preferred_cipher => 11, - revocation_key => 12, - issuer => 16, - notation => 20, - preferred_digest => 21, - preferred_compression => 22, - keyserver_prefs => 23, - preferred_keyserver => 24, - primary_uid => 25, - policy_uri => 26, - usage_flags => 27, - signers_uid => 28, - revocation_reason => 29, - features => 30, - signature_target => 31, - embedded_signature => 32, - }; - -# bitstring (see RFC 4880 section 5.2.3.24) -my $features = { mdc => 0x01 - }; - -# bitstring (see RFC 4880 5.2.3.17) -my $keyserver_prefs = { nomodify => 0x80 - }; - -###### end lookup tables ###### - -# FIXME: if we want to be able to interpret openpgp data as well as -# produce it, we need to produce key/value-swapped lookup tables as well. - - -########### Math/Utility Functions ############## - - -# see the bottom of page 43 of RFC 4880 -sub simple_checksum { - my $bytes = shift; - - return unpack("%32W*",$bytes) % 65536; -} - -# calculate the multiplicative inverse of a mod b this is euclid's -# extended algorithm. For more information see: -# http://en.wikipedia.org/wiki/Extended_Euclidean_algorithm the -# arguments here should be Crypt::OpenSSL::Bignum objects. $a should -# be the larger of the two values, and the two values should be -# coprime. - -sub modular_multi_inverse { - my $a = shift; - my $b = shift; - - - my $origdivisor = $b->copy(); - - my $ctx = Crypt::OpenSSL::Bignum::CTX->new(); - my $x = Crypt::OpenSSL::Bignum->zero(); - my $y = Crypt::OpenSSL::Bignum->one(); - my $lastx = Crypt::OpenSSL::Bignum->one(); - my $lasty = Crypt::OpenSSL::Bignum->zero(); - - my $finalquotient; - my $finalremainder; - - while (! $b->is_zero()) { - my ($quotient, $remainder) = $a->div($b, $ctx); - - $a = $b; - $b = $remainder; - - my $temp = $x; - $x = $lastx->sub($quotient->mul($x, $ctx)); - $lastx = $temp; - - $temp = $y; - $y = $lasty->sub($quotient->mul($y, $ctx)); - $lasty = $temp; - } - - if (!$a->is_one()) { - die "did this math wrong.\n"; - } - - # let's make sure that we return a positive value because RFC 4880, - # section 3.2 only allows unsigned values: - - ($finalquotient, $finalremainder) = $lastx->add($origdivisor)->div($origdivisor, $ctx); - - return $finalremainder; -} - - -############ OpenPGP formatting functions ############ - -# make an old-style packet out of the given packet type and body. -# old-style (see RFC 4880 section 4.2) -sub make_packet { - my $type = shift; - my $body = shift; - my $options = shift; - - my $len = length($body); - my $pseudolen = $len; - - # if the caller wants to use at least N octets of packet length, - # pretend that we're using that many. - if (defined $options && defined $options->{'packet_length'}) { - $pseudolen = 2**($options->{'packet_length'} * 8) - 1; - } - if ($pseudolen < $len) { - $pseudolen = $len; - } - - my $lenbytes; - my $lencode; - - if ($pseudolen < 2**8) { - $lenbytes = $old_format_packet_lengths->{one}; - $lencode = 'C'; - } elsif ($pseudolen < 2**16) { - $lenbytes = $old_format_packet_lengths->{two}; - $lencode = 'n'; - } elsif ($pseudolen < 2**31) { - ## not testing against full 32 bits because i don't want to deal - ## with potential overflow. - $lenbytes = $old_format_packet_lengths->{four}; - $lencode = 'N'; - } else { - ## what the hell do we do here? - $lenbytes = $old_format_packet_lengths->{indeterminate}; - $lencode = ''; - } - - return pack('C'.$lencode, 0x80 + ($type * 4) + $lenbytes, $len). - $body; -} - - -# takes a Crypt::OpenSSL::Bignum, returns it formatted as OpenPGP MPI -# (RFC 4880 section 3.2) -sub mpi_pack { - my $num = shift; - - my $val = $num->to_bin(); - my $mpilen = length($val)*8; - -# this is a kludgy way to get the number of significant bits in the -# first byte: - my $bitsinfirstbyte = length(sprintf("%b", ord($val))); - - $mpilen -= (8 - $bitsinfirstbyte); - - return pack('n', $mpilen).$val; -} - -# takes a Crypt::OpenSSL::Bignum, returns an MPI packed in preparation -# for an OpenSSH-style public key format. see: -# http://marc.info/?l=openssh-unix-dev&m=121866301718839&w=2 -sub openssh_mpi_pack { - my $num = shift; - - my $val = $num->to_bin(); - my $mpilen = length($val); - - my $ret = pack('N', $mpilen); - - # if the first bit of the leading byte is high, we should include a - # 0 byte: - if (ord($val) & 0x80) { - $ret = pack('NC', $mpilen+1, 0); - } - - return $ret.$val; -} - -sub openssh_pubkey_pack { - my $key = shift; - - my ($modulus, $exponent) = $key->get_key_parameters(); - - return openssh_mpi_pack(Crypt::OpenSSL::Bignum->new_from_bin("ssh-rsa")). - openssh_mpi_pack($exponent). - openssh_mpi_pack($modulus); -} - -# pull an OpenPGP-specified MPI off of a given stream, returning it as -# a Crypt::OpenSSL::Bignum. -sub read_mpi { - my $instr = shift; - my $readtally = shift; - - my $bitlen; - read($instr, $bitlen, 2) or die "could not read MPI length.\n"; - $bitlen = unpack('n', $bitlen); - $$readtally += 2; - - my $bytestoread = POSIX::floor(($bitlen + 7)/8); - my $ret; - read($instr, $ret, $bytestoread) or die "could not read MPI body.\n"; - $$readtally += $bytestoread; - return Crypt::OpenSSL::Bignum->new_from_bin($ret); -} - - -# FIXME: genericize these to accept either RSA or DSA keys: -sub make_rsa_pub_key_body { - my $key = shift; - my $timestamp = shift; - - my ($n, $e) = $key->get_key_parameters(); - - return - pack('CN', 4, $timestamp). - pack('C', $asym_algos->{rsa}). - mpi_pack($n). - mpi_pack($e); -} - -sub make_rsa_sec_key_body { - my $key = shift; - my $timestamp = shift; - - # we're not using $a and $b, but we need them to get to $c. - my ($n, $e, $d, $p, $q) = $key->get_key_parameters(); - - my $c3 = modular_multi_inverse($p, $q); - - my $secret_material = mpi_pack($d). - mpi_pack($p). - mpi_pack($q). - mpi_pack($c3); - - # according to Crypt::OpenSSL::RSA, the closest value we can get out - # of get_key_parameters is 1/q mod p; but according to sec 5.5.3 of - # RFC 4880, we're actually looking for u, the multiplicative inverse - # of p, mod q. This is why we're calculating the value directly - # with modular_multi_inverse. - - return - pack('CN', 4, $timestamp). - pack('C', $asym_algos->{rsa}). - mpi_pack($n). - mpi_pack($e). - pack('C', 0). # seckey material is not encrypted -- see RFC 4880 sec 5.5.3 - $secret_material. - pack('n', simple_checksum($secret_material)); -} - -# expects an RSA key (public or private) and a timestamp -sub fingerprint { - my $key = shift; - my $timestamp = shift; - - my $rsabody = make_rsa_pub_key_body($key, $timestamp); - - return Digest::SHA1::sha1(pack('Cn', 0x99, length($rsabody)).$rsabody); -} - - -# FIXME: handle DSA keys as well! -sub pem2openpgp { - my $rsa = shift; - my $uid = shift; - my $args = shift; - - $rsa->use_sha1_hash(); - - # see page 22 of RFC 4880 for why i think this is the right padding - # choice to use: - $rsa->use_pkcs1_padding(); - - if (! $rsa->check_key()) { - die "key does not check"; - } - - my $version = pack('C', 4); - # strong assertion of identity: - my $sigtype = pack('C', $sig_types->{positive_certification}); - # RSA - my $pubkey_algo = pack('C', $asym_algos->{rsa}); - # SHA1 - my $hash_algo = pack('C', $digests->{sha1}); - - # FIXME: i'm worried about generating a bazillion new OpenPGP - # certificates from the same key, which could easily happen if you run - # this script more than once against the same key (because the - # timestamps will differ). How can we prevent this? - - # this environment variable (if set) overrides the current time, to - # be able to create a standard key? If we read the key from a file - # instead of stdin, should we use the creation time on the file? - my $timestamp = 0; - if (defined $args->{timestamp}) { - $timestamp = ($args->{timestamp} + 0); - } else { - $timestamp = time(); - } - - my $creation_time_packet = pack('CCN', 5, $subpacket_types->{sig_creation_time}, $timestamp); - - - my $flags = 0; - if (! defined $args->{usage_flags}) { - $flags = $usage_flags->{certify}; - } else { - my @ff = split(",", $args->{usage_flags}); - foreach my $f (@ff) { - if (! defined $usage_flags->{$f}) { - die "No such flag $f"; - } - $flags |= $usage_flags->{$f}; - } - } - - my $usage_packet = pack('CCC', 2, $subpacket_types->{usage_flags}, $flags); - - - # how should we determine how far off to set the expiration date? - # default is no expiration. Specify the timestamp in seconds from the - # key creation. - my $expiration_packet = ''; - if (defined $args->{expiration}) { - my $expires_in = $args->{expiration} + 0; - $expiration_packet = pack('CCN', 5, $subpacket_types->{key_expiration_time}, $expires_in); - } - - - # prefer AES-256, AES-192, AES-128, CAST5, 3DES: - my $pref_sym_algos = pack('CCCCCCC', 6, $subpacket_types->{preferred_cipher}, - $ciphers->{aes256}, - $ciphers->{aes192}, - $ciphers->{aes128}, - $ciphers->{cast5}, - $ciphers->{tripledes} - ); - - # prefer SHA-1, SHA-256, RIPE-MD/160 - my $pref_hash_algos = pack('CCCCC', 4, $subpacket_types->{preferred_digest}, - $digests->{sha1}, - $digests->{sha256}, - $digests->{ripemd160} - ); - - # prefer ZLIB, BZip2, ZIP - my $pref_zip_algos = pack('CCCCC', 4, $subpacket_types->{preferred_compression}, - $zips->{zlib}, - $zips->{bzip2}, - $zips->{zip} - ); - - # we support the MDC feature: - my $feature_subpacket = pack('CCC', 2, $subpacket_types->{features}, - $features->{mdc}); - - # keyserver preference: only owner modify (???): - my $keyserver_pref = pack('CCC', 2, $subpacket_types->{keyserver_prefs}, - $keyserver_prefs->{nomodify}); - - my $subpackets_to_be_hashed = - $creation_time_packet. - $usage_packet. - $expiration_packet. - $pref_sym_algos. - $pref_hash_algos. - $pref_zip_algos. - $feature_subpacket. - $keyserver_pref; - - my $subpacket_octets = pack('n', length($subpackets_to_be_hashed)); - - my $sig_data_to_be_hashed = - $version. - $sigtype. - $pubkey_algo. - $hash_algo. - $subpacket_octets. - $subpackets_to_be_hashed; - - my $pubkey = make_rsa_pub_key_body($rsa, $timestamp); - my $seckey = make_rsa_sec_key_body($rsa, $timestamp); - - # this is for signing. it needs to be an old-style header with a - # 2-packet octet count. - - my $key_data = make_packet($packet_types->{pubkey}, $pubkey, {'packet_length'=>2}); - - # take the last 8 bytes of the fingerprint as the keyid: - my $keyid = substr(fingerprint($rsa, $timestamp), 20 - 8, 8); - - # the v4 signature trailer is: - - # version number, literal 0xff, and then a 4-byte count of the - # signature data itself. - my $trailer = pack('CCN', 4, 0xff, length($sig_data_to_be_hashed)); - - my $uid_data = - pack('CN', 0xb4, length($uid)). - $uid; - - my $datatosign = - $key_data. - $uid_data. - $sig_data_to_be_hashed. - $trailer; - - my $data_hash = Digest::SHA1::sha1_hex($datatosign); - - my $issuer_packet = pack('CCa8', 9, $subpacket_types->{issuer}, $keyid); - - my $sig = Crypt::OpenSSL::Bignum->new_from_bin($rsa->sign($datatosign)); - - my $sig_body = - $sig_data_to_be_hashed. - pack('n', length($issuer_packet)). - $issuer_packet. - pack('n', hex(substr($data_hash, 0, 4))). - mpi_pack($sig); - - return - make_packet($packet_types->{seckey}, $seckey). - make_packet($packet_types->{uid}, $uid). - make_packet($packet_types->{sig}, $sig_body); -} - - -sub openpgp2ssh { - my $instr = shift; - my $fpr = shift; - - if (defined $fpr) { - if (length($fpr) < 8) { - die "We need at least 8 hex digits of fingerprint.\n"; - } - $fpr = uc($fpr); - } - - my $packettag; - my $dummy; - my $tag; - - my $key; - - while (! eof($instr)) { - read($instr, $packettag, 1); - $packettag = ord($packettag); - - my $packetlen; - if ( ! (0x80 & $packettag)) { - die "This is not an OpenPGP packet\n"; - } - if (0x40 & $packettag) { - $tag = (0x3f & $packettag); - my $nextlen = 0; - read($instr, $nextlen, 1); - $nextlen = ord($nextlen); - if ($nextlen < 192) { - $packetlen = $nextlen; - } elsif ($nextlen < 224) { - my $newoct; - read($instr, $newoct, 1); - $newoct = ord($newoct); - $packetlen = (($nextlen - 192) << 8) + ($newoct) + 192; - } elsif ($nextlen == 255) { - read($instr, $nextlen, 4); - $packetlen = unpack('N', $nextlen); - } else { - # packet length is undefined. - } - } else { - my $lentype; - $lentype = 0x03 & $packettag; - $tag = ( 0x3c & $packettag ) >> 2; - if ($lentype == 0) { - read($instr, $packetlen, 1) or die "could not read packet length\n"; - $packetlen = unpack('C', $packetlen); - } elsif ($lentype == 1) { - read($instr, $packetlen, 2) or die "could not read packet length\n"; - $packetlen = unpack('n', $packetlen); - } elsif ($lentype == 2) { - read($instr, $packetlen, 4) or die "could not read packet length\n"; - $packetlen = unpack('N', $packetlen); - } else { - # packet length is undefined. - } - } - - if (! defined($packetlen)) { - die "Undefined packet lengths are not supported.\n"; - } - - if ($tag == $packet_types->{pubkey} || - $tag == $packet_types->{pub_subkey} || - $tag == $packet_types->{seckey} || - $tag == $packet_types->{sec_subkey}) { - my $ver; - my $readbytes = 0; - read($instr, $ver, 1) or die "could not read key version\n"; - $readbytes += 1; - $ver = ord($ver); - - if ($ver != 4) { - printf(STDERR "We only work with version 4 keys. This key appears to be version %s.\n", $ver); - read($instr, $dummy, $packetlen - $readbytes) or die "Could not skip past this packet.\n"; - } else { - - my $timestamp; - read($instr, $timestamp, 4) or die "could not read key timestamp.\n"; - $readbytes += 4; - $timestamp = unpack('N', $timestamp); - - my $algo; - read($instr, $algo, 1) or die "could not read key algorithm.\n"; - $readbytes += 1; - $algo = ord($algo); - if ($algo != $asym_algos->{rsa}) { - printf(STDERR "We only support RSA keys (this key used algorithm %d).\n", $algo); - read($instr, $dummy, $packetlen - $readbytes) or die "Could not skip past this packet.\n"; - } else { - ## we have an RSA key. - my $modulus = read_mpi($instr, \$readbytes); - my $exponent = read_mpi($instr, \$readbytes); - - my $pubkey = Crypt::OpenSSL::RSA->new_key_from_parameters($modulus, $exponent); - my $foundfpr = fingerprint($pubkey, $timestamp); - - my $foundfprstr = Crypt::OpenSSL::Bignum->new_from_bin($foundfpr)->to_hex(); - - # is this a match? - if ((!defined($fpr)) || - (substr($foundfprstr, -1 * length($fpr)) eq $fpr)) { - if (defined($key)) { - die "Found two matching keys.\n"; - } - $key = $pubkey; - } - - if ($tag == $packet_types->{seckey} || - $tag == $packet_types->{sec_subkey}) { - if (!defined($key)) { # we don't think the public part of - # this key matches - read($instr, $dummy, $packetlen - $readbytes) or die "Could not skip past this packet.\n"; - } else { - my $s2k; - read($instr, $s2k, 1) or die "Could not read S2K octet.\n"; - $readbytes += 1; - $s2k = ord($s2k); - if ($s2k == 0) { - # secret material is unencrypted - # see http://tools.ietf.org/html/rfc4880#section-5.5.3 - my $d = read_mpi($instr, \$readbytes); - my $p = read_mpi($instr, \$readbytes); - my $q = read_mpi($instr, \$readbytes); - my $u = read_mpi($instr, \$readbytes); - - my $checksum; - read($instr, $checksum, 2) or die "Could not read checksum of secret key material.\n"; - $readbytes += 2; - $checksum = unpack('n', $checksum); - - # FIXME: compare with the checksum! how? the data is - # gone into the Crypt::OpenSSL::Bignum - - $key = Crypt::OpenSSL::RSA->new_key_from_parameters($modulus, - $exponent, - $d, - $p, - $q); - - $key->check_key() or die "Secret key is not a valid RSA key.\n"; - } else { - print(STDERR "We cannot handle encrypted secret keys. Skipping!\n") ; - read($instr, $dummy, $packetlen - $readbytes) or die "Could not skip past this packet.\n"; - } - } - } - - } - } - } else { - read($instr, $dummy, $packetlen) or die "Could not skip past this packet!\n"; - } - } - - return $key; -} - - -for (basename($0)) { - if (/^pem2openpgp$/) { - my $rsa; - my $stdin; - - my $uid = shift; - defined($uid) or die "You must specify a user ID string.\n"; - - # FIXME: fail if there is no given user ID; or should we default to - # hostname_long() from Sys::Hostname::Long ? - - - if (defined $ENV{PEM2OPENPGP_NEWKEY}) { - $rsa = Crypt::OpenSSL::RSA->generate_key($ENV{PEM2OPENPGP_NEWKEY}); - } else { - $stdin = do { - local $/; # slurp! - ; - }; - - $rsa = Crypt::OpenSSL::RSA->new_private_key($stdin); - } - - print pem2openpgp($rsa, - $uid, - { timestamp => $ENV{PEM2OPENPGP_TIMESTAMP}, - expiration => $ENV{PEM2OPENPGP_EXPIRATION}, - usage_flags => $ENV{PEM2OPENPGP_USAGE_FLAGS}, - } - ); - } - elsif (/^openpgp2ssh$/) { - my $fpr = shift; - my $instream; - open($instream,'-'); - binmode($instream, ":bytes"); - my $key = openpgp2ssh($instream, $fpr); - if (defined($key)) { - if ($key->is_private()) { - print $key->get_private_key_string(); - } else { - print "ssh-rsa ".encode_base64(openssh_pubkey_pack($key), '')."\n"; - } - } else { - die "No matching key found.\n"; - } - } - else { - die "Unrecognized keytrans call.\n"; - } -} - diff --git a/src/openpgp2ssh b/src/openpgp2ssh new file mode 120000 index 0000000..edcb6a3 --- /dev/null +++ b/src/openpgp2ssh @@ -0,0 +1 @@ +share/keytrans \ No newline at end of file diff --git a/src/pem2openpgp b/src/pem2openpgp new file mode 120000 index 0000000..edcb6a3 --- /dev/null +++ b/src/pem2openpgp @@ -0,0 +1 @@ +share/keytrans \ No newline at end of file diff --git a/src/share/keytrans b/src/share/keytrans new file mode 100755 index 0000000..8bf17fb --- /dev/null +++ b/src/share/keytrans @@ -0,0 +1,775 @@ +#!/usr/bin/perl -w -T + +# pem2openpgp: take a PEM-encoded RSA private-key on standard input, a +# User ID as the first argument, and generate an OpenPGP secret key +# and certificate from it. + +# WARNING: the secret key material *will* appear on stdout (albeit in +# OpenPGP form) -- if you redirect stdout to a file, make sure the +# permissions on that file are appropriately locked down! + +# Usage: + +# pem2openpgp 'ssh://'$(hostname -f) < /etc/ssh/ssh_host_rsa_key | gpg --import + +# Authors: +# Jameson Rollins +# Daniel Kahn Gillmor + +# Started on: 2009-01-07 02:01:19-0500 + +# License: GPL v3 or later (we may need to adjust this given that this +# connects to OpenSSL via perl) + +use strict; +use warnings; +use File::Basename; +use Crypt::OpenSSL::RSA; +use Crypt::OpenSSL::Bignum; +use Crypt::OpenSSL::Bignum::CTX; +use Digest::SHA1; +use MIME::Base64; +use POSIX; + +## make sure all length() and substr() calls use bytes only: +use bytes; + +my $old_format_packet_lengths = { one => 0, + two => 1, + four => 2, + indeterminate => 3, +}; + +# see RFC 4880 section 9.1 (ignoring deprecated algorithms for now) +my $asym_algos = { rsa => 1, + elgamal => 16, + dsa => 17, + }; + +# see RFC 4880 section 9.2 +my $ciphers = { plaintext => 0, + idea => 1, + tripledes => 2, + cast5 => 3, + blowfish => 4, + aes128 => 7, + aes192 => 8, + aes256 => 9, + twofish => 10, + }; + +# see RFC 4880 section 9.3 +my $zips = { uncompressed => 0, + zip => 1, + zlib => 2, + bzip2 => 3, + }; + +# see RFC 4880 section 9.4 +my $digests = { md5 => 1, + sha1 => 2, + ripemd160 => 3, + sha256 => 8, + sha384 => 9, + sha512 => 10, + sha224 => 11, + }; + +# see RFC 4880 section 5.2.3.21 +my $usage_flags = { certify => 0x01, + sign => 0x02, + encrypt_comms => 0x04, + encrypt_storage => 0x08, + encrypt => 0x0c, ## both comms and storage + split => 0x10, # the private key is split via secret sharing + authenticate => 0x20, + shared => 0x80, # more than one person holds the entire private key + }; + +# see RFC 4880 section 4.3 +my $packet_types = { pubkey_enc_session => 1, + sig => 2, + symkey_enc_session => 3, + onepass_sig => 4, + seckey => 5, + pubkey => 6, + sec_subkey => 7, + compressed_data => 8, + symenc_data => 9, + marker => 10, + literal => 11, + trust => 12, + uid => 13, + pub_subkey => 14, + uat => 17, + symenc_w_integrity => 18, + mdc => 19, + }; + +# see RFC 4880 section 5.2.1 +my $sig_types = { binary_doc => 0x00, + text_doc => 0x01, + standalone => 0x02, + generic_certification => 0x10, + persona_certification => 0x11, + casual_certification => 0x12, + positive_certification => 0x13, + subkey_binding => 0x18, + primary_key_binding => 0x19, + key_signature => 0x1f, + key_revocation => 0x20, + subkey_revocation => 0x28, + certification_revocation => 0x30, + timestamp => 0x40, + thirdparty => 0x50, + }; + + +# see RFC 4880 section 5.2.3.1 +my $subpacket_types = { sig_creation_time => 2, + sig_expiration_time => 3, + exportable => 4, + trust_sig => 5, + regex => 6, + revocable => 7, + key_expiration_time => 9, + preferred_cipher => 11, + revocation_key => 12, + issuer => 16, + notation => 20, + preferred_digest => 21, + preferred_compression => 22, + keyserver_prefs => 23, + preferred_keyserver => 24, + primary_uid => 25, + policy_uri => 26, + usage_flags => 27, + signers_uid => 28, + revocation_reason => 29, + features => 30, + signature_target => 31, + embedded_signature => 32, + }; + +# bitstring (see RFC 4880 section 5.2.3.24) +my $features = { mdc => 0x01 + }; + +# bitstring (see RFC 4880 5.2.3.17) +my $keyserver_prefs = { nomodify => 0x80 + }; + +###### end lookup tables ###### + +# FIXME: if we want to be able to interpret openpgp data as well as +# produce it, we need to produce key/value-swapped lookup tables as well. + + +########### Math/Utility Functions ############## + + +# see the bottom of page 43 of RFC 4880 +sub simple_checksum { + my $bytes = shift; + + return unpack("%32W*",$bytes) % 65536; +} + +# calculate the multiplicative inverse of a mod b this is euclid's +# extended algorithm. For more information see: +# http://en.wikipedia.org/wiki/Extended_Euclidean_algorithm the +# arguments here should be Crypt::OpenSSL::Bignum objects. $a should +# be the larger of the two values, and the two values should be +# coprime. + +sub modular_multi_inverse { + my $a = shift; + my $b = shift; + + + my $origdivisor = $b->copy(); + + my $ctx = Crypt::OpenSSL::Bignum::CTX->new(); + my $x = Crypt::OpenSSL::Bignum->zero(); + my $y = Crypt::OpenSSL::Bignum->one(); + my $lastx = Crypt::OpenSSL::Bignum->one(); + my $lasty = Crypt::OpenSSL::Bignum->zero(); + + my $finalquotient; + my $finalremainder; + + while (! $b->is_zero()) { + my ($quotient, $remainder) = $a->div($b, $ctx); + + $a = $b; + $b = $remainder; + + my $temp = $x; + $x = $lastx->sub($quotient->mul($x, $ctx)); + $lastx = $temp; + + $temp = $y; + $y = $lasty->sub($quotient->mul($y, $ctx)); + $lasty = $temp; + } + + if (!$a->is_one()) { + die "did this math wrong.\n"; + } + + # let's make sure that we return a positive value because RFC 4880, + # section 3.2 only allows unsigned values: + + ($finalquotient, $finalremainder) = $lastx->add($origdivisor)->div($origdivisor, $ctx); + + return $finalremainder; +} + + +############ OpenPGP formatting functions ############ + +# make an old-style packet out of the given packet type and body. +# old-style (see RFC 4880 section 4.2) +sub make_packet { + my $type = shift; + my $body = shift; + my $options = shift; + + my $len = length($body); + my $pseudolen = $len; + + # if the caller wants to use at least N octets of packet length, + # pretend that we're using that many. + if (defined $options && defined $options->{'packet_length'}) { + $pseudolen = 2**($options->{'packet_length'} * 8) - 1; + } + if ($pseudolen < $len) { + $pseudolen = $len; + } + + my $lenbytes; + my $lencode; + + if ($pseudolen < 2**8) { + $lenbytes = $old_format_packet_lengths->{one}; + $lencode = 'C'; + } elsif ($pseudolen < 2**16) { + $lenbytes = $old_format_packet_lengths->{two}; + $lencode = 'n'; + } elsif ($pseudolen < 2**31) { + ## not testing against full 32 bits because i don't want to deal + ## with potential overflow. + $lenbytes = $old_format_packet_lengths->{four}; + $lencode = 'N'; + } else { + ## what the hell do we do here? + $lenbytes = $old_format_packet_lengths->{indeterminate}; + $lencode = ''; + } + + return pack('C'.$lencode, 0x80 + ($type * 4) + $lenbytes, $len). + $body; +} + + +# takes a Crypt::OpenSSL::Bignum, returns it formatted as OpenPGP MPI +# (RFC 4880 section 3.2) +sub mpi_pack { + my $num = shift; + + my $val = $num->to_bin(); + my $mpilen = length($val)*8; + +# this is a kludgy way to get the number of significant bits in the +# first byte: + my $bitsinfirstbyte = length(sprintf("%b", ord($val))); + + $mpilen -= (8 - $bitsinfirstbyte); + + return pack('n', $mpilen).$val; +} + +# takes a Crypt::OpenSSL::Bignum, returns an MPI packed in preparation +# for an OpenSSH-style public key format. see: +# http://marc.info/?l=openssh-unix-dev&m=121866301718839&w=2 +sub openssh_mpi_pack { + my $num = shift; + + my $val = $num->to_bin(); + my $mpilen = length($val); + + my $ret = pack('N', $mpilen); + + # if the first bit of the leading byte is high, we should include a + # 0 byte: + if (ord($val) & 0x80) { + $ret = pack('NC', $mpilen+1, 0); + } + + return $ret.$val; +} + +sub openssh_pubkey_pack { + my $key = shift; + + my ($modulus, $exponent) = $key->get_key_parameters(); + + return openssh_mpi_pack(Crypt::OpenSSL::Bignum->new_from_bin("ssh-rsa")). + openssh_mpi_pack($exponent). + openssh_mpi_pack($modulus); +} + +# pull an OpenPGP-specified MPI off of a given stream, returning it as +# a Crypt::OpenSSL::Bignum. +sub read_mpi { + my $instr = shift; + my $readtally = shift; + + my $bitlen; + read($instr, $bitlen, 2) or die "could not read MPI length.\n"; + $bitlen = unpack('n', $bitlen); + $$readtally += 2; + + my $bytestoread = POSIX::floor(($bitlen + 7)/8); + my $ret; + read($instr, $ret, $bytestoread) or die "could not read MPI body.\n"; + $$readtally += $bytestoread; + return Crypt::OpenSSL::Bignum->new_from_bin($ret); +} + + +# FIXME: genericize these to accept either RSA or DSA keys: +sub make_rsa_pub_key_body { + my $key = shift; + my $timestamp = shift; + + my ($n, $e) = $key->get_key_parameters(); + + return + pack('CN', 4, $timestamp). + pack('C', $asym_algos->{rsa}). + mpi_pack($n). + mpi_pack($e); +} + +sub make_rsa_sec_key_body { + my $key = shift; + my $timestamp = shift; + + # we're not using $a and $b, but we need them to get to $c. + my ($n, $e, $d, $p, $q) = $key->get_key_parameters(); + + my $c3 = modular_multi_inverse($p, $q); + + my $secret_material = mpi_pack($d). + mpi_pack($p). + mpi_pack($q). + mpi_pack($c3); + + # according to Crypt::OpenSSL::RSA, the closest value we can get out + # of get_key_parameters is 1/q mod p; but according to sec 5.5.3 of + # RFC 4880, we're actually looking for u, the multiplicative inverse + # of p, mod q. This is why we're calculating the value directly + # with modular_multi_inverse. + + return + pack('CN', 4, $timestamp). + pack('C', $asym_algos->{rsa}). + mpi_pack($n). + mpi_pack($e). + pack('C', 0). # seckey material is not encrypted -- see RFC 4880 sec 5.5.3 + $secret_material. + pack('n', simple_checksum($secret_material)); +} + +# expects an RSA key (public or private) and a timestamp +sub fingerprint { + my $key = shift; + my $timestamp = shift; + + my $rsabody = make_rsa_pub_key_body($key, $timestamp); + + return Digest::SHA1::sha1(pack('Cn', 0x99, length($rsabody)).$rsabody); +} + + +# FIXME: handle DSA keys as well! +sub pem2openpgp { + my $rsa = shift; + my $uid = shift; + my $args = shift; + + $rsa->use_sha1_hash(); + + # see page 22 of RFC 4880 for why i think this is the right padding + # choice to use: + $rsa->use_pkcs1_padding(); + + if (! $rsa->check_key()) { + die "key does not check"; + } + + my $version = pack('C', 4); + # strong assertion of identity: + my $sigtype = pack('C', $sig_types->{positive_certification}); + # RSA + my $pubkey_algo = pack('C', $asym_algos->{rsa}); + # SHA1 + my $hash_algo = pack('C', $digests->{sha1}); + + # FIXME: i'm worried about generating a bazillion new OpenPGP + # certificates from the same key, which could easily happen if you run + # this script more than once against the same key (because the + # timestamps will differ). How can we prevent this? + + # this environment variable (if set) overrides the current time, to + # be able to create a standard key? If we read the key from a file + # instead of stdin, should we use the creation time on the file? + my $timestamp = 0; + if (defined $args->{timestamp}) { + $timestamp = ($args->{timestamp} + 0); + } else { + $timestamp = time(); + } + + my $creation_time_packet = pack('CCN', 5, $subpacket_types->{sig_creation_time}, $timestamp); + + + my $flags = 0; + if (! defined $args->{usage_flags}) { + $flags = $usage_flags->{certify}; + } else { + my @ff = split(",", $args->{usage_flags}); + foreach my $f (@ff) { + if (! defined $usage_flags->{$f}) { + die "No such flag $f"; + } + $flags |= $usage_flags->{$f}; + } + } + + my $usage_packet = pack('CCC', 2, $subpacket_types->{usage_flags}, $flags); + + + # how should we determine how far off to set the expiration date? + # default is no expiration. Specify the timestamp in seconds from the + # key creation. + my $expiration_packet = ''; + if (defined $args->{expiration}) { + my $expires_in = $args->{expiration} + 0; + $expiration_packet = pack('CCN', 5, $subpacket_types->{key_expiration_time}, $expires_in); + } + + + # prefer AES-256, AES-192, AES-128, CAST5, 3DES: + my $pref_sym_algos = pack('CCCCCCC', 6, $subpacket_types->{preferred_cipher}, + $ciphers->{aes256}, + $ciphers->{aes192}, + $ciphers->{aes128}, + $ciphers->{cast5}, + $ciphers->{tripledes} + ); + + # prefer SHA-1, SHA-256, RIPE-MD/160 + my $pref_hash_algos = pack('CCCCC', 4, $subpacket_types->{preferred_digest}, + $digests->{sha1}, + $digests->{sha256}, + $digests->{ripemd160} + ); + + # prefer ZLIB, BZip2, ZIP + my $pref_zip_algos = pack('CCCCC', 4, $subpacket_types->{preferred_compression}, + $zips->{zlib}, + $zips->{bzip2}, + $zips->{zip} + ); + + # we support the MDC feature: + my $feature_subpacket = pack('CCC', 2, $subpacket_types->{features}, + $features->{mdc}); + + # keyserver preference: only owner modify (???): + my $keyserver_pref = pack('CCC', 2, $subpacket_types->{keyserver_prefs}, + $keyserver_prefs->{nomodify}); + + my $subpackets_to_be_hashed = + $creation_time_packet. + $usage_packet. + $expiration_packet. + $pref_sym_algos. + $pref_hash_algos. + $pref_zip_algos. + $feature_subpacket. + $keyserver_pref; + + my $subpacket_octets = pack('n', length($subpackets_to_be_hashed)); + + my $sig_data_to_be_hashed = + $version. + $sigtype. + $pubkey_algo. + $hash_algo. + $subpacket_octets. + $subpackets_to_be_hashed; + + my $pubkey = make_rsa_pub_key_body($rsa, $timestamp); + my $seckey = make_rsa_sec_key_body($rsa, $timestamp); + + # this is for signing. it needs to be an old-style header with a + # 2-packet octet count. + + my $key_data = make_packet($packet_types->{pubkey}, $pubkey, {'packet_length'=>2}); + + # take the last 8 bytes of the fingerprint as the keyid: + my $keyid = substr(fingerprint($rsa, $timestamp), 20 - 8, 8); + + # the v4 signature trailer is: + + # version number, literal 0xff, and then a 4-byte count of the + # signature data itself. + my $trailer = pack('CCN', 4, 0xff, length($sig_data_to_be_hashed)); + + my $uid_data = + pack('CN', 0xb4, length($uid)). + $uid; + + my $datatosign = + $key_data. + $uid_data. + $sig_data_to_be_hashed. + $trailer; + + my $data_hash = Digest::SHA1::sha1_hex($datatosign); + + my $issuer_packet = pack('CCa8', 9, $subpacket_types->{issuer}, $keyid); + + my $sig = Crypt::OpenSSL::Bignum->new_from_bin($rsa->sign($datatosign)); + + my $sig_body = + $sig_data_to_be_hashed. + pack('n', length($issuer_packet)). + $issuer_packet. + pack('n', hex(substr($data_hash, 0, 4))). + mpi_pack($sig); + + return + make_packet($packet_types->{seckey}, $seckey). + make_packet($packet_types->{uid}, $uid). + make_packet($packet_types->{sig}, $sig_body); +} + + +sub openpgp2ssh { + my $instr = shift; + my $fpr = shift; + + if (defined $fpr) { + if (length($fpr) < 8) { + die "We need at least 8 hex digits of fingerprint.\n"; + } + $fpr = uc($fpr); + } + + my $packettag; + my $dummy; + my $tag; + + my $key; + + while (! eof($instr)) { + read($instr, $packettag, 1); + $packettag = ord($packettag); + + my $packetlen; + if ( ! (0x80 & $packettag)) { + die "This is not an OpenPGP packet\n"; + } + if (0x40 & $packettag) { + $tag = (0x3f & $packettag); + my $nextlen = 0; + read($instr, $nextlen, 1); + $nextlen = ord($nextlen); + if ($nextlen < 192) { + $packetlen = $nextlen; + } elsif ($nextlen < 224) { + my $newoct; + read($instr, $newoct, 1); + $newoct = ord($newoct); + $packetlen = (($nextlen - 192) << 8) + ($newoct) + 192; + } elsif ($nextlen == 255) { + read($instr, $nextlen, 4); + $packetlen = unpack('N', $nextlen); + } else { + # packet length is undefined. + } + } else { + my $lentype; + $lentype = 0x03 & $packettag; + $tag = ( 0x3c & $packettag ) >> 2; + if ($lentype == 0) { + read($instr, $packetlen, 1) or die "could not read packet length\n"; + $packetlen = unpack('C', $packetlen); + } elsif ($lentype == 1) { + read($instr, $packetlen, 2) or die "could not read packet length\n"; + $packetlen = unpack('n', $packetlen); + } elsif ($lentype == 2) { + read($instr, $packetlen, 4) or die "could not read packet length\n"; + $packetlen = unpack('N', $packetlen); + } else { + # packet length is undefined. + } + } + + if (! defined($packetlen)) { + die "Undefined packet lengths are not supported.\n"; + } + + if ($tag == $packet_types->{pubkey} || + $tag == $packet_types->{pub_subkey} || + $tag == $packet_types->{seckey} || + $tag == $packet_types->{sec_subkey}) { + my $ver; + my $readbytes = 0; + read($instr, $ver, 1) or die "could not read key version\n"; + $readbytes += 1; + $ver = ord($ver); + + if ($ver != 4) { + printf(STDERR "We only work with version 4 keys. This key appears to be version %s.\n", $ver); + read($instr, $dummy, $packetlen - $readbytes) or die "Could not skip past this packet.\n"; + } else { + + my $timestamp; + read($instr, $timestamp, 4) or die "could not read key timestamp.\n"; + $readbytes += 4; + $timestamp = unpack('N', $timestamp); + + my $algo; + read($instr, $algo, 1) or die "could not read key algorithm.\n"; + $readbytes += 1; + $algo = ord($algo); + if ($algo != $asym_algos->{rsa}) { + printf(STDERR "We only support RSA keys (this key used algorithm %d).\n", $algo); + read($instr, $dummy, $packetlen - $readbytes) or die "Could not skip past this packet.\n"; + } else { + ## we have an RSA key. + my $modulus = read_mpi($instr, \$readbytes); + my $exponent = read_mpi($instr, \$readbytes); + + my $pubkey = Crypt::OpenSSL::RSA->new_key_from_parameters($modulus, $exponent); + my $foundfpr = fingerprint($pubkey, $timestamp); + + my $foundfprstr = Crypt::OpenSSL::Bignum->new_from_bin($foundfpr)->to_hex(); + + # is this a match? + if ((!defined($fpr)) || + (substr($foundfprstr, -1 * length($fpr)) eq $fpr)) { + if (defined($key)) { + die "Found two matching keys.\n"; + } + $key = $pubkey; + } + + if ($tag == $packet_types->{seckey} || + $tag == $packet_types->{sec_subkey}) { + if (!defined($key)) { # we don't think the public part of + # this key matches + read($instr, $dummy, $packetlen - $readbytes) or die "Could not skip past this packet.\n"; + } else { + my $s2k; + read($instr, $s2k, 1) or die "Could not read S2K octet.\n"; + $readbytes += 1; + $s2k = ord($s2k); + if ($s2k == 0) { + # secret material is unencrypted + # see http://tools.ietf.org/html/rfc4880#section-5.5.3 + my $d = read_mpi($instr, \$readbytes); + my $p = read_mpi($instr, \$readbytes); + my $q = read_mpi($instr, \$readbytes); + my $u = read_mpi($instr, \$readbytes); + + my $checksum; + read($instr, $checksum, 2) or die "Could not read checksum of secret key material.\n"; + $readbytes += 2; + $checksum = unpack('n', $checksum); + + # FIXME: compare with the checksum! how? the data is + # gone into the Crypt::OpenSSL::Bignum + + $key = Crypt::OpenSSL::RSA->new_key_from_parameters($modulus, + $exponent, + $d, + $p, + $q); + + $key->check_key() or die "Secret key is not a valid RSA key.\n"; + } else { + print(STDERR "We cannot handle encrypted secret keys. Skipping!\n") ; + read($instr, $dummy, $packetlen - $readbytes) or die "Could not skip past this packet.\n"; + } + } + } + + } + } + } else { + read($instr, $dummy, $packetlen) or die "Could not skip past this packet!\n"; + } + } + + return $key; +} + + +for (basename($0)) { + if (/^pem2openpgp$/) { + my $rsa; + my $stdin; + + my $uid = shift; + defined($uid) or die "You must specify a user ID string.\n"; + + # FIXME: fail if there is no given user ID; or should we default to + # hostname_long() from Sys::Hostname::Long ? + + + if (defined $ENV{PEM2OPENPGP_NEWKEY}) { + $rsa = Crypt::OpenSSL::RSA->generate_key($ENV{PEM2OPENPGP_NEWKEY}); + } else { + $stdin = do { + local $/; # slurp! + ; + }; + + $rsa = Crypt::OpenSSL::RSA->new_private_key($stdin); + } + + print pem2openpgp($rsa, + $uid, + { timestamp => $ENV{PEM2OPENPGP_TIMESTAMP}, + expiration => $ENV{PEM2OPENPGP_EXPIRATION}, + usage_flags => $ENV{PEM2OPENPGP_USAGE_FLAGS}, + } + ); + } + elsif (/^openpgp2ssh$/) { + my $fpr = shift; + my $instream; + open($instream,'-'); + binmode($instream, ":bytes"); + my $key = openpgp2ssh($instream, $fpr); + if (defined($key)) { + if ($key->is_private()) { + print $key->get_private_key_string(); + } else { + print "ssh-rsa ".encode_base64(openssh_pubkey_pack($key), '')."\n"; + } + } else { + die "No matching key found.\n"; + } + } + else { + die "Unrecognized keytrans call.\n"; + } +} + -- cgit v1.2.3 From 48cb182a7d0265aabed84d74b010ff0b24fa078c Mon Sep 17 00:00:00 2001 From: Daniel Kahn Gillmor Date: Sun, 1 Mar 2009 12:12:18 -0500 Subject: removed base64 invocation in favor of perl to reduce dependency spread. --- src/share/ma/setup | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/share/ma/setup b/src/share/ma/setup index e77afff..f991050 100644 --- a/src/share/ma/setup +++ b/src/share/ma/setup @@ -57,7 +57,7 @@ EOF if [ -z "$CORE_FPR" ] ; then log info "setting up Monkeysphere authentication trust core..." - local CORE_UID=$(printf "Monkeysphere authentication trust core UID (random string: %s)" $(head -c21 Date: Sun, 1 Mar 2009 13:34:01 -0500 Subject: fix two bugs in monkeysphere:check_gpg_sec_key_id that were causing gen_subkey to fail --- src/monkeysphere | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/monkeysphere b/src/monkeysphere index 6db4827..809b1ac 100755 --- a/src/monkeysphere +++ b/src/monkeysphere @@ -69,7 +69,7 @@ check_gpg_sec_key_id() { gpgSecOut=$(gpg_user --fixed-list-mode --list-secret-keys --with-colons 2>/dev/null | egrep '^sec:') ;; 1) - gpgSecOut=$(gpg_user --fixed-list-mode --list-secret-keys --with-colons "$keyID" | egrep '^sec:') || failure + gpgSecOut=$(gpg_user --fixed-list-mode --list-secret-keys --with-colons "$1" | egrep '^sec:') || failure ;; *) failure "You must specify only a single primary key ID." @@ -86,9 +86,9 @@ check_gpg_sec_key_id() { echo "$gpgSecOut" | cut -d: -f5 ;; *) - echo "Multiple primary secret keys found:" - echo "$gpgSecOut" | cut -d: -f5 - echo "Please specify which primary key to use." + echo "Multiple primary secret keys found:" >&2 + echo "$gpgSecOut" | cut -d: -f5 >&2 + echo "Please specify which primary key to use." >&2 failure ;; esac -- cgit v1.2.3 From 15d752f93a3a9807430fe8b3cd6e16f3cede8e7c Mon Sep 17 00:00:00 2001 From: Daniel Kahn Gillmor Date: Sun, 1 Mar 2009 13:40:12 -0500 Subject: updating header comments in keytrans now that it serves two purposes. --- src/share/keytrans | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) (limited to 'src') diff --git a/src/share/keytrans b/src/share/keytrans index 8bf17fb..8b2e2ea 100755 --- a/src/share/keytrans +++ b/src/share/keytrans @@ -1,5 +1,15 @@ #!/usr/bin/perl -w -T +# keytrans: this is an RSA key translation utility; it is capable of +# transforming RSA keys (both public keys and secret keys) between +# several popular representations, including OpenPGP, PEM-encoded +# PKCS#1 DER, and OpenSSH-style public key lines. + +# How it behaves depends on the name under which it is invoked. The +# two implementations currently are: pem2openpgp and openpgp2ssh. + + + # pem2openpgp: take a PEM-encoded RSA private-key on standard input, a # User ID as the first argument, and generate an OpenPGP secret key # and certificate from it. @@ -12,6 +22,23 @@ # pem2openpgp 'ssh://'$(hostname -f) < /etc/ssh/ssh_host_rsa_key | gpg --import + + + +# openpgp2ssh: take a stream of OpenPGP packets containing public or +# secret key material on standard input, and a Key ID (or fingerprint) +# as the first argument. Find the matching key in the input stream, +# and emit it on stdout in an OpenSSH-compatible format. If the input +# key is an OpenPGP public key (either primary or subkey), the output +# will be an OpenSSH single-line public key. If the input key is an +# OpenPGP secret key, the output will be a PEM-encoded RSA key. + +# Example usage: + +# gpg --export-secret-subkeys --export-options export-reset-subkey-passwd $KEYID | \ +# openpgp2ssh $KEYID | ssh-add /dev/stdin + + # Authors: # Jameson Rollins # Daniel Kahn Gillmor -- cgit v1.2.3 From 183d64eed7eb9724ca6c96f656cb02f475158d0e Mon Sep 17 00:00:00 2001 From: Daniel Kahn Gillmor Date: Sun, 1 Mar 2009 14:02:35 -0500 Subject: normalizing failure invocations in check_gpg_sec_key_id(). --- src/monkeysphere | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/monkeysphere b/src/monkeysphere index 809b1ac..2d54376 100755 --- a/src/monkeysphere +++ b/src/monkeysphere @@ -86,10 +86,10 @@ check_gpg_sec_key_id() { echo "$gpgSecOut" | cut -d: -f5 ;; *) - echo "Multiple primary secret keys found:" >&2 - echo "$gpgSecOut" | cut -d: -f5 >&2 - echo "Please specify which primary key to use." >&2 - failure + local seckeys=$(echo "$gpgSecOut" | cut -d: -f5) + failure "Multiple primary secret keys found: +$seckeys +Please specify which primary key to use." ;; esac } -- cgit v1.2.3 From ebd776722e0fd6dfacc79146c368d148f0e266cb Mon Sep 17 00:00:00 2001 From: Jameson Graef Rollins Date: Sun, 1 Mar 2009 14:53:37 -0500 Subject: break out default variables into their own file: defaultenv this allows the common file to be sourced without reseting variables to their defaults, which was causing a problem with su_monkeysphere_user. also added some more debug messages. --- Makefile | 1 + src/monkeysphere | 3 ++- src/monkeysphere-authentication | 3 ++- src/monkeysphere-host | 3 ++- src/share/common | 34 +++++++++------------------------- src/share/ma/update_users | 1 + tests/basic | 1 - 7 files changed, 17 insertions(+), 29 deletions(-) (limited to 'src') diff --git a/Makefile b/Makefile index 07e8fb9..9873d32 100755 --- a/Makefile +++ b/Makefile @@ -52,6 +52,7 @@ install: all installman install src/monkeysphere $(DESTDIR)$(PREFIX)/bin install src/monkeysphere-host src/monkeysphere-authentication $(DESTDIR)$(PREFIX)/sbin install -m 0644 src/share/common $(DESTDIR)$(PREFIX)/share/monkeysphere + install -m 0644 src/share/defaultenv $(DESTDIR)$(PREFIX)/share/monkeysphere install -m 0755 src/share/keytrans $(DESTDIR)$(PREFIX)/share/monkeysphere ln -s ../share/monkeysphere/keytrans $(DESTDIR)$(PREFIX)/bin/pem2openpgp ln -s ../share/monkeysphere/keytrans $(DESTDIR)$(PREFIX)/bin/openpgp2ssh diff --git a/src/monkeysphere b/src/monkeysphere index 2d54376..8d59d08 100755 --- a/src/monkeysphere +++ b/src/monkeysphere @@ -18,7 +18,8 @@ PGRM=$(basename $0) SYSSHAREDIR=${MONKEYSPHERE_SYSSHAREDIR:-"/usr/share/monkeysphere"} export SYSSHAREDIR -. "${SYSSHAREDIR}/common" || exit 1 +. "${SYSSHAREDIR}/defaultenv" +. "${SYSSHAREDIR}/common" # sharedir for host functions MSHAREDIR="${SYSSHAREDIR}/m" diff --git a/src/monkeysphere-authentication b/src/monkeysphere-authentication index c5c48d5..3344f38 100755 --- a/src/monkeysphere-authentication +++ b/src/monkeysphere-authentication @@ -21,7 +21,8 @@ PGRM=$(basename $0) SYSSHAREDIR=${MONKEYSPHERE_SYSSHAREDIR:-"/usr/share/monkeysphere"} export SYSSHAREDIR -. "${SYSSHAREDIR}/common" || exit 1 +. "${SYSSHAREDIR}/defaultenv" +. "${SYSSHAREDIR}/common" SYSDATADIR=${MONKEYSPHERE_SYSDATADIR:-"/var/lib/monkeysphere"} export SYSDATADIR diff --git a/src/monkeysphere-host b/src/monkeysphere-host index 9e4a8c4..b9a15ae 100755 --- a/src/monkeysphere-host +++ b/src/monkeysphere-host @@ -21,7 +21,8 @@ PGRM=$(basename $0) SYSSHAREDIR=${MONKEYSPHERE_SYSSHAREDIR:-"/usr/share/monkeysphere"} export SYSSHAREDIR -. "${SYSSHAREDIR}/common" || exit 1 +. "${SYSSHAREDIR}/defaultenv" +. "${SYSSHAREDIR}/common" SYSDATADIR=${MONKEYSPHERE_SYSDATADIR:-"/var/lib/monkeysphere"} export SYSDATADIR diff --git a/src/share/common b/src/share/common index a9d23b2..1cdd549 100644 --- a/src/share/common +++ b/src/share/common @@ -13,28 +13,6 @@ # all-caps variables are meant to be user supplied (ie. from config # file) and are considered global -######################################################################## -### COMMON VARIABLES - -# managed directories -SYSCONFIGDIR=${MONKEYSPHERE_SYSCONFIGDIR:-"/etc/monkeysphere"} -export SYSCONFIGDIR - -# default log level -LOG_LEVEL="INFO" - -# default keyserver -KEYSERVER="pool.sks-keyservers.net" - -# whether or not to check keyservers by defaul -CHECK_KEYSERVER="true" - -# default monkeysphere user -MONKEYSPHERE_USER="monkeysphere" - -# default about whether or not to prompt -PROMPT="true" - ######################################################################## ### UTILITY FUNCTIONS @@ -461,6 +439,7 @@ check_key_file_permissions() { # return zero if all clear, or go to next path if [ "$path" = '/' ] ; then + log debug "path ok." return 0 else check_key_file_permissions "$uname" $(dirname "$path") @@ -926,7 +905,8 @@ process_known_hosts() { failure "known_hosts file '$KNOWN_HOSTS' does not exist." fi - log debug "processing known_hosts file..." + log debug "processing known_hosts file:" + log debug " $KNOWN_HOSTS" hosts=$(meat "$KNOWN_HOSTS" | cut -d ' ' -f 1 | grep -v '^|.*$' | tr , ' ' | tr '\n' ' ') @@ -1014,6 +994,9 @@ update_authorized_keys() { nIDsOK=0 nIDsBAD=0 + log debug "updating authorized_keys file:" + log debug " $AUTHORIZED_KEYS" + # check permissions on the authorized_keys file path check_key_file_permissions "$USER" "$AUTHORIZED_KEYS" || failure @@ -1087,11 +1070,12 @@ process_authorized_user_ids() { failure "authorized_user_ids file '$authorizedUserIDs' does not exist." fi + log debug "processing authorized_user_ids file:" + log debug " $authorizedUserIDs" + # check permissions on the authorized_user_ids file path check_key_file_permissions "$USER" "$authorizedUserIDs" || failure - log debug "processing authorized_user_ids file..." - if ! meat "$authorizedUserIDs" > /dev/null ; then log debug " no user IDs to process." return diff --git a/src/share/ma/update_users b/src/share/ma/update_users index c180b56..3a5c006 100644 --- a/src/share/ma/update_users +++ b/src/share/ma/update_users @@ -80,6 +80,7 @@ for uname in $unames ; do # translating ssh-style path variables authorizedUserIDs=$(translate_ssh_variables "$uname" "$AUTHORIZED_USER_IDS") if [ -s "$authorizedUserIDs" ] ; then + log debug "authorized_user_ids file found." # check permissions on the authorized_user_ids file path if check_key_file_permissions "$uname" "$authorizedUserIDs" ; then # copy user authorized_user_ids file to temporary diff --git a/tests/basic b/tests/basic index f6d1f3b..7277168 100755 --- a/tests/basic +++ b/tests/basic @@ -275,7 +275,6 @@ monkeysphere-authentication update-users $(whoami) # FIXME: this is maybe not failing properly for: # ms: improper group or other writability on path '/tmp'. - ###################################################################### ### TESTS -- cgit v1.2.3 From 23969f7aadf7611ed73d300b23c8fbfca91cb66a Mon Sep 17 00:00:00 2001 From: Jameson Graef Rollins Date: Sun, 1 Mar 2009 15:27:36 -0500 Subject: explicity set the USER variable, since it's needed for checking file permissions. add/modify some debug messages. --- src/monkeysphere | 3 +++ src/share/common | 14 ++++++++------ src/share/ma/update_users | 1 + 3 files changed, 12 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/monkeysphere b/src/monkeysphere index 8d59d08..aa9276c 100755 --- a/src/monkeysphere +++ b/src/monkeysphere @@ -189,6 +189,9 @@ export GNUPGHOME mkdir -p -m 0700 "$GNUPGHOME" export LOG_LEVEL +# explicitly set the USER variable, for checking file permissions +export USER=$(whoami) + # get subcommand COMMAND="$1" [ "$COMMAND" ] || failure "Type '$PGRM help' for usage." diff --git a/src/share/common b/src/share/common index 1cdd549..c6d6b8e 100644 --- a/src/share/common +++ b/src/share/common @@ -427,13 +427,15 @@ check_key_file_permissions() { # return 1 if path has invalid owner if [ "$owner" != "$uname" -a "$owner" != 'root' ] ; then - log error "improper ownership on path '$path'." + log error "improper ownership on path '$path':" + log error " $owner != ($uname|root)" return 1 fi # return 2 if path has group or other writability if is_write "$gAccess" || is_write "$oAccess" ; then - log error "improper group or other writability on path '$path'." + log error "improper group or other writability on path '$path':" + log error " group: $gAccess, other: $oAcess" return 2 fi @@ -667,14 +669,14 @@ process_user_id() { if [ "$keyOK" -a "$uidOK" -a "$lastKeyOK" ] ; then log verbose " * acceptable primary key." if [ -z "$sshKey" ] ; then - log error " ! primary key could not be translated (not RSA or DSA?)." + log error " ! primary key could not be translated (not RSA?)." else echo "0:${sshKey}" fi else log debug " - unacceptable primary key." if [ -z "$sshKey" ] ; then - log debug " ! primary key could not be translated (not RSA or DSA?)." + log debug " ! primary key could not be translated (not RSA?)." else echo "1:${sshKey}" fi @@ -725,14 +727,14 @@ process_user_id() { if [ "$keyOK" -a "$uidOK" -a "$lastKeyOK" ] ; then log verbose " * acceptable sub key." if [ -z "$sshKey" ] ; then - log error " ! sub key could not be translated (not RSA or DSA?)." + log error " ! sub key could not be translated (not RSA?)." else echo "0:${sshKey}" fi else log debug " - unacceptable sub key." if [ -z "$sshKey" ] ; then - log debug " ! sub key could not be translated (not RSA or DSA?)." + log debug " ! sub key could not be translated (not RSA?)." else echo "1:${sshKey}" fi diff --git a/src/share/ma/update_users b/src/share/ma/update_users index 3a5c006..195e982 100644 --- a/src/share/ma/update_users +++ b/src/share/ma/update_users @@ -88,6 +88,7 @@ for uname in $unames ; do cat "$authorizedUserIDs" > "$TMP_AUTHORIZED_USER_IDS" # export needed variables + export USER="$uname" export AUTHORIZED_KEYS export TMP_AUTHORIZED_USER_IDS -- cgit v1.2.3 From 033b2e76b81746e91f2f15580125164a8821bf0d Mon Sep 17 00:00:00 2001 From: Jameson Graef Rollins Date: Sun, 1 Mar 2009 15:48:21 -0500 Subject: add defaultenv file that was missed in ebd776722e0fd6dfacc79146c368d148f0e266cb --- src/share/defaultenv | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 src/share/defaultenv (limited to 'src') diff --git a/src/share/defaultenv b/src/share/defaultenv new file mode 100644 index 0000000..b54a518 --- /dev/null +++ b/src/share/defaultenv @@ -0,0 +1,29 @@ +# -*-shell-script-*- +# This should be sourced by bash (though we welcome changes to make it POSIX sh compliant) + +# Shared sh variables for the monkeysphere +# +# Written by +# Jameson Rollins +# +# Copyright 2009, released under the GPL, version 3 or later + +# managed directories +SYSCONFIGDIR=${MONKEYSPHERE_SYSCONFIGDIR:-"/etc/monkeysphere"} +export SYSCONFIGDIR + +# default log level +LOG_LEVEL="INFO" + +# default keyserver +KEYSERVER="pool.sks-keyservers.net" + +# whether or not to check keyservers by defaul +CHECK_KEYSERVER="true" + +# default monkeysphere user +MONKEYSPHERE_USER="monkeysphere" + +# default about whether or not to prompt +PROMPT="true" + -- cgit v1.2.3 From 7b64ab42881f4702b6a7800dc06c94a742109fda Mon Sep 17 00:00:00 2001 From: Daniel Kahn Gillmor Date: Sun, 1 Mar 2009 17:11:59 -0500 Subject: switched $USER to $FILE_OWNER; new name is more semantically clear and less likely to collide with other common uses of $USER. --- src/monkeysphere | 4 ++-- src/share/common | 6 +++--- src/share/ma/update_users | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/monkeysphere b/src/monkeysphere index aa9276c..1641d32 100755 --- a/src/monkeysphere +++ b/src/monkeysphere @@ -189,8 +189,8 @@ export GNUPGHOME mkdir -p -m 0700 "$GNUPGHOME" export LOG_LEVEL -# explicitly set the USER variable, for checking file permissions -export USER=$(whoami) +# explicitly set the FILE_OWNER variable, for checking file permissions +export FILE_OWNER=$(whoami) # get subcommand COMMAND="$1" diff --git a/src/share/common b/src/share/common index c6d6b8e..dd5dc16 100644 --- a/src/share/common +++ b/src/share/common @@ -846,7 +846,7 @@ update_known_hosts() { (umask 0022 && touch "$KNOWN_HOSTS") # check permissions on the known_hosts file path - check_key_file_permissions "$USER" "$KNOWN_HOSTS" || failure + check_key_file_permissions "$FILE_OWNER" "$KNOWN_HOSTS" || failure # create a lockfile on known_hosts: lock create "$KNOWN_HOSTS" @@ -1000,7 +1000,7 @@ update_authorized_keys() { log debug " $AUTHORIZED_KEYS" # check permissions on the authorized_keys file path - check_key_file_permissions "$USER" "$AUTHORIZED_KEYS" || failure + check_key_file_permissions "$FILE_OWNER" "$AUTHORIZED_KEYS" || failure # create a lockfile on authorized_keys lock create "$AUTHORIZED_KEYS" @@ -1076,7 +1076,7 @@ process_authorized_user_ids() { log debug " $authorizedUserIDs" # check permissions on the authorized_user_ids file path - check_key_file_permissions "$USER" "$authorizedUserIDs" || failure + check_key_file_permissions "$FILE_OWNER" "$authorizedUserIDs" || failure if ! meat "$authorizedUserIDs" > /dev/null ; then log debug " no user IDs to process." diff --git a/src/share/ma/update_users b/src/share/ma/update_users index 195e982..a48bbd1 100644 --- a/src/share/ma/update_users +++ b/src/share/ma/update_users @@ -88,7 +88,7 @@ for uname in $unames ; do cat "$authorizedUserIDs" > "$TMP_AUTHORIZED_USER_IDS" # export needed variables - export USER="$uname" + export FILE_OWNER="$uname" export AUTHORIZED_KEYS export TMP_AUTHORIZED_USER_IDS -- cgit v1.2.3 From a9e9b3ae93b43b00700c379937895017bb530b08 Mon Sep 17 00:00:00 2001 From: Daniel Kahn Gillmor Date: Sun, 1 Mar 2009 18:05:11 -0500 Subject: refer to the m-h set-expire instead of m-h extend-key in m-h diagnostics. --- src/share/mh/diagnostics | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/share/mh/diagnostics b/src/share/mh/diagnostics index 2f65f89..3746020 100644 --- a/src/share/mh/diagnostics +++ b/src/share/mh/diagnostics @@ -63,11 +63,11 @@ else if [ "$expire" ]; then if (( "$expire" < "$curdate" )); then echo "! Host key is expired." - echo " - Recommendation: extend lifetime of key with 'monkeysphere-host extend-key'" + echo " - Recommendation: extend lifetime of key with 'monkeysphere-host set-expire'" problemsfound=$(($problemsfound+1)) elif (( "$expire" < "$warndate" )); then echo "! Host key expires in less than $warnwindow:" $(advance_date $(( $expire - $curdate )) seconds +%F) - echo " - Recommendation: extend lifetime of key with 'monkeysphere-host extend-key'" + echo " - Recommendation: extend lifetime of key with 'monkeysphere-host set-expire'" problemsfound=$(($problemsfound+1)) fi fi -- cgit v1.2.3 From c7ad73e5b9516c74a1e049322b89076f4878ddba Mon Sep 17 00:00:00 2001 From: Daniel Kahn Gillmor Date: Sun, 1 Mar 2009 19:56:41 -0500 Subject: proposed fix for issue 630; since m-a u operates on a saved copy of the users authorized_user_ids file, we should only check filesystem permissions against the monkeysphere user, not the target user. --- src/share/ma/update_users | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'src') diff --git a/src/share/ma/update_users b/src/share/ma/update_users index a48bbd1..67fabb2 100644 --- a/src/share/ma/update_users +++ b/src/share/ma/update_users @@ -88,12 +88,11 @@ for uname in $unames ; do cat "$authorizedUserIDs" > "$TMP_AUTHORIZED_USER_IDS" # export needed variables - export FILE_OWNER="$uname" export AUTHORIZED_KEYS export TMP_AUTHORIZED_USER_IDS # process authorized_user_ids file, as monkeysphere user - su_monkeysphere_user \ + FILE_OWNER="$MONKEYSPHERE_USER" su_monkeysphere_user \ ". ${SYSSHAREDIR}/common; process_authorized_user_ids $TMP_AUTHORIZED_USER_IDS" \ || returnCode="$?" else -- cgit v1.2.3 From 18d6d63571d18c50a4c943742c6cebbb100d4277 Mon Sep 17 00:00:00 2001 From: Jameson Graef Rollins Date: Mon, 2 Mar 2009 12:40:28 -0500 Subject: get rid of FILE_OWNER variable, in favor of just using $(whoami) when running check_key_file_permissions in update_known_hosts, update_authorized_keys, and process_authorized_user_ids. this is fine, since the policy is just that a user is always updating their own files. closes monkeysphere bug #630. --- src/monkeysphere | 3 --- src/share/common | 6 +++--- src/share/ma/update_users | 2 +- 3 files changed, 4 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/monkeysphere b/src/monkeysphere index 1641d32..8d59d08 100755 --- a/src/monkeysphere +++ b/src/monkeysphere @@ -189,9 +189,6 @@ export GNUPGHOME mkdir -p -m 0700 "$GNUPGHOME" export LOG_LEVEL -# explicitly set the FILE_OWNER variable, for checking file permissions -export FILE_OWNER=$(whoami) - # get subcommand COMMAND="$1" [ "$COMMAND" ] || failure "Type '$PGRM help' for usage." diff --git a/src/share/common b/src/share/common index dd5dc16..83f2d6f 100644 --- a/src/share/common +++ b/src/share/common @@ -846,7 +846,7 @@ update_known_hosts() { (umask 0022 && touch "$KNOWN_HOSTS") # check permissions on the known_hosts file path - check_key_file_permissions "$FILE_OWNER" "$KNOWN_HOSTS" || failure + check_key_file_permissions $(whoami) "$KNOWN_HOSTS" || failure # create a lockfile on known_hosts: lock create "$KNOWN_HOSTS" @@ -1000,7 +1000,7 @@ update_authorized_keys() { log debug " $AUTHORIZED_KEYS" # check permissions on the authorized_keys file path - check_key_file_permissions "$FILE_OWNER" "$AUTHORIZED_KEYS" || failure + check_key_file_permissions $(whoami) "$AUTHORIZED_KEYS" || failure # create a lockfile on authorized_keys lock create "$AUTHORIZED_KEYS" @@ -1076,7 +1076,7 @@ process_authorized_user_ids() { log debug " $authorizedUserIDs" # check permissions on the authorized_user_ids file path - check_key_file_permissions "$FILE_OWNER" "$authorizedUserIDs" || failure + check_key_file_permissions $(whoami) "$authorizedUserIDs" || failure if ! meat "$authorizedUserIDs" > /dev/null ; then log debug " no user IDs to process." diff --git a/src/share/ma/update_users b/src/share/ma/update_users index 67fabb2..3a5c006 100644 --- a/src/share/ma/update_users +++ b/src/share/ma/update_users @@ -92,7 +92,7 @@ for uname in $unames ; do export TMP_AUTHORIZED_USER_IDS # process authorized_user_ids file, as monkeysphere user - FILE_OWNER="$MONKEYSPHERE_USER" su_monkeysphere_user \ + su_monkeysphere_user \ ". ${SYSSHAREDIR}/common; process_authorized_user_ids $TMP_AUTHORIZED_USER_IDS" \ || returnCode="$?" else -- cgit v1.2.3 From 8cabd14f454708cdb0310d77e4897e860fc87ecc Mon Sep 17 00:00:00 2001 From: Jameson Graef Rollins Date: Mon, 2 Mar 2009 12:42:48 -0500 Subject: very small tweaks to usages. --- src/monkeysphere-authentication | 2 +- src/monkeysphere-host | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/monkeysphere-authentication b/src/monkeysphere-authentication index 3344f38..db658ae 100755 --- a/src/monkeysphere-authentication +++ b/src/monkeysphere-authentication @@ -56,7 +56,7 @@ subcommands: update-users (u) [USER]... update user authorized_keys files add-id-certifier (c+) [KEYID|FILE] import and tsign a certification key - --domain (-n) DOMAIN limit ID certifications to DOMAIN + --domain (-n) DOMAIN limit ID certifications to DOMAIN (*) --trust (-t) TRUST trust level of certifier (full) --depth (-d) DEPTH trust depth for certifier (1) remove-id-certifier (c-) KEYID remove a certification key diff --git a/src/monkeysphere-host b/src/monkeysphere-host index b9a15ae..c03fb27 100755 --- a/src/monkeysphere-host +++ b/src/monkeysphere-host @@ -58,7 +58,7 @@ subcommands: set-expire (e) [EXPIRE] set host key expiration add-hostname (n+) NAME[:PORT] add hostname user ID to host key revoke-hostname (n-) NAME[:PORT] revoke hostname user ID - add-revoker (r+) [KEYID|FILE] add a revoker to the host key + add-revoker (r+) [KEYID|FILE] add a revoker to the host key revoke-key generate and/or publish revocation certificate for host key -- cgit v1.2.3 From bd5aac0e2eae2dd73c35b6bbb2e79ef48c98ca21 Mon Sep 17 00:00:00 2001 From: Jameson Graef Rollins Date: Mon, 2 Mar 2009 12:45:48 -0500 Subject: fix remove_monkeysphere_line function to properly handle empty files. --- src/share/common | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/share/common b/src/share/common index 83f2d6f..83120d1 100644 --- a/src/share/common +++ b/src/share/common @@ -354,12 +354,15 @@ remove_monkeysphere_lines() { file="$1" - if [ -z "$file" ] ; then + # return error if file does not exist + if [ ! -e "$file" ] ; then return 1 fi - if [ ! -e "$file" ] ; then - return 1 + # just return ok if the file is empty, since there aren't any + # lines to remove + if [ ! -s "$file" ] ; then + return 0 fi tempfile=$(mktemp "${file}.XXXXXXX") || \ -- cgit v1.2.3 From 05c96da9d1774a1b9ca6782384a4317671bcd622 Mon Sep 17 00:00:00 2001 From: Daniel Kahn Gillmor Date: Mon, 2 Mar 2009 13:02:35 -0500 Subject: usage review/tweaks for m-a and m-h --- src/monkeysphere-authentication | 18 +++++++++--------- src/monkeysphere-host | 2 +- 2 files changed, 10 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/monkeysphere-authentication b/src/monkeysphere-authentication index db658ae..ae4f3f4 100755 --- a/src/monkeysphere-authentication +++ b/src/monkeysphere-authentication @@ -53,17 +53,17 @@ usage: $PGRM [options] [args] Monkeysphere authentication admin tool. subcommands: - update-users (u) [USER]... update user authorized_keys files + update-users (u) [USER]... update user authorized_keys files - add-id-certifier (c+) [KEYID|FILE] import and tsign a certification key - --domain (-n) DOMAIN limit ID certifications to DOMAIN (*) - --trust (-t) TRUST trust level of certifier (full) - --depth (-d) DEPTH trust depth for certifier (1) - remove-id-certifier (c-) KEYID remove a certification key - list-id-certifiers (c) list certification keys + add-id-certifier (c+) KEYID|FILE import and tsign a certification key + [--domain (-n) DOMAIN] limit ID certifications to DOMAIN + [--trust (-t) TRUST] trust level of certifier (default: full) + [--depth (-d) DEPTH] trust depth for certifier (default: 1) + remove-id-certifier (c-) KEYID remove a certification key + list-id-certifiers (c) list certification keys - version (v) show version number - help (h,?) this help + version (v) show version number + help (h,?) this help See ${PGRM}(8) for more info. EOF diff --git a/src/monkeysphere-host b/src/monkeysphere-host index c03fb27..7fb3980 100755 --- a/src/monkeysphere-host +++ b/src/monkeysphere-host @@ -58,7 +58,7 @@ subcommands: set-expire (e) [EXPIRE] set host key expiration add-hostname (n+) NAME[:PORT] add hostname user ID to host key revoke-hostname (n-) NAME[:PORT] revoke hostname user ID - add-revoker (r+) [KEYID|FILE] add a revoker to the host key + add-revoker (r+) KEYID|FILE add a revoker to the host key revoke-key generate and/or publish revocation certificate for host key -- cgit v1.2.3 From 6fb913f396e513148dd270c1ecca8eda537e50c6 Mon Sep 17 00:00:00 2001 From: Jameson Graef Rollins Date: Mon, 2 Mar 2009 15:35:06 -0500 Subject: added ability to specify subkeys to add to agent with MONKEYSPHERE_SUBKEYS_FOR_AGENT variable. --- packaging/debian/changelog | 4 ++- src/share/m/subkey_to_ssh_agent | 55 +++++++++++++++++++++++++++-------------- 2 files changed, 39 insertions(+), 20 deletions(-) (limited to 'src') diff --git a/packaging/debian/changelog b/packaging/debian/changelog index 8b3b922..786d410 100644 --- a/packaging/debian/changelog +++ b/packaging/debian/changelog @@ -8,13 +8,15 @@ monkeysphere (0.24~pre-1) UNRELEASED; urgency=low - improved transitions/0.23 script so it no longer fails in common circumstances (Closes: #517779) - RSA only: no longer handles DSA keys + - added ability to specify subkeys to add to ssh agent with + new MONKEYSPHERE_SUBKEYS_FOR_AGENT environment variable * update/cleanup maintainer scripts * remove GnuTLS dependency. * remove versioned coreutils | base64 dependency. * added Build-Deps for dh_autotest. * switch to Architecture: all - -- Daniel Kahn Gillmor Sun, 01 Mar 2009 11:47:41 -0500 + -- Jameson Graef Rollins Mon, 02 Mar 2009 15:33:44 -0500 monkeysphere (0.23.1-1) unstable; urgency=low diff --git a/src/share/m/subkey_to_ssh_agent b/src/share/m/subkey_to_ssh_agent index ec596bd..aa647a6 100644 --- a/src/share/m/subkey_to_ssh_agent +++ b/src/share/m/subkey_to_ssh_agent @@ -37,26 +37,34 @@ subkey_to_ssh_agent() { if [ "$sshaddresponse" = "2" ]; then failure "Could not connect to ssh-agent" fi - - # get list of secret keys (to work around bug - # https://bugs.g10code.com/gnupg/issue945): - secretkeys=$(gpg_user --list-secret-keys --with-colons --fixed-list-mode \ - --fingerprint | \ - grep '^fpr:' | cut -f10 -d: | awk '{ print "0x" $1 "!" }') - - if [ -z "$secretkeys" ]; then - failure "You have no secret keys in your keyring! + + # if the MONKEYSPHERE_SUBKEYS_FOR_AGENT variable is set, use the + # keys specified there + if [ "$MONKEYSPHERE_SUBKEYS_FOR_AGENT" ] ; then + authsubkeys="$MONKEYSPHERE_SUBKEYS_FOR_AGENT" + + # otherwise find all authentication-capable subkeys and use those + else + # get list of secret keys + # (to work around bug https://bugs.g10code.com/gnupg/issue945): + secretkeys=$(gpg_user --list-secret-keys --with-colons --fixed-list-mode \ + --fingerprint | \ + grep '^fpr:' | cut -f10 -d: | awk '{ print "0x" $1 "!" }') + + if [ -z "$secretkeys" ]; then + failure "You have no secret keys in your keyring! You might want to run 'gpg --gen-key'." - fi + fi - authsubkeys=$(gpg_user --list-secret-keys --with-colons --fixed-list-mode \ - --fingerprint --fingerprint $secretkeys | \ - cut -f1,5,10,12 -d: | grep -A1 '^ssb:[^:]*::[^:]*a[^:]*$' | \ - grep '^fpr::' | cut -f3 -d: | sort -u) - - if [ -z "$authsubkeys" ]; then - failure "no authentication-capable subkeys available. -You might want to 'monkeysphere gen-subkey'" + authsubkeys=$(gpg_user --list-secret-keys --with-colons --fixed-list-mode \ + --fingerprint --fingerprint $secretkeys | \ + cut -f1,5,10,12 -d: | grep -A1 '^ssb:[^:]*::[^:]*a[^:]*$' | \ + grep '^fpr::' | cut -f3 -d: | sort -u) + + if [ -z "$authsubkeys" ]; then + failure "no authentication-capable subkeys available. +You might want to run 'monkeysphere gen-subkey'." + fi fi workingdir=$(msmktempdir) @@ -68,7 +76,16 @@ You might want to 'monkeysphere gen-subkey'" # through to ssh-add. should we limit it to known ones? For # example: -d or -c and/or -t - for subkey in $authsubkeys; do + for subkey in $authsubkeys; do + # test that the subkey has proper capability + capability=$(gpg_user --list-secret-keys --with-colons --fixed-list-mode \ + --fingerprint --fingerprint "0x${subkey}!" \ + | egrep -B 1 "^fpr:::::::::${subkey}:$" | grep "^ssb:" | cut -d: -f12) + if ! check_capability "$capability" 'a' ; then + log error "Did not find authentication-capable subkey with key ID '$subkey'." + continue + fi + # choose a label by which this key will be known in the agent: # we are labelling the key by User ID instead of by # fingerprint, but filtering out all / characters to make sure -- cgit v1.2.3 From 964d1c805c5866ea7f4a2c38808ccc3a5db490f5 Mon Sep 17 00:00:00 2001 From: Daniel Kahn Gillmor Date: Mon, 2 Mar 2009 17:42:33 -0500 Subject: quieting down the transition script (and m-a setup). --- src/share/ma/setup | 4 ++-- src/transitions/0.23 | 21 +++++++++++---------- 2 files changed, 13 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/src/share/ma/setup b/src/share/ma/setup index f991050..b453f3c 100644 --- a/src/share/ma/setup +++ b/src/share/ma/setup @@ -82,7 +82,7 @@ EOF # ensure that the authentication sphere checker has absolute ownertrust on the expected key. log debug "setting ultimate owner trust on core key in gpg_sphere..." - printf "%s:6:\n" "$CORE_FPR" | gpg_sphere "--import-ownertrust" + printf "%s:6:\n" "$CORE_FPR" | gpg_sphere "--import-ownertrust" 2>&1 | log verbose gpg_sphere "--export-ownertrust" 2>&1 | log debug # check the owner trust @@ -101,7 +101,7 @@ EOF # our preferences are reasonable (i.e. 3 marginal OR 1 fully # trusted certifications are sufficient to grant full validity. log debug "checking trust model for authentication ..." - local TRUST_MODEL=$(gpg_sphere "--with-colons --fixed-list-mode --list-keys" \ + local TRUST_MODEL=$(gpg_sphere "--with-colons --fixed-list-mode --list-keys" 2>/dev/null \ | head -n1 | grep "^tru:" | cut -d: -f3,6,7) log debug "sphere trust model: $TRUST_MODEL" if [ "$TRUST_MODEL" != '1:3:1' ] ; then diff --git a/src/transitions/0.23 b/src/transitions/0.23 index b0c967a..4410ae8 100755 --- a/src/transitions/0.23 +++ b/src/transitions/0.23 @@ -71,7 +71,7 @@ if [ -d "$SYSDATADIR"/gnupg-host ] ; then # get the old host keygrip (don't know why there would be more # than one, but we'll transfer all tsigs made by any key that # had been given ultimate ownertrust): - for authgrip in $(GNUPGHOME="$SYSDATADIR"/gnupg-host gpg --no-permission-warning --export-ownertrust | \ + for authgrip in $(GNUPGHOME="$SYSDATADIR"/gnupg-host gpg --quiet --no-tty --no-permission-warning --export-ownertrust | \ grep ':6:$' | \ sed -r 's/^[A-F0-9]{24}([A-F0-9]{16}):6:$/\1/') ; do @@ -87,7 +87,7 @@ if [ -d "$SYSDATADIR"/gnupg-host ] ; then # one of those certifications (even if later # certifications had different parameters). - GNUPGHOME="$SYSDATADIR"/gnupg-host gpg --no-permission-warning --fingerprint --with-colons --fixed-list-mode --check-sigs | \ + GNUPGHOME="$SYSDATADIR"/gnupg-host gpg --quiet --no-tty --no-permission-warning --fingerprint --with-colons --fixed-list-mode --check-sigs | \ cut -f 1,2,5,8,9,10 -d: | \ egrep '^(fpr:::::|sig:!:'"$authgrip"':[[:digit:]]+ [[:digit:]]+:)' | \ while IFS=: read -r type validity grip trustparams trustdomain fpr ; do @@ -129,7 +129,7 @@ if [ -d "$SYSDATADIR"/gnupg-host ] ; then CERTKEY=$(mktemp ${TMPDIR:-/tmp}/mstransition.XXXXXXXX) log "Adding identity certifier with fingerprint %s\n" "$keyfpr" - GNUPGHOME="$SYSDATADIR"/gnupg-host gpg --no-permission-warning --export "0x$keyfpr" --export-options export-clean >"$CERTKEY" + GNUPGHOME="$SYSDATADIR"/gnupg-host gpg --quiet --no-tty --no-permission-warning --export "0x$keyfpr" --export-options export-clean >"$CERTKEY" MONKEYSPHERE_PROMPT=false monkeysphere-authentication add-identity-certifier $finaldomain --trust "$truststring" --depth "$trustdepth" "$CERTKEY" rm -f "$CERTKEY" # clear the fingerprint so that we don't @@ -149,9 +149,9 @@ if [ -d "$SYSDATADIR"/gnupg-host ] ; then log "Not transferring host key info because host directory already exists.\n" else if [ -s "$SYSDATADIR"/ssh_host_rsa_key ] || \ - GNUPGHOME="$SYSDATADIR"/gnupg-host gpg --no-permission-warning --with-colons --list-secret-keys | grep -q '^sec:' ; then + GNUPGHOME="$SYSDATADIR"/gnupg-host gpg --quiet --no-tty --no-permission-warning --with-colons --list-secret-keys | grep -q '^sec:' ; then - FPR=$(GNUPGHOME="$SYSDATADIR"/gnupg-host gpg --no-permission-warning --with-colons --fixed-list-mode --list-secret-keys --fingerprint | awk -F: '/^fpr:/{ print $10 }' ) + FPR=$(GNUPGHOME="$SYSDATADIR"/gnupg-host gpg --quiet --no-tty --no-permission-warning --with-colons --fixed-list-mode --list-secret-keys --fingerprint | awk -F: '/^fpr:/{ print $10 }' ) # create host home mkdir -p $(dirname "$MHDATADIR") @@ -168,12 +168,12 @@ if [ -d "$SYSDATADIR"/gnupg-host ] ; then # FIXME: if all self-sigs are expired, then the secret key import may # fail anyway. How should we deal with that? - if (GNUPGHOME="$SYSDATADIR"/gnupg-host gpg --no-permission-warning --export-secret-keys && \ - GNUPGHOME="$SYSDATADIR"/gnupg-host gpg --no-permission-warning --export "$FPR") | \ + if (GNUPGHOME="$SYSDATADIR"/gnupg-host gpg --quiet --no-tty --no-permission-warning --export-secret-keys && \ + GNUPGHOME="$SYSDATADIR"/gnupg-host gpg --quiet --no-tty --no-permission-warning --export "$FPR") | \ GNUPGHOME="$NEWDATADIR" gpg --quiet --no-tty --import ; then : we are in good shape! else - if ! GNUPGHOME="$NEWDATADIR" gpg --list-secret-key >/dev/null ; then + if ! GNUPGHOME="$NEWDATADIR" gpg --quiet --no-tty --list-secret-key >/dev/null ; then log "The old host key (%s) was not imported properly.\n" "$FPR" exit 1 fi @@ -202,8 +202,9 @@ fi # the new authentication keyring. if [ -d "${SYSDATADIR}/gnupg-authentication" ] ; then - GNUPGHOME="${SYSDATADIR}/gnupg-authentication" gpg --no-permission-warning --export | \ - monkeysphere-authentication gpg-cmd --import || \ + GNUPGHOME="${SYSDATADIR}/gnupg-authentication" \ + gpg --quiet --no-tty --no-permission-warning --export 2>/dev/null | \ + monkeysphere-authentication gpg-cmd --import 2>/dev/null || \ log "No OpenPGP certificates imported into monkeysphere-authentication trust sphere.\n" mkdir -p "$STASHDIR" -- cgit v1.2.3 From cf04c38691c1fa80ad9ac65175e034fbff7ab0c3 Mon Sep 17 00:00:00 2001 From: Daniel Kahn Gillmor Date: Tue, 3 Mar 2009 00:13:11 -0500 Subject: transitions/0.23: when backing up old gnupg-{host,authentication}, timestamp backups so that they are relatively unique: this makes collisions less likely if the script gets run twice (failing the first time), and helps record the history of the cleanup as well --- src/transitions/0.23 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/transitions/0.23 b/src/transitions/0.23 index 4410ae8..3964558 100755 --- a/src/transitions/0.23 +++ b/src/transitions/0.23 @@ -193,7 +193,7 @@ if [ -d "$SYSDATADIR"/gnupg-host ] ; then mkdir -p "$STASHDIR" chmod 0700 "$STASHDIR" - mv "${SYSDATADIR}/gnupg-host" "$STASHDIR" + mv "${SYSDATADIR}/gnupg-host" "$STASHDIR"/gnupg-host.$(date '+%F_%T%z') fi @@ -209,5 +209,5 @@ if [ -d "${SYSDATADIR}/gnupg-authentication" ] ; then mkdir -p "$STASHDIR" chmod 0700 "$STASHDIR" - mv "${SYSDATADIR}/gnupg-authentication" "$STASHDIR" + mv "${SYSDATADIR}/gnupg-authentication" "$STASHDIR"/gnupg-authentication.$(date '+%F_%T%z') fi -- cgit v1.2.3 From b94c148b51a53f47ac2513af0e400cc9234bc3dd Mon Sep 17 00:00:00 2001 From: Daniel Kahn Gillmor Date: Tue, 3 Mar 2009 01:15:50 -0500 Subject: quieted down m-a add_certifier: there is no reason why the admin should be shown gpg noise. --- src/monkeysphere-authentication | 2 +- src/share/ma/add_certifier | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/monkeysphere-authentication b/src/monkeysphere-authentication index ae4f3f4..b0dcc88 100755 --- a/src/monkeysphere-authentication +++ b/src/monkeysphere-authentication @@ -100,7 +100,7 @@ core_fingerprint() { gpg_core_sphere_sig_transfer() { log debug "exporting core local sigs to sphere..." gpg_core --export-options export-local-sigs --export | \ - gpg_sphere "--import-options import-local-sigs --import" + gpg_sphere "--import-options import-local-sigs --import" 2>&1 | log debug } ######################################################################## diff --git a/src/share/ma/add_certifier b/src/share/ma/add_certifier index 6f85ecf..544a3f0 100644 --- a/src/share/ma/add_certifier +++ b/src/share/ma/add_certifier @@ -108,7 +108,7 @@ if [ -f "$keyID" -o "$keyID" = '-' ] ; then fi # load the key - gpg_sphere "--import" <"$keyID" \ + gpg_sphere "--import" <"$keyID" 2>/dev/null \ || failure "could not read key from '$keyID'" # else, get the key from the keyserver -- cgit v1.2.3 From 91fee4b8616ce94be3b18f58b8d361d784ce92a6 Mon Sep 17 00:00:00 2001 From: Jameson Graef Rollins Date: Tue, 3 Mar 2009 11:56:00 -0500 Subject: fix to logging to prefix all log output with log prefix, and allow changing of log prefix. --- src/monkeysphere | 1 + src/monkeysphere-authentication | 1 + src/monkeysphere-host | 1 + src/share/common | 7 +++---- 4 files changed, 6 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/monkeysphere b/src/monkeysphere index 8d59d08..f721108 100755 --- a/src/monkeysphere +++ b/src/monkeysphere @@ -182,6 +182,7 @@ AUTHORIZED_KEYS=${MONKEYSPHERE_AUTHORIZED_KEYS:=$AUTHORIZED_KEYS} AUTHORIZED_USER_IDS=${MONKEYSPHERE_AUTHORIZED_USER_IDS:="${MONKEYSPHERE_HOME}/authorized_user_ids"} REQUIRED_HOST_KEY_CAPABILITY=${MONKEYSPHERE_REQUIRED_HOST_KEY_CAPABILITY:="a"} REQUIRED_USER_KEY_CAPABILITY=${MONKEYSPHERE_REQUIRED_USER_KEY_CAPABILITY:="a"} +LOG_PREFIX=${MONKEYSPHERE_LOG_PREFIX:='ms: '} # export GNUPGHOME and make sure gpg home exists with proper # permissions diff --git a/src/monkeysphere-authentication b/src/monkeysphere-authentication index b0dcc88..85ff04f 100755 --- a/src/monkeysphere-authentication +++ b/src/monkeysphere-authentication @@ -129,6 +129,7 @@ REQUIRED_USER_KEY_CAPABILITY=${MONKEYSPHERE_REQUIRED_USER_KEY_CAPABILITY:="a"} GNUPGHOME_CORE=${MONKEYSPHERE_GNUPGHOME_CORE:="${MADATADIR}/core"} GNUPGHOME_SPHERE=${MONKEYSPHERE_GNUPGHOME_SPHERE:="${MADATADIR}/sphere"} CORE_KEYLENGTH=${MONKEYSPHERE_CORE_KEYLENGTH:="2048"} +LOG_PREFIX=${MONKEYSPHERE_LOG_PREFIX:='ms: '} # export variables needed in su invocation export DATE diff --git a/src/monkeysphere-host b/src/monkeysphere-host index 7fb3980..b052ca1 100755 --- a/src/monkeysphere-host +++ b/src/monkeysphere-host @@ -230,6 +230,7 @@ PROMPT=${MONKEYSPHERE_PROMPT:=$PROMPT} # other variables GNUPGHOME_HOST=${MONKEYSPHERE_GNUPGHOME_HOST:="${MHDATADIR}"} +LOG_PREFIX=${MONKEYSPHERE_LOG_PREFIX:='ms: '} # export variables needed in su invocation export DATE diff --git a/src/share/common b/src/share/common index 83120d1..ea872ba 100644 --- a/src/share/common +++ b/src/share/common @@ -76,11 +76,10 @@ log() { fi if [ "$priority" = "$level" -a "$output" = 'true' ] ; then if [ "$1" ] ; then - echo -n "ms: " >&2 - echo "$@" >&2 + echo "$@" else - cat >&2 - fi + cat + fi | sed 's/^/'"${LOG_PREFIX}"'/' >&2 fi done } -- cgit v1.2.3 From db21b3340c2b7ade19eaecb306814fc0e54666f1 Mon Sep 17 00:00:00 2001 From: Daniel Kahn Gillmor Date: Tue, 10 Mar 2009 02:06:25 -0400 Subject: cleaning up a lingering non-portable mktemp invocation. --- .../security/monkeysphere/files/patch-src_monkeysphere-host | 11 +++++++++++ src/monkeysphere-host | 2 +- 2 files changed, 12 insertions(+), 1 deletion(-) create mode 100644 packaging/freebsd/security/monkeysphere/files/patch-src_monkeysphere-host (limited to 'src') diff --git a/packaging/freebsd/security/monkeysphere/files/patch-src_monkeysphere-host b/packaging/freebsd/security/monkeysphere/files/patch-src_monkeysphere-host new file mode 100644 index 0000000..9414c73 --- /dev/null +++ b/packaging/freebsd/security/monkeysphere/files/patch-src_monkeysphere-host @@ -0,0 +1,11 @@ +--- src/monkeysphere-host ++++ src/monkeysphere-host +@@ -103,7 +103,7 @@ update_gpg_pub_file() { + load_fingerprint() { + if [ -f "$HOST_KEY_FILE" ] ; then + HOST_FINGERPRINT=$( \ +- (FUBAR=$(mktemp -d) && export GNUPGHOME="$FUBAR" \ ++ (FUBAR=$(msmktempdir) && export GNUPGHOME="$FUBAR" \ + && gpg --quiet --import \ + && gpg --quiet --list-keys --with-colons --with-fingerprint \ + && rm -rf "$FUBAR") <"$HOST_KEY_FILE" \ diff --git a/src/monkeysphere-host b/src/monkeysphere-host index b052ca1..6136399 100755 --- a/src/monkeysphere-host +++ b/src/monkeysphere-host @@ -103,7 +103,7 @@ update_gpg_pub_file() { load_fingerprint() { if [ -f "$HOST_KEY_FILE" ] ; then HOST_FINGERPRINT=$( \ - (FUBAR=$(mktemp -d) && export GNUPGHOME="$FUBAR" \ + (FUBAR=$(msmktempdir) && export GNUPGHOME="$FUBAR" \ && gpg --quiet --import \ && gpg --quiet --list-keys --with-colons --with-fingerprint \ && rm -rf "$FUBAR") <"$HOST_KEY_FILE" \ -- cgit v1.2.3