diff options
Diffstat (limited to 'usr/bin/setupslavecard.sh')
-rwxr-xr-x | usr/bin/setupslavecard.sh | 502 |
1 files changed, 502 insertions, 0 deletions
diff --git a/usr/bin/setupslavecard.sh b/usr/bin/setupslavecard.sh new file mode 100755 index 0000000..cdf3adf --- /dev/null +++ b/usr/bin/setupslavecard.sh @@ -0,0 +1,502 @@ +#!/bin/bash + +# Smart Card Management Tool (c) 2009 Timothy Pearson +# +# 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 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +# The [secure] temporary directory for authentication +SECURE_DIRECTORY=/tmp/smartauth + +# Create the secure directory and lock it down +mkdir -p $SECURE_DIRECTORY +chown root $SECURE_DIRECTORY +chgrp root $SECURE_DIRECTORY +chmod 600 $SECURE_DIRECTORY +SECURE_DIRECTORY=$(mktemp /tmp/smartauth/setupcard.XXXXXXXXXX) +rm -rf $SECURE_DIRECTORY +mkdir -p $SECURE_DIRECTORY +chown root $SECURE_DIRECTORY +chgrp root $SECURE_DIRECTORY +chmod 600 $SECURE_DIRECTORY + +# See if required programs are installed +scriptor=$(whereis scriptor) +if [[ $scriptor == "scriptor:" ]]; then + echo "ERROR: scriptor is not installed! This program cannot continue!" + zenity --error --text "ERROR: scriptor is not installed!\nThis program cannot continue!\n\nUsually, scriptor is part of the pcsc-tools package." + exit +fi +opensc=$(whereis opensc-explorer) +if [[ $opensc == "opensc-explorer:" ]]; then + echo "ERROR: opensc-explorer is not installed! This program cannot continue!" + zenity --error --text "ERROR: opensc-explorer is not installed!\nThis program cannot continue!\n\nUsually, opensc-explorer is part of the opensc package." + exit +fi + +# Get card ATR +FOUND_SUPPORTED_CARD=0 +echo "RESET" > $SECURE_DIRECTORY/query +scriptor $SECURE_DIRECTORY/query 1> $SECURE_DIRECTORY/response2 +authokresponse="OK: " +response1=$(cat $SECURE_DIRECTORY/response2 | grep "$authokresponse") +if [[ $response1 != "" ]]; then + cat $SECURE_DIRECTORY/response2 | tr -d '\n' > $SECURE_DIRECTORY/response4 + stringtoreplace="Using T=0 protocolRESET> RESET< OK: " + newstring="" + sed -i "s#${stringtoreplace}#${newstring}#g" $SECURE_DIRECTORY/response4 + smartatr=$(cat $SECURE_DIRECTORY/response4) + echo "Got ATR: $smartatr" + if [[ $smartatr == "3B BE 18 00 00 41 05 10 00 00 00 00 00 00 00 00 00 90 00 " ]]; then + echo "Detected ACOS5 card" + COMMAND_MODE="acos" + CARD_NICE_NAME="ACOS5" + FOUND_SUPPORTED_CARD=1 + fi + if [[ $smartatr == "3B 02 14 50 " ]]; then + echo "Detected Schlumberger CryptoFlex card" + COMMAND_MODE="cryptoflex" + CARD_NICE_NAME="Schlumberger CryptoFlex" + FOUND_SUPPORTED_CARD=1 + fi +else + echo "No card detected!" + zenity --error --text "ERROR: No SmartCard detected!" + exit 1 +fi + +if [[ $FOUND_SUPPORTED_CARD -eq 0 ]]; then + echo "Unsupported SmartCard detected! ATR: $smartatr" + zenity --error --text "ERROR: Unsupported SmartCard detected!\n\nATR: $smartatr" + exit 1 +fi + + +if [[ $COMMAND_MODE == "cryptoflex" ]]; then + GET_CHALLENGE="C0 84 00 00 08" + EXTERNAL_AUTH="C0 82 00 00 07 01" + SELECT_FILE="C0 A4 00 00 02" + DELETE_FILE="F0 E4 00 00 02" +fi + +if [[ $COMMAND_MODE == "acos" ]]; then + GET_CHALLENGE="00 84 00 00 08" + EXTERNAL_AUTH="00 82 00 81 08" + SELECT_FILE="00 A4 00 00 02" + DELETE_FILE="00 E4 00 00 00" + READ_BINARY="00 B0 00 00 FF" + UPDATE_BINARY="00 D6 00 00 FF" + ACTIVATE_FILE="00 44 00 00 02" +fi + +CREATE_LIFE_CYCLE="01" + +createfile () +{ + if [[ $COMMAND_MODE == "cryptoflex" ]]; then + # Create transparent file with permissions: + # delete, terminate, activate, deactivate, update, read for Key 1 and Key 2 only + echo "F0 E0 00 FF 10 FF FF 00 $1 $2 01 3F 44 FF 44 01 03 11 FF 11" > $SECURE_DIRECTORY/query + scriptor $SECURE_DIRECTORY/query 1> $SECURE_DIRECTORY/response2 2>/dev/null + fi + + if [[ $COMMAND_MODE == "acos" ]]; then + # Select MF + echo "00 A4 00 00 00" > $SECURE_DIRECTORY/query + scriptor $SECURE_DIRECTORY/query 1> $SECURE_DIRECTORY/response2 + echo $(cat $SECURE_DIRECTORY/response2) + + # Select DF 1000 under MF + echo "$SELECT_FILE 10 00" > $SECURE_DIRECTORY/query + scriptor $SECURE_DIRECTORY/query 1> $SECURE_DIRECTORY/response2 + echo $(cat $SECURE_DIRECTORY/response2) + # Create transparent file with permissions: + # delete, terminate, activate, deactivate, update, read for Key 1, Key 2, and Key 3 only (SE 04) + # created in DF 1000 under MF, SE file is 10FE + # SIZE TRANSPARENT + + echo "00 E0 00 00 1A 62 18 80 02 00 $1 82 01 01 83 02 $2 8A 01 $CREATE_LIFE_CYCLE 8C 08 7F 04 04 04 04 04 04 04" > $SECURE_DIRECTORY/query + scriptor $SECURE_DIRECTORY/query 1> $SECURE_DIRECTORY/response2 2>/dev/null + echo $(cat $SECURE_DIRECTORY/response2) + fi +} + +updatekey () +{ + if [[ $COMMAND_MODE == "cryptoflex" ]]; then + echo "$SELECT_FILE 00 11" > $SECURE_DIRECTORY/query + scriptor $SECURE_DIRECTORY/query 1> $SECURE_DIRECTORY/response2 2>/dev/null + echo "C0 D6 00 0D 0C 08 00 $1 05 05" > $SECURE_DIRECTORY/query + scriptor $SECURE_DIRECTORY/query 1> $SECURE_DIRECTORY/response2 2>/dev/null + fi +} + +hexcvt () +{ + echo ""$1" "16" o p" | dc +} + +authenticatecard () { + if [[ $authenticated != "1" ]]; then + if [[ -e /etc/smartauth/slave.key ]]; then + autkey=$(cat /etc/smartauth/slave.key) + else + autkey=$(zenity --entry --hide-text --title="SmartCard Transport Key" --text="Please enter the 16-character Smart Card transport key [AUT1] in hexidecimal. Example: 0123456789abcdef") + fi + if [[ ${#autkey} -eq 16 ]]; then + if [[ $COMMAND_MODE == "acos" ]]; then + # Select MF + echo "00 A4 00 00 00" > $SECURE_DIRECTORY/query + scriptor $SECURE_DIRECTORY/query 1> $SECURE_DIRECTORY/response2 + echo $(cat $SECURE_DIRECTORY/response2) + # Make sure DF 1000 is selected + echo "$SELECT_FILE 10 00" > $SECURE_DIRECTORY/query + scriptor $SECURE_DIRECTORY/query 1> $SECURE_DIRECTORY/response2 + echo $(cat $SECURE_DIRECTORY/response2) + fi + + # Authenticate card + echo $GET_CHALLENGE > $SECURE_DIRECTORY/authscript + + scriptor $SECURE_DIRECTORY/authscript | grep 'Normal processing' > $SECURE_DIRECTORY/challenge + perl -pi -e 's/ //g' $SECURE_DIRECTORY/challenge + perl -pi -e 's/:Normalprocessing.//g' $SECURE_DIRECTORY/challenge + perl -pi -e 's/<//g' $SECURE_DIRECTORY/challenge + xxd -r -p $SECURE_DIRECTORY/challenge $SECURE_DIRECTORY/challenge + + # Now DES encrypt the challenge + # Later, change the initialization vector to random if possible + openssl des-ecb -in $SECURE_DIRECTORY/challenge -out $SECURE_DIRECTORY/response -K $autkey -iv 1 + + if [[ $COMMAND_MODE == "acos" ]]; then + # Truncate to 8 bytes + dd if=$SECURE_DIRECTORY/response of=$SECURE_DIRECTORY/response2 bs=1 count=8 + + # Expand to standard hex listing format + xxd -g 1 $SECURE_DIRECTORY/response2 $SECURE_DIRECTORY/response + dd if=$SECURE_DIRECTORY/response of=$SECURE_DIRECTORY/response2 bs=1 count=23 skip=9 + fi + + if [[ $COMMAND_MODE == "cryptoflex" ]]; then + # Truncate to 6 bytes + dd if=$SECURE_DIRECTORY/response of=$SECURE_DIRECTORY/response2 bs=1 count=6 + + # Expand to standard hex listing format + xxd -g 1 $SECURE_DIRECTORY/response2 $SECURE_DIRECTORY/response + dd if=$SECURE_DIRECTORY/response of=$SECURE_DIRECTORY/response2 bs=1 count=17 skip=9 + fi + + # Assemble the response file + response2=$(cat $SECURE_DIRECTORY/response2) + response1="$EXTERNAL_AUTH ${response2}" + echo $response1 > $SECURE_DIRECTORY/response + + # Send the response! + scriptor $SECURE_DIRECTORY/response > $SECURE_DIRECTORY/response2 + echo $(cat $SECURE_DIRECTORY/response2) + + # Get the result + authokresponse="< 90 00 : Normal processing" + response1=$(cat $SECURE_DIRECTORY/response2 | grep "$authokresponse") + echo $response1 + if [[ $response1 != "" ]]; then + echo "Smart card validation successfull!" + echo "Smart card login successfull!" + echo $autkey > /etc/smartauth/slave.key + authenticated="1" + else + echo "Login failed" + if [[ -e /etc/smartauth/slave.key ]]; then + rm -f /etc/smartauth/slave.key + authenticatecard + else + zenity --error --text "That transport key is incorrect!\n\nPlease remember that there are a limited number\nof failed login attempts for this key,\nafter which your SmartCard will become useless." + fi + fi + else + echo "AUT1 key not 16 characters!" + zenity --error --text "That transport key is invalid!" + fi + fi +} + +get_file () { + if [[ $COMMAND_MODE == "acos" ]]; then + # Select EF $1 under DF 1000 + echo "$SELECT_FILE $1" > $SECURE_DIRECTORY/query + scriptor $SECURE_DIRECTORY/query 1> $SECURE_DIRECTORY/response2 + echo $(cat $SECURE_DIRECTORY/response2) + + # Read binary + echo "$READ_BINARY" > $SECURE_DIRECTORY/query + scriptor $SECURE_DIRECTORY/query 1> $SECURE_DIRECTORY/response2 + authokresponse="90 00 : Normal processing" + response1=$(cat $SECURE_DIRECTORY/response2 | grep "$authokresponse") + if [[ $response1 != "" ]]; then + cat $SECURE_DIRECTORY/response2 | tr -d '\n' > $SECURE_DIRECTORY/response4 + stringtoreplace="Using T=0 protocol00 B0 00 00 FF> 00 B0 00 00 FF< " + newstring="" + sed -i "s#${stringtoreplace}#${newstring}#g" $SECURE_DIRECTORY/response4 + stringtoreplace=" 90 00 : Normal processing." + newstring="" + sed -i "s#${stringtoreplace}#${newstring}#g" $SECURE_DIRECTORY/response4 + if [[ $2 == "text" ]]; then + stringtoreplace=" 00" + newstring="" + sed -i "s#${stringtoreplace}#${newstring}#g" $SECURE_DIRECTORY/response4 + fi + echo $(cat $SECURE_DIRECTORY/response4) + rm -f $SECURE_DIRECTORY/lukskey + xxd -r -p $SECURE_DIRECTORY/response4 $SECURE_DIRECTORY/lukskey + RESPONSE=$SECURE_DIRECTORY/lukskey + fi + fi + + if [[ $COMMAND_MODE == "cryptoflex" ]]; then + FILE=${1/ /} + echo "get $FILE" | opensc-explorer + RESPONSE="3F00_$FILE" + fi +} + +update_file () { + if [[ $COMMAND_MODE == "acos" ]]; then + # Select EF $1 under DF 1000 + echo "$SELECT_FILE $1" > $SECURE_DIRECTORY/query + scriptor $SECURE_DIRECTORY/query 1> $SECURE_DIRECTORY/response2 + echo $(cat $SECURE_DIRECTORY/response2) + + # Update existing file + # Zero pad input file + dd if=/dev/zero of=$SECURE_DIRECTORY/response2 bs=1 count=255 + dd if=$2 of=$SECURE_DIRECTORY/response2 bs=1 count=255 conv=notrunc + + # Truncate to 255 bytes and expand to standard hex listing format + xxd -l 255 -ps -c 1 $SECURE_DIRECTORY/response2 > $SECURE_DIRECTORY/response + cat $SECURE_DIRECTORY/response | tr '\n' ' ' > $SECURE_DIRECTORY/hexready + echo "$UPDATE_BINARY $(cat $SECURE_DIRECTORY/hexready)" > $SECURE_DIRECTORY/query + scriptor $SECURE_DIRECTORY/query 1> $SECURE_DIRECTORY/response2 2>/dev/null + echo $(cat $SECURE_DIRECTORY/response2) + fi + + if [[ $COMMAND_MODE == "cryptoflex" ]]; then + # Delete old file + echo "$DELETE_FILE $1" > $SECURE_DIRECTORY/query + scriptor $SECURE_DIRECTORY/query 1> $SECURE_DIRECTORY/response2 2>/dev/null + echo $(cat $SECURE_DIRECTORY/response2) + + # Create new file + createfile "FF" $1 + FILE=${1/ /} + echo "put $FILE $2" | opensc-explorer + fi +} + +insertnewtext () { + FOUNDTEXT=$(cat $2 | grep $1) + echo $FOUNDTEXT; + if [[ $FOUNDTEXT != "" ]]; then + echo "$1 already exists in $2" + else + echo $1 >> $2 + fi +} + +getcolumn () { + perl -ne '@cols = split; print "$cols['$1']\n"' ; +} + +function loadusername { + echo "Loading username..." + authenticatecard + if [[ $authenticated = "1" ]]; then + zenity --entry --title="SmartCard Username" --text="Please enter the username of the account to be associated with this SmartCard" > $SECURE_DIRECTORY/username + update_file "10 02" "$SECURE_DIRECTORY/username" + rm -f $SECURE_DIRECTORY/username + fi +} + +function loadpassword { + echo "Loading password..." + authenticatecard + if [[ $authenticated = "1" ]]; then + zenity --entry --hide-text --title="SmartCard Password" --text="Please enter the password of the account that is associated with this SmartCard" > $SECURE_DIRECTORY/password + update_file "10 03" "$SECURE_DIRECTORY/password" + rm -f $SECURE_DIRECTORY/password + fi +} + +function loadminutes { + echo "Loading minutes..." + authenticatecard + if [[ $authenticated = "1" ]]; then + echo "$(zenity --entry --hide-text --title="SmartCard Computer Minutes" --text="Please enter the number of computer minutes for this SmartCard")" > $SECURE_DIRECTORY/password + update_file "10 05" "$SECURE_DIRECTORY/password" + rm -f $SECURE_DIRECTORY/password + fi +} + +function enablerestrictedmode { + echo "Enabling restricted mode..." + authenticatecard + if [[ $authenticated = "1" ]]; then + echo "SLAVE" > $SECURE_DIRECTORY/password + update_file "10 04" "$SECURE_DIRECTORY/password" + rm -f $SECURE_DIRECTORY/password + fi +} + +function disablerestrictedmode { + echo "Disabling restricted mode..." + authenticatecard + if [[ $authenticated = "1" ]]; then + echo "NORMAL" > $SECURE_DIRECTORY/password + update_file "10 04" "$SECURE_DIRECTORY/password" + rm -f $SECURE_DIRECTORY/password + fi +} + +GREETER="Welcome to the SmartCard slave authentication setup utility!\n\nCard ATR: $smartatr\nDetected: $CARD_NICE_NAME\n\nPlease select an action from the list below:" + +while [[ 1 -eq 1 ]]; do + if [[ $# -eq 0 ]]; then + selection=$(zenity --width=400 --height=400 --list --radiolist --title="SmartCard Authentication Setup" \ + --text="$GREETER" \ + --column="" --column="Action" \ + TRUE "Load Computer Minutes into Smart Card [File 1005]" \ + FALSE "Enable Restricted Mode [File 1004]" \ + FALSE "Disable Restricted Mode [File 1004]" \ + FALSE "Load username into Smart Card [File 1002]" \ + FALSE "Load password into Smart Card [File 1003]" \ + FALSE "Update Smart Card Transport Key [AUT1]"); + fi + + if [[ $selection = "Load username into Smart Card [File 1002]" ]]; then + loadusername + fi + + if [[ $selection = "Load password into Smart Card [File 1003]" ]]; then + loadpassword + fi + + if [[ $selection = "Load Computer Minutes into Smart Card [File 1005]" ]]; then + loadminutes + fi + + if [[ $selection = "Enable Restricted Mode [File 1004]" ]]; then + enablerestrictedmode + fi + + if [[ $selection = "Disable Restricted Mode [File 1004]" ]]; then + disablerestrictedmode + fi + + if [[ $selection = "Update Smart Card Transport Key [AUT1]" ]]; then + echo "Updating AUT1..." + authenticatecard + if [[ $authenticated = "1" ]]; then + if [[ $COMMAND_MODE == "acos" ]]; then + # Select MF + echo "00 A4 00 00 00" > $SECURE_DIRECTORY/query + scriptor $SECURE_DIRECTORY/query 1> $SECURE_DIRECTORY/response2 + echo $(cat $SECURE_DIRECTORY/response2) + + # Select DF 1000 under MF + echo "$SELECT_FILE 10 00" > $SECURE_DIRECTORY/query + scriptor $SECURE_DIRECTORY/query 1> $SECURE_DIRECTORY/response2 + echo $(cat $SECURE_DIRECTORY/response2) + + # Select EF 10FD under DF 1000 + echo "$SELECT_FILE 10 FD" > $SECURE_DIRECTORY/query + scriptor $SECURE_DIRECTORY/query 1> $SECURE_DIRECTORY/response2 + echo $(cat $SECURE_DIRECTORY/response2) + + # Initialize first key record in file 10FD + # Key 1, 8-byte 1DES authentication only + autkey="" + while [[ ${#autkey} != 16 ]]; do + autkey=$(zenity --entry --hide-text --title="SmartCard Transport Key" --text="Please enter the new 16-character Smart Card transport key [AUT1] in hexidecimal. Example: 0123456789abcdef") + done + autkey2=${autkey:0:2} + autkey2="${autkey2} ${autkey:2:2}" + autkey2="${autkey2} ${autkey:4:2}" + autkey2="${autkey2} ${autkey:6:2}" + autkey2="${autkey2} ${autkey:8:2}" + autkey2="${autkey2} ${autkey:10:2}" + autkey2="${autkey2} ${autkey:12:2}" + autkey2="${autkey2} ${autkey:14:2}" + echo "00 DC 00 00 0C 81 01 55 05 $autkey2" > $SECURE_DIRECTORY/query + scriptor $SECURE_DIRECTORY/query 1> $SECURE_DIRECTORY/response2 + echo $(cat $SECURE_DIRECTORY/response2) + fi + + if [[ $COMMAND_MODE == "cryptoflex" ]]; then + autkey4=$(zenity --entry --hide-text --title="SmartCard Transport Key" --text="Please enter the new 16-character Smart Card transport key [AUT1] in hexidecimal. Example: 0123456789abcdef") + if [[ ${#autkey4} -eq 16 ]]; then + autkey2=${autkey4:0:2} + autkey2="${autkey2} ${autkey4:2:2}" + autkey2="${autkey2} ${autkey4:4:2}" + autkey2="${autkey2} ${autkey4:6:2}" + autkey2="${autkey2} ${autkey4:8:2}" + autkey2="${autkey2} ${autkey4:10:2}" + autkey2="${autkey2} ${autkey4:12:2}" + autkey2="${autkey2} ${autkey4:14:2}" + echo "Attempting Smart Card key update..." + updatekey ${autkey2} + autkey=$autkey4 + if [[ $authenticated = "1" ]]; then + cp -Rp /etc/smartauth/smartauth.sh.in /usr/bin/smartauth.sh + OLDKEY="<your key in hexidecimal>" + authenticatecard + if [[ $authenticated = "1" ]]; then + NEWKEY=$autkey + echo $NEWKEY > /etc/smartauth/smartauth.key + sed -i "s#${OLDKEY}#${NEWKEY}#g" /usr/bin/smartauth.sh + chmod 600 /usr/bin/smartauth.sh + chmod a+x /usr/bin/smartauth.sh + echo "Updating initramfs" + update-initramfs -u all + echo "Securing directories..." + chmod 600 "/boot/initrd.img-$(uname -r)" + chmod -R 600 /etc/smartauth + if [ -e "/usr/bin/smartauthmon.sh" ]; then + selection="Enable automatic login for KDE3.5" + else + echo "KDE3.5 login disabled; not altering" + fi + else + zenity --error --text "A SmartCard authentication error has occurred." + fi + else + zenity --error --text "A SmartCard authentication error has occurred." + fi + else + echo "AUT1 key not 16 characters!" + zenity --error --text "The new transport key is invalid!" + fi + fi + fi + fi + + if [[ $selection = "" ]]; then + echo "Exiting!" + rm -rf $SECURE_DIRECTORY + chmod -R 600 /etc/smartauth + chown -R root /etc/smartauth + chmod a+x /usr/bin/smartauth.sh + chmod a+x /usr/bin/smartauthmon.sh + chmod 600 "/boot/initrd.img-$(uname -r)" + chown root "/boot/initrd.img-$(uname -r)" + exit + fi +done |