commit 63ed8f2480c7e42f04a1a9edd4d6a2287074c9ad
parent b89665a20ce042d69e3834750e5b654eef7cbc90
Author: Jaromil <jaromil@dyne.org>
Date: Sun, 22 Mar 2015 23:38:01 +0100
remember fingerprint of known smtp servers
Diffstat:
4 files changed, 70 insertions(+), 25 deletions(-)
diff --git a/src/jaro b/src/jaro
@@ -63,6 +63,7 @@ fi
WORKDIR=${JAROWORKDIR:-$WORKDIR}
# load our zuper extension
+zkv=1
source $WORKDIR/zlibs/zuper
@@ -130,6 +131,9 @@ vars+=(name login imap imap_port smtp smtp_port protocol password auth accountop
typeset -ah folders exclude
vars+=(host port type)
+# global for server fingerprints
+vars+=(fingerprint)
+
# global variables for addressbook
vars+=(hostname addressbook addressbook_tmp)
@@ -826,5 +830,5 @@ main() {
check_bin
main $@
-endgame NOERRORS
-#return $exitcode
+# endgame NOERRORS
+# return $exitcode
diff --git a/src/zlibs/email b/src/zlibs/email
@@ -263,6 +263,10 @@ fetch() {
################################################
# read an email from stdin and send it via msmtp
smtp_send() {
+ fn smtp-send
+ req=(account)
+ ckreq
+
read_account ${account}
{ test $? != 0 } && {
error "Invalid account: $account"
@@ -279,6 +283,42 @@ smtp_send() {
host=$smtp
port=$smtp_port
+ # load known fingerprints
+ typeset -A smtp_fingerprints
+ [[ -s $MAILDIRS/smtp_fingerprints.zkv ]] && {
+ zkv.load $MAILDIRS/smtp_fingerprints.zkv }
+ known_fingerprint=${smtp_fingerprints[$smtp:$port]}
+ # get the server's fingerprint
+ print QUIT \
+ | openssl s_client -starttls smtp \
+ -connect $smtp:$smtp_port \
+ -showcerts 2>/dev/null \
+ | openssl x509 -fingerprint -md5 -noout \
+ | awk -F '=' '/Fingerprint/ {print $2}' | sysread fingerprint
+ fingerprint=$(print $fingerprint | trim)
+ # force printing fingerprint to stderr
+ oldquiet=$QUIET
+ QUIET=0
+ act "known fingerprint: $known_fingerprint"
+ act "server fingerprint: $fingerprint"
+ [[ "$known_fingerprint" = "$fingerprint" ]] || {
+ warning "fingerprint difference detected"
+ # not the same?
+ if [[ "$known_fingerprint" = "" ]]; then
+ # never knew before, save it
+ act "$smtp:$port new fingerprint acknowledged"
+ smtp_fingerprints[$smtp:$port]="$fingerprint"
+ else
+ error "Server fingerprint mismatch!"
+ warning "The known one was different, this may be a man in the middle!"
+ warning "To override and forget the old one, edit $MAILDIRS/smtp_fingerprints.zkv"
+ return 1
+ fi
+ }
+ QUIET=$oldquiet
+
+ zkv.save smtp_fingerprints $MAILDIRS/smtp_fingerprints.zkv
+
ask_password
[[ $? = 0 ]] || {
error "Error retrieving password for $login on $smtp"
diff --git a/src/zlibs/helpers b/src/zlibs/helpers
@@ -353,7 +353,7 @@ human_size() {
# TODO: save fingeprints of servers and check connections
-fingerprint() {
+get-smtp-fingerprint() {
# dyne.org one:
# tls_fingerprint 6A:D4:DF:E4:20:32:F9:66:94:35:0C:33:9D:74:96:5C
@@ -370,7 +370,7 @@ fingerprint() {
-connect $smtp:$smtp_port \
-showcerts 2>/dev/null \
| openssl x509 -fingerprint -md5 -noout \
- | awk -F '=' '/^MD5 Fingerprint/ {print $2}'
+ | awk -F '=' '/Fingerprint/ {print $2}' | sysread fingerprint
}
diff --git a/src/zlibs/zuper b/src/zlibs/zuper
@@ -24,11 +24,15 @@
##########################
typeset -aU vars
typeset -aU arrs
-vars=(debug quiet ztmpfile)
-arrs=()
+vars=(DEBUG QUIET ztmpfile)
+arrs=(req freq)
-debug=${debug:-0}
-quiet=${quiet:-0}
+# reset list of destructors
+destruens=()
+
+# global execution flags
+DEBUG=${DEBUG:-0}
+QUIET=${QUIET:-0}
vars+=(zuper_version)
zuper_version=0.1
@@ -93,48 +97,39 @@ function _msg() {
function _message say act() {
local notice="message"
[[ "$1" = "-n" ]] && shift && notice="inline"
- [[ $quiet = 1 ]] || _msg "$notice" $@
+ [[ $QUIET = 1 ]] || _msg "$notice" $@
return 0
}
function _verbose xxx func() {
- [[ $debug = 1 ]] && _msg verbose $@
+ [[ $DEBUG = 1 ]] && _msg verbose $@
return 0
}
function _success yes notice() {
- [[ $quiet = 1 ]] || _msg success $@
+ [[ $QUIET = 1 ]] || _msg success $@
return 0
}
function _warning no warn warning() {
- [[ $quiet = 1 ]] || _msg warning $@
+ [[ $QUIET = 1 ]] || _msg warning $@
return 0
}
function _failure fatal die error() {
# typeset -i exitcode=${exitv:-1}
- [[ $quiet = 1 ]] || _msg failure $@
+ [[ $QUIET = 1 ]] || _msg failure $@
return 1
}
function _print() {
- [[ $quiet = 1 ]] || _msg print $@
+ [[ $QUIET = 1 ]] || _msg print $@
return 0
}
-
fn() {
- local msg="$1"
- command -v gettext 1>/dev/null 2>/dev/null \
- && msg="$(gettext -s "$1")"
- for i in $(seq 2 ${#}); do
- msg=${(S)msg//::$(($i - 1))*::/$*[$i]}
- done
-
- fun="$msg"
- func "$fun"
+ fun="$@"
req=()
freq=()
}
@@ -181,7 +176,10 @@ zdump() {
done
}
-
+# handy wrappers for throw/catch execution of blocks where we need the
+# program to exit on any error (non-zero) returned by any function
+throw() { function TRAPZERR() { zerr; return 1 } }
+catch() { function TRAPZERR() { } }
##########################
# Endgame handling
@@ -215,6 +213,9 @@ endgame() {
return 0
}
+# Register endgame() to be called at exit.
+# unlike TRAPEXIT, the zshexit() hook is not called when functions exit.
+zshexit() { endgame EXIT; return $? }
##########################
# Temp file handling