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:
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}'`