The monkeysphere {import,gen}_subkey functions were not up-to-date.
authorJameson Graef Rollins <jrollins@finestructure.net>
Thu, 19 Feb 2009 20:19:02 +0000 (15:19 -0500)
committerJameson Graef Rollins <jrollins@finestructure.net>
Thu, 19 Feb 2009 20:19:02 +0000 (15:19 -0500)
did a lot of work to bring them up-to-date, and better handle argument
checking.  also updated man page, changelog, and tests/basic.

man/man1/monkeysphere.1
packaging/debian/changelog
src/monkeysphere
src/share/m/gen_subkey
src/share/m/import_subkey
src/share/mh/import_key
tests/basic

index 3ed43e1c87e394918078918d9f508f0d76af74a3..345e1d8135190c1fb87b586bbcba996ea4801d20 100644 (file)
@@ -56,24 +56,32 @@ ID, 1 if no matching keys were found at all, and 2 if matching keys
 were found but none were acceptable.  `a' may be used in place of
 `update-authorized_keys'.
 .TP
 were found but none were acceptable.  `a' may be used in place of
 `update-authorized_keys'.
 .TP
+.B import-subkey FILE [KEYID]
+Import an existing ssh RSA key as an authentication subkey for a
+private key in your GnuPG keyring.  KEYID is the key ID for the
+primary key for which the subkey with "authentication" capability will
+be imported.  If no key ID is specified, but only one key exists in
+the secret keyring, that key will be used.  `i' may be used in place
+of `import-subkey'.
+.TP
 .B gen-subkey [KEYID]
 Generate an authentication subkey for a private key in your GnuPG
 .B gen-subkey [KEYID]
 Generate an authentication subkey for a private key in your GnuPG
-keyring.  For the primary key with the specified key ID, generate a
-subkey with "authentication" capability that can be used for
-monkeysphere transactions.  An expiration length can be specified with
-the `-e' or `--expire' option (prompt otherwise).  If no key ID is
+keyring.  KEYID is the key ID for the primary key for which the subkey
+with "authentication" capability will be generated.  If no key ID is
 specified, but only one key exists in the secret keyring, that key
 specified, but only one key exists in the secret keyring, that key
-will be used.  `g' may be used in place of `gen-subkey'.
+will be used.  The length of the generated key can be specified with
+the `--length` or `-l` option.  `g' may be used in place of
+`gen-subkey'.
 .TP
 .B ssh-proxycommand
 .TP
 .B ssh-proxycommand
-an ssh proxy command that can be used
-to trigger a monkeysphere update of the ssh known_hosts file for a
-host that is being connected to with ssh.  This works by updating the
-known_hosts file for the host first, before an attempted connection to
-the host is made.  Once the known_hosts file has been updated, a TCP
-connection to the host is made by exec'ing netcat(1).  Regular ssh
-communication is then done over this netcat TCP connection (see
-ProxyCommand in ssh_config(5) for more info).
+An ssh ProxyCommand that can be used to trigger a monkeysphere update
+of the ssh known_hosts file for a host that is being connected to with
+ssh.  This works by updating the known_hosts file for the host first,
+before an attempted connection to the host is made.  Once the
+known_hosts file has been updated, a TCP connection to the host is
+made by exec'ing netcat(1).  Regular ssh communication is then done
+over this netcat TCP connection (see ProxyCommand in ssh_config(5) for
+more info).
 
 This command is meant to be run as the ssh "ProxyCommand".  This can
 either be done by specifying the proxy command on the command line:
 
 This command is meant to be run as the ssh "ProxyCommand".  This can
 either be done by specifying the proxy command on the command line:
@@ -108,9 +116,10 @@ change in the future, possibly by adding a deferred check, so that
 hosts that go from non-monkeysphere-enabled to monkeysphere-enabled
 will be properly checked.
 
 hosts that go from non-monkeysphere-enabled to monkeysphere-enabled
 will be properly checked.
 
