]> gitweb.fluxo.info Git - firma.git/commitdiff
modificacoes feitas pelo luis, como uma funcao para escolha de uids
authorrhatto <rhatto>
Fri, 5 Aug 2005 16:02:15 +0000 (16:02 +0000)
committerrhatto <rhatto>
Fri, 5 Aug 2005 16:02:15 +0000 (16:02 +0000)
firma

diff --git a/firma b/firma
index 433d6c126a5d1f08fca1277d01ad6675a522578a..5588c47b4db1f6144e7c7919a612af7c70d5a8fd 100755 (executable)
--- a/firma
+++ b/firma
@@ -1,6 +1,6 @@
 #!/bin/bash
 #
-# firma v0.3: encrypted mailing list manager
+# firma: encrypted mailing list manager
 # feedback: rhatto@riseup.net luis@riseup.net | GPL
 #
 # list configuration is passed thru the config file,
@@ -15,7 +15,7 @@
 #
 
 FIRMA_LIST_PATH="/usr/local/etc/lists"
-VERSION="0.3-cvs"
+VERSION="0.3"
 
 # todo:
 # errase all vars before quit the game
@@ -24,23 +24,35 @@ VERSION="0.3-cvs"
 # umask ....
 
 function usage {
-  echo "usage: `basename $0` <option> <list-name>"
-  echo "-c: create a new list"
-  echo "-p: process a message"
-  echo "-r: admin and user requests (mail only)"
-  echo "-a: admin commands"
+  echo "usage: $(basename $0) OPTION [LIST-NAME]"
+  echo "  -a: admin commands"
+  echo "  -c: create a new list"
+  echo "  -h: display this help and exit"
+  echo "  -p: process a message"
+  echo "  -r: admin and user requests (mail only)"
+  echo "  -v: output version information and exit"
 }
 
+function version {
+  echo "firma $VERSION"
+  echo "Copyright (C) 2005 A Firma, Inc."
+  echo "This program comes with ABSOLUTELY NO WARRANTY."
+  echo "This is free software, and you are welcome to redistribute it"
+  echo "under certain conditions. See the GNU General Public License"
+  echo "for more details."
+}
+
+
 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"
+    echo "$CONFIG_FILE: GPG binary ($GPG) could not be found."
     exit 1
   elif [ ! -f $MAIL -o ! -x $MAIL ]; then
-    echo -e "\n$1: Mail program ($MAIL) could not be found.\n"
+    echo "$CONFIG_FILE: Mail program ($MAIL) could not be found."
     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"
+    echo "$CONFIG_FILE: GPG home directory ($GPGDIR) or the GPG keyrings could not be found."
       exit 1
   elif [ -z "$(cat $CONFIG | grep -o ^PASSWD=\'[^\']*\'$)" -o \
          -z "$(echo -n $PASSWD)" -o \
@@ -48,39 +60,39 @@ function check_config {
          -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"
+    echo "$CONFIG_FILE: PASSWD is empty or does not meet the minimum complexity requirements."
+    echo "$CONFIG_FILE: Please set a new passphrase for the list's private key. Make it at least"
+    echo "$CONFIG_FILE: 25 characters long (using a combination of letters, numbers and at least"
+    echo "$CONFIG_FILE: 5 special characters) and enclose it in 'single quotes'. The passphrase"
+    echo "$CONFIG_FILE: itself, though, cannot contain any single quote."
     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"
+    echo "$CONFIG_FILE: GPG key for list \"$LISTNAME\" could not be found."
+    echo "$CONFIG_FILE: Note that this parameter expects an email address."
     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"
+        echo "$CONFIG_FILE: GPG key for list administrator \"$ADMIN\" could not be found."
+        echo "$CONFIG_FILE: Note that this parameter expects one or more space separated email addresses."
         exit 1
       fi; }
     done
   fi
 }
 
