#!/bin/sh #---------------------------------------------------------------------------- # /var/install/bin/system-ssh-create-client-keys - create SSH client keys # # Creation: 2015-01-12 jed # Last Update: $Id$ # # Copyright (c) 2015-@@YEAR@@ the eisfair team, team(at)eisfair(dot)org # # Usage: system-ssh-create-client-keys [options] # # --batch - run script in batch mode" # --comment "my comment" - comment to add to new keys # --key ed25519|rsa|ecdsa|dsa - generate a 'specific' key # --pass "my passphrase" - set a passphrase for the key # --path "destination path for key files" - path to save the new key # --quiet - suppress screen output # --user "valid-username" - user name to create key for # --rsabits 2048|3072|4096|6142|8192 - bits to generate RSA key" # --help - show this help # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. #---------------------------------------------------------------------------- # include eislib . /var/install/include/eislib #exec 2>/tmp/system-create-client-keys-$$.log #set -x #---------------------------------------------------------------------------- # my own echo #---------------------------------------------------------------------------- myecho() { if [ "${quiet}" != '--quiet' ] then _me_exit=0 _me_switch='' _me_outstr='' while [ ${_me_exit} -eq 0 ] do case $1 in -n|*-std|*stdbr|*-info|*-warn|*-error|*-link|*-ok|*-fail|*-tty|*-html|*-file ) _me_switch="${_me_switch}$1 " shift ;; * ) _me_outstr="$*" _me_exit=1 ;; esac done # be verbose mecho ${_me_switch} "${_me_outstr}" fi } #---------------------------------------------------------------------------- # return absolute path to a file # # input : $1 - path of file # output: absolute path of file #---------------------------------------------------------------------------- abs_path() { _ap_path="`dirname "$1"`" _ap_file="`basename "$1"`" # check if ~/ has been used echo "${_ap_path}" | grep -q "^[[:space:]]*~/" if [ $? -eq 0 ] then # insert path to $HOME _ap_path=$(echo "${_ap_path}" | sed "s#^[[:space:]]*~/#${HOME}/#") fi cd ${_ap_path} if [ "${_ap_file}" = "." ] then # directory printf "$(pwd)\n" else # file printf "$(pwd)/$_ap_file\n" fi cd "${OLDPWD}" } #---------------------------------------------------------------------------- # show help #---------------------------------------------------------------------------- show_help() { myecho myecho "Usage: system-ssh-create-client-keys [options]" myecho myecho " --batch - run script in batch mode" myecho " --comment 'my comment' - comment to add to new keys" myecho " --key ed25519|rsa|ecdsa|dsa - generate a 'specific' key" myecho " --pass 'my passphrase' - set a passphrase for the key" myecho " --path 'destination path for key files' - path to save the new key" myecho " --quiet - suppress screen output" myecho " --rsabits 2048|3072|4096|6142|8192 - bits to generate RSA key" myecho " --user 'valid-username' - user name to create key for" myecho " --help - show this help" myecho } #============================================================================ # main #============================================================================ cmd_line="$*" # command line parameters echo "${cmd_line}" | grep -q -E "\-path " if [ $? -ne 0 ] then # set default destination directory dest_path="${HOME}/.ssh" fi batch='no' comment='-C ""' # '-C' - no comment key_list='ed25519 rsa' # list of keys to generate passphrase='-N ""' # '-N ""' - no passphrase, '' - ask for passphrase quiet='' # '--quiet' - do not print any message quiet_short='' rsabits='4096' # default RSA bits to generate keys user="`whoami`" # default user # read command line parameters while [ $# -ne 0 ] do case $1 in *-batch ) batch='yes' shift ;; *-comment ) comment="-C \"$2\"" shift; shift ;; *-key ) case "$2" in ed25519|rsa|ecdsa|dsa ) key_list="$2" ;; * ) myecho --warn "Invalid key type given, using default value!" ;; esac shift; shift ;; *-pass ) if [ "$2" = "" ] then passphrase='' else passphrase="-N \"$2\"" fi shift; shift ;; *-path ) dest_path="`abs_path "$2"`" shift; shift ;; *-quiet ) quiet='--quiet' quiet_short='-q' shift ;; *-rsabits ) case "$2" in 2048|3072|4096|6142|8192 ) rsabits="$2" ;; * ) myecho --warn "Invalid bits value given, using default value!" ;; esac shift; shift ;; *-user ) grep -q "^$2:" /etc/passwd if [ $? -eq 0 ] then # user exists user="$2" fi shift; shift ;; * ) show_help exit 1 ;; esac done if [ "${user}" != "`whoami`" ] then # run as a different user su - ${user} -s /bin/sh -c "`abs_path "$0"` ${cmd_line}" else _ask_tmpfile=$(/bin/mktemp -t ask-ssh.XXXXXXXXX) clrhome myecho -n --info "Generate private SSH2 keys for user '" myecho -n --warn "${user}" myecho --info "'" myecho # check if destination directory exists if [ ! -d "${dest_path}" ] then answer1='no' /var/install/bin/ask "Directory '${dest_path}' doesn't exist! Do you want to create it" 'n' > ${_ask_tmpfile} rc=${?} read answer1 < ${_ask_tmpfile} rm -f ${_ask_tmpfile} # if ask break, ask returned 255 if [ ${rc} = 255 ] then answer1='no' fi if [ "${answer1}" = 'yes' ] then mkdir -p "${dest_path}" fi fi if [ -d "${dest_path}" ] then # destination path is in users home directory echo "${dest_path}" | grep -q "${HOME}/\.ssh" if [ $? -eq 0 ] then # change access permissions chmod 0700 "${HOME}/.ssh" fi # 2015-01-08/JED - reworked based on information about SSH hardening on the following # website https://stribika.github.io/2015/01/04/secure-secure-shell.html for KEY in ${key_list} do key_create='no' key_file="${dest_path}/id_${KEY}" # -a number - number of KDF rounds for new key format or moduli primality tests # -b bits - number of bits in the key to create key_bits='' case ${KEY} in dsa ) # DSA keys must be exactly 1024 bits as specified by FIPS 186-2 run_option="${comment} ${passphrase} -a 100 -b 1024" key_bits='(1024 bits)' ;; rsa ) run_option="${comment} ${passphrase} -a 100 -b ${rsabits}" key_bits="(${rsabits} bits)" ;; * ) run_option="${comment} ${passphrase} -a 100" ;; esac myecho "Creating key '${key_file}' ${key_bits} ..." if [ -e ${key_file} -a "${batch}" = "no" ] then # key file exists! answer2='no' /var/install/bin/ask "File already exists, do you want to overwrite it" 'n' > ${_ask_tmpfile} rc=${?} read answer2 < ${_ask_tmpfile} rm -f ${_ask_tmpfile} # if ask break, ask returned 255 if [ ${rc} = 255 ] then answer2='no' fi if [ "${answer2}" = 'yes' ] then key_create='yes' rm -f ${key_file} fi else key_create='yes' if [ "${batch}" = "yes" ] then rm -f ${key_file} fi fi if [ "${key_create}" = "yes" ] then # create new key eval /usr/bin/ssh-keygen ${quiet_short} -t ${KEY} ${run_option} -f ${key_file} # check if key has been added to the ssh config file ssh_file="${HOME}/.ssh/config" key_path="`dirname "${key_file}"`" key_name="`basename "${key_file}"`" if [ "${key_path}" != "${HOME}/.ssh" -o "${key_name}" != "id_${KEY}" ] then if [ -f "${ssh_file}" ] then # key has not been stored in the $HOME/.ssh directory or # the standard key name 'id_' has not been used # In this case an 'IdentityFile' entry is necessary to use # this key found=0 # file ~/.ssh/config exists, check if an key entry already exists tmp_file=$(grep -E -i "^identityfile .*" "${ssh_file}" | sed -e 's/^[Ii][Dd][Ee][Nn][Tt][Ii][Tt][Yy][Ff][Ii][Ll][Ee] *//' -e 's/ *$//') if [ $? -eq 0 ] then # key entry found, check if the path has correctly been set for TFILE in ${tmp_file} do # check if key entry exists tmp_name="`basename "${TFILE}"`" if [ "${tmp_name}" = "${key_name}" ] then # key name exists, check key file path tmp_path="`dirname "${TFILE}"`" tmp_path="`abs_path "${tmp_path}"`" if [ "${tmp_path}" = "${key_path}" ] then # key path matches! found=1 break fi fi done fi if [ ${found} -eq 0 ] then # path differs myecho myecho --warn "To make use of the new key, add the following line to the file" myecho --warn "${HOME}/.ssh/config: 'IdentityFile ${key_file}'" fi else myecho myecho --warn "To make use of the new key, create a file ${HOME}/.ssh/config and add" myecho --warn "at least the following line: 'IdentityFile ${key_file}'" myecho --warn "The file /etc/ssh/ssh_config can be used as a template." fi # if [ -f "${ssh_file}" ] fi # if [ "${key_path}" != "${HOME}/.ssh" -o "${key_name}" != "id_${KEY}" ] fi # if [ "${key_create}" = "yes" ] myecho done fi rm -f ${_ask_tmpfile} fi #============================================================================ # End #============================================================================ exit 0