From f45cdc98117a84f071759462c7ae212f4bc5ab2e Mon Sep 17 00:00:00 2001 From: markus schnalke Date: Sat, 7 Jul 2012 10:54:20 +0200 Subject: [PATCH] Added Neil Rickert's mhsign. It is adjusted to mmh and thus somehow different to the original version. mhpgp will follow soon. --- .gitignore | 1 + docs/README.mhsign-mhpgp | 145 +++++++++++++++++++++ man/Makefile.in | 8 +- man/mhsign.man1 | 106 ++++++++++++++++ man/mmh-intro.man7 | 2 + uip/Makefile.in | 8 +- uip/mhsign.sh | 312 ++++++++++++++++++++++++++++++++++++++++++++++ 7 files changed, 576 insertions(+), 6 deletions(-) create mode 100644 docs/README.mhsign-mhpgp create mode 100644 man/mhsign.man1 create mode 100755 uip/mhsign.sh diff --git a/.gitignore b/.gitignore index 5c91101..cd4425b 100644 --- a/.gitignore +++ b/.gitignore @@ -43,6 +43,7 @@ /uip/mhparam /uip/mhpath /uip/mhshow +/uip/mhsign /uip/mhstore /uip/mhtest /uip/mmh diff --git a/docs/README.mhsign-mhpgp b/docs/README.mhsign-mhpgp new file mode 100644 index 0000000..61269c6 --- /dev/null +++ b/docs/README.mhsign-mhpgp @@ -0,0 +1,145 @@ +mhpgp, mhsign +------------- + +This software (shell scripts) written by Neil Rickert. + +It is placed in the public domain. You are free to use it and modify +it to suit your needs. + + +The scripts are adjusted to mmh by markus schnalke . +They work a bit different today. The following excrept of the README +and CHANGES files of the Neil's distribution is preserved for +documentation. + + +These are scripts for using with MH or nmh. + +The two scripts are tuned for the use of gnupg. It is not too hard +to adapt to pgp2, pgp5 or pgp6.5. But why bother, since gnupg has +clearly become the way to go for unix. + +Use: + + mhpgp ## to verify signature or decrypt current message. + + edit mhsign [-e] ## to sign [encrypt] at the whatnow prompt. + +See the man page for mhsign on creating a file "pgpkeys" in your MH +directory or GNUPGHOME directory. + + +Change log for mhsign: + +RCS file: RCS/mhsign,v +Working file: mhsign +head: 1.1 +branch: 1.1.0 +locks: strict +access list: +symbolic names: +keyword substitution: kv +total revisions: 10; selected revisions: 10 +description: +Program to sign [encrypt] a message from whatnow prompt. +---------------------------- +revision 1.1 +date: 2003/06/14 18:38:14; author: rickert; state: Exp; +branches: 1.1.0; +Initial revision +---------------------------- +revision 1.1.0.9 +date: 2007/05/30 14:48:40; author: rickert; state: Exp; lines: +14 -9 +Make sure that an MD5 hash is used with "-R" when signing. +---------------------------- +revision 1.1.0.8 +date: 2007/01/21 04:18:04; author: rickert; state: Exp; lines: +2 -2 +Fix unmatched quote +---------------------------- +revision 1.1.0.7 +date: 2004/06/13 20:14:52; author: rickert; state: Exp; lines: +3 -3 +Make sure that gnupg-1.3.6 uses the correct digest in pgp2 compatibility mode +---------------------------- +revision 1.1.0.6 +date: 2004/05/23 00:49:43; author: rickert; state: Exp; lines: +6 -6 +Use "--always-trust", and ignore any "encrypt-to" in options file +---------------------------- +revision 1.1.0.5 +date: 2004/02/25 04:03:44; author: rickert; state: Exp; lines: +12 -7 +When using -b with mime signature, turn off textmode and include the +trailing blanks in the signed data. There is no point in using -b +unless the trailing blanks are significant, in which case they should +be protected by the signature. +---------------------------- +revision 1.1.0.4 +date: 2003/09/13 19:56:53; author: rickert; state: Exp; lines: +10 -6 +Skip comment lines in '.pgpkeys'. +Allow preferred keys to come from environment +Use case insensitive search (grep -i) for .pgpkeys lookup of + addresses. +---------------------------- +revision 1.1.0.3 +date: 2003/07/19 14:30:32; author: rickert; state: Exp; lines: +20 -3 +Put personal keys in ".pgpkeys" database, so that script does not +need to be personalized. +---------------------------- +revision 1.1.0.2 +date: 2003/07/18 23:26:41; author: rickert; state: Exp; lines: +17 -13 +Force pgp/mime format if the message is already multipart mime. +---------------------------- +revision 1.1.0.1 +date: 2003/06/22 00:48:09; author: rickert; state: Exp; lines: +8 -2 +Check in $GNUPGHOME for .pgpkeys . This allows a per-keyring list +============================================================================= + +Change log for mhpgp: + +RCS file: RCS/mhpgp,v +Working file: mhpgp +head: 1.1 +branch: 1.1.0 +locks: strict +access list: +symbolic names: +keyword substitution: kv +total revisions: 8; selected revisions: 8 +description: +Script for pgp verify/decrypt of mh messages (uses gnupg) +---------------------------- +revision 1.1 +date: 2003/07/19 16:50:32; author: rickert; state: Exp; +branches: 1.1.0; +Initial revision +---------------------------- +revision 1.1.0.7 +date: 2005/11/29 06:25:05; author: rickert; state: Exp; lines: +3 -1 +If a message does not end in "\n" after decryption, then add "\n". +---------------------------- +revision 1.1.0.6 +date: 2005/07/13 01:00:10; author: rickert; state: Exp; lines: +2 -2 +Fix mishandling of boundary=string; +---------------------------- +revision 1.1.0.5 +date: 2004/09/05 14:49:59; author: rickert; state: Exp; lines: +2 -2 +Fix line endings when building a decrypted message (-w flag), the +encrypted text might use CRLF. +---------------------------- +revision 1.1.0.4 +date: 2004/02/22 17:14:02; author: rickert; state: Exp; lines: +27 -10 +Add "-b" option to strip blanks on pgpmime signature +Use "getopts" for checking options. +---------------------------- +revision 1.1.0.3 +date: 2003/09/09 04:29:11; author: rickert; state: Exp; lines: +3 -2 +Don't use exec, as that skips the trap and temp files are not deleted +---------------------------- +revision 1.1.0.2 +date: 2003/07/26 00:06:40; author: rickert; state: Exp; lines: +33 -11 +Drop "-o outfile". Add "-w" to write back as a message to current folder. +This allows easier examination of mime components that might be in +the encrypted portion. +---------------------------- +revision 1.1.0.1 +date: 2003/07/19 16:57:16; author: rickert; state: Exp; lines: +4 -7 +Clean up script, for more general usefulness +============================================================================= diff --git a/man/Makefile.in b/man/Makefile.in index 5b34a34..0866e0d 100644 --- a/man/Makefile.in +++ b/man/Makefile.in @@ -49,11 +49,11 @@ SEDMAN = $(SED) -f man.sed $< > $@ $(SEDMAN) # man pages to install in $(mandir)/$(manext1) -MAN1SRC = ali. anno. burst. comp. dist. flist. flists. folder. folders. \ - forw. inc. mark. mhbuild. mhl. mhlist. mmh. mmhwrap. \ - mhmail. mhparam. mhpath. mhstore. new. fnext. \ +MAN1SRC = ali. anno. burst. comp. dist. flist. flists. folder. folders. \ + forw. inc. mark. mhbuild. mhl. mhlist. mhsign. mmh. mmhwrap. \ + mhmail. mhparam. mhpath. mhstore. new. fnext. \ fprev. unseen. next. packf. pick. prev. prompter. rcvdist. rcvpack. \ - rcvstore. refile. repl. rmf. rmm. scan. send. sendfiles. \ + rcvstore. refile. repl. rmf. rmm. scan. send. sendfiles. \ show. slocal. sortm. whatnow. whom. MAN5SRC = mh-alias. mh-format. mh-mail. mh-profile. mh-tailor. diff --git a/man/mhsign.man1 b/man/mhsign.man1 new file mode 100644 index 0000000..2febe2c --- /dev/null +++ b/man/mhsign.man1 @@ -0,0 +1,106 @@ +.\" +.\" %nmhwarning% +.\" +.TH MHSIGN %manext1% "%nmhdate%" MH.6.8 [%nmhversion%] +.SH NAME +mhsign \- sign or encrypt a message with gnupg +.SH SYNOPSIS +.HP 5 +.na +.B mhsign +.RB [ \-encrypt ] +.RB [ \-mime ] +.I file +.RB [ \-Version ] +.RB [ \-help ] +.ad +.SH DESCRIPTION +.B mhsign +is a script to simplify signing and encrypting command line +MH mail, using gnupg. +.PP +.B mhsign +is normally invoked automatically by +.BR send . +When used directly, the source file, typically an MH draft file, +is replaced by the signed or encrypted message. +To permit recovery from mistakes, +a backup copy of the original file is saved, under the same name +with `.orig' appended. +.PP +The following options are recognized: +.TP +.B \-encrypt +Encrypt to recipients, in addition to signing. +The message will also be encrypted to the signing key. +.TP +.B \-mime +Use the PGP/MIME standard for signing and encrypting. +This is automatic if the message is already a multipart MIME message. +Otherwise the default is to sign/encrypt in the old-fashioned +non-MIME manner, for compatibility with older software. +.QP +When a message is signed but not encrypted, using the PGP/MIME +formatting, any line beginning with ``From '' will be indented, and any +trailing spaces will be removed from lines in the message body. +This is to ensure maximum compatibility. +Where trailing blanks are important (sending patches, for example), +it would be wise to use quoted-printable or other MIME encoding +for that component. +.PP +The signing key is automatically determinded by gnupg, +unless the the profile entry +.IR Pgpkey +defines it. +The environment variable +.IR MMHPGPKEY +has highest precedence and can be used to overrule the key uid temporarily. +.PP +For encryption, the public keys of the recipients are taken from +the gnupg keyring. +To handle exceptions, e.g. recipient addresses that do not +match the key uid in the keyring, a file named +.I pgpkeys +may be used. +It should be located either in the gnupg directory (normally $HOME/.gnupg) +or in the mmh directory (normally $HOME/.mmh). +If both files exist, the one in the gnupg directory takes precedence. +.PP +A sample +.I pgpkeys +file: +.sp +.RS 5 +.nf +0x88888888 john@nowhere.example.org +e5fda812 meillo@marmaro.de +.fi +.RE + +.SH FILES +.fc ^ ~ +.nf +.ta \w'%etcdir%/ExtraBigFileName 'u +^$HOME/.gnupg/pgpkeys~^Pubkey exceptions for encrypting +^$HOME/.mmh/pgpkeys~^... alternative location +.fi + +.SH "PROFILE COMPONENTS" +.fc ^ ~ +.nf +.ta 2.4i +.ta \w'ExtraBigProfileName 'u +^Pgpkey:~^To determine the user's signing key +.fi + +.SH "SEE ALSO" +whom(1), send(1), mhpgp(1), gpg(1) + +.SH DEFAULTS +None + +.SH CONTEXT +None + +.SH BUGS +None diff --git a/man/mmh-intro.man7 b/man/mmh-intro.man7 index f8c7aae..7686ac1 100644 --- a/man/mmh-intro.man7 +++ b/man/mmh-intro.man7 @@ -198,6 +198,7 @@ commands: ^mhmail(1)~^\- send mail (mailx replacement) ^mhparam(1)~^\- print mmh profile components ^mhpath(1)~^\- print full pathnames of mmh messages and folders +^mhsign(1)~^\- sign or encrypt a message with gnupg ^mhstore(1)~^\- store contents of MIME messages into files ^mmh(1)~^\- initialize the mmh environment ^next(1)~^\- show the next message @@ -219,6 +220,7 @@ commands: ^slocal(1)~^\- asynchronously filter and deliver new mail ^sortm(1)~^\- sort messages ^whatnow(1)~^\- prompting front\-end for send +^whom(1)~^\- list recipients of a message .sp ^ap(8)~^\- parse addresses 822\-style ^dp(8)~^\- parse dates 822\-style diff --git a/uip/Makefile.in b/uip/Makefile.in index f0c258e..12cf74e 100644 --- a/uip/Makefile.in +++ b/uip/Makefile.in @@ -48,7 +48,7 @@ SETGID_MAIL = @SETGID_MAIL@ # commands to build CMDS = ali anno burst comp dist flist folder forw mmh mark \ - mhbuild mhl \ + mhbuild mhl mhsign \ mhlist mhmail mhparam mhpath mhstore new packf pick \ print-mimetype prompter rcvdist rcvpack rcvstore refile repl rmf \ rmm scan send sendfiles show slocal sortm spost whatnow whom @@ -66,7 +66,7 @@ SCMDS = inc SRCS = ali.c aliasbr.c anno.c ap.c burst.c comp.c \ dist.c distsbr.c dp.c dropsbr.c flist.c fmtdump.c \ folder.c forw.c inc.c mark.c mmh.sh mmhwrap.sh mhbuild.c \ - mhfree.c mhl.c mhlist.c mhlistsbr.c \ + mhfree.c mhl.c mhlist.c mhlistsbr.c mhsign.sh \ mhmail.c mhmisc.c mhoutsbr.c mhparam.c mhparse.c \ mhpath.c mhshow.c mhshowsbr.c mhstore.c mhtest.c \ new.c packf.c pick.c print-mimetype.sh \ @@ -134,6 +134,10 @@ mmhwrap: mmhwrap.sh sed "s,%bindir%,"$(bindir)"," $(srcdir)/mmhwrap.sh >mmhwrap chmod +x mmhwrap +mhsign: mhsign.sh + cp $(srcdir)/mhsign.sh mhsign + chmod +x mhsign + mhbuild: mhbuild.o mhoutsbr.o mhmisc.o mhfree.o mhparse.o termsbr.o $(LOCALLIBS) $(LINK) mhbuild.o mhoutsbr.o mhmisc.o mhfree.o mhparse.o $(LINKLIBS) $(TERMLIB) diff --git a/uip/mhsign.sh b/uip/mhsign.sh new file mode 100755 index 0000000..ac56bc2 --- /dev/null +++ b/uip/mhsign.sh @@ -0,0 +1,312 @@ +#!/bin/sh +# Based on mhsign 1.1.0.9 2007/05/30 14:48:40 by Neil Rickert +# Adjusted to mmh by markus schnalke , 2012-07 + + +# mhsign: +# -encrypt: Encrypt to recipients of message. This implies signing. +# -mime: Use MIME pgp standard. For signature, trailing blanks +# will be removed and any "From " line will be indented for +# best compatibility. Enforced for multipart messages. + +usage="Usage: mhsign [-encrypt] [-mime] file" + +# defaults +usemime=n +function=sign + + +# find out the signing key +userid="$MMHPGPKEY" +if [ "x$userid" = "x" ] ; then + userid="`mhparam pgpkey`" +fi +userid="`gpg --list-secret-keys --with-colons 2>/dev/null | + sed -n '/^sec/{p;q}' | cut -d: -f5`" +if [ "x$userid" = x ] ; then + echo "No secret key found" >&2 + exit 1 +fi + +# find out the file of recipient key exceptions (for encrypt only) +keyfile="${MMH:-$HOME/.mmh}/pgpkeys" +if [ ! -r "$keyfile" ] ; then + keyfile="${GNUPGHOME:-$HOME/.gnupg}/pgpkeys" + if [ ! -r "$keyfile" ] ; then + keyfile=/dev/null + fi +fi + +# prepend the default options from the profile +set -- `mhparam -nocomp ${0##*/}` "$@" + +while : ; do + case "$1" in + -e*) + function=encrypt + ;; + -m*) + usemime=y + ;; + -V*) + echo "mhsign has no own version number, thus this instead:" + folder -Version + exit 0 + ;; + -h*|-*) + echo "$usage" >&2 + exit 1 + ;; + *) + break + esac + shift +done + +if [ $# -ne 1 ] ; then + echo "$usage" >&2 + exit 1 +fi + +TEMP=/tmp/${0##*/}.$$ +umask 077 +mkdir $TEMP || exit 1 +trap "rm -rf $TEMP" 0 1 2 15 + +### lookupkeyfile address -- lookup one address in our database +lookupkeyfile() { + key=`grep -i "^[^#].*[ ]$1\$" "$keyfile" 2>/dev/null` + if [ $? != 0 ] ; then + return 1 + fi + echo "$key" | sed 's/[ ].*//;q' + return 0 +} + +### lookupkeyring address -- lookup one address in keyring +lookupkeyring() { + key=`gpg --list-keys --with-colons "<$1>" 2>/dev/null` + if [ $? != 0 ] ; then + return 1 + fi + echo "$key" | sed -n '/^pub/{p;q}' | cut -d: -f5 + return 0 +} + +### lookupkeys file -- set $KL to list of recipient keys +lookupkeys() { + KL= + status=0 + if whom -ali -notocc -bcc "$1" >/dev/null ; then + echo "Encryption is not supported for BCCs" >&2 + return 1 + fi + + for i in `whom -ali -tocc -nobcc "$1"` ; do + case "$i" in + '|'*) echo "Ignoring pipe address" >&2 + continue ;; + *@*) ;; + *) i="$i@`hostname -f`" ;; + esac + if k=`lookupkeyfile "$i"` ; then + KL="$KL $k" + elif k=`lookupkeyring "$i"` ; then + KL="$KL $k" + else + echo "Could not find key for <$i>" >&2 + status=1 + fi + done + return $status +} + +### getheader headername msgfile +getheader() { + HDR=`sed -n -e '/^-*$/q' -e 's/^\([^ :]*\):.*/\1/p' $2 | + grep -i '^'"$1"'$' | head -1` + if [ "$HDR" = "" ] ; then return 1 ; fi + sed -n -e ':a + /^-*$/q + /^'"$HDR"':/b x + d + b a + :x + p + n + /^[ ]/b x + b a' $2 + return 0 +} + +### headbody msgfile # separate msgfile into $TEMP/head $TEMP/body +headbody() { + sed -n '1,/^\-*$/p' "$1" > $TEMP/head + sed '1,/^-*$/d' "$1" > $TEMP/body +} + +### fixheaders -- remove Content headers, add newheaders +fixheaders() { + sed -n ':a + /^-*$/q + /^[Cc][Oo][Nn][Tt][Ee][Nn][Tt]-/b r + p + n + b a + :r + n + /^[ ]/b r + b a' $TEMP/head + cat $TEMP/newheaders + grep "^-" $TEMP/head || echo "" +} + +### newboundary -- output a suitable boundary marker +newboundary() { + b=$$_`date|sed 's/[ : ]/_/g'` + for i in 0 x '=' _ + , Z 9 4 ; do + if grep "^--$b" $TEMP/body >/dev/null 2>&1 ; then + ## oops, bad boundary -- try again + b=`echo $i$b | tr \ +'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456780=+,_' \ +'3Ba+c98bdACmzXpqR,tTuMDSs_hLkwZ0ef7PQrW=2x5l6E14ZKivIVgOjoJnGNUyHF'` + else + echo "$b" + return 0 + fi + done + echo "Failed to generate unique mime boundary" >&2 + exit 1 +} + +### detachsign -- sign $TEMP/body, output in $TEMP/body.asc +detachsign() { + gpg -u "$userid" --armor --textmode --detach-sign \ + <$TEMP/body >$TEMP/body.asc +} + +### sign --- inline signature for $TEMP/body, output in $TEMP/body.asc +sign() { + gpg -u "$userid" --armor --textmode --clearsign \ + <$TEMP/body >$TEMP/body.asc +} + +### encrypt recipients -- encrypt $TEMP/body to recipients +encrypt() { + R= + for i in $KL ; do + R="$R -r $i" + done + gpg --no-encrypt-to -u "$userid" --armor --textmode \ + --always-trust --output $TEMP/body.asc \ + -r "$userid" $R --sign --encrypt $TEMP/body +} + +### Mainline processing + +FILE="$1" ## we assume a disk file +if [ ! -r "$FILE" ] ; then + echo "cannot read $FILE" >&2 + exit 1 +fi + +case "$function" in +encrypt) + lookupkeys "$FILE" || exit 1 +esac + +cp "$FILE" "$FILE.orig" +outfile="$FILE" +headbody "$FILE" + +CT="" +if grep -i "^mime-version:" $TEMP/head >/dev/null 2>&1 ; then + >$TEMP/newheaders + if CT=`getheader content-type $TEMP/head` ; then + echo "$CT" >$TEMP/newbody + if grep -i multipart $TEMP/newbody >/dev/null 2>&1 ; then + usemime=y # Force MIME if already multi-part + fi + getheader content-transfer-encoding $TEMP/head \ + >>$TEMP/newbody || : + else + CT="" + fi +else + echo "Mime-Version: 1.0" >$TEMP/newheaders +fi + +if [ "$usemime" = n ] ; then + ### non-MIME ### + case "$function" in + sign) + sign || exit 1 ;; + encrypt) + encrypt || exit 1 ;; + esac + cat $TEMP/head $TEMP/body.asc >$outfile || exit 1 + exit 0 +fi + +### MIME ### + +BDRY="`newboundary`" + +if [ "$CT" = "" ] ; then + echo "Content-Type: text/plain; charset=us-ascii" >$TEMP/newbody +fi +echo >>$TEMP/newbody + +case $function in +sign) + sed 's/^From / &/; s/[ ]*$//' $TEMP/body >>$TEMP/newbody + if grep "^From " $TEMP/body >/dev/null 2>&1 ; then + echo 'Warning: "From " lines in message body have been indented' >&2 + fi + if grep "[ ]$" $TEMP/body >/dev/null 2>&1 ; then + echo 'Warning: trailing blanks removed from message body' >&2 + fi + echo 'Content-Type: multipart/signed; protocol="application/pgp-signature";' >>$TEMP/newheaders + echo " micalg=pgp-sha1"'; boundary="'"$BDRY"'"' >>$TEMP/newheaders + + sed -e 's/$/ /' "$TEMP/newbody" >"$TEMP/body" + detachsign || exit 1 + ( + echo "--$BDRY" + cat $TEMP/newbody + echo + echo "--$BDRY" + echo "Content-Type: application/pgp-signature" + echo + cat $TEMP/body.asc + echo + echo "--$BDRY--" + echo + ) >$TEMP/body + ;; + +encrypt) + cat $TEMP/body >>$TEMP/newbody + echo 'Content-Type: multipart/encrypted; protocol="application/pgp-encrypted";' >>$TEMP/newheaders + echo " boundary=\"$BDRY\"" >> $TEMP/newheaders + + mv $TEMP/newbody $TEMP/body || exit 1 + encrypt || exit 1 + ( + echo "--$BDRY" + echo "Content-Type: application/pgp-encrypted" + echo + echo "Version: 1" + echo + echo "--$BDRY" + echo "Content-Type: application/octet-stream" + echo + cat $TEMP/body.asc + echo + echo "--$BDRY--" + echo + ) >"$TEMP/body" + ;; +esac + +fixheaders | cat - $TEMP/body >"$outfile" -- 1.7.10.4