-function GPGSTDERR {
+function get_gpg_stderr {
   # 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 ;
+  echo -e "$PASSWD\n${GPG_MESSAGE[@]}" | sed -e 's/^ //' | ($GPGDECRYPT --status-fd 2 1> /dev/null) 2>&1
 }
 
-function SUBSCRIBERS {
+function get_subscribers_list {
   # get list susbscriber's addresses
-  $GPGLIST | sed -ne "/$LISTNAME/Id" -e '/pub/p' | cut -d : -f 10 | grep -o '<[^<>]*>$' | sed -e 's/[<>]//g' ;
+  $GPGLIST | sed -ne "/$LISTNAME/Id" -e '/pub/p' | cut -d : -f 10 | grep -o '<[^<>]*>$' | sed -e 's/[<>]//g'
 }
 
 function get_message {
-  n=0;
+  n=0
   while read STDIN; do
     MESSAGE[$n]="$STDIN\n"
     ((++n))
@@ -88,10 +100,12 @@ function get_message {
 }
 
 function get_gpg_message {
-  signal=0; x=0;
+  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))
+      GPG_MESSAGE[$x]=${MESSAGE[$count]}
+      ((++x))
       signal=1
     elif [[ $signal == "1" ]]; then
       GPG_MESSAGE[$x]=${MESSAGE[$count]}
@@ -103,11 +117,17 @@ function get_gpg_message {
   done
 }
 
-function get_headers {
+function get_message_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:")
+  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:" | sed -e 's/^ //')
   SUBJECT=$(echo -e "${MESSAGE[@]}" | grep -m 1 "Subject:" | cut -d : -f 2- | sed -e 's/^ //')
 }
 
@@ -120,8 +140,8 @@ Message from: $FROM
 Subject: $SUBJECT
 $DATE
   
-$(GPGSTDERR | grep -F 'gpg: Signature made')
-$(GPGSTDERR | grep -F 'gpg: Good signature from')
+$(get_gpg_stderr | grep -F 'gpg: Signature made')
+$(get_gpg_stderr | 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
 }
@@ -134,8 +154,8 @@ Message from: $FROM
 Subject: [BAD SIGNATURE] $SUBJECT
 $DATE
   
-$(GPGSTDERR | grep -F 'gpg: Signature made')
-$(GPGSTDERR | grep -F 'gpg: BAD signature from')
+$(get_gpg_stderr | grep -F 'gpg: Signature made')
+$(get_gpg_stderr | 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
 }
@@ -162,19 +182,19 @@ function process_message {
   # process a message sent to the list
 
   get_message
-  get_headers 
+  get_message_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
+  if (get_gpg_stderr | grep -Fq GOODSIG); then
   
-    for EMAIL in $(SUBSCRIBERS); do 
+    for EMAIL in $(get_subscribers_list); 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
+  elif (get_gpg_stderr | grep -Fq BADSIG) ; then
   
     for EMAIL in $(echo $LISTADMIN $FROMADD); do
       message_list_error $EMAIL
@@ -252,10 +272,77 @@ function gpg_args {
   GPGENCRYPT="$GPGCOMMAND --passphrase-fd 0 --always-trust --encrypt --sign --armor --recipient"
 }
 
+function list_admin {
+  if [ "$1" = "use" ]; then
+    if [ "$#" -lt "2" ]; then
+      echo "$(basename $0): Too few arguments. Command \"use\" expects an email address as argument."
+      return 1
+    elif [ "$#" -gt "2" ]; then
+      echo "$(basename $0): Too many arguments. Command \"use\" expects just one email address as argument."
+      return 1
+    elif [ -z "$(echo -ne $2 | grep -o '[^@]\+@[^@]\+')" ]; then
+      echo "$(basename $0): Invalid argument. Command \"use\" expects an email address as argument."
+      return 1
+    else
+      choose_uid $2
+    fi
+  else
+    echo "$(basename $0): \"$1\": command not found"
+  fi
+}
+
+function choose_uid {
+
+  KEYID="$($GPGLIST --fixed-list-mode $1 2> /dev/null | grep ^pub | cut -d : -f 5 | grep -o '.\{8\}$')"
+
+  if [ -z "$($GPGLIST --fingerprint --fixed-list-mode $1 2> /dev/null | grep -i \<$1\>:$ | cut -d : -f 10)" ]; then
+    echo "$CONFIG_FILE: \"$(echo -ne $1 | tr A-Z a-z)\" is not associated with any public key on this keyring."
+    return 1
+  elif [ "$($GPGLIST --fixed-list-mode $1 2> /dev/null | grep ^uid | wc -l)" -eq "1" ]; then
+    echo "$CONFIG_FILE: \"$(echo -ne $1 | tr A-Z a-z)\" is part of the only UID on public key \"$KEYID\"."
+    return 1
+  elif [ "$($GPGLIST --fixed-list-mode $1 2> /dev/null | grep -iF $1 | cut -d : -f 10 | wc -l)" -gt "1" ]; then
+    echo "$CONFIG_FILE: \"$(echo -ne $1 | tr A-Z a-z)\" is listed in more than one UID on this keyring. Narrow down your selection"
+    echo "$CONFIG_FILE: or delete all but one of the public keys associated with this email address."
+    return 1
+  fi
+
+  expect -nN -- << EOF
+    log_user 0
+    set timeout 5
+
+    set keyid [eval exec $GPG --fingerprint --with-colons --fixed-list-mode $1 | grep ^fpr | cut -d : -f 10]
+    set uid_count [eval exec $GPG --list-keys --with-colons --fixed-list-mode \$keyid | grep ^uid | wc -l]
+    set chosen_uid [eval exec $GPG --list-keys --with-colons --fixed-list-mode \$keyid | grep ^uid | grep -ni $1 | cut -d : -f 1]
+
+    eval spawn -noecho $GPG --with-colons --command-fd 0 --status-fd 1 --edit-key \$keyid
+    expect "GET_LINE keyedit.prompt" {
+      set uid 1
+      while { \$uid <= \$uid_count } {
+        if { \$uid != \$chosen_uid } {
+          send "uid \$uid\n"
+          expect "GET_LINE keyedit.prompt"
+        }
+        set uid [incr uid]
+      }
+      send "deluid\n"
+      expect "GET_BOOL keyedit.remove.uid.okay" {send "yes\n"}
+      expect "GET_LINE keyedit.prompt" {send "save\n"}
+      expect "GOT_IT"
+    }
+
+    wait
+    send_user "$CONFIG_FILE: \"$(echo -ne $1 | tr A-Z a-z)\" chosen successfully. [ expr \$uid_count - 1 ] UIDs deleted from public key \"$KEYID\".\n"
+    interact
+
+EOF
+}
+
 # main -
 # command line checking
-if [ -z $2 ]; then
-  usage; exit 1
+if [ -z "$2" -a "$1" != "-c" -a "$1" != "-h" -a "$1" != "-v" ]; then
+  usage
+  exit 1
 else
   CONFIG_FILE="$2"
   CONFIG_PATH="$FIRMA_LIST_PATH/$2"
@@ -263,11 +350,13 @@ else
 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
+if [ "$1" != "-c" -a "$1" != "-h" -a "$1" != "-v" ]; then
+  if [ -f $CONFIG ]; then
+    shopt -u sourcepath && source $CONFIG
+  else
+    echo "$(basename $0): Configuration file \"$CONFIG\" could not be found."
+    exit 1
+  fi
 fi
 
 declare -a MESSAGE
@@ -276,18 +365,40 @@ declare n
 export LANG=en_US
 
 # get gpg parameters and check the config
-gpg_args ; check_config
+if [ "$1" = "-a" -o "$1" = "-p" -o "$1" = "-r" ]; then
+  gpg_args
+  check_config
+fi
 
 # command line parsing
-if [[ $1 == "-c" ]]; then
-  newlist 
-elif [[ $1 == "-p" ]]; then
+if [ "$1" = "-a" ]; then
+
+  declare -a ADMINCOMMANDS
+
+  n=0
+  while read STDIN; do
+    ADMINCOMMANDS[$n]="$STDIN\n"
+    ((n++))
+  done
+
+  for i in $(seq 0 $((${#ADMINCOMMANDS[@]} - 1))); do
+    if [ ! -z "$(echo -ne ${ADMINCOMMANDS[$i]})" -a "$(echo -ne ${ADMINCOMMANDS[$i]} | cut -c1)" != "#" ]; then
+      list_admin $(echo -ne "${ADMINCOMMANDS[$i]}")
+    fi
+  done
+
+elif [ "$1" = "-c" ]; then
+  newlist
+elif [ "$1" = "-h" ]; then
+  usage
+elif [ "$1" = "-p" ]; then
   process_message
-elif [[ $1 == "-a" ]]; then
-  list_admin
-elif [[ $1 == "-r" ]]; then
+elif [ "$1" = "-r" ]; then
   list_request
+elif [ "$1" = "-v" ]; then
+  version
 else
-  usage; exit 1
+  usage
+  exit 1
 fi