aboutsummaryrefslogtreecommitdiff
path: root/misc
diff options
context:
space:
mode:
Diffstat (limited to 'misc')
-rw-r--r--misc/poc/README1
-rwxr-xr-xmisc/poc/firma-0.153
-rwxr-xr-xmisc/poc/firma-0.1.557
-rwxr-xr-xmisc/poc/firma-0.1.6147
-rwxr-xr-xmisc/poc/firma-0.2108
-rwxr-xr-xmisc/poc/firma-0.2.1133
-rwxr-xr-xmisc/poc/firma-0.2.2153
-rwxr-xr-xmisc/poc/firma-0.2.3192
-rwxr-xr-xmisc/poc/firma-0.2.4211
-rwxr-xr-xmisc/poc/firma-0.2.x280
-rw-r--r--misc/python/README2
-rwxr-xr-xmisc/python/firma.py85
12 files changed, 1422 insertions, 0 deletions
diff --git a/misc/poc/README b/misc/poc/README
new file mode 100644
index 0000000..693db64
--- /dev/null
+++ b/misc/poc/README
@@ -0,0 +1 @@
+Proof of concept and initial versions.
diff --git a/misc/poc/firma-0.1 b/misc/poc/firma-0.1
new file mode 100755
index 0000000..eab39e6
--- /dev/null
+++ b/misc/poc/firma-0.1
@@ -0,0 +1,53 @@
+#!/bin/bash
+#
+# firma v0.1: simple encrypted mailing list aliases
+# feedback: rhatto@riseup.net | GPL
+#
+# list configuration is passed thru the a config file,
+# where you put PARAMETER=value (whithout spaces)
+#
+# MAIL= path for mail program
+# GPG= path for gnupg binary
+# TMP= where you want the temp files
+# LISTNAME= list email
+# GPGDIR= gpg dir for the lists' keyring
+# PASSWD= passwd for the lists' keyring
+
+# eval the config file
+source $1
+
+GPGCOMMAND="$GPG -q --homedir $GPGDIR"
+GPGLIST="$GPGCOMMAND --list-keys"
+GPGDECRYPT="$GPGCOMMAND --decrypt"
+GPGENCRYPT="$GPGCOMMAND --always-trust -e -s -a -r"
+
+rm $TMP $TMP.gpg
+touch $TMP; chmod 600 $TMP;
+touch $TMP.gpg; chmod 600 $TMP.gpg;
+
+# todo: use an array
+while read STDIN; do
+ echo $STDIN >> $TMP
+done
+
+# get the headers
+FROM=$(grep -m 1 ^From: $TMP | cut -f 2 -d :)
+DATE=$(grep -m 1 ^Date: $TMP)
+SUBJECT=$(grep -m 1 ^Subject: $TMP)
+
+# detect the encrypted message
+sed -n '/-----BEGIN PGP MESSAGE-----/,/-----END PGP MESSAGE-----/p' $TMP >> $TMP.gpg
+
+# encrypting and sending for each recipient on the list
+for EMAIL in $($GPGLIST | grep pub | cut -d "<" -f 2 | sed -e 's/>//' | grep @ | grep -v $LISTNAME); do
+
+ echo "$PASSWD
+ Message from: $FROM
+ $SUBJECT
+ $DATE
+
+ $(echo "$PASSWD" | $GPGDECRYPT $TMP.gpg)" | sed -e 's/=20$//' | $GPGENCRYPT $EMAIL | $MAIL -r $LISTNAME $EMAIL
+
+done
+
+rm $TMP $TMP.gpg
diff --git a/misc/poc/firma-0.1.5 b/misc/poc/firma-0.1.5
new file mode 100755
index 0000000..029a09d
--- /dev/null
+++ b/misc/poc/firma-0.1.5
@@ -0,0 +1,57 @@
+#!/bin/bash
+#
+# firma v0.2: simple encrypted mailing list aliases
+# feedback: rhatto@riseup.net | GPL
+#
+# list configuration is passed through a config file,
+# where you put PARAMETER=value (whithout spaces)
+#
+# MAIL= path for mail program
+# GPG= path for gnupg binary
+# TMP= where you want the temp files
+# LISTNAME= list email
+# GPGDIR= gpg dir for the lists' keyring
+# PASSWD= passwd for the lists' keyring
+# FOOTER= message footer
+
+# eval the config file
+source $1
+
+GPGCOMMAND="$GPG -q --homedir $GPGDIR"
+GPGLIST="$GPGCOMMAND --list-keys"
+GPGDECRYPT="$GPGCOMMAND --decrypt"
+GPGENCRYPT="$GPGCOMMAND --always-trust -e -s -a -r"
+
+rm $TMP $TMP.gpg
+touch $TMP; chmod 600 $TMP;
+touch $TMP.gpg; chmod 600 $TMP.gpg;
+
+# todo: use an array
+while read STDIN; do
+ echo $STDIN >> $TMP
+done
+
+# get the headers
+FROM=$(grep -m 1 ^From: $TMP | cut -f 2 -d :)
+DATE=$(grep -m 1 ^Date: $TMP)
+SUBJECT=$(grep -m 1 ^Subject: $TMP)
+
+# detect the encrypted message
+sed -n '/-----BEGIN PGP MESSAGE-----/,/-----END PGP MESSAGE-----/p' $TMP >> $TMP.gpg
+
+# encrypting and sending for each recipient on the list
+for EMAIL in $($GPGLIST | grep pub | cut -d "<" -f 2 | sed -e 's/>//' | grep @ | grep -v $LISTNAME); do
+
+ echo "$PASSWD
+ Message from: $FROM
+ $SUBJECT
+ $DATE
+
+ $(echo "$PASSWD" | $GPGDECRYPT $TMP.gpg)
+
+ ---
+ $FOOTER " | sed -e 's/=20$//' | $GPGENCRYPT $EMAIL | $MAIL -r $LISTNAME $EMAIL
+
+done
+
+rm $TMP $TMP.gpg
diff --git a/misc/poc/firma-0.1.6 b/misc/poc/firma-0.1.6
new file mode 100755
index 0000000..239c9a5
--- /dev/null
+++ b/misc/poc/firma-0.1.6
@@ -0,0 +1,147 @@
+#!/bin/bash
+#
+# firma v0.2: simple encrypted mailing list aliases
+# feedback: rhatto@riseup.net | GPL
+#
+# list configuration is passed through a config file,
+# where you put PARAMETER=value (whithout spaces)
+#
+# MAIL= path for mail program
+# GPG= path for gnupg binary
+# TMP= where you want the temp files
+# LISTNAME= list email
+# GPGDIR= gpg dir for the lists' keyring
+# PASSWD= passwd for the lists' keyring
+# FOOTER= message footer
+# ALLOWSENDKEY = set to 1 if you want people automatically receive the list
+# key requesting through listname-request@example.tld
+# with subject: key
+#
+# design / todo:
+#
+# - list-request:
+# - key (allow send key)
+# - help
+# - subscribe: exchange pubkey
+# - unsubscribe
+# - strings
+# - check signatures
+# - create list
+# - archive (optional)
+# - logfile (optional)
+# - gpg --no-tty --display-charset --utf8-strings ?
+#
+# sintax: firma -c || firma config-file
+# -c: create a new list
+# config-file: parse the email from stdin
+# with the parameters specified in the
+# config-file
+#
+# fix:
+#
+# - special chars
+# - id's recipient selection
+#
+
+fuction _refresh_cache {
+ rm $1 $1.gpg
+ touch $1; chmod 600 $1;
+ touch $1.gpg; chmod 600 $TMP.gpg;
+}
+
+function _process_message {
+ # get the headers
+ FROM=$(grep -m 1 ^From: $1 | cut -f 2 -d :)
+ DATE=$(grep -m 1 ^Date: $1)
+ SUBJECT=$(grep -m 1 ^Subject: $1)
+
+ # detect the encrypted message
+ sed -n '/-----BEGIN PGP MESSAGE-----/,/-----END PGP MESSAGE-----/p' $1 >> $1.gpg
+
+ # encrypting and sending for each recipient on the list
+ for EMAIL in $($GPGLIST | grep pub | cut -d "<" -f 2 | sed -e 's/>//' | grep @ | grep -v $LISTNAME); do
+
+ echo "$PASSWD
+ Message from: $FROM
+ $SUBJECT
+ $DATE
+
+ $(echo "$PASSWD" | $GPGDECRYPT $1.gpg)
+
+ ---
+ $FOOTER
+ " | sed -e 's/=20$//' | $GPGENCRYPT $EMAIL | $MAIL -r $LISTNAME $EMAIL
+ done
+}
+
+function _process_request {
+
+ # todo: support subjects like "key ", etc
+ FROM=$(grep -m 1 ^From: $1 | cut -f 2 -d :)
+ REQUEST=$(grep -m 1 ^Subject: $1)
+ if [[ $REQUEST == "key" ]]; then
+ if [[ $ALLOWSENDKEY == 1 ]]; then
+ # send key to From: recipient
+ else
+ # dont send the key; return error message
+ fi
+ else if [[ $REQUEST == "subscribe" ]]; then
+ # check if user put its pubkey and
+ # ask the list for subscribe From: recipient
+ else if [[ $REQUEST == "unsubscribe" ]]; then
+ # unsubscribe and advise the list
+ else
+ # error message
+ fi
+
+}
+
+function _process {
+
+ # eval the config file
+ source $1
+
+ GPGCOMMAND="$GPG -q --homedir $GPGDIR"
+ GPGLIST="$GPGCOMMAND --list-keys"
+ GPGDECRYPT="$GPGCOMMAND --decrypt"
+ GPGENCRYPT="$GPGCOMMAND --always-trust --hidden-recipient --textmode -e -s -a -r"
+
+ # clear the cache before read the message
+ _refresh_cache $TMP
+
+ # todo: use an array
+ while read STDIN; do
+ echo $STDIN >> $TMP
+ done
+
+ # check with action is requested depending on the To: field
+ TO=$(grep -m 1 ^To: $)
+ if [[ $TO == $LISTNAME ]]; then _process_message $TMP;
+ else _process_request $TMP;
+ fi
+
+ # clear after process
+ _refresh_cache $TMP
+
+}
+
+function newlist {
+
+ LISTHOME =
+ LISTNANE =
+ ...
+
+ $GPGCOMMAND --gen-key
+
+}
+
+# check sintax
+if [[ $1 = "-c" ]]; then
+ _newlist;
+else if [ -f $1 ];
+ then _process $1;
+else
+ echo sintax: $0 [-c] [config-file];
+fi
+
+rm $TMP $TMP.gpg
diff --git a/misc/poc/firma-0.2 b/misc/poc/firma-0.2
new file mode 100755
index 0000000..5cf85d2
--- /dev/null
+++ b/misc/poc/firma-0.2
@@ -0,0 +1,108 @@
+#!/bin/bash
+#
+# firma v0.2: simple encrypted mailing list aliases
+# feedback: rhatto@riseup.net luis@riseup.net | GPL
+#
+# list configuration is passed thru the config file,
+# where you put PARAMETER=value (whithout spaces)
+#
+# MAIL= path for mail program
+# GPG= path for gnupg binary
+# TMP= where you want the temp files
+# LISTNAME= list email
+# LISTADMIN= list administrator email addresses (space separated)
+# GPGDIR= gpg dir for the lists' keyring
+# PASSWD= passwd for the lists' keyring
+
+# eval the config file
+source $1
+
+# declare GPG variables
+GPGCOMMAND="$GPG --quiet --homedir $GPGDIR --batch --no-tty --no-use-agent --no-permission-warning"
+GPGLIST="$GPGCOMMAND --list-keys"
+GPGDECRYPT="$GPGCOMMAND --passphrase-fd 0 --decrypt"
+GPGENCRYPT="$GPGCOMMAND --passphrase-fd 0 --always-trust --encrypt --sign --armor --recipient"
+
+# declare functions
+# discard $GPGDECRYPT STDOUT and get its STDERR instead, for signature checking
+function GPGSTDERR {
+ echo "$PASSWD" | ($GPGDECRYPT --status-fd 2 $TMP.gpg 1> /dev/null) 2>&1 ;
+}
+
+# get list susbscriber addresses
+function SUBSCRIBERS {
+ $GPGLIST | sed -n "/$LISTNAME/d;/pub/p" | grep -o '<.*>' | sed -e 's/[<>]//g' ;
+}
+
+# create the temporary files and restrict their permissions
+rm -f $TMP $TMP.gpg
+touch $TMP; chmod 600 $TMP;
+touch $TMP.gpg; chmod 600 $TMP.gpg;
+
+# todo: use an array
+while read STDIN; do
+ echo $STDIN >> $TMP
+done
+
+# get the message headers
+# todo: find a better place for $FROMADD since its not part of the message headers
+FROM=$(grep -m 1 ^From: $TMP | cut -f 2 -d :)
+FROMADD=$(echo $FROMADD | if grep -q '<' ; then echo $FROMADD | grep -o '<.*>' | sed -e 's/[<>]//g' ; else echo $FROMADD ; fi)
+DATE=$(grep -m 1 ^Date: $TMP)
+SUBJECT=$(grep -m 1 ^Subject: $TMP | cut -f 2 -d :)
+
+# get the encrypted message
+sed -n '/-----BEGIN PGP MESSAGE-----/,/-----END PGP MESSAGE-----/p' $TMP >> $TMP.gpg
+
+# if signature is OK, encrypt and send it for each list subscriber
+# todo: declare a function to decrypt, re-encrypt and send the list messages
+if (GPGSTDERR | grep -q 'GOODSIG') ; then
+
+ for EMAIL in $(SUBSCRIBERS); do
+
+ echo "$PASSWD
+ Message from: $FROM
+ Subject: $SUBJECT
+ $DATE
+
+ $(GPGSTDERR | grep 'gpg: Signature made')
+ $(GPGSTDERR | grep 'gpg: Good signature from')
+
+$(echo "$PASSWD" | $GPGDECRYPT $TMP.gpg 2> /dev/null)" | sed -e 's/=20$//' | $GPGENCRYPT $EMAIL | $MAIL -r $LISTNAME $EMAIL
+
+ done
+
+# else, if signature is BAD, email it back to sender and to list admins
+elif (GPGSTDERR | grep -q 'BADSIG') ; then
+
+ echo "$PASSWD
+ Message from: $FROM
+ Subject: [BAD SIGNATURE] $SUBJECT
+ $DATE
+
+ $(GPGSTDERR | grep 'gpg: Signature made')
+ $(GPGSTDERR | grep 'gpg: BAD signature from')
+
+$(echo "$PASSWD" | $GPGDECRYPT $TMP.gpg 2> /dev/null)" | sed -e 's/=20$//' | $GPGENCRYPT $LISTADMIN $FROMADD | $MAIL -r $LISTNAME $LISTADMIN $FROMADD
+
+# else, probably either the message was not signed or the sender is not subscribed to the list
+# email the message back to sender including a note about this
+# todo: parse STDERR to find out why the signature couldn't be checked and send more specific errors back to sender
+else
+
+ echo "
+ Message from: $FROM
+ Subject: [RETURNED MAIL] $SUBJECT
+ $DATE
+
+ [ It was not possible to process this message. Either or both
+ the message was not encrypted and/or signed, or you are not
+ subscribed to this list. Contact the list administrator if
+ you have any questions. ]
+
+ --
+ firma v0.2" | $MAIL -r $LISTNAME $FROMADD
+
+fi
+
+rm -f $TMP $TMP.gpg
diff --git a/misc/poc/firma-0.2.1 b/misc/poc/firma-0.2.1
new file mode 100755
index 0000000..13ee6da
--- /dev/null
+++ b/misc/poc/firma-0.2.1
@@ -0,0 +1,133 @@
+#!/bin/bash
+#
+# firma v0.2.1: simple encrypted mailing list aliases
+# feedback: rhatto@riseup.net luis@riseup.net | GPL
+#
+# list configuration is passed thru the config file,
+# where you put PARAMETER=value (whithout spaces)
+#
+# MAIL= path for mail program
+# GPG= path for gnupg binary
+# TMP= where you want the temp files
+# LISTNAME= list email
+# LISTADMIN= list administrator email addresses (space separated)
+# GPGDIR= gpg dir for the lists' keyring
+# PASSWD= passwd for the lists' keyring
+
+# eval the config file
+source $1
+
+# declare GPG variables
+GPGCOMMAND="$GPG --quiet --homedir $GPGDIR --batch --no-tty --no-use-agent --no-permission-warning"
+GPGLIST="$GPGCOMMAND --list-keys --with-colons"
+GPGDECRYPT="$GPGCOMMAND --passphrase-fd 0 --decrypt"
+GPGENCRYPT="$GPGCOMMAND --passphrase-fd 0 --always-trust --encrypt --sign --armor --hidden-recipient"
+
+# check configuration file parameters
+# todo: check if $TMP directory/files exist and if password is at least n characters long
+if [ ! -x $GPG -o ! -f $GPG ]; then
+ echo -e "\n$1: GPG binary ($GPG) could not be found.\n"
+ exit
+elif [ ! -x $MAIL -o ! -f $MAIL ]; then
+ echo -e "\n$1: Mail program ($MAIL) could not be found.\n"
+ exit
+elif [ ! -d $GPGDIR -o ! -f $GPGDIR/pubring.gpg -o ! -f $GPGDIR/secring.gpg ]; then
+ echo -e "\n$1: GPG home directory ($GPGDIR) or the GPG keyrings could not be found.\n"
+ exit
+elif [ -z $($GPGLIST | grep -o "<$LISTNAME>") ]; then
+ echo -e "\n$1: GPG key for list \"$LISTNAME\" could not be found."
+ echo -e "$1: Note that this parameter expects an email address.\n"
+ exit
+else
+ for ADMIN in $LISTADMIN; do {
+ if [ -z $($GPGLIST | grep -o "<$ADMIN>") ]; then
+ echo -e "\n$1: GPG key for list administrator \"$ADMIN\" could not be found."
+ echo -e "$1: Note that this parameter expects one or more email addresses.\n"
+ exit
+ fi; }
+ done
+fi
+
+# declare functions
+# discard $GPGDECRYPT STDOUT and get its STDERR instead, for signature checking
+function GPGSTDERR {
+ echo "$PASSWD" | ($GPGDECRYPT --status-fd 2 $TMP.gpg 1> /dev/null) 2>&1 ;
+}
+
+# get list susbscriber addresses
+function SUBSCRIBERS {
+ $GPGLIST | sed -n "/$LISTNAME/d;/pub/p" | grep -o "<.*>" | sed -e "s/[<>]//g" ;
+}
+
+# create the temporary files and restrict their permissions
+rm -f $TMP $TMP.gpg
+touch $TMP; chmod 600 $TMP;
+touch $TMP.gpg; chmod 600 $TMP.gpg;
+
+# todo: use an array
+while read STDIN; do
+ echo $STDIN >> $TMP
+done
+
+# get the message headers
+# todo: find a better place for $FROMADD since its not part of the message headers
+FROM=$(grep -m 1 "^From:" $TMP | cut -d : -f 2- | sed "s/^ //")
+FROMADD=$(echo $FROM | if grep -q "<" ; then echo $FROM | grep -o "<.*>" | sed -e "s/[<>]//g" ; else echo $FROM ; fi)
+DATE=$(grep -m 1 "^Date:" $TMP)
+SUBJECT=$(grep -m 1 "^Subject:" $TMP | cut -d : -f 2- | sed "s/^ //")
+
+# get the encrypted message
+sed -n "/-----BEGIN PGP MESSAGE-----/,/-----END PGP MESSAGE-----/p" $TMP >> $TMP.gpg
+
+# if signature is Good, encrypt and send it for each list subscriber
+# todo: declare a function to decrypt, re-encrypt and send the list messages
+if (GPGSTDERR | grep -q "GOODSIG") ; then
+
+ for EMAIL in $(SUBSCRIBERS); do
+
+ echo "$PASSWD
+ Message from: $FROM
+ Subject: $SUBJECT
+ $DATE
+
+ $(GPGSTDERR | grep "gpg: Signature made")
+ $(GPGSTDERR | grep "gpg: Good signature from")
+
+$(echo "$PASSWD" | $GPGDECRYPT $TMP.gpg 2> /dev/null)" | sed -e "s/=20$//" | $GPGENCRYPT $EMAIL | $MAIL -r $LISTNAME $EMAIL
+
+ done
+
+# else, if signature is BAD, email it back to sender and to list admins
+elif (GPGSTDERR | grep -q "BADSIG") ; then
+
+ echo "$PASSWD
+ Message from: $FROM
+ Subject: [BAD SIGNATURE] $SUBJECT
+ $DATE
+
+ $(GPGSTDERR | grep "gpg: Signature made")
+ $(GPGSTDERR | grep "gpg: BAD signature from")
+
+$(echo "$PASSWD" | $GPGDECRYPT $TMP.gpg 2> /dev/null)" | sed -e "s/=20$//" | $GPGENCRYPT $LISTADMIN $FROMADD | $MAIL -r $LISTNAME $LISTADMIN $FROMADD
+
+# else, probably either the message was not signed or the sender is not subscribed to the list
+# email the message back to sender including a note about this
+# todo: parse STDERR to find out why the signature couldn't be checked and send more specific errors back to sender
+else
+
+ echo "
+ Message from: $FROM
+ Subject: [RETURNED MAIL] $SUBJECT
+ $DATE
+
+ [ It was not possible to process this message. Either or both
+ the message was not encrypted and/or signed, or you are not
+ subscribed to this list. Contact the list administrator if
+ you have any questions. ]
+
+ --
+ firma v0.2.1" | $MAIL -r $LISTNAME $FROMADD
+
+fi
+
+rm -f $TMP $TMP.gpg
diff --git a/misc/poc/firma-0.2.2 b/misc/poc/firma-0.2.2
new file mode 100755
index 0000000..f1a8f27
--- /dev/null
+++ b/misc/poc/firma-0.2.2
@@ -0,0 +1,153 @@
+#!/bin/bash
+#
+# firma v0.2.2: simple encrypted mailing list aliases
+# feedback: rhatto@riseup.net luis@riseup.net | GPL
+#
+# list configuration is passed thru the config file,
+# where you put PARAMETER=value (whithout spaces)
+#
+# MAIL= path for mail program
+# GPG= path for gnupg binary
+# TMP= where you want the temp files
+# LISTNAME= list email
+# LISTADMIN= list administrator email addresses (space separated)
+# GPGDIR= gpg dir for the lists' keyring
+# PASSWD= passwd for the lists' keyring
+
+# if the configuration file exists, disable "sourcepath" and evaluate the parameters
+if [ -f $1 ]; then
+ shopt -u sourcepath && source $1
+else
+ echo -e "\nConfiguration file \"$1\" could not be found.\n"
+ exit
+fi
+
+# declare GPG variables
+GPGCOMMAND="$GPG --quiet --homedir $GPGDIR --batch --no-tty --no-use-agent --no-permission-warning"
+GPGLIST="$GPGCOMMAND --list-keys --with-colons"
+GPGDECRYPT="$GPGCOMMAND --passphrase-fd 0 --decrypt"
+GPGENCRYPT="$GPGCOMMAND --passphrase-fd 0 --always-trust --encrypt --sign --armor --recipient"
+
+# check configuration file parameters
+# todo: check if $TMP directory/files exist
+if [ ! -f $GPG -o ! -x $GPG ]; then
+ echo -e "\n$1: GPG binary ($GPG) could not be found.\n"
+ exit
+elif [ ! -f $MAIL -o ! -x $MAIL ]; then
+ echo -e "\n$1: Mail program ($MAIL) could not be found.\n"
+ exit
+elif [ ! -d $GPGDIR -o ! -f $GPGDIR/pubring.gpg -o ! -f $GPGDIR/secring.gpg ]; then
+ echo -e "\n$1: GPG home directory ($GPGDIR) or the GPG keyrings could not be found.\n"
+ exit
+elif [ -z "$(cat $1 | grep -o ^PASSWD=\'[^\']*\'$)" -o \
+ -z "$(echo -n $PASSWD)" -o \
+ "$(echo -n $PASSWD | wc -m)" -lt "25" -o \
+ -z "$(echo -n $PASSWD | grep -o [[:lower:][:upper:]])" -o \
+ -z "$(echo -n $PASSWD | grep -o [[:digit:]])" -o \
+ "$(echo -n $PASSWD | grep -o [[:punct:]] | wc -l)" -lt "5" ]; then
+ echo -e "\n$1: PASSWD is empty or does not meet the minimum complexity requirements."
+ echo "$1: Please set a new passphrase for the list's private key. Make it at least"
+ echo "$1: 25 characters long (using a combination of letters, numbers and at least"
+ echo "$1: 5 special characters) and enclose it in 'single quotes'. The passphrase"
+ echo -e "$1: itself, though, cannot contain any single quote.\n"
+ exit
+elif [ -z "$($GPGLIST | grep ^pub | cut -d : -f 10 | grep -i \<$LISTNAME\>$)" ]; then
+ echo -e "\n$1: GPG key for list \"$LISTNAME\" could not be found."
+ echo -e "$1: Note that this parameter expects an email address.\n"
+ exit
+else
+ for ADMIN in $LISTADMIN; do {
+ if [ -z "$($GPGLIST | grep ^pub | cut -d : -f 10 | grep -i \<$ADMIN\>$)" ]; then
+ echo -e "\n$1: GPG key for list administrator \"$ADMIN\" could not be found."
+ echo -e "$1: Note that this parameter expects one or more space separated email addresses.\n"
+ exit
+ fi; }
+ done
+fi
+
+# declare functions
+# discard $GPGDECRYPT STDOUT and get its STDERR instead, for signature checking
+function GPGSTDERR {
+ echo $PASSWD | ($GPGDECRYPT --status-fd 2 $TMP.gpg 1> /dev/null) 2>&1 ;
+}
+
+# get list susbscriber addresses
+function SUBSCRIBERS {
+ $GPGLIST | sed -ne "/$LISTNAME/Id" -e '/pub/p' | cut -d : -f 10 | grep -o '<[^<>]*>$' | sed -e 's/[<>]//g' ;
+}
+
+# create the temporary files and restrict their permissions
+rm -f $TMP $TMP.gpg
+touch $TMP && chmod 600 $TMP
+touch $TMP.gpg && chmod 600 $TMP.gpg
+
+# todo: use an array
+while read STDIN; do
+ echo $STDIN >> $TMP
+done
+
+# get the message headers and the sender's email address
+FROM=$(grep -m 1 ^From: $TMP | cut -d : -f 2- | sed -e 's/^ //')
+FROMADD=$(if [ -z "$(echo $FROM | grep '>$')" ] ; then echo $FROM ; else echo $FROM | grep -o '<[^<>]*>$' | sed -e 's/[<>]//g' ; fi)
+DATE=$(grep -m 1 ^Date: $TMP)
+SUBJECT=$(grep -m 1 ^Subject: $TMP | cut -d : -f 2- | sed -e 's/^ //')
+
+# get the encrypted message
+sed -ne '/-----BEGIN PGP MESSAGE-----/,/-----END PGP MESSAGE-----/p' $TMP >> $TMP.gpg
+
+# if signature is Good, encrypt and send it for each list subscriber
+# todo: declare a function to decrypt, re-encrypt and send the list messages
+if (GPGSTDERR | grep -Fq GOODSIG) ; then
+
+ for EMAIL in $(SUBSCRIBERS); do
+
+ echo "$PASSWD
+ Message from: $FROM
+ Subject: $SUBJECT
+ $DATE
+
+ $(GPGSTDERR | grep -F 'gpg: Signature made')
+ $(GPGSTDERR | grep -F 'gpg: Good signature from')
+
+$(echo $PASSWD | $GPGDECRYPT $TMP.gpg 2> /dev/null)" | sed -e 's/=20$//' | $GPGENCRYPT $EMAIL | $MAIL -r $LISTNAME $EMAIL
+
+ done
+
+# else, if signature is BAD, email it back to the list admins and to sender
+elif (GPGSTDERR | grep -Fq BADSIG) ; then
+
+ for EMAIL in $(echo $LISTADMIN $FROMADD); do
+
+ echo "$PASSWD
+ Message from: $FROM
+ Subject: [BAD SIGNATURE] $SUBJECT
+ $DATE
+
+ $(GPGSTDERR | grep -F 'gpg: Signature made')
+ $(GPGSTDERR | grep -F 'gpg: BAD signature from')
+
+$(echo $PASSWD | $GPGDECRYPT $TMP.gpg 2> /dev/null)" | sed -e 's/=20$//' | $GPGENCRYPT $EMAIL | $MAIL -r $LISTNAME $EMAIL
+
+ done
+
+# else, probably either the message was not signed or the sender is not subscribed to the list
+# email the message back to sender including a note about this
+# todo: parse STDERR to find out why the signature couldn't be checked and send more specific errors back to sender
+else
+
+ echo "
+ Message from: $FROM
+ Subject: [RETURNED MAIL] $SUBJECT
+ $DATE
+
+ [ It was not possible to process this message. Either or both
+ the message was not encrypted and/or signed, or you are not
+ subscribed to this list. Contact the list administrator if
+ you have any questions. ]
+
+ --
+ firma v0.2.2" | $MAIL -r $LISTNAME $FROMADD
+
+fi
+
+rm -f $TMP $TMP.gpg
diff --git a/misc/poc/firma-0.2.3 b/misc/poc/firma-0.2.3
new file mode 100755
index 0000000..2864115
--- /dev/null
+++ b/misc/poc/firma-0.2.3
@@ -0,0 +1,192 @@
+#!/bin/bash
+#
+# firma v0.2.3: encrypted mailing list manager
+# feedback: rhatto@riseup.net luis@riseup.net | GPL
+#
+# list configuration is passed thru the config file,
+# where you put PARAMETER=value (whithout spaces)
+#
+# MAIL= path for mail program
+# GPG= path for gnupg binary
+# TMP= where you want the temp files
+# LISTNAME= list email
+# LISTADMIN= list administrator email addresses (space separated)
+# GPGDIR= gpg dir for the lists' keyring
+# PASSWD= passwd for the lists' keyring
+#
+
+VERSION=0.2.3
+
+function usage {
+ echo usage: $0 firma \<option\> \<config-file\>
+ echo -c: create a new list using config-file
+ echo -p: process a message
+ echo -a: admin commands
+}
+
+function check_config {
+ # check configuration file parameters
+ # todo: check if $TMP directory/files exist
+ if [ ! -f $GPG -o ! -x $GPG ]; then
+ echo -e "\n$1: GPG binary ($GPG) could not be found.\n"
+ exit 1
+ elif [ ! -f $MAIL -o ! -x $MAIL ]; then
+ echo -e "\n$1: Mail program ($MAIL) could not be found.\n"
+ exit 1
+ elif [ ! -d $GPGDIR -o ! -f $GPGDIR/pubring.gpg -o ! -f $GPGDIR/secring.gpg ]; then
+ echo -e "\n$1: GPG home directory ($GPGDIR) or the GPG keyrings could not be found.\n"
+ exit 1
+ elif [ -z "$(cat $CONFIG | grep -o ^PASSWD=\'[^\']*\'$)" -o \
+ -z "$(echo -n $PASSWD)" -o \
+ "$(echo -n $PASSWD | wc -m)" -lt "25" -o \
+ -z "$(echo -n $PASSWD | grep -o [[:lower:][:upper:]])" -o \
+ -z "$(echo -n $PASSWD | grep -o [[:digit:]])" -o \
+ "$(echo -n $PASSWD | grep -o [[:punct:]] | wc -l)" -lt "5" ]; then
+ echo -e "\n$CONFIG: PASSWD is empty or does not meet the minimum complexity requirements."
+ echo "$1: Please set a new passphrase for the list's private key. Make it at least"
+ echo "$1: 25 characters long (using a combination of letters, numbers and at least"
+ echo "$1: 5 special characters) and enclose it in 'single quotes'. The passphrase"
+ echo -e "$CONFIG: itself, though, cannot contain any single quote.\n"
+ exit 1
+ elif [ -z "$($GPGLIST | grep ^pub | cut -d : -f 10 | grep -i \<$LISTNAME\>$)" ]; then
+ echo -e "\n$CONFIG: GPG key for list \"$LISTNAME\" could not be found."
+ echo -e "$CONFIG: Note that this parameter expects an email address.\n"
+ exit 1
+ else
+ for ADMIN in $LISTADMIN; do {
+ if [ -z "$($GPGLIST | grep ^pub | cut -d : -f 10 | grep -i \<$ADMIN\>$)" ]; then
+ echo -e "\n$CONFIG: GPG key for list administrator \"$ADMIN\" could not be found."
+ echo -e "$CONFIG: Note that this parameter expects one or more space separated email addresses.\n"
+ exit 1
+ fi; }
+ done
+ fi
+}
+
+function GPGSTDERR {
+ # discard $GPGDECRYPT STDOUT and get its STDERR instead, for signature checking
+ echo $PASSWD | ($GPGDECRYPT --status-fd 2 $TMP.gpg 1> /dev/null) 2>&1 ;
+}
+
+function SUBSCRIBERS {
+ # get list susbscriber's addresses
+ $GPGLIST | sed -ne "/$LISTNAME/Id" -e '/pub/p' | cut -d : -f 10 | grep -o '<[^<>]*>$' | sed -e 's/[<>]//g' ;
+}
+
+function process_message {
+ # process a message sent to the list
+
+ # create the temporary files and restrict their permissions
+ rm -f $TMP $TMP.gpg
+ touch $TMP && chmod 600 $TMP
+ touch $TMP.gpg && chmod 600 $TMP.gpg
+
+ # todo: use an array
+ while read STDIN; do
+ echo $STDIN >> $TMP
+ done
+
+ # get the message headers and the sender's email address
+ FROM=$(grep -m 1 ^From: $TMP | cut -d : -f 2- | sed -e 's/^ //')
+ FROMADD=$(if [ -z "$(echo $FROM | grep '>$')" ] ; then echo $FROM ; else echo $FROM | grep -o '<[^<>]*>$' | sed -e 's/[<>]//g' ; fi)
+ DATE=$(grep -m 1 ^Date: $TMP)
+ SUBJECT=$(grep -m 1 ^Subject: $TMP | cut -d : -f 2- | sed -e 's/^ //')
+
+ # get the encrypted message
+ sed -ne '/-----BEGIN PGP MESSAGE-----/,/-----END PGP MESSAGE-----/p' $TMP >> $TMP.gpg
+
+ # if signature is Good, encrypt and send it for each list subscriber
+ # todo: declare a function to decrypt, re-encrypt and send the list messages
+ if (GPGSTDERR | grep -Fq GOODSIG) ; then
+
+ for EMAIL in $(SUBSCRIBERS); do
+
+ echo "$PASSWD
+ Message from: $FROM
+ Subject: $SUBJECT
+ $DATE
+
+ $(GPGSTDERR | grep -F 'gpg: Signature made')
+ $(GPGSTDERR | grep -F 'gpg: Good signature from')
+
+ $(echo $PASSWD | $GPGDECRYPT $TMP.gpg 2> /dev/null)" | sed -e 's/=20$//' | $GPGENCRYPT $EMAIL | $MAIL -r $LISTNAME $EMAIL
+
+ done
+
+ # else, if signature is BAD, email it back to the list admins and to sender
+ elif (GPGSTDERR | grep -Fq BADSIG) ; then
+
+ for EMAIL in $(echo $LISTADMIN $FROMADD); do
+
+ echo "$PASSWD
+ Message from: $FROM
+ Subject: [BAD SIGNATURE] $SUBJECT
+ $DATE
+
+ $(GPGSTDERR | grep -F 'gpg: Signature made')
+ $(GPGSTDERR | grep -F 'gpg: BAD signature from')
+
+ $(echo $PASSWD | $GPGDECRYPT $TMP.gpg 2> /dev/null)" | sed -e 's/=20$//' | $GPGENCRYPT $EMAIL | $MAIL -r $LISTNAME $EMAIL
+
+ done
+
+ # else, probably either the message was not signed or the sender is not subscribed to the list
+ # email the message back to sender including a note about this
+ # todo: parse STDERR to find out why the signature couldn't be checked and send more specific errors back to sender
+ else
+
+ echo "
+ Message from: $FROM
+ Subject: [RETURNED MAIL] $SUBJECT
+ $DATE
+
+ [ It was not possible to process this message. Either or both
+ the message was not encrypted and/or signed, or you are not
+ subscribed to this list. Contact the list administrator if
+ you have any questions. ]
+
+ --
+ firma v$VERSION" | $MAIL -r $LISTNAME $FROMADD
+
+ fi
+
+ rm -f $TMP $TMP.gpg
+
+}
+
+# main -
+# command line checking
+if [ -z $2 ]; then
+ usage; exit 1
+else
+ CONFIG=$2
+fi
+
+# if the configuration file exists, disable "sourcepath" and evaluate the parameters
+if [ -f $CONFIG ] && [[ $1 != "-c" ]]; then
+ shopt -u sourcepath && source $CONFIG
+else
+ echo -e "\nConfiguration file \"$CONFIG\" could not be found.\n"
+ exit 1
+fi
+
+# declare GPG variables
+GPGCOMMAND="$GPG --quiet --homedir $GPGDIR --batch --no-tty --no-use-agent --no-permission-warning"
+GPGLIST="$GPGCOMMAND --list-keys --with-colons"
+GPGDECRYPT="$GPGCOMMAND --passphrase-fd 0 --decrypt"
+GPGENCRYPT="$GPGCOMMAND --passphrase-fd 0 --always-trust --encrypt --sign --armor --recipient"
+
+# then check the config
+check_config
+
+# command line parsing
+if [[ $1 == "-c" ]]; then
+ newlist
+elif [[ $1 == "-p" ]]; then
+ process_message
+elif [[ $1 == "-a" ]]; then
+ admin_task
+else
+ usage; exit 1
+fi
+
diff --git a/misc/poc/firma-0.2.4 b/misc/poc/firma-0.2.4
new file mode 100755
index 0000000..6418782
--- /dev/null
+++ b/misc/poc/firma-0.2.4
@@ -0,0 +1,211 @@
+#!/bin/bash
+#
+# firma v0.2.4: encrypted mailing list manager
+# feedback: rhatto@riseup.net luis@riseup.net | GPL
+#
+# list configuration is passed thru the config file,
+# where you put PARAMETER=value (whithout spaces)
+#
+# MAIL= path for mail program
+# GPG= path for gnupg binary
+# LISTNAME= list email
+# LISTADMIN= list administrator email addresses (space separated)
+# GPGDIR= gpg dir for the lists' keyring
+# PASSWD= passwd for the lists' keyring
+#
+
+VERSION=0.2.4
+
+function usage {
+ echo usage: $0 firma \<option\> \<config-file\>
+ echo -c: create a new list using config-file
+ echo -p: process a message
+ echo -a: admin commands
+}
+
+function check_config {
+ # check configuration file parameters
+ if [ ! -f $GPG -o ! -x $GPG ]; then
+ echo -e "\n$1: GPG binary ($GPG) could not be found.\n"
+ exit 1
+ elif [ ! -f $MAIL -o ! -x $MAIL ]; then
+ echo -e "\n$1: Mail program ($MAIL) could not be found.\n"
+ exit 1
+ elif [ ! -d $GPGDIR -o ! -f $GPGDIR/pubring.gpg -o ! -f $GPGDIR/secring.gpg ]; then
+ echo -e "\n$1: GPG home directory ($GPGDIR) or the GPG keyrings could not be found.\n"
+ exit 1
+ elif [ -z "$(cat $CONFIG | grep -o ^PASSWD=\'[^\']*\'$)" -o \
+ -z "$(echo -n $PASSWD)" -o \
+ "$(echo -n $PASSWD | wc -m)" -lt "25" -o \
+ -z "$(echo -n $PASSWD | grep -o [[:lower:][:upper:]])" -o \
+ -z "$(echo -n $PASSWD | grep -o [[:digit:]])" -o \
+ "$(echo -n $PASSWD | grep -o [[:punct:]] | wc -l)" -lt "5" ]; then
+ echo -e "\n$CONFIG: PASSWD is empty or does not meet the minimum complexity requirements."
+ echo "$1: Please set a new passphrase for the list's private key. Make it at least"
+ echo "$1: 25 characters long (using a combination of letters, numbers and at least"
+ echo "$1: 5 special characters) and enclose it in 'single quotes'. The passphrase"
+ echo -e "$CONFIG: itself, though, cannot contain any single quote.\n"
+ exit 1
+ elif [ -z "$($GPGLIST | grep ^pub | cut -d : -f 10 | grep -i \<$LISTNAME\>$)" ]; then
+ echo -e "\n$CONFIG: GPG key for list \"$LISTNAME\" could not be found."
+ echo -e "$CONFIG: Note that this parameter expects an email address.\n"
+ exit 1
+ else
+ for ADMIN in $LISTADMIN; do {
+ if [ -z "$($GPGLIST | grep ^pub | cut -d : -f 10 | grep -i \<$ADMIN\>$)" ]; then
+ echo -e "\n$CONFIG: GPG key for list administrator \"$ADMIN\" could not be found."
+ echo -e "$CONFIG: Note that this parameter expects one or more space separated email addresses.\n"
+ exit 1
+ fi; }
+ done
+ fi
+}
+
+function GPGSTDERR {
+ # discard $GPGDECRYPT STDOUT and get its STDERR instead, for signature checking
+ echo -e "$PASSWD\n${GPG_MESSAGE[@]}" | sed -e 's/^ //' | ($GPGDECRYPT --status-fd 2 1> /dev/null) 2>&1 ;
+}
+
+function SUBSCRIBERS {
+ # get list susbscriber's addresses
+ $GPGLIST | sed -ne "/$LISTNAME/Id" -e '/pub/p' | cut -d : -f 10 | grep -o '<[^<>]*>$' | sed -e 's/[<>]//g' ;
+}
+
+function get_message {
+ n=0;
+ while read STDIN; do
+ MESSAGE[$n]="$STDIN\n"
+ ((++n))
+ done
+}
+
+function get_gpg_message {
+ signal=0; x=0;
+ for ((count=0;count<=n;count++)); do
+ if [[ $signal == "0" ]] && [[ "$(echo "${MESSAGE[$count]}" | grep -v -e "-----BEGIN PGP MESSAGE-----")" == "" ]]; then
+ GPG_MESSAGE[$x]=${MESSAGE[$count]}; ((++x))
+ signal=1
+ elif [[ $signal == "1" ]]; then
+ GPG_MESSAGE[$x]=${MESSAGE[$count]}
+ ((++x))
+ if [[ "$(echo "${MESSAGE[$count]}" | grep -v -e "-----END PGP MESSAGE-----")" == "" ]]; then
+ signal=0
+ fi
+ fi
+ done
+}
+
+function get_headers {
+ # get the message headers and the sender's email address
+ FROM=$(echo -e "${MESSAGE[@]}" | grep -m 1 "From:" | cut -d : -f 2- | sed -e 's/^ //')
+ FROMADD=$(if [ -z "$(echo $FROM | grep '>$')" ] ; then echo $FROM ; else echo $FROM | grep -o '<[^<>]*>$' | sed -e 's/[<>]//
+g' ; fi)
+ DATE=$(echo -e "${MESSAGE[@]}" | grep -m 1 "Date:")
+ SUBJECT=$(echo -e "${MESSAGE[@]}" | grep -m 1 "Subject:" | cut -d : -f 2- | sed -e 's/^ //')
+}
+
+function process_message {
+ # process a message sent to the list
+
+ get_message
+ get_headers
+ get_gpg_message
+
+ # if signature is Good, encrypt and send it for each list subscriber
+ # todo: declare a function to decrypt, re-encrypt and send the list messages
+ if (GPGSTDERR | grep -Fq GOODSIG) ; then
+
+ for EMAIL in $(SUBSCRIBERS); do
+
+ echo "$PASSWD
+ Message from: $FROM
+ Subject: $SUBJECT
+ $DATE
+
+ $(GPGSTDERR | grep -F 'gpg: Signature made')
+ $(GPGSTDERR | grep -F 'gpg: Good signature from')
+
+ $(echo -e "$PASSWD\n${GPG_MESSAGE[@]}" | $GPGDECRYPT 2> /dev/null)" | sed -e 's/=20$//' | $GPGENCRYPT $EMAIL | $MAIL -r $LISTNAME $EMAIL
+
+ done
+
+ # else, if signature is BAD, email it back to the list admins and to sender
+ elif (GPGSTDERR | grep -Fq BADSIG) ; then
+
+ for EMAIL in $(echo $LISTADMIN $FROMADD); do
+
+ echo "$PASSWD
+ Message from: $FROM
+ Subject: [BAD SIGNATURE] $SUBJECT
+ $DATE
+
+ $(GPGSTDERR | grep -F 'gpg: Signature made')
+ $(GPGSTDERR | grep -F 'gpg: BAD signature from')
+
+ $(echo -e "$PASSWD\n${GPG_MESSAGE[@]}" | $GPGDECRYPT 2> /dev/null)" | sed -e 's/=20$//' | $GPGENCRYPT $EMAIL | $MAIL -r $LISTNAME $EMAIL
+
+ done
+
+ # else, probably either the message was not signed or the sender is not subscribed to the list
+ # email the message back to sender including a note about this
+ # todo: parse STDERR to find out why the signature couldn't be checked and send more specific errors back to sender
+ else
+
+ echo "
+ Message from: $FROM
+ Subject: [RETURNED MAIL] $SUBJECT
+ $DATE
+
+ [ It was not possible to process this message. Either or both
+ the message was not encrypted and/or signed, or you are not
+ subscribed to this list. Contact the list administrator if
+ you have any questions. ]
+
+ --
+ firma v$VERSION" | $MAIL -r $LISTNAME $FROMADD
+
+ fi
+
+}
+
+# main -
+# command line checking
+if [ -z $2 ]; then
+ usage; exit 1
+else
+ CONFIG=$2
+fi
+
+# if the configuration file exists, disable "sourcepath" and evaluate the parameters
+if [ -f $CONFIG ] && [[ $1 != "-c" ]]; then
+ shopt -u sourcepath && source $CONFIG
+else
+ echo -e "\nConfiguration file \"$CONFIG\" could not be found.\n"
+ exit 1
+fi
+
+declare -a MESSAGE
+declare -a GPG_MESSAGE
+declare n
+export LANG=en_US
+
+# declare GPG variables
+GPGCOMMAND="$GPG --quiet --homedir $GPGDIR --batch --no-tty --no-use-agent --no-permission-warning"
+GPGLIST="$GPGCOMMAND --list-keys --with-colons"
+GPGDECRYPT="$GPGCOMMAND --passphrase-fd 0 --decrypt"
+GPGENCRYPT="$GPGCOMMAND --passphrase-fd 0 --always-trust --encrypt --sign --armor --recipient"
+
+# then check the config
+check_config
+
+# command line parsing
+if [[ $1 == "-c" ]]; then
+ newlist
+elif [[ $1 == "-p" ]]; then
+ process_message
+elif [[ $1 == "-a" ]]; then
+ admin_task
+else
+ usage; exit 1
+fi
+
diff --git a/misc/poc/firma-0.2.x b/misc/poc/firma-0.2.x
new file mode 100755
index 0000000..126f998
--- /dev/null
+++ b/misc/poc/firma-0.2.x
@@ -0,0 +1,280 @@
+#!/bin/bash
+#
+# firma v0.3: encrypted mailing list manager
+# feedback: rhatto@riseup.net luis@riseup.net | GPL
+#
+# list configuration is passed thru the config file,
+# where you put PARAMETER=value (whithout spaces)
+#
+# MAIL= path for mail program
+# GPG= path for gnupg binary
+# LISTNAME= list email
+# LISTADMIN= list administrator email addresses (space separated)
+# GPGDIR= gpg dir for the lists' keyring
+# PASSWD= passwd for the lists' keyring
+#
+
+FIRMA_LIST_PATH=/usr/local/etc/lists
+VERSION=0.3
+
+# todo:
+# errase all vars before quit the game
+# unset MESSAGE
+# unset GPG_MESSAGE
+# umask ....
+
+function usage {
+ echo usage: $0 firma \<option\> \<config-file\>
+ echo -c: create a new list using config-file
+ echo -p: process a message
+ echo -r: admin and user requests (mail only)
+ echo -a: admin commands
+}
+
+function check_config {
+ # check configuration file parameters
+ if [ ! -f $GPG -o ! -x $GPG ]; then
+ echo -e "\n$1: GPG binary ($GPG) could not be found.\n"
+ exit 1
+ elif [ ! -f $MAIL -o ! -x $MAIL ]; then
+ echo -e "\n$1: Mail program ($MAIL) could not be found.\n"
+ exit 1
+ elif [ ! -d $GPGDIR -o ! -f $GPGDIR/pubring.gpg -o ! -f $GPGDIR/secring.gpg ]; then
+ echo -e "\n$1: GPG home directory ($GPGDIR) or the GPG keyrings could not be found.\n"
+ exit 1
+ elif [ -z "$(cat $CONFIG | grep -o ^PASSWD=\'[^\']*\'$)" -o \
+ -z "$(echo -n $PASSWD)" -o \
+ "$(echo -n $PASSWD | wc -m)" -lt "25" -o \
+ -z "$(echo -n $PASSWD | grep -o [[:lower:][:upper:]])" -o \
+ -z "$(echo -n $PASSWD | grep -o [[:digit:]])" -o \
+ "$(echo -n $PASSWD | grep -o [[:punct:]] | wc -l)" -lt "5" ]; then
+ echo -e "\n$CONFIG: PASSWD is empty or does not meet the minimum complexity requirements."
+ echo "$1: Please set a new passphrase for the list's private key. Make it at least"
+ echo "$1: 25 characters long (using a combination of letters, numbers and at least"
+ echo "$1: 5 special characters) and enclose it in 'single quotes'. The passphrase"
+ echo -e "$CONFIG: itself, though, cannot contain any single quote.\n"
+ exit 1
+ elif [ -z "$($GPGLIST | grep ^pub | cut -d : -f 10 | grep -i \<$LISTNAME\>$)" ]; then
+ echo -e "\n$CONFIG: GPG key for list \"$LISTNAME\" could not be found."
+ echo -e "$CONFIG: Note that this parameter expects an email address.\n"
+ exit 1
+ else
+ for ADMIN in $LISTADMIN; do {
+ if [ -z "$($GPGLIST | grep ^pub | cut -d : -f 10 | grep -i \<$ADMIN\>$)" ]; then
+ echo -e "\n$CONFIG: GPG key for list administrator \"$ADMIN\" could not be found."
+ echo -e "$CONFIG: Note that this parameter expects one or more space separated email addresses.\n"
+ exit 1
+ fi; }
+ done
+ fi
+}
+
+function GPGSTDERR {
+ # discard $GPGDECRYPT STDOUT and get its STDERR instead, for signature checking
+ echo -e "$PASSWD\n${GPG_MESSAGE[@]}" | sed -e 's/^ //' | ($GPGDECRYPT --status-fd 2 1> /dev/null) 2>&1 ;
+}
+
+function SUBSCRIBERS {
+ # get list susbscriber's addresses
+ $GPGLIST | sed -ne "/$LISTNAME/Id" -e '/pub/p' | cut -d : -f 10 | grep -o '<[^<>]*>$' | sed -e 's/[<>]//g' ;
+}
+
+function get_message {
+ n=0;
+ while read STDIN; do
+ MESSAGE[$n]="$STDIN\n"
+ ((++n))
+ done
+}
+
+function get_gpg_message {
+ signal=0; x=0;
+ for ((count=0;count<=n;count++)); do
+ if [[ $signal == "0" ]] && [[ "$(echo "${MESSAGE[$count]}" | grep -v -e "-----BEGIN PGP MESSAGE-----")" == "" ]]; then
+ GPG_MESSAGE[$x]=${MESSAGE[$count]}; ((++x))
+ signal=1
+ elif [[ $signal == "1" ]]; then
+ GPG_MESSAGE[$x]=${MESSAGE[$count]}
+ ((++x))
+ if [[ "$(echo "${MESSAGE[$count]}" | grep -v -e "-----END PGP MESSAGE-----")" == "" ]]; then
+ signal=0
+ fi
+ fi
+ done
+}
+
+function get_headers {
+ # get the message headers and the sender's email address
+ FROM=$(echo -e "${MESSAGE[@]}" | grep -m 1 "From:" | cut -d : -f 2- | sed -e 's/^ //')
+ FROMADD=$(if [ -z "$(echo $FROM | grep '>$')" ] ; then echo $FROM ; else echo $FROM | grep -o '<[^<>]*>$' | sed -e 's/[<>]//
+g' ; fi)
+ DATE=$(echo -e "${MESSAGE[@]}" | grep -m 1 "Date:")
+ SUBJECT=$(echo -e "${MESSAGE[@]}" | grep -m 1 "Subject:" | cut -d : -f 2- | sed -e 's/^ //')
+}
+
+function message_list {
+# compose and send a message to the list
+# $1: subscriber email
+# sorry no identation :P
+echo "$PASSWD
+Message from: $FROM
+Subject: $SUBJECT
+$DATE
+
+$(GPGSTDERR | grep -F 'gpg: Signature made')
+$(GPGSTDERR | grep -F 'gpg: Good signature from')
+
+$(echo -e "$PASSWD\n${GPG_MESSAGE[@]}" | $GPGDECRYPT 2> /dev/null)" | sed -e 's/=20$//' | $GPGENCRYPT $1 | $MAIL -r $LISTNAME $1
+}
+
+function message_list_error {
+# compose and send an error message
+# sorry no identation :P
+echo "$PASSWD
+Message from: $FROM
+Subject: [BAD SIGNATURE] $SUBJECT
+$DATE
+
+$(GPGSTDERR | grep -F 'gpg: Signature made')
+$(GPGSTDERR | grep -F 'gpg: BAD signature from')
+
+$(echo -e "$PASSWD\n${GPG_MESSAGE[@]}" | $GPGDECRYPT 2> /dev/null)" | sed -e 's/=20$//' | $GPGENCRYPT $1 | $MAIL -r $LISTNAME $1
+}
+
+function message_list_return {
+# send a bouce message
+# $1: sender email (usually $FROMADD)
+# sorry no identation :P
+echo "
+Message from: $FROM
+Subject: [RETURNED MAIL] $SUBJECT
+$DATE
+
+ [ It was not possible to process this message. Either or both
+ the message was not encrypted and/or signed, or you are not
+ subscribed to this list. Contact the list administrator if
+ you have any questions. ]
+
+ --
+ firma v$VERSION" | $MAIL -r $LISTNAME $1
+}
+
+function process_message {
+ # process a message sent to the list
+
+ get_message
+ get_headers
+ get_gpg_message
+
+ # if signature is Good, encrypt and send it for each list subscriber
+ # todo: declare a function to decrypt, re-encrypt and send the list messages
+ if (GPGSTDERR | grep -Fq GOODSIG); then
+
+ for EMAIL in $(SUBSCRIBERS); do
+ message_list $EMAIL
+ done
+
+ # else, if signature is BAD, email it back to the list admins and to sender
+ elif (GPGSTDERR | grep -Fq BADSIG) ; then
+
+ for EMAIL in $(echo $LISTADMIN $FROMADD); do
+ message_list_error $EMAIL
+ done
+
+ # else, probably either the message was not signed or the sender is not subscribed to the list
+ # email the message back to sender including a note about this
+ # todo: parse STDERR to find out why the signature couldn't be checked and send more specific errors back to sender
+ else
+ message_list_return $FROMADD
+ fi
+
+}
+
+function newlist {
+ # create a list if it doesnt already exist
+ if [ ! -d "$CONFIG_PATH" ]; then
+ echo creating folder $CONFIG_PATH...
+ mkdir "$CONFIG_PATH" # || (echo "error creating $CONFIG_PATH: installation aborted"; exit 1)
+ echo "creating list config file and will ask some questions."
+
+ GPGDIR="$CONFIG_PATH"
+
+ read -p "path to nail command (eg, /usr/bin/nail): " MAIL
+ read -p "path to gpg binary (eg, /usr/bin/gpg): " GPG
+
+ # if [ ! -x $GPG ]; then
+
+ read -p "list keyring folder (defaults to $GPGDIR): " GPGDIR
+
+ # todo: please no utf-8 (see DETAILS)
+ read -p "list email (eg, firma@domain.tld): " LISTNAME
+ read -p "list admins emails (space delimited)" LISTADMIN
+ read -p "password for list keyring (use a huge one): " PASSWD
+
+ # todo: key specs (size, expiry date...)
+
+ echo "creating your config..."
+ touch $CONFIG
+ chown root.root $CONFIG
+ chmod 600 $CONFIG
+ if [ -f $CONFIG ]; then
+ echo -e "MAIL=$MAIL\nGPG=$GPG\nGPGDIR=$GPGDIR\nLISTNAME=$LISTNAME\nLISTADMIN=$LISTADMIN\nPASSWD=$PASSWD" > $CONFIG
+ echo "now generating your keyring..."
+ # re-eval GPGCOMMAND
+ # todo: GPGFLAGS depende de GPGDIR
+ GPGCOMMAND="$GPG $GPGFLAGS"
+ $GPGCOMMAND --gen-key
+
+ fi
+ else
+ echo error creating $CONFIG_FILE: list already exists
+ exit 1
+ fi
+}
+
+# main -
+# command line checking
+if [ -z $2 ]; then
+ usage; exit 1
+else
+ CONFIG_FILE="$2"
+ CONFIG_PATH="$FIRMA_LIST_PATH/$2"
+ CONFIG="$CONFIG_PATH/$2.conf"
+fi
+
+# if the configuration file exists, disable "sourcepath" and evaluate the parameters
+if [ -f $CONFIG ] && [[ $1 != "-c" ]]; then
+ shopt -u sourcepath && source $CONFIG
+else
+ echo -e "\nConfiguration file \"$CONFIG\" could not be found.\n"
+ exit 1
+fi
+
+declare -a MESSAGE
+declare -a GPG_MESSAGE
+declare n
+export LANG=en_US
+
+# declare GPG variables
+GPGFLAGS="--quiet --homedir $GPGDIR --batch --no-tty --no-use-agent --no-permission-warning"
+GPGCOMMAND="$GPG $GPGFLAGS"
+GPGLIST="$GPGCOMMAND --list-keys --with-colons"
+GPGDECRYPT="$GPGCOMMAND --passphrase-fd 0 --decrypt"
+GPGENCRYPT="$GPGCOMMAND --passphrase-fd 0 --always-trust --encrypt --sign --armor --recipient"
+
+# then check the config
+check_config
+
+# command line parsing
+if [[ $1 == "-c" ]]; then
+ newlist
+elif [[ $1 == "-p" ]]; then
+ process_message
+elif [[ $1 == "-a" ]]; then
+ list_admin
+elif [[ $1 == "-r" ]]; then
+ list_request
+else
+ usage; exit 1
+fi
+
diff --git a/misc/python/README b/misc/python/README
new file mode 100644
index 0000000..4f75401
--- /dev/null
+++ b/misc/python/README
@@ -0,0 +1,2 @@
+Initial and broken code. Needs GnuPGInterface available at
+http://py-gnupg.sourceforge.net.
diff --git a/misc/python/firma.py b/misc/python/firma.py
new file mode 100755
index 0000000..19f9c9d
--- /dev/null
+++ b/misc/python/firma.py
@@ -0,0 +1,85 @@
+#!/usr/bin/python
+""" Firma - Encrypted Mailing List Manager - Python Version
+
+firma: GnuPG-based encrypted mailing list manager
+Feedback: firma@sarava.org
+
+ Firma 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 2 of the License, or (at your option) any later
+ version.
+
+ Firma 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, write to the Free Software Foundation, Inc., 59 Temple
+ Place - Suite 330, Boston, MA 02111-1307, USA
+
+Lets use: http://docs.python.org/lib/module-email.html
+ http://docs.python.org/lib/module-smtplib.html
+ http://py-gnupg.sourceforge.net/
+
+Lets split the work:
+
+ - create list
+ - create folder, set permissions
+ - create config file
+ - create keyring, set permissions again
+ - admin list
+ - parse config file
+ - from command line
+ - parse comand line args
+ - exec admin tasks
+ - display output
+ - from email
+ - decrypt message
+ - parse command line args
+ - exec admin tasks
+ - record output
+ - encrypt and send back output
+ - process message
+ - parse config file
+ - read stdin and store as original message
+ - decrypt message
+ - if encrypted and signed, encrypt again and send to all subscribers
+
+"""
+
+import GnuPGInterface
+
+# first we'll create just a routine that sets up a new gpg keyring
+
+class NewKey(GnuPGInterface.GnuPG):
+ """ Class used to create a new gpg keyring """
+ def __init__(self):
+ GnuPGInterface.GnuPG.__init__(self)
+ self.options.armor = 0
+ self.options.extra_args.append("--gen-key")
+ self.options.meta_interactive = 0
+
+ def __setitem__(self, key, value):
+ if key == "homedir" and value:
+ # TODO: check if --homedir already is on self.options.extra_args
+ # TODO: check if the folder referenced by "value" exists
+ self.options.extra_args.append("--homedir %s" % value)
+ # TODO: else raises an exception?
+
+class DelKey(GnuPGInterface.GnuPG):
+ """ Class used to delete a key from a keyring """
+ def __init__(self):
+ GnuPGInterface.GnuPG.__init__(self)
+
+class RevokeKey(GnuPGInterface.GnuPG):
+ """ Class used to revoke a key """
+ def __init__(self):
+ GnuPGInterface.GnuPG.__init__(self)
+
+# lets start the code
+
+passwd = "senha"
+newkey = NewKey()
+newkey = ["homedir"] = "firma-python/keyring-teste"
+
+print newkey.options.extra_args