jaromail

a commandline tool to easily and privately handle your e-mail
git clone git://parazyd.org/jaromail.git
Log | Files | Refs | Submodules | README

commit 6881b3d99d95e9549575491d0d6d3dcd1711b289
parent 7b066ed12bd1d2a02cb0054e1387cb41217b01af
Author: Jaromil <jaromil@dyne.org>
Date:   Wed, 10 Apr 2013 12:55:32 +0200

new local keyring to save passwords

Diffstat:
Msrc/zlibs/accounts | 65++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------
Msrc/zlibs/email | 51+++++++++++++++++++++++++--------------------------
2 files changed, 83 insertions(+), 33 deletions(-)

diff --git a/src/zlibs/accounts b/src/zlibs/accounts @@ -51,6 +51,8 @@ list_accounts() { # arg 1 : account type, es: imap or smtp # -a defines which account name other than 'default' +# results in the definition of global account variables: +# name login host protocol port auth folders accountopt read_account() { typeset -al all unset name email host login transport \ @@ -190,7 +192,7 @@ ask_password() { func "Looking for password in keyring: $name" ################### # USE GNOME KEYRING - { test $GNOMEKEY = 1 } && { + if [ "$GNOMEKEY" = "1" ]; then print "protocol=${type}\npath=jaromail/${email}\nusername=${login}\nhost=${host}\n\n" \ | $WORKDIR/bin/jaro-gnome-keyring check if [ $? != 0 ]; then # its a new password @@ -203,7 +205,15 @@ ask_password() { password=`print "protocol=${type}\npath=jaromail/${email}\nusername=${login}\nhost=${host}\n\n" | $WORKDIR/bin/jaro-gnome-keyring get` fi return 0 - } + elif [ -r $WORKDIR/keyring ]; then + _hash=`print "$transport:$email:$host" | shasum` + lookup="`lookup_secret ${_hash}`" + { test "$lookup" = "" } || { + act "Using saved password for $email ($transport on $host)" + password="$lookup" + return 0 + } + fi #################### # USE PINENTRY ALONE new_password @@ -218,6 +228,16 @@ ask_password() { esac } +lookup_secret() { + hash=$1 + if [ "$2" = "" ]; then key=password + else key="$2"; fi + cat <<EOF | ${SQL} -column -batch $WORKDIR/keyring +SELECT ${key} FROM secrets +WHERE hash IS "${hash}"; +EOF +} + new_password() { notice "Setting a new password for $name" password=`pin_entry $login $host` @@ -277,8 +297,8 @@ EOF else # password is blank or aborted - # USE GNOME KEYRING - { test $GNOMEKEY = 1 } && { + # save it into gnome keyring + if [ $GNOMEKEY = 1 ]; then cat <<EOF | $WORKDIR/bin/jaro-gnome-keyring erase protocol=${type} @@ -291,8 +311,40 @@ EOF return 1 } act "No new password given, old password erased." return 0 - } + + else # save it into local keyring + { test -r $WORKDIR/keyring } || { + # make sure the local keyring exists + touch $WORKDIR/keyring + chmod 600 $WORKDIR/keyring + chown $_uid:$_gid $WORKDIR/keyring + cat <<EOF | ${SQL} -batch $WORKDIR/keyring +CREATE TABLE secrets +( + hash text collate unique, + password text collate +); +EOF + } + # calculate the hash for this entry + hash=`print "$transport:$email:$host" | shasum` + # check if the entry is already present + lookup="`lookup_secret ${hash} rowid`" + if [ "$lookup" = "" ]; then # new entry + cat <<EOF | ${SQL} -batch $WORKDIR/keyring +INSERT INTO secrets (hash, password) +VALUES ("${hash}", "${password}"); +EOF + act "saved new password in local keyring" + else # update entry + cat <<EOF | ${SQL} -batch $WORKDIR/keyring +UPDATE secrets SET password="${password}" WHERE hash LIKE "${hash}"; +EOF + act "updated local keyring with new password" + fi + return 0 + fi return 1 fi @@ -310,4 +362,4 @@ change_password() { { test $? = 0 } && { test $DRYRUN != 1 } && { new_password } -}- \ No newline at end of file +} diff --git a/src/zlibs/email b/src/zlibs/email @@ -89,7 +89,10 @@ fetch() { { test "$account" = "" } && { fetchall; return $? } +# setup global account variables read_account ${account_type} ${account} +# name login host protocol port auth folders accountopt + { test $? != 0 } && { error "Error on account entry: $account_type $account" return 1 @@ -123,51 +126,48 @@ fetch() { { test $DRYRUN != 1 } && { - tmp=$TMPDIR/$host.fetch.$RANDOM - newlock $tmp - cat <<EOF > $tmp -poll $host with proto IMAP user "$login" there with password "$password" -EOF + fmconf=("poll $host with proto IMAP user \"$login\" there with password \"$password\"") + unset password if ! [ -z $accountopt ]; then # add option configuration - print "${accountopt}" >> $tmp; fi + fmconf+=(" ${accountopt} "); fi if ! [ -z $folders ]; then # add folder configuration - print "folder ${folders}" >> $tmp; fi + fmconf+=(" folder ${folders} "); fi + + fmconf+=(" ssl warnings 3600 and wants mda \"procmail -m $PROCMAILDIR/rc\" ") - cat <<EOF >> $tmp -ssl warnings 3600 and wants mda "procmail -m $PROCMAILDIR/rc" -EOF if [ "$cert" = "check" ]; then - cat <<EOF >> $tmp -sslcertck sslcertpath '$WORKDIR/certs' -EOF + fmconf+=(" sslcertck sslcertpath '$WORKDIR/certs' ") fi - cat <<EOF >> $tmp -antispam 571 550 501 554 -EOF + + + fmconf+=(" antispam 571 550 501 554 ") + # try login without doing anything - fetchmail -c -f $tmp + print "$fmconf" | fetchmail -c -f - + res=$? # examine result - case $? in + case $ret in 1) notice "No mails for $name" - unlink $tmp + unset $fmconf return 1 ;; 2) error "Invalid or unknown certificate for $host" - unlink $tmp + unset $fmconf return 1 ;; 3) error "Invalid password for user $login at $host" - unlink $tmp + unset $fmconf return 1 ;; - *) ;; + *) + func "fetchmail returns $ret" ;; esac # archive old procmail log @@ -185,11 +185,10 @@ EOF act "please wait while downloading mails..." - cat $tmp | fetchmail -f $tmp - # TODO: substitute this with cat conf | fetchmail -f - - # to avoid writing the password in clear on filesystem + print " $fmconf " | fetchmail -f - + + unset $fmconf - unlink $tmp unlink $addressbook_tmp total=`mailstat -k $WORKDIR/log/procmail.log | tail -n1 | awk '{print $2}'`