From 001803289d137b61b84778a518744be47bf3e70b Mon Sep 17 00:00:00 2001 From: Andrew Cady Date: Sat, 9 Oct 2021 05:16:40 -0400 Subject: rename executable to cryptonomic-vpn --- connect-vpn.sh | 375 -------------------------------------------------------- cryptonomic-vpn | 375 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 375 insertions(+), 375 deletions(-) delete mode 100755 connect-vpn.sh create mode 100755 cryptonomic-vpn diff --git a/connect-vpn.sh b/connect-vpn.sh deleted file mode 100755 index 5e95558..0000000 --- a/connect-vpn.sh +++ /dev/null @@ -1,375 +0,0 @@ -#!/bin/bash -set -e -[ "$UID" = 0 ] || exec sudo -- "$0" "$@" - -help() -{ - prefixU="Usage: $0 " - prefix0=" $0 " - prefix1=${prefix0//?/ } - cat < - -$prefix0 --remote-ip \\ -$prefix1 --remote-name - - -Usage: - -$prefix0 --remote-ip \\ -$prefix1 --remote-name \\ -$prefix1 [--remote-key-type rsa] \\ -$prefix1 [--local-key ] - - -Options: - - --remote-name - - Specify the name that we give to the remote side. - - Remote name is mandatory, except that if a single non-option argument is - given, then it is treated as if it were the argument to --remote-name. - - --remote-ip - - The IP specifies an IP to connect to. - - The name specifies a name we give to the remote side. - - If not specified, the hostname specified with the --remote-name option - will be resolved to obtain the IP. - - --remote-key-type - - The remote key will be fetched via the SSH protocol on port 22 on the - remote IP. This option specifies which server key type to request from - the server. - - If specified, it must be 'rsa'. - - --local-key - - This specifies the location of the private key file. - - The filename is considered relative to /etc/ssh if it has no slashes. - - The default is 'ssh_host_rsa_key'. - - The key must be an RSA key. - -EOF -} - - -# Default command line argument values. -NO_ACT=y -REMOTE_KEY_TYPE=rsa -LOCAL_KEY=ssh_host_rsa_key - -# Hard-coded private key source and destinations. -LOCAL_KEY_DEST_BASENAME=ssh_host_rsa_key -LOCAL_PRIVATE_KEY_DEST=/etc/swanctl/private/$LOCAL_KEY_DEST_BASENAME -LOCAL_PUBLIC_KEY_DEST=/etc/swanctl/pubkey/$LOCAL_KEY_DEST_BASENAME.pub - -die() { printf 'Error: %s\n' "$*" >&2; exit 1; } -warn() { printf 'Warning: %s\n' "$*" >&2; } - -parse_options() -{ - OPTS=$(getopt \ - --options 'hynf' \ - --longoptions 'help,yes-act,no-act,remote-ip:,remote-name:,remote-key-type:,local-key:' \ - -n connect-vpn \ - -- "$@") - eval set -- "$OPTS" - unset OPTS - - while true - do - case "$1" in - -h | --help ) help; exit;; - -y | --yes-act ) NO_ACT=;; - -n | --no-act ) NO_ACT=y;; - --remote-ip ) shift; REMOTE_IP=$1;; - --remote-name ) shift; REMOTE_NAME=$1;; - --remote-key-type ) shift; REMOTE_KEY_TYPE=$1;; - --local-key ) shift; LOCAL_KEY=$1;; - -- ) shift; break;; - esac - shift - done - - case "$# $1" in - 1\ *.*.*.cryptonomic.net) CRYPTONOMIC_DOMAIN=$1; shift ;; - 1\ *) REMOTE_NAME=$1; shift ;; - esac - - if [ "$CRYPTONOMIC_DOMAIN" ] - then - REMOTE_NAME=${CRYPTONOMIC_DOMAIN%%.*} - [ "$REMOTE_IP" ] || REMOTE_IP=$(resolve_domain_name "$REMOTE_NAME") - - elif [ $# != 0 ] - then - help - exit 1 - fi - - # The validation functions modify the values to normalize them. - validate_remote_ip || die 'invalid remote ip' - validate_remote_name || die "invalid remote name '$REMOTE_NAME'" - validate_remote_key_type || die 'invalid remote key type' - validate_local_key || die 'invalid local key' -} - -resolve_domain_name() -{ - normalize_address "$@" -} - -normalize_address() -{ - local IP - [ "$1" ] || return - IP=$(getent ahosts "$1") - IP=${IP%% *} - [ "$IP" ] || return - echo "$IP" -} - -validate_remote_ip() -{ - REMOTE_IP=$(normalize_address "${REMOTE_IP:-$REMOTE_NAME}") -} - -validate_remote_name() -{ - domain_name_regexp='^[[:alpha:]][-.[:alnum:]]*[[:alnum:]]*$' - [[ $REMOTE_NAME =~ $domain_name_regexp ]] -} - -validate_remote_key_type() -{ - [ "$REMOTE_KEY_TYPE" = rsa ] -} - -validate_local_key() -{ - # TODO: check that it is RSA - case "$LOCAL_KEY" in - */*) ;; - *) LOCAL_KEY=/etc/ssh/$LOCAL_KEY ;; - esac - [ -f "$LOCAL_KEY" -a -r "$LOCAL_KEY" ] || die "local key ($LOCAL_KEY)" -} - -main() -{ - parse_options "$@" - if [ "$NO_ACT" ] - then - exec 2>&1 - keycopy - test_new_config - else - die unimplemented - fi - exit -} - -match_and_drop_first_word() -{ - expect=$1 - while read word rest - do - if [ "$word" = "$expect" ] - then - printf '%s\n' "$rest" - return - fi - done - false -} - -keyscan() -{ - if [ -e keyscan.cache ] - then - cat keyscan.cache - else - semi_quietly ssh-keyscan -t "${REMOTE_KEY_TYPE}" "$1" - fi -} - -write_successfully() -{ - local f=$(mktemp) || return - local out="$1" - [ "$2" = -- ] || return - shift 2 - if "$@" > "$f" - then - if [ "$NO_ACT" ] - then - ( - exec >&2 - echo "Write $out:" - case "$(file --mime-encoding "$f")" in - *': binary') xxd "$f" ;; - *) cat "$f" ;; - esac | sed 's/^/ /' - echo - ) - rm -f "$f" - else - mv "$f" "$out" - fi - else - rm -f "$f" - return 1 - fi -} - -semi_quietly() -{ - local t=$(mktemp) - if "$@" 2>"$t" - then - rm -f "$t" - else - cat "$t" >&2 - fi -} - -openssl() -{ - semi_quietly command openssl "$@" -} - -write_public_key() -{ - openssl rsa -in "$1" -outform DER -} -write_private_key() -{ - openssl rsa -in "$1" -outform DER -pubout -} - -write_remote_key() -{ - case "$REMOTE_KEY_TYPE" in - rsa) ssh-keygen -e -f "$1" -m PEM | openssl rsa -RSAPublicKey_in -outform DER ;; - *) echo "Unsupported key type." >&2; exit 1 ;; - esac -} - -keycopy() -{ - private_key_tmp=$(mktemp) || return - cp "$LOCAL_KEY" "$private_key_tmp" - ssh-keygen -N '' -p -m PEM -f "$private_key_tmp" >/dev/null 2>&1 - trap 'rm -f "$private_key_tmp"' EXIT - - write_successfully "$LOCAL_PRIVATE_KEY_DEST" -- write_private_key "$private_key_tmp" - write_successfully "$LOCAL_PUBLIC_KEY_DEST" -- write_public_key "$private_key_tmp" - - trap - EXIT - rm -f "$private_key_tmp" - - trap 'rm -f "$t"' EXIT - t=$(mktemp) - keyscan "$REMOTE_IP" | match_and_drop_first_word "$REMOTE_IP" > "$t" - write_successfully /etc/swanctl/pubkey/"$REMOTE_NAME".pub -- write_remote_key "$t" - trap - EXIT - rm -f "$t" -} - -nocomments() -{ - sed 's/#.*//; /^ *$/d' -} - -config() -{ - local conn="$1" remote_addrs="$2" local_key="$3" - local public_key_file="$4" private_key_file="$5" - local remote_ts=0::0/0 vips=:: - id=$(key_to_suffix "$local_key") || return - sed -e 's/^ //' < + +$prefix0 --remote-ip \\ +$prefix1 --remote-name + + +Usage: + +$prefix0 --remote-ip \\ +$prefix1 --remote-name \\ +$prefix1 [--remote-key-type rsa] \\ +$prefix1 [--local-key ] + + +Options: + + --remote-name + + Specify the name that we give to the remote side. + + Remote name is mandatory, except that if a single non-option argument is + given, then it is treated as if it were the argument to --remote-name. + + --remote-ip + + The IP specifies an IP to connect to. + + The name specifies a name we give to the remote side. + + If not specified, the hostname specified with the --remote-name option + will be resolved to obtain the IP. + + --remote-key-type + + The remote key will be fetched via the SSH protocol on port 22 on the + remote IP. This option specifies which server key type to request from + the server. + + If specified, it must be 'rsa'. + + --local-key + + This specifies the location of the private key file. + + The filename is considered relative to /etc/ssh if it has no slashes. + + The default is 'ssh_host_rsa_key'. + + The key must be an RSA key. + +EOF +} + + +# Default command line argument values. +NO_ACT=y +REMOTE_KEY_TYPE=rsa +LOCAL_KEY=ssh_host_rsa_key + +# Hard-coded private key source and destinations. +LOCAL_KEY_DEST_BASENAME=ssh_host_rsa_key +LOCAL_PRIVATE_KEY_DEST=/etc/swanctl/private/$LOCAL_KEY_DEST_BASENAME +LOCAL_PUBLIC_KEY_DEST=/etc/swanctl/pubkey/$LOCAL_KEY_DEST_BASENAME.pub + +die() { printf 'Error: %s\n' "$*" >&2; exit 1; } +warn() { printf 'Warning: %s\n' "$*" >&2; } + +parse_options() +{ + OPTS=$(getopt \ + --options 'hynf' \ + --longoptions 'help,yes-act,no-act,remote-ip:,remote-name:,remote-key-type:,local-key:' \ + -n connect-vpn \ + -- "$@") + eval set -- "$OPTS" + unset OPTS + + while true + do + case "$1" in + -h | --help ) help; exit;; + -y | --yes-act ) NO_ACT=;; + -n | --no-act ) NO_ACT=y;; + --remote-ip ) shift; REMOTE_IP=$1;; + --remote-name ) shift; REMOTE_NAME=$1;; + --remote-key-type ) shift; REMOTE_KEY_TYPE=$1;; + --local-key ) shift; LOCAL_KEY=$1;; + -- ) shift; break;; + esac + shift + done + + case "$# $1" in + 1\ *.*.*.cryptonomic.net) CRYPTONOMIC_DOMAIN=$1; shift ;; + 1\ *) REMOTE_NAME=$1; shift ;; + esac + + if [ "$CRYPTONOMIC_DOMAIN" ] + then + REMOTE_NAME=${CRYPTONOMIC_DOMAIN%%.*} + [ "$REMOTE_IP" ] || REMOTE_IP=$(resolve_domain_name "$REMOTE_NAME") + + elif [ $# != 0 ] + then + help + exit 1 + fi + + # The validation functions modify the values to normalize them. + validate_remote_ip || die 'invalid remote ip' + validate_remote_name || die "invalid remote name '$REMOTE_NAME'" + validate_remote_key_type || die 'invalid remote key type' + validate_local_key || die 'invalid local key' +} + +resolve_domain_name() +{ + normalize_address "$@" +} + +normalize_address() +{ + local IP + [ "$1" ] || return + IP=$(getent ahosts "$1") + IP=${IP%% *} + [ "$IP" ] || return + echo "$IP" +} + +validate_remote_ip() +{ + REMOTE_IP=$(normalize_address "${REMOTE_IP:-$REMOTE_NAME}") +} + +validate_remote_name() +{ + domain_name_regexp='^[[:alpha:]][-.[:alnum:]]*[[:alnum:]]*$' + [[ $REMOTE_NAME =~ $domain_name_regexp ]] +} + +validate_remote_key_type() +{ + [ "$REMOTE_KEY_TYPE" = rsa ] +} + +validate_local_key() +{ + # TODO: check that it is RSA + case "$LOCAL_KEY" in + */*) ;; + *) LOCAL_KEY=/etc/ssh/$LOCAL_KEY ;; + esac + [ -f "$LOCAL_KEY" -a -r "$LOCAL_KEY" ] || die "local key ($LOCAL_KEY)" +} + +main() +{ + parse_options "$@" + if [ "$NO_ACT" ] + then + exec 2>&1 + keycopy + test_new_config + else + die unimplemented + fi + exit +} + +match_and_drop_first_word() +{ + expect=$1 + while read word rest + do + if [ "$word" = "$expect" ] + then + printf '%s\n' "$rest" + return + fi + done + false +} + +keyscan() +{ + if [ -e keyscan.cache ] + then + cat keyscan.cache + else + semi_quietly ssh-keyscan -t "${REMOTE_KEY_TYPE}" "$1" + fi +} + +write_successfully() +{ + local f=$(mktemp) || return + local out="$1" + [ "$2" = -- ] || return + shift 2 + if "$@" > "$f" + then + if [ "$NO_ACT" ] + then + ( + exec >&2 + echo "Write $out:" + case "$(file --mime-encoding "$f")" in + *': binary') xxd "$f" ;; + *) cat "$f" ;; + esac | sed 's/^/ /' + echo + ) + rm -f "$f" + else + mv "$f" "$out" + fi + else + rm -f "$f" + return 1 + fi +} + +semi_quietly() +{ + local t=$(mktemp) + if "$@" 2>"$t" + then + rm -f "$t" + else + cat "$t" >&2 + fi +} + +openssl() +{ + semi_quietly command openssl "$@" +} + +write_public_key() +{ + openssl rsa -in "$1" -outform DER +} +write_private_key() +{ + openssl rsa -in "$1" -outform DER -pubout +} + +write_remote_key() +{ + case "$REMOTE_KEY_TYPE" in + rsa) ssh-keygen -e -f "$1" -m PEM | openssl rsa -RSAPublicKey_in -outform DER ;; + *) echo "Unsupported key type." >&2; exit 1 ;; + esac +} + +keycopy() +{ + private_key_tmp=$(mktemp) || return + cp "$LOCAL_KEY" "$private_key_tmp" + ssh-keygen -N '' -p -m PEM -f "$private_key_tmp" >/dev/null 2>&1 + trap 'rm -f "$private_key_tmp"' EXIT + + write_successfully "$LOCAL_PRIVATE_KEY_DEST" -- write_private_key "$private_key_tmp" + write_successfully "$LOCAL_PUBLIC_KEY_DEST" -- write_public_key "$private_key_tmp" + + trap - EXIT + rm -f "$private_key_tmp" + + trap 'rm -f "$t"' EXIT + t=$(mktemp) + keyscan "$REMOTE_IP" | match_and_drop_first_word "$REMOTE_IP" > "$t" + write_successfully /etc/swanctl/pubkey/"$REMOTE_NAME".pub -- write_remote_key "$t" + trap - EXIT + rm -f "$t" +} + +nocomments() +{ + sed 's/#.*//; /^ *$/d' +} + +config() +{ + local conn="$1" remote_addrs="$2" local_key="$3" + local public_key_file="$4" private_key_file="$5" + local remote_ts=0::0/0 vips=:: + id=$(key_to_suffix "$local_key") || return + sed -e 's/^ //' <