-Setting the MONKEYSPHERE_CHECK_KEYSERVER
-variable (to `true' or `false') will override the keyserver-checking policy
-defined above.
+Setting the CHECK_KEYSERVER variable in the config file or the
+MONKEYSPHERE_CHECK_KEYSERVER environment variable to either `true' or
+`false' will override the keyserver-checking policy defined above and
+either always or never check the keyserver for host key updates.
 
 .TP
 .B subkey-to-ssh-agent [ssh-add arguments]
 
 .TP
 .B subkey-to-ssh-agent [ssh-add arguments]
index 6a9ea18f76e4f08c7612464edaa2cc80640f6bd9..fc317d9e1b3935bcb09a3e3a4f043368ab1b7760 100644 (file)
@@ -16,12 +16,12 @@ monkeysphere (0.23~pre-1) UNRELEASED; urgency=low
     functions that require it to be there.
   * get rid of getopts dependency
   * added version output option
     functions that require it to be there.
   * get rid of getopts dependency
   * added version output option
-  * check that existing authentication keys are valid in gen_key
-     function.
+  * better checks on validity of existing authentication subkeys when
+    doing monkeysphere {import,gen}_subkey.
   * add transition infrastructure for major changes between releases (see
     transitions/README.txt)
 
   * add transition infrastructure for major changes between releases (see
     transitions/README.txt)
 
- -- Daniel Kahn Gillmor <dkg@fifthhorseman.net>  Thu, 19 Feb 2009 02:14:44 -0500
+ -- Jameson Graef Rollins <jrollins@finestructure.net>  Thu, 19 Feb 2009 15:11:04 -0500
 
 monkeysphere (0.22-1) unstable; urgency=low
 
 
 monkeysphere (0.22-1) unstable; urgency=low
 
index 992ca063ab475f5a554db0c09f787941f8807c34..4169f2a541cd4e1fe18d7b87abeb97bfcc48d568 100755 (executable)
@@ -45,12 +45,9 @@ Monkeysphere client tool.
 subcommands:
  update-known_hosts (k) [HOST]...    update known_hosts file
  update-authorized_keys (a)          update authorized_keys file
 subcommands:
  update-known_hosts (k) [HOST]...    update known_hosts file
  update-authorized_keys (a)          update authorized_keys file
- import-subkey (i)                   import existing ssh key as gpg subkey
-   --keyfile (-f) FILE                 key file to import
-   --expire (-e) EXPIRE                date to expire
+ import-subkey (i) FILE [KEYID]      import existing ssh key as gpg subkey
  gen-subkey (g) [KEYID]              generate an authentication subkey
    --length (-l) BITS                  key length in bits (2048)
  gen-subkey (g) [KEYID]              generate an authentication subkey
    --length (-l) BITS                  key length in bits (2048)
-   --expire (-e) EXPIRE                date to expire
  ssh-proxycommand                    monkeysphere ssh ProxyCommand
  subkey-to-ssh-agent (s)             store authentication subkey in ssh-agent
  version (v)                         show version number
  ssh-proxycommand                    monkeysphere ssh ProxyCommand
  subkey-to-ssh-agent (s)             store authentication subkey in ssh-agent
  version (v)                         show version number
@@ -59,6 +56,83 @@ subcommands:
 EOF
 }
 
 EOF
 }
 
