2 # Based on mhsign 1.1.0.9 2007/05/30 14:48:40 by Neil Rickert
3 # Adjusted to mmh by markus schnalke <meillo@marmaro.de>, 2012-07
7 # -encrypt: Encrypt to recipients of message. This implies signing.
8 # -mime: Use MIME pgp standard. For signature, trailing blanks
9 # will be removed and any "From " line will be indented for
10 # best compatibility. Enforced for multipart messages.
12 usage="Usage: mhsign [-encrypt] [-mime] [-Version] [-help] file"
19 # find out the signing key
21 if [ -z "$userid" ] ; then
22 userid="`mhparam pgpkey`"
24 if [ -z "$userid" ] ; then
25 userid="`gpg --list-secret-keys --with-colons --fixed-list-mode \
27 grep '^sec' | sort -t: -k3,3nr -k 6,6nr |
29 $7=="" || $7 > "'"\`date +%s\`"'" {
34 if [ -z "$userid" ] ; then
35 echo "No secret key found" >&2
39 # find out the file of recipient key exceptions (for encrypt only)
40 keyfile="${MMH:-$HOME/.mmh}/pgpkeys"
41 if [ ! -r "$keyfile" ] ; then
42 keyfile="${GNUPGHOME:-$HOME/.gnupg}/pgpkeys"
43 if [ ! -r "$keyfile" ] ; then
48 # prepend the default options from the profile
49 set -- `mhparam -nocomp ${0##*/}` "$@"
60 echo "mhsign has no own version number, thus this instead:"
74 if [ $# -ne 1 ] ; then
82 trap "rm -rf $TEMP" 0 1 2 15
84 ### lookupkeyfile address -- lookup one address in our database
86 key=`grep -i "^[^#].*[ ]$1\$" "$keyfile" 2>/dev/null`
90 echo "$key" | sed 's/[ ].*//;q'
94 ### lookupkeyring address -- lookup one address in keyring
96 key=`gpg --list-keys --with-colons "<$1>" 2>/dev/null`
100 echo "$key" | sed -n '/^pub:[^idre]:/{p;q;}' | cut -d: -f5
104 ### Do a best guess at FQDN
107 hostname -f 2>/dev/null || uname -n
110 ### lookupkeys file -- set $KL to list of recipient keys
114 if whom -ali -notocc -bcc "$1" >/dev/null ; then
115 echo "Encryption is not supported for BCCs" >&2
119 # extract the actual address
120 format='%<{error}%{error}: %{text}%|%(addr{text})%>'
121 addresses=`whom -ali -tocc -nobcc "$1" |sed 's_$_,_'`
122 addresses=`%libdir%/ap -form "=$format" "$addresses"`
124 for i in $addresses ; do
126 '|'*) echo "Ignoring pipe address" >&2
129 *) i="$i@`mh_hostname`" ;;
131 if k=`lookupkeyfile "$i"` ; then
133 elif k=`lookupkeyring "$i"` ; then
136 echo "Could not find key for <$i>" >&2
143 ### getheader headername msgfile
145 HDR=`sed -n -e '/^-*$/q' -e 's/^\([^ :]*\):.*/\1/p' $2 |
146 grep -i '^'"$1"'$' | head -1`
147 if [ "$HDR" = "" ] ; then return 1 ; fi
161 ### headbody msgfile # separate msgfile into $TEMP/head $TEMP/body
163 sed -n '1,/^\-*$/p' "$1" > $TEMP/head
164 sed '1,/^-*$/d' "$1" > $TEMP/body
167 ### fixheaders -- remove Content headers, add newheaders
171 /^[Cc][Oo][Nn][Tt][Ee][Nn][Tt]-/b r
180 grep "^-" $TEMP/head || echo ""
183 ### newboundary -- output a suitable boundary marker
185 b=$$_`date|sed 's/[ : ]/_/g'`
186 for i in 0 x '=' _ + , Z 9 4 ; do
187 if grep "^--$b" $TEMP/body >/dev/null 2>&1 ; then
188 ## oops, bad boundary -- try again
190 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456780=+,_' \
191 '3Ba+c98bdACmzXpqR,tTuMDSs_hLkwZ0ef7PQrW=2x5l6E14ZKivIVgOjoJnGNUyHF'`
197 echo "Failed to generate unique mime boundary" >&2
201 ### detachsign -- sign $TEMP/body, output in $TEMP/body.asc
203 gpg -u "$userid" --armor --textmode --detach-sign \
204 <$TEMP/body >$TEMP/body.asc
207 ### sign --- inline signature for $TEMP/body, output in $TEMP/body.asc
209 gpg -u "$userid" --armor --textmode --clearsign \
210 <$TEMP/body >$TEMP/body.asc
213 ### encrypt recipients -- encrypt $TEMP/body to recipients
219 gpg --no-encrypt-to -u "$userid" --armor --textmode \
220 --always-trust --output $TEMP/body.asc \
221 -r "$userid" $R --sign --encrypt $TEMP/body
224 ### Mainline processing
226 FILE="$1" ## we assume a disk file
227 if [ ! -r "$FILE" ] ; then
228 echo "cannot read $FILE" >&2
234 lookupkeys "$FILE" || exit 1
237 cp "$FILE" "$FILE.orig"
242 if grep -i "^mime-version:" $TEMP/head >/dev/null 2>&1 ; then
244 if CT=`getheader content-type $TEMP/head` ; then
245 echo "$CT" >$TEMP/newbody
246 if grep -i multipart $TEMP/newbody >/dev/null 2>&1 ; then
247 usemime=y # Force MIME if already multi-part
249 getheader content-transfer-encoding $TEMP/head \
255 echo "Mime-Version: 1.0" >$TEMP/newheaders
258 if [ "$usemime" = n ] ; then
266 cat $TEMP/head $TEMP/body.asc >$outfile || exit 1
274 if [ "$CT" = "" ] ; then
275 echo "Content-Type: text/plain; charset=us-ascii" >$TEMP/newbody
281 sed 's/^From / &/; s/[
\r ]*$//' $TEMP/body >>$TEMP/newbody
282 if grep "^From " $TEMP/body >/dev/null 2>&1 ; then
283 echo 'Warning: "From " lines in message body have been indented' >&2
285 if grep "[
\r ]$" $TEMP/body >/dev/null 2>&1 ; then
286 echo 'Warning: trailing blanks removed from message body' >&2
288 echo 'Content-Type: multipart/signed; protocol="application/pgp-signature";' >>$TEMP/newheaders
289 echo " micalg=pgp-sha1"'; boundary="'"$BDRY"'"' >>$TEMP/newheaders
291 sed -e 's/$/
\r/' "$TEMP/newbody" >"$TEMP/body"
298 echo "Content-Type: application/pgp-signature"
308 cat $TEMP/body >>$TEMP/newbody
309 echo 'Content-Type: multipart/encrypted; protocol="application/pgp-encrypted";' >>$TEMP/newheaders
310 echo " boundary=\"$BDRY\"" >> $TEMP/newheaders
312 mv $TEMP/newbody $TEMP/body || exit 1
316 echo "Content-Type: application/pgp-encrypted"
321 echo "Content-Type: application/octet-stream"
331 fixheaders | cat - $TEMP/body >"$outfile"