Added Neil Rickert's mhsign.
authormarkus schnalke <meillo@marmaro.de>
Sat, 7 Jul 2012 08:54:20 +0000 (10:54 +0200)
committermarkus schnalke <meillo@marmaro.de>
Sat, 7 Jul 2012 08:54:20 +0000 (10:54 +0200)
It is adjusted to mmh and thus somehow different to the original version.
mhpgp will follow soon.

.gitignore
docs/README.mhsign-mhpgp [new file with mode: 0644]
man/Makefile.in
man/mhsign.man1 [new file with mode: 0644]
man/mmh-intro.man7
uip/Makefile.in
uip/mhsign.sh [new file with mode: 0755]

index 5c91101..cd4425b 100644 (file)
@@ -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 (file)
index 0000000..61269c6
--- /dev/null
@@ -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 <meillo@marmaro.de>.
+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
+=============================================================================
index 5b34a34..0866e0d 100644 (file)
@@ -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 (file)
index 0000000..2febe2c
--- /dev/null
@@ -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
index f8c7aae..7686ac1 100644 (file)
@@ -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
index f0c258e..12cf74e 100644 (file)
@@ -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 (executable)
index 0000000..ac56bc2
--- /dev/null
@@ -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 <meillo@marmaro.de>, 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/[ \r        ]*$//' $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 "[ \r    ]$" $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/$/\r/' "$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"