+# take a secret key ID and check that only zero or one ID is provided,
+# and that it corresponds to only a single secret key ID
+check_gpg_sec_key_id() {
+    local gpgSecOut
+
+    case "$#" in
+       0)
+           gpgSecOut=$(gpg --quiet --fixed-list-mode --list-secret-keys --with-colons 2>/dev/null | egrep '^sec:')
+           ;;
+       1)
+           gpgSecOut=$(gpg --quiet --fixed-list-mode --list-secret-keys --with-colons "$keyID" | egrep '^sec:') || failure
+           ;;
+       *)
+           failure "You must specify only a single primary key ID."
+           ;;
+    esac
+
+    # check that only a single secret key was found
+    case $(echo "$gpgSecOut" | grep -c '^sec:') in
+       0)
+           failure "No secret keys found.  Create an OpenPGP key with the following command:
+ gpg --gen-key"
+           ;;
+       1)
+           echo "$gpgSecOut" | cut -d: -f5
+           ;;
+       *)
+           echo "Multiple primary secret keys found:" | log error
+           echo "$gpgSecOut" | cut -d: -f5 | log error
+           echo "Please specify which primary key to use." | log error
+           failure
+           ;;
+    esac
+}
+
+# check that a valid authentication subkey does not already exist
+check_gpg_authentication_subkey() {
+    local keyID
+    local IFS
+    local line
+    local type
+    local validity
+    local usage
+
+    keyID="$1"
+
+    # check that a valid authentication key does not already exist
+    IFS=$'\n'
+    for line in $(gpg --quiet --fixed-list-mode --list-keys --with-colons "$keyID") ; do
+       type=$(echo "$line" | cut -d: -f1)
+       validity=$(echo "$line" | cut -d: -f2)
+       usage=$(echo "$line" | cut -d: -f12)
+
+       # look at keys only
+       if [ "$type" != 'pub' -a "$type" != 'sub' ] ; then
+           continue
+       fi
+       # check for authentication capability
+       if ! check_capability "$usage" 'a' ; then
+           continue
+       fi
+       # if authentication key is valid, prompt to continue
+       if [ "$validity" = 'u' ] ; then
+           log error "A valid authentication key already exists for primary key '$keyID'."
+           if [ "$PROMPT" = "true" ] ; then
+               read -p "Are you sure you would like to generate another one? (y/N) " OK; OK=${OK:N}
+               if [ "${OK/y/Y}" != 'Y' ] ; then
+                   failure "aborting."
+               fi
+               break
+           else
+               failure "aborting."
+           fi
+       fi
+    done
+}
+
 ########################################################################
 # MAIN
 ########################################################################
 ########################################################################
 # MAIN
 ########################################################################
index d926ad551116e57e6c3e4510b9923af5e7f23618..7c3ebb7e54ddc7b0bc04850fde94c9191961364c 100644 (file)
 
 gen_subkey(){
     local keyLength
 
 gen_subkey(){
     local keyLength
-    local keyExpire
+    local gpgSecOut
     local keyID
     local keyID
-    local gpgOut
-    local userID
+    local editCommands
+    local fifoDir
 
     # get options
     while true ; do
 
     # get options
     while true ; do
@@ -27,10 +27,6 @@ gen_subkey(){
                keyLength="$2"
                shift 2
                ;;
                keyLength="$2"
                shift 2
                ;;
-           -e|--expire)
-               keyExpire="$2"
-               shift 2
-               ;;
            *)
                if [ "$(echo "$1" | cut -c 1)" = '-' ] ; then
                    failure "Unknown option '$1'.
            *)
                if [ "$(echo "$1" | cut -c 1)" = '-' ] ; then
                    failure "Unknown option '$1'.
@@ -41,67 +37,11 @@ Type '$PGRM help' for usage."
        esac
     done
 
        esac
     done
 
