Merge commit 'dkg/master'
[monkeysphere.git] / src / share / m / gen_subkey
1 # -*-shell-script-*-
2 # This should be sourced by bash (though we welcome changes to make it POSIX sh compliant)
3
4 # Monkeysphere gen-subkey subcommand
5 #
6 # The monkeysphere scripts are written by:
7 # Jameson Rollins <jrollins@finestructure.net>
8 # Jamie McClelland <jm@mayfirst.org>
9 # Daniel Kahn Gillmor <dkg@fifthhorseman.net>
10 #
11 # They are Copyright 2008-2009, and are all released under the GPL,
12 # version 3 or later.
13
14 # generate a subkey with the 'a' usage flags set
15
16 gen_subkey(){
17     local keyLength
18     local keyExpire
19     local keyID
20     local gpgOut
21     local userID
22
23     # get options
24     while true ; do
25         case "$1" in
26             -l|--length)
27                 keyLength="$2"
28                 shift 2
29                 ;;
30             -e|--expire)
31                 keyExpire="$2"
32                 shift 2
33                 ;;
34             *)
35                 if [ "$(echo "$1" | cut -c 1)" = '-' ] ; then
36                     failure "Unknown option '$1'.
37 Type '$PGRM help' for usage."
38                 fi
39                 break
40                 ;;
41         esac
42     done
43
44     case "$#" in
45         0)
46             gpgSecOut=$(gpg --quiet --fixed-list-mode --list-secret-keys --with-colons 2>/dev/null | egrep '^sec:')
47             ;;
48         1)
49             gpgSecOut=$(gpg --quiet --fixed-list-mode --list-secret-keys --with-colons "$1" | egrep '^sec:') || failure
50             ;;
51         *)
52             failure "You must specify only a single primary key ID."
53             ;;
54     esac
55
56     # check that only a single secret key was found
57     case $(echo "$gpgSecOut" | grep -c '^sec:') in
58         0)
59             failure "No secret keys found.  Create an OpenPGP key with the following command:
60  gpg --gen-key"
61             ;;
62         1)
63             keyID=$(echo "$gpgSecOut" | cut -d: -f5)
64             ;;
65         *)
66             echo "Multiple primary secret keys found:"
67             echo "$gpgSecOut" | cut -d: -f5
68             failure "Please specify which primary key to use."
69             ;;
70     esac
71
72     # check that a valid authentication key does not already exist
73     IFS=$'\n'
74     for line in $(gpg --quiet --fixed-list-mode --list-keys --with-colons "$keyID") ; do
75         type=$(echo "$line" | cut -d: -f1)
76         validity=$(echo "$line" | cut -d: -f2)
77         usage=$(echo "$line" | cut -d: -f12)
78
79         # look at keys only
80         if [ "$type" != 'pub' -a "$type" != 'sub' ] ; then
81             continue
82         fi
83         # check for authentication capability
84         if ! check_capability "$usage" 'a' ; then
85             continue
86         fi
87         # if authentication key is valid, prompt to continue
88         if [ "$validity" = 'u' ] ; then
89             echo "A valid authentication key already exists for primary key '$keyID'."
90             read -p "Are you sure you would like to generate another one? (y/N) " OK; OK=${OK:N}
91             if [ "${OK/y/Y}" != 'Y' ] ; then
92                 failure "aborting."
93             fi
94             break
95         fi
96     done
97
98     # set subkey defaults
99     # prompt about key expiration if not specified
100     keyExpire=$(get_gpg_expiration "$keyExpire")
101
102     # generate the list of commands that will be passed to edit-key
103     editCommands=$(cat <<EOF
104 addkey
105 7
106 S
107 E
108 A
109 Q
110 $keyLength
111 $keyExpire
112 save
113 EOF
114 )
115
116     log verbose "generating subkey..."
117     fifoDir=$(mktemp -d ${TMPDIR:-/tmp}/tmp.XXXXXXXXXX)
118     (umask 077 && mkfifo "$fifoDir/pass")
119     echo "$editCommands" | gpg --passphrase-fd 3 3< "$fifoDir/pass" --expert --command-fd 0 --edit-key "$keyID" &
120
121     # FIXME: this needs to fail more gracefully if the passphrase is incorrect
122     passphrase_prompt  "Please enter your passphrase for $keyID: " "$fifoDir/pass"
123
124     rm -rf "$fifoDir"
125     wait
126     log verbose "done."
127 }