commit 07089619b2d0e2a6a86df600c88e71a38a4e9fdd
parent 3acb6ce9fbc3d99d1bd14e8d6a9da44cc1bb6cd2
Author: Jaromil <jaromil@dyne.org>
Date: Sun, 3 Jun 2012 18:06:32 +0200
password handling using gnome-keyring on GNU systems
Diffstat:
4 files changed, 151 insertions(+), 31 deletions(-)
diff --git a/build-gnu.sh b/build-gnu.sh
@@ -27,12 +27,12 @@ case $distro in
gcc -Os -static -o fetchaddr fetchaddr.o helpers.o rfc2047.o rfc822.o;
cd - > /dev/null
echo
- # echo "gnome-keyring"
- # cd src/gnome-keyring
- # [ -x jaro-gnome-keyring ] || \
- # gcc `pkg-config --cflags --libs glib-2.0 gnome-keyring-1` \
- # -O2 -o jaro-gnome-keyring jaro-gnome-keyring.c
- # cd - > /dev/null
+ echo "gnome-keyring"
+ cd src/gnome-keyring
+# [ -x jaro-gnome-keyring ] || \
+ gcc `pkg-config --cflags --libs glib-2.0 gnome-keyring-1` \
+ -O2 -o jaro-gnome-keyring jaro-gnome-keyring.c
+ cd - > /dev/null
echo "Done compiling."
echo "Now run ./install.sh and Jaro Mail will be ready in ~/Mail"
echo "or \"./install.sh path\" to install it somewhere else."
diff --git a/install.sh b/install.sh
@@ -244,6 +244,7 @@ for mod in ${lbdb_modules}; do
done
cp src/lbdb/dotlock $WORKDIR/.lbdb/
cp src/lbdb/fetchaddr $WORKDIR/.lbdb/
+cp src/gnome-keyring/jaro-gnome-keyring $WORKDIR/bin/
chmod +x $WORKDIR/.lbdb/*
ln -sf $WORKDIR/.lbdb/lbdb-fetchaddr $WORKDIR/bin/
ln -sf $WORKDIR/.lbdb/lbdbq $WORKDIR/bin/
diff --git a/src/gnome-keyring/jaro-gnome-keyring.c b/src/gnome-keyring/jaro-gnome-keyring.c
@@ -1,3 +1,26 @@
+/* Jaro Mail gnome keyring handler
+
+ Originally from some Gnome example code, slightly modified
+
+ Copyright (C) 2012 Denis Roio <jaromil@dyne.org>
+
+ * This source code is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Public License as published
+ * by the Free Software Foundation; either version 3 of the License,
+ * or (at your option) any later version.
+ *
+ * This source code 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.
+ * Please refer to the GNU Public License for more details.
+ *
+ * You should have received a copy of the GNU Public License along with
+ * this source code; if not, write to:
+ * Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
@@ -36,7 +59,7 @@ error(const char *err, ...)
va_end(params);
}
-static void
+static int
get_password(git_credential_t *cred)
{
GnomeKeyringResult keyres;
@@ -50,13 +73,34 @@ get_password(git_credential_t *cred)
"username", cred->username,
NULL);
if (keyres != GNOME_KEYRING_RESULT_OK) {
- return;
+ return 1;
}
- g_printf("password=%s\n", pass);
+ g_printf("%s\n", pass);
gnome_keyring_free_password(pass);
+ return 0;
}
-static void
+static int
+check_password(git_credential_t *cred)
+{
+ GnomeKeyringResult keyres;
+ gchar *pass = NULL;
+
+ keyres = gnome_keyring_find_password_sync(&git_schema,
+ &pass,
+ "protocol", cred->protocol,
+ "host", cred->host,
+ "path", cred->path,
+ "username", cred->username,
+ NULL);
+ if (keyres != GNOME_KEYRING_RESULT_OK) {
+ return 1;
+ }
+ gnome_keyring_free_password(pass);
+ return 0;
+}
+
+static int
store_password(git_credential_t *cred)
{
gchar desc[1024];
@@ -65,7 +109,7 @@ store_password(git_credential_t *cred)
/* Only store complete credentials */
if (!cred->protocol || !cred->host ||
!cred->username || !cred->password)
- return;
+ return 1;
g_snprintf(desc, sizeof(desc), "Git %s", cred->host);
keyres = gnome_keyring_store_password_sync(&git_schema,
@@ -79,11 +123,12 @@ store_password(git_credential_t *cred)
NULL);
if (keyres != GNOME_KEYRING_RESULT_OK) {
error("failed to store password");
- return;
+ return 1;
}
+ return 0;
}
-static void
+static int
erase_password(git_credential_t *cred)
{
GnomeKeyringResult keyres;
@@ -96,8 +141,9 @@ erase_password(git_credential_t *cred)
NULL);
if (keyres != GNOME_KEYRING_RESULT_OK) {
error("failed to delete password");
- return;
+ return 1;
}
+ return 0;
}
static int
@@ -147,6 +193,7 @@ int
main(int argc, const char **argv)
{
git_credential_t cred = {0};
+ int res = 0;
if (argc < 2) {
error("Usage: git credential-gnomekeyring <get|store|erase>");
@@ -159,15 +206,18 @@ main(int argc, const char **argv)
}
if (strcmp(argv[1], "get") == 0) {
- get_password(&cred);
+ res = get_password(&cred);
+ }
+ if (strcmp(argv[1], "check") == 0) {
+ res = check_password(&cred);
}
else if (strcmp(argv[1], "store") == 0) {
- store_password(&cred);
+ res = store_password(&cred);
}
else if (strcmp(argv[1], "erase") == 0) {
- erase_password(&cred);
+ res = erase_password(&cred);
}
clear_credential(&cred);
- return 0;
+ return res;
}
diff --git a/src/jaro b/src/jaro
@@ -222,9 +222,10 @@ ask_password() {
func "Looking for password in keyring: $1 @ $2"
security find-internet-password -a $1 -s $2 > /dev/null
if [ $? != 0 ]; then # its a new password
- password=`pin_entry $1 @ $2`
- act "New password set for $1 @ $2"
- security add-internet-password -a $1 -s $2 -w "${password}"
+ new_password
+ { test $? = 0 } && {
+ error "Password input aborted."
+ return 1 }
else
act "Using saved password for $1 @ $2"
password=`security find-internet-password -a $1 -s $2 -g \
@@ -232,20 +233,70 @@ ask_password() {
fi
return 0
;;
+ #####################################
GNU)
+ func "Looking for password in keyring: $1 @ $2"
+ echo "protocol=${type}\npath=jaromail/${email}\nusername=${login}\nhost=${host}\n\n" | $WORKDIR/bin/jaro-gnome-keyring check
+ if [ $? != 0 ]; then # its a new password
+ new_password
+ { test $? = 0 } && {
+ error "Password input aborted."
+ return 1 }
+ else # password found into gnome keyring
+ act "Using saved password for $1 @ $2"
+ password=`echo "protocol=${type}\npath=jaromail/${email}\nusername=${login}\nhost=${host}\n\n" | $WORKDIR/bin/jaro-gnome-keyring get`
+ fi
+ return 0
+ ;;
+ *)
+ error "Unknown system, can't figure out how to handle passwords"
+ return 1
+ esac
+}
+
+new_password() {
+ case $OS in
+ MAC)
+ password=`pin_entry $1 $2`
+ act "New password set for $1 @ $2"
+ security add-internet-password -a $1 -s $2 -w "${password}"
+ # TODO: erase and error codes
+ ;;
+ GNU)
+ notice "Setting a new password for $login @ $host"
password=`pin_entry $login $host`
if [ "$password" != "" ]; then
+ cat <<EOF | $WORKDIR/bin/jaro-gnome-keyring store
+protocol=${type}
+path=jaromail/${email}
+username=${login}
+host=${host}
+password=${password}
+EOF
+ { test $? != 0 } && {
+ unset password
+ error "Error saving password in Gnome keyring"
+ return 1 }
return 0
else
- return 1
- fi
+ cat <<EOF | $WORKDIR/bin/jaro-gnome-keyring erase
+protocol=${type}
+path=jaromail/${email}
+username=${login}
+host=${host}
+EOF
+ { test $? != 0 } && {
+ error "Error accessing password in Gnome keyring"
+ return 1 }
+ act "No new password given, old password erased."
+ return 0
+ fi
;;
*)
error "Unknown system, can't figure out how to handle passwords"
return 1
esac
}
-
switch_identity() {
if [ "$name" != "" ]; then
act "switch to identity: $name <$login>"
@@ -304,8 +355,9 @@ maildirmake() {
read_account() {
typeset -al all
- if [ -z $1 ]; then type="*"
-
+ if [ -z $1 ]; then
+ type=`echo $account | cut -d. -f1`
+ account=`echo $account | cut -d. -f2`
else type=$1 # smtp, imap, pop ... file prefixes"
fi
@@ -313,12 +365,14 @@ read_account() {
for a in `find $WORKDIR/Accounts -name "$type.$account*"`; do all+=($a); done
if [ ${#all} = 0 ]; then
error "No $type account found: $account"
+ error "Refine your argument using 'type.account'"
+ error "For instance: imap.default or smtp.default"
return 1
elif [ ${#all} != 1 ]; then
error "Too many $type accounts named $account"
act -n ""
for i in ${=all}; do echo -n "`basename ${i}` "; done
- echo; error "Refine your account keyword"
+ echo; error "Refine your account keyword using -a option"
return 1
fi
@@ -557,11 +611,10 @@ fetch() {
notice "Fetching mails for $name"
ask_password $login $host
- if [ $? != 0 ]; then
+ { test $? != 0 } && {
error "Error retrieving password for $login on $host"
- unset password all
- return 1
- fi
+ unset password all; return 1
+ }
newlock $WORKDIR/tmp/$host.fetch
cat <<EOF > $WORKDIR/tmp/$host.fetch
@@ -663,6 +716,10 @@ send() {
ask_password $login $host
+ { test $? != 0 } && {
+ error "Error retrieving password for $login on $host"
+ unset password all; return 1
+ }
newlock $WORKDIR/tmp/$host.send
cat <<EOF > $WORKDIR/tmp/$host.send
@@ -733,6 +790,12 @@ peek() {
sleep 2
# escape at sign in login
ilogin=`echo $login | sed 's/@/\\@/'`
+ ask_password $login $host
+ { test $? != 0 } && {
+ error "Error retrieving password for $login on $host"
+ unset password all; return 1
+ }
+
mutt -F $MUTTDIR/rc -f ${iproto}://${ilogin}@${host}${folder}
# TODO automatic input of password in mutt
return $?
@@ -1142,6 +1205,8 @@ Options:
Maintenance commands:
+ passwd reset password for the account in use
+
update refresh configurations
queue add a mail into outbox
@@ -1190,6 +1255,7 @@ main()
subcommands_opts[merge]=""
subcommands_opts[filter]=""
+ subcommands_opts[passwd]=""
subcommands_opts[cert]=""
subcommands_opts[source]=""
@@ -1290,6 +1356,9 @@ main()
merge) merge ${PARAM} ;;
filter) filter ${PARAM} ;;
+ passwd) read_account;
+ { test $? = 0 } && { new_password ${PARAM} }
+ ;;
cert) cert ${PARAM} ;;
'source') CLEANEXIT=0; return 0 ;;