-    case "$#" in
-       0)
-           gpgSecOut=$(gpg --quiet --fixed-list-mode --list-secret-keys --with-colons 2>/dev/null | egrep '^sec:')
-           ;;
-       1)
-           gpgSecOut=$(gpg --quiet --fixed-list-mode --list-secret-keys --with-colons "$1" | egrep '^sec:') || failure
-           ;;
-       *)
-           failure "You must specify only a single primary key ID."
-           ;;
-    esac
-
-    # check that only a single secret key was found
-    case $(echo "$gpgSecOut" | grep -c '^sec:') in
-       0)
-           failure "No secret keys found.  Create an OpenPGP key with the following command:
- gpg --gen-key"
-           ;;
-       1)
-           keyID=$(echo "$gpgSecOut" | cut -d: -f5)
-           ;;
-       *)
-           echo "Multiple primary secret keys found:"
-           echo "$gpgSecOut" | cut -d: -f5
-           failure "Please specify which primary key to use."
-           ;;
-    esac
+    # check that the keyID is unique
+    keyID=$(check_gpg_sec_key_id "$@")
 
 
-    # check that a valid authentication key does not already exist
-    IFS=$'\n'
-    for line in $(gpg --quiet --fixed-list-mode --list-keys --with-colons "$keyID") ; do
-       type=$(echo "$line" | cut -d: -f1)
-       validity=$(echo "$line" | cut -d: -f2)
-       usage=$(echo "$line" | cut -d: -f12)
-
-       # look at keys only
-       if [ "$type" != 'pub' -a "$type" != 'sub' ] ; then
-           continue
-       fi
-       # check for authentication capability
-       if ! check_capability "$usage" 'a' ; then
-           continue
-       fi
-       # if authentication key is valid, prompt to continue
-       if [ "$validity" = 'u' ] ; then
-           log error "A valid authentication key already exists for primary key '$keyID'."
-           if [ "$PROMPT" = "true" ] ; then
-               read -p "Are you sure you would like to generate another one? (y/N) " OK; OK=${OK:N}
-               if [ "${OK/y/Y}" != 'Y' ] ; then
-                   failure "aborting."
-               fi
-               break
-           else
-               failure "aborting."
-           fi
-       fi
-    done
-
-    # set subkey defaults
-    # prompt about key expiration if not specified
-    keyExpire=$(get_gpg_expiration "$keyExpire")
+    # check that an authentication subkey does not already exist
+    check_gpg_authentication_subkey "$keyID"
 
     # generate the list of commands that will be passed to edit-key
     editCommands=$(cat <<EOF
 
     # generate the list of commands that will be passed to edit-key
     editCommands=$(cat <<EOF
@@ -112,19 +52,24 @@ E
 A
 Q
 $keyLength
 A
 Q
 $keyLength
-$keyExpire
+0
 save
 EOF
 )
 
 save
 EOF
 )
 
-    log verbose "generating subkey..."
+    # setup the temp fifo dir for retrieving the key password
+    log debug "creating password fifo..."
     fifoDir=$(msmktempdir)
     fifoDir=$(msmktempdir)
+    trap "rm -rf $fifoDir" EXIT
     (umask 077 && mkfifo "$fifoDir/pass")
     (umask 077 && mkfifo "$fifoDir/pass")
+
+    log verbose "generating subkey..."
     echo "$editCommands" | gpg --passphrase-fd 3 3< "$fifoDir/pass" --expert --command-fd 0 --edit-key "$keyID" &
 
     # FIXME: this needs to fail more gracefully if the passphrase is incorrect
     passphrase_prompt  "Please enter your passphrase for $keyID: " "$fifoDir/pass"
 
     echo "$editCommands" | gpg --passphrase-fd 3 3< "$fifoDir/pass" --expert --command-fd 0 --edit-key "$keyID" &
 
     # FIXME: this needs to fail more gracefully if the passphrase is incorrect
     passphrase_prompt  "Please enter your passphrase for $keyID: " "$fifoDir/pass"
 
+    trap - EXIT
     rm -rf "$fifoDir"
     wait
     log verbose "done."
     rm -rf "$fifoDir"
     wait
     log verbose "done."
index 8b044568848c2ab6ca22a8717e6ed2b678b1e87c..d71c2581719db705ce4dd8b44afe624b68ef569e 100644 (file)
 # import an existing ssh key as a gpg subkey
 
 import_subkey() {
 # import an existing ssh key as a gpg subkey
 
 import_subkey() {
-    local keyFile="~/.ssh/id_rsa"
-    local keyExpire
+    local sshKeyFile
     local keyID
     local keyID
-    local gpgOut
-    local userID
-
-    # get options
-    while true ; do
-       case "$1" in
-           -f|--keyfile)
-               keyFile="$2"
-               shift 2
-               ;;
-           -e|--expire)
-               keyExpire="$2"
-               shift 2
-               ;;
-           *)
-               if [ "$(echo "$1" | cut -c 1)" = '-' ] ; then
-                   failure "Unknown option '$1'.
-Type '$PGRM help' for usage."
-               fi
-               break
-               ;;
-       esac
-    done
-
-    log verbose "importing ssh key..."
+    local gpgSecOut
+    local fifoDir
+
+    sshKeyFile="$1"
+    shift
+
+    # check that key file specified
+    if [ -z "$sshKeyFile" ] ; then
+       failure "Must specify ssh key file to import, or specify '-' for stdin."
+    fi
+
+    # check that the keyID is unique
+    keyID=$(check_gpg_sec_key_id "$@")
+
+    # check that an authentication subkey does not already exist
+    check_gpg_authentication_subkey "$keyID"
+
+    # setup the temp fifo dir for retrieving the key password
+    log debug "creating password fifo..."
     fifoDir=$(msmktempdir)
     fifoDir=$(msmktempdir)
