From 5bb8d410b08bf36d1ff3f36257ac364080d80aa9 Mon Sep 17 00:00:00 2001 From: Jameson Graef Rollins Date: Mon, 1 Sep 2008 23:07:30 -0700 Subject: Start modifications to output logging with LOG_LEVEL. --- src/common | 63 ++++++++++---------- src/monkeysphere | 12 ++-- src/monkeysphere-server | 21 +++---- src/monkeysphere-ssh-proxycommand | 21 ++++--- website/doc.mdwn | 122 +------------------------------------- 5 files changed, 66 insertions(+), 173 deletions(-) diff --git a/src/common b/src/common index d90730f..34d9b5a 100644 --- a/src/common +++ b/src/common @@ -28,11 +28,12 @@ failure() { # write output to stderr log() { - echo -n "ms: " >&2 - echo "$@" >&2 -} + local level -loge() { + level="$1" + shift + + echo -n "ms: " >&2 echo "$@" >&2 } @@ -368,13 +369,12 @@ gpg_fetch_userid() { userID="$1" - log -n " checking keyserver $KEYSERVER... " + log info " checking keyserver $KEYSERVER... " echo 1,2,3,4,5 | \ gpg --quiet --batch --with-colons \ --command-fd 0 --keyserver "$KEYSERVER" \ --search ="$userID" > /dev/null 2>&1 returnCode="$?" - loge "done." # if the user is the monkeysphere user, then update the # monkeysphere user's trustdb @@ -396,10 +396,13 @@ gpg_fetch_userid() { # (see /usr/share/doc/gnupg/DETAILS.gz) # output is one line for every found key, in the following format: # -# flag:fingerprint +# flag:sshKey # # "flag" is an acceptability flag, 0 = ok, 1 = bad -# "fingerprint" is the fingerprint of the key +# "sshKey" is the translated gpg key +# +# all log output must go to stderr, as stdout is used to pass the +# flag:sshKey to the calling function. # # expects global variable: "MODE" process_user_id() { @@ -438,7 +441,7 @@ process_user_id() { # if the gpg query return code is not 0, return 1 if [ "$?" -ne 0 ] ; then - log " no primary keys found." + log error " no primary keys found." return 1 fi @@ -455,21 +458,21 @@ process_user_id() { lastKeyOK= fingerprint= - log " primary key found: $keyid" + log error " primary key found: $keyid" # if overall key is not valid, skip if [ "$validity" != 'u' -a "$validity" != 'f' ] ; then - log " - unacceptable primary key validity ($validity)." + log error " - unacceptable primary key validity ($validity)." continue fi # if overall key is disabled, skip if check_capability "$usage" 'D' ; then - log " - key disabled." + log error " - key disabled." continue fi # if overall key capability is not ok, skip if ! check_capability "$usage" $requiredPubCapability ; then - log " - unacceptable primary key capability ($usage)." + log error " - unacceptable primary key capability ($usage)." continue fi @@ -483,7 +486,7 @@ process_user_id() { ;; 'uid') # user ids if [ "$lastKey" != pub ] ; then - log " - got a user ID after a sub key?! user IDs should only follow primary keys!" + log error " - got a user ID after a sub key?! user IDs should only follow primary keys!" continue fi # if an acceptable user ID was already found, skip @@ -504,16 +507,16 @@ process_user_id() { # output a line for the primary key # 0 = ok, 1 = bad if [ "$keyOK" -a "$uidOK" -a "$lastKeyOK" ] ; then - log " * acceptable primary key." + log error " * acceptable primary key." if [ -z "$sshKey" ] ; then - log " ! primary key could not be translated (not RSA or DSA?)." + log error " ! primary key could not be translated (not RSA or DSA?)." else echo "0:${sshKey}" fi else - log " - unacceptable primary key." + log error " - unacceptable primary key." if [ -z "$sshKey" ] ; then - log " ! primary key could not be translated (not RSA or DSA?)." + log error " ! primary key could not be translated (not RSA or DSA?)." else echo "1:${sshKey}" fi @@ -560,16 +563,16 @@ process_user_id() { # output a line for the sub key # 0 = ok, 1 = bad if [ "$keyOK" -a "$uidOK" -a "$lastKeyOK" ] ; then - log " * acceptable sub key." + log error " * acceptable sub key." if [ -z "$sshKey" ] ; then - log " ! sub key could not be translated (not RSA or DSA?)." + log error " ! sub key could not be translated (not RSA or DSA?)." else echo "0:${sshKey}" fi else - log " - unacceptable sub key." + log error " - unacceptable sub key." if [ -z "$sshKey" ] ; then - log " ! sub key could not be translated (not RSA or DSA?)." + log error " ! sub key could not be translated (not RSA or DSA?)." else echo "1:${sshKey}" fi @@ -595,7 +598,7 @@ process_host_known_hosts() { host="$1" userID="ssh://${host}" - log "processing: $host" + log info "processing: $host" nKeys=0 nKeysOK=0 @@ -696,7 +699,7 @@ update_known_hosts() { # note if the known_hosts file was updated if [ "$(file_hash "$KNOWN_HOSTS")" != "$fileCheck" ] ; then - log "known_hosts file updated." + log info "known_hosts file updated." fi # if an acceptable host was found, return 0 @@ -719,12 +722,12 @@ update_known_hosts() { process_known_hosts() { local hosts - log "processing known_hosts file..." + log info "processing known_hosts file..." hosts=$(meat "$KNOWN_HOSTS" | cut -d ' ' -f 1 | grep -v '^|.*$' | tr , ' ' | tr '\n' ' ') if [ -z "$hosts" ] ; then - log "no hosts to process." + log error "no hosts to process." return fi @@ -744,7 +747,7 @@ process_uid_authorized_keys() { userID="$1" - log "processing: $userID" + log info "processing: $userID" nKeys=0 nKeysOK=0 @@ -839,7 +842,7 @@ update_authorized_keys() { # note if the authorized_keys file was updated if [ "$(file_hash "$AUTHORIZED_KEYS")" != "$fileCheck" ] ; then - log "authorized_keys file updated." + log info "authorized_keys file updated." fi # if an acceptable id was found, return 0 @@ -866,10 +869,10 @@ process_authorized_user_ids() { authorizedUserIDs="$1" - log "processing authorized_user_ids file..." + log info "processing authorized_user_ids file..." if ! meat "$authorizedUserIDs" > /dev/null ; then - log "no user IDs to process." + log error "no user IDs to process." return fi diff --git a/src/monkeysphere b/src/monkeysphere index d585bfd..da72c9a 100755 --- a/src/monkeysphere +++ b/src/monkeysphere @@ -33,7 +33,7 @@ umask 077 ######################################################################## usage() { - cat <&2 usage: $PGRM [options] [args] MonkeySphere client tool. @@ -145,7 +145,7 @@ save EOF ) - log "generating subkey..." + log info "generating subkey..." fifoDir=$(mktemp -d) (umask 077 && mkfifo "$fifoDir/pass") echo "$editCommands" | gpg --passphrase-fd 3 3< "$fifoDir/pass" --expert --command-fd 0 --edit-key "$keyID" & @@ -154,7 +154,7 @@ EOF rm -rf "$fifoDir" wait - log "done." + log info "done." } function subkey_to_ssh_agent() { @@ -280,6 +280,7 @@ mkdir -p -m 0700 "$MONKEYSPHERE_HOME" # set empty config variables with ones from the environment, or from # config file, or with defaults +LOG_LEVEL=${MONKEYSPHERE_LOG_LEVEL:=${LOG_LEVEL:="INFO"}} GNUPGHOME=${MONKEYSPHERE_GNUPGHOME:=${GNUPGHOME:="${HOME}/.gnupg"}} KEYSERVER=${MONKEYSPHERE_KEYSERVER:="$KEYSERVER"} # if keyserver not specified in env or monkeysphere.conf, @@ -305,6 +306,7 @@ REQUIRED_USER_KEY_CAPABILITY=${MONKEYSPHERE_REQUIRED_USER_KEY_CAPABILITY:="a"} # permissions export GNUPGHOME mkdir -p -m 0700 "$GNUPGHOME" +export LOG_LEVEL # get subcommand COMMAND="$1" @@ -331,7 +333,7 @@ case $COMMAND in else # exit if the known_hosts file does not exist if [ ! -e "$KNOWN_HOSTS" ] ; then - log "known_hosts file '$KNOWN_HOSTS' does not exist." + log error "known_hosts file '$KNOWN_HOSTS' does not exist." exit fi @@ -355,7 +357,7 @@ case $COMMAND in # exit if the authorized_user_ids file is empty if [ ! -e "$AUTHORIZED_USER_IDS" ] ; then - log "authorized_user_ids file '$AUTHORIZED_USER_IDS' does not exist." + log error "authorized_user_ids file '$AUTHORIZED_USER_IDS' does not exist." exit fi diff --git a/src/monkeysphere-server b/src/monkeysphere-server index 4c8ecdc..0aa6dbc 100755 --- a/src/monkeysphere-server +++ b/src/monkeysphere-server @@ -33,7 +33,7 @@ RETURN=0 ######################################################################## usage() { - cat <&2 usage: $PGRM [options] [args] MonkeySphere server admin tool. @@ -156,7 +156,7 @@ update_users() { for uname in $unames ; do # check all specified users exist if ! getent passwd "$uname" >/dev/null ; then - log "----- unknown user '$uname' -----" + log info "----- unknown user '$uname' -----" continue fi @@ -172,17 +172,17 @@ update_users() { fi fi - log "----- user: $uname -----" + log info "----- user: $uname -----" # exit if the authorized_user_ids file is empty if ! check_key_file_permissions "$uname" "$AUTHORIZED_USER_IDS" ; then - log "Improper permissions on authorized_user_ids file path." + log error "Improper permissions on authorized_user_ids file path." continue fi # check permissions on the authorized_keys file path if ! check_key_file_permissions "$uname" "$RAW_AUTHORIZED_KEYS" ; then - log "Improper permissions on authorized_keys file path path." + log error "Improper permissions on authorized_keys file path path." continue fi @@ -226,9 +226,8 @@ update_users() { # add user-controlled authorized_keys file path if specified if [ "$rawAuthorizedKeys" != '-' -a -s "$rawAuthorizedKeys" ] ; then - log -n "adding raw authorized_keys file... " + log info "adding raw authorized_keys file... " cat "$rawAuthorizedKeys" >> "$AUTHORIZED_KEYS" - loge "done." fi # openssh appears to check the contents of the @@ -346,7 +345,7 @@ EOF EOF ) - log "generating server key..." + log info "generating server key..." echo "$keyParameters" | gpg_host --batch --gen-key # output the server fingerprint @@ -356,7 +355,7 @@ EOF fingerprint=$(fingerprint_server_key) # export host ownertrust to authentication keyring - log "setting ultimate owner trust for server key..." + log info "setting ultimate owner trust for server key..." echo "${fingerprint}:6:" | gpg_authentication "--import-ownertrust" # translate the private key to ssh format, and export to a file @@ -365,7 +364,7 @@ EOF (umask 077 && \ gpg_host --export-secret-key "$fingerprint" | \ openpgp2ssh "$fingerprint" > "${VARLIB}/ssh_host_rsa_key") - log "Private SSH host key output to file: ${VARLIB}/ssh_host_rsa_key" + log info "Private SSH host key output to file: ${VARLIB}/ssh_host_rsa_key" } # extend the lifetime of a host key: @@ -856,6 +855,7 @@ unset MONKEYSPHERE_USER # set empty config variable with ones from the environment, or with # defaults +LOG_LEVEL=${MONKEYSPHERE_LOG_LEVEL:=${LOG_LEVEL:="info"}} KEYSERVER=${MONKEYSPHERE_KEYSERVER:=${KEYSERVER:="subkeys.pgp.net"}} AUTHORIZED_USER_IDS=${MONKEYSPHERE_AUTHORIZED_USER_IDS:=${AUTHORIZED_USER_IDS:="%h/.config/monkeysphere/authorized_user_ids"}} RAW_AUTHORIZED_KEYS=${MONKEYSPHERE_RAW_AUTHORIZED_KEYS:=${RAW_AUTHORIZED_KEYS:="%h/.ssh/authorized_keys"}} @@ -871,6 +871,7 @@ GNUPGHOME_AUTHENTICATION=${MONKEYSPHERE_GNUPGHOME_AUTHENTICATION:="${VARLIB}/gnu export DATE export MODE export MONKEYSPHERE_USER +export LOG_LEVEL export KEYSERVER export CHECK_KEYSERVER export REQUIRED_USER_KEY_CAPABILITY diff --git a/src/monkeysphere-ssh-proxycommand b/src/monkeysphere-ssh-proxycommand index 780ff03..0e66e10 100755 --- a/src/monkeysphere-ssh-proxycommand +++ b/src/monkeysphere-ssh-proxycommand @@ -13,15 +13,22 @@ # established. Can be added to ~/.ssh/config as follows: # ProxyCommand monkeysphere-ssh-proxycommand %h %p +######################################################################## +SHARE=${MONKEYSPHERE_SHARE:-"/usr/share/monkeysphere"} +. "${SHARE}/common" || exit 1 + +######################################################################## + usage() { cat <&2 usage: ssh -o ProxyCommand="$(basename $0) %h %p" ... EOF } -log() { - echo "$@" >&2 -} +######################################################################## + +# export the monkeysphere log level +export MONKEYSPHERE_LOG_LEVEL if [ "$1" = '--no-connect' ] ; then NO_CONNECT='true' @@ -34,9 +41,9 @@ PORT="$2" MS_HOME=${MS_HOME:-"${HOME}/.config/monkeysphere"} if [ -z "$HOST" ] ; then - log "host must be specified." + echo "Host not specified." >&2 usage - exit 1 + exit 255 fi if [ -z "$PORT" ] ; then PORT=22 @@ -88,7 +95,7 @@ if [ -z "$NO_CONNECT" ] ; then elif (which socat 2>/dev/null >/dev/null); then exec socat STDIO "TCP:$HOST:$PORT" else - log "Neither netcat nor socat found -- could not complete monkeysphere-ssh-proxycommand connection to $HOST:$PORT" - exit 1 + echo "Neither netcat nor socat found -- could not complete monkeysphere-ssh-proxycommand connection to $HOST:$PORT" >&2 + exit 255 fi fi diff --git a/website/doc.mdwn b/website/doc.mdwn index 6a978ce..0b65aed 100644 --- a/website/doc.mdwn +++ b/website/doc.mdwn @@ -20,124 +20,4 @@ Monkeysphere relies on: * [OpenPGP (RFC 4880)](http://tools.ietf.org/html/rfc4880) * [Secure Shell Authentication Protocol (RFC 4252)](http://tools.ietf.org/html/rfc4252) * [URI scheme for SSH, RFC draft](http://tools.ietf.org/wg/secsh/draft-ietf-secsh-scp-sftp-ssh-uri/) - -# Similar Projects # - -The monkeysphere isn't the only project intending to implement a PKI -for OpenSSH. We provide links to these other projects because they're -interesting, though we have concerns with their approaches. - -All of the other projects we've found so far require a patched version -of OpenSSH, which makes adoption more difficult. Most people don't -build their own software, and simply overlaying a patched binary is -associated with significant maintenance (and therefore security) -problems. - -While ultimately contributing a patch to -[OpenSSH](http://openssh.com/) (or any -[free](http://www.chiark.greenend.org.uk/~sgtatham/putty/) -[SSH](http://www.lysator.liu.se/~nisse/lsh/) -[implementation](http://matt.ucc.asn.au/dropbear/dropbear.html)) is -not a bad thing, we hope to be able to better establish the use of a -PKI without resorting to source modification. - -### openssh-gpg ### - -[openssh-gpg](http://www.red-bean.com/~nemo/openssh-gpg/) is a patch -against OpenSSH to support OpenPGP certificates. According to its -documentation, it is intended to support [`pgp-sign-rsa` and -`pgp-sign-dss` public key algorithms for hosts, as specified by the -IETF](http://tools.ietf.org/html/rfc4253#section-6.6). - -Some concerns with `openssh-gpg`: - - * This patch is old; it doesn't appear to have been maintained beyond - OpenSSH 3.6p1. As of this writing, OpenSSH 5.1p1 is current. - - * It only provides infrastructure in one direction: the user - authenticating the host by name. There doesn't seem to be a - mechanism for dealing with identifying users by name, or allowing - users to globally revoke or update keys. - - * The choice of User ID (`anything goes here (and here!) - `) for host keys overlaps with the current use - of the User ID space. While it's unlikely that someone actually - uses this e-mail address in the web of trust, it would be a nasty - collision, as the holder of that key could impersonate the server - in question. The monkeysphere uses [User IDs of the form - `ssh://foo.example.net`](http://tools.ietf.org/wg/secsh/draft-ietf-secsh-scp-sftp-ssh-uri/) - to avoid collisions with existing use. - - * It's not clear that `openssh-gpg` acknowledges or respects the - [usage flags](http://tools.ietf.org/html/rfc4880#section-5.2.3.21) - on the host keys. This means that it could accept a "sign-only" - key as suitable for authenticating a host, despite the - clearly-marked intentions of the key-holder. - -### Perspectives OpenSSH client ### - -[The Perspectives project](http://www.cs.cmu.edu/~perspectives/) at -CMU has released an [openssh client that uses network -notaries](http://www.cs.cmu.edu/~perspectives/openssh.html) to bolster -your confidence in newly-seen keys. This offers a defense against a -narrow MITM attack (e.g. by someone who controls your local gateway) -by simply verifying that other machines from around the network see -the same keys for the remote host that you're seeing. - -This tactic is quite useful, but doesn't take the system as far as it -could go, and doesn't tie into any existing web of trust. - -Some concerns with the Perspectives OpenSSH client: - - * This client won't help if you are connecting to machines behind - firewalls, on NAT'ed LANs, with source IP filtering, or otherwise - in a restricted network state. - - * There is still a question of why you should trust these particular - notaries during your verification. Who are the notaries? How - could they be compromised? - - * It only provides infrastructure in one direction: the user - authenticating the host by name. There is no mechanism for dealing - with identifying users by name, or allowing users to globally - revoke or change keys. - - * It doesn't provide any mechanism for key rotation or revocation: - Perspectives won't help you if you need to re-key your machine. - -### OpenSSH with X.509v3 certificates ### - -Roumen Petrov [maintains a patch to OpenSSH that works with the X.509 -PKI model](http://www.roumenpetrov.info/openssh/). This is the -certificate hierarchy commonly used by TLS (and SSL). - -Some concerns about OpenSSH with X.509v3: - - * the X.509 certificate specification itself [encourages corporate - consolidation and centralized global "trust" because of its - single-issuer architectural - limitation](http://lair.fifthhorseman.net/~dkg/tls-centralization/). - This results in an expensive and cumbersome system for smaller - players, and it also doesn't correspond to the true distributed - nature of human-to-human trust. Furthermore, centralized global - "trusted authorities" create a tempting target for attack, and a - single-point-of-failure if an attack is successful. - - Depending on how you declare your trust relationships, OpenPGP is - capable of providing the same hierarchical structure as X.509, but - it is not limited to such a structure. The OpenPGP Web of Trust - model is more flexible and more adaptable to represent real-world - trust than X.509's rigid hierarchy. - - * X.509 certificates can identify hosts by name, but not by - individual service. This means that a compromised web or e-mail - server with access to the X.509 key for that service could re-use - its certificate as an SSH server, and it would be able to - masquerade successfully. - - The monkeysphere uses [User IDs of the form - `ssh://foo.example.net`](http://tools.ietf.org/wg/secsh/draft-ietf-secsh-scp-sftp-ssh-uri/), - so they are not by-default shared across services on the same host - (you can still share a key across services on the same host if you - like, but the service User IDs can be certified independently of - one another). + * [Other similar projects](/others) -- cgit v1.2.3