+    trap "rm -rf $fifoDir" EXIT
     (umask 077 && mkfifo "$fifoDir/pass")
     (umask 077 && mkfifo "$fifoDir/pass")
-    ssh2openpgp | gpg --passphrase-fd 3 3< "$fifoDir/pass" --expert --command-fd 0 --import &
 
 
+    # import ssh key to as authentication subkey
+    if [ "$sshKeyFile" = '-' ] ; then
+       log verbose "importing ssh key from stdin..."
+       ssh2openpgp \
+           | gpg --passphrase-fd 3 3< "$fifoDir/pass" --expert --command-fd 0 --import &
+    else
+       log verbose "importing ssh key from file '$sshKeyFile'..."
+       ssh2openpgp <"$sshKeyFile" \
+           | gpg --passphrase-fd 3 3< "$fifoDir/pass" --expert --command-fd 0 --import &
+    fi
+
+    # get the password if needed
     passphrase_prompt  "Please enter your passphrase for $keyID: " "$fifoDir/pass"
 
     passphrase_prompt  "Please enter your passphrase for $keyID: " "$fifoDir/pass"
 
+    trap - EXIT
     rm -rf "$fifoDir"
     wait
     log verbose "done."
     rm -rf "$fifoDir"
     wait
     log verbose "done."
index 6394ad734fec1e601f92d1362329ae9ba51f06ad..040b41c57140862760b9e10dcac2189bdcb44f65 100644 (file)
@@ -21,6 +21,11 @@ local userID
 sshKeyFile="$1"
 hostName="$2"
 
 sshKeyFile="$1"
 hostName="$2"
 
+# check that key file specified
+if [ -z "$sshKeyFile" ] ; then
+    failure "Must specify ssh key file to import, or specify '-' for stdin."
+fi
+
 # use the default hostname if not specified
 if [ -z "$hostName" ] ; then
     hostName=$(hostname -f) || failure "Could not determine hostname."
 # use the default hostname if not specified
 if [ -z "$hostName" ] ; then
     hostName=$(hostname -f) || failure "Could not determine hostname."
@@ -45,9 +50,7 @@ mkdir -p "${GNUPGHOME_HOST}"
 chmod 700 "${GNUPGHOME_HOST}"
 
 # import ssh key to a private key
 chmod 700 "${GNUPGHOME_HOST}"
 
 # import ssh key to a private key
-if [ -z "$sshKeyFile" ] ; then
-    failure "Must specify ssh key file to import, or specify '-' for stdin."
-elif [ "$sshKeyFile" = '-' ] ; then
+if [ "$sshKeyFile" = '-' ] ; then
     log verbose "importing ssh key from stdin..."
     PEM2OPENPGP_USAGE_FLAGS=authenticate pem2openpgp "$userID" \
        | gpg_host --import
     log verbose "importing ssh key from stdin..."
     PEM2OPENPGP_USAGE_FLAGS=authenticate pem2openpgp "$userID" \
        | gpg_host --import
index 0b91531124d00e5caa4ac419615c7a132036d0a3..3d5097791196055e89ab8c85d69d068839ef7cbd 100755 (executable)
@@ -243,7 +243,7 @@ monkeysphere-authentication list-certifiers
 # generate an auth subkey for the test user that expires in 2 days
 echo "##################################################"
 echo "### generating key for testuser..."
 # generate an auth subkey for the test user that expires in 2 days
 echo "##################################################"
 echo "### generating key for testuser..."
-monkeysphere gen-subkey --expire 2
+monkeysphere gen-subkey
 
 # add server key to testuser keychain
 echo "##################################################"
 
 # add server key to testuser keychain
 echo "##################################################"