add option to get password from macOS Keychain
this is better than using PassCmd, as it allows the keychain manager to identify the calling process and therefore use a selective whitelist. unlike in the now removed example, we use an "internet password" for the imap protocol, rather than a "generic password" - this seems more appropriate. based on a patch by Oliver Runge <oliver.runge@gmail.com>
This commit is contained in:
parent
03b15dbdd3
commit
198ca65b6e
2
NEWS
2
NEWS
|
@ -13,6 +13,8 @@ IMAP mailbox subscriptions are supported now.
|
||||||
|
|
||||||
The IMAP user query can be scripted now.
|
The IMAP user query can be scripted now.
|
||||||
|
|
||||||
|
Added built-in support for macOS Keychain.
|
||||||
|
|
||||||
[1.3.0]
|
[1.3.0]
|
||||||
|
|
||||||
Network timeout handling has been added.
|
Network timeout handling has been added.
|
||||||
|
|
34
configure.ac
34
configure.ac
|
@ -1,7 +1,9 @@
|
||||||
AC_INIT([isync], [1.4.0])
|
AC_INIT([isync], [1.4.0])
|
||||||
AC_CONFIG_HEADERS([autodefs.h])
|
AC_CONFIG_HEADERS([autodefs.h])
|
||||||
AM_INIT_AUTOMAKE
|
|
||||||
|
|
||||||
|
AC_CANONICAL_TARGET
|
||||||
|
|
||||||
|
AM_INIT_AUTOMAKE
|
||||||
AM_MAINTAINER_MODE
|
AM_MAINTAINER_MODE
|
||||||
|
|
||||||
AC_PROG_CC_C99
|
AC_PROG_CC_C99
|
||||||
|
@ -198,6 +200,29 @@ fi
|
||||||
|
|
||||||
AM_CONDITIONAL(with_mdconvert, test "x$ac_cv_berkdb4" = xyes)
|
AM_CONDITIONAL(with_mdconvert, test "x$ac_cv_berkdb4" = xyes)
|
||||||
|
|
||||||
|
case $target_os in
|
||||||
|
darwin*)
|
||||||
|
darwin=yes
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
darwin=no
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
AC_ARG_WITH(
|
||||||
|
macos-keychain,
|
||||||
|
[AS_HELP_STRING([--with-macos-keychain], [Support macOS keychain])],
|
||||||
|
[have_macos_keychain=$withval],
|
||||||
|
[have_macos_keychain=$darwin])
|
||||||
|
if test "x$have_macos_keychain" != xno; then
|
||||||
|
if test $darwin = no; then
|
||||||
|
AC_MSG_ERROR([Cannot use macOS Keychain outside macOS.])
|
||||||
|
fi
|
||||||
|
have_macos_keychain=yes
|
||||||
|
AC_DEFINE(HAVE_MACOS_KEYCHAIN, 1, [Define to 1 if you have the macOS Keychain Services API.])
|
||||||
|
AC_SUBST(KEYCHAIN_LIBS, ["-Wl,-framework,Security"])
|
||||||
|
fi
|
||||||
|
|
||||||
AC_CONFIG_FILES([Makefile src/Makefile isync.spec])
|
AC_CONFIG_FILES([Makefile src/Makefile isync.spec])
|
||||||
AC_OUTPUT
|
AC_OUTPUT
|
||||||
|
|
||||||
|
@ -222,4 +247,11 @@ if test "x$ac_cv_berkdb4" = xyes; then
|
||||||
else
|
else
|
||||||
AC_MSG_RESULT([Not using Berkeley DB])
|
AC_MSG_RESULT([Not using Berkeley DB])
|
||||||
fi
|
fi
|
||||||
|
if test $darwin = yes; then
|
||||||
|
if test "x$have_macos_keychain" = xyes; then
|
||||||
|
AC_MSG_RESULT([Using macOS Keychain])
|
||||||
|
else
|
||||||
|
AC_MSG_RESULT([Not using macOS Keychain])
|
||||||
|
fi
|
||||||
|
fi
|
||||||
AC_MSG_RESULT()
|
AC_MSG_RESULT()
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
mbsync_SOURCES = main.c sync.c config.c util.c socket.c driver.c drv_imap.c drv_maildir.c drv_proxy.c
|
mbsync_SOURCES = main.c sync.c config.c util.c socket.c driver.c drv_imap.c drv_maildir.c drv_proxy.c
|
||||||
mbsync_LDADD = $(DB_LIBS) $(SSL_LIBS) $(SOCK_LIBS) $(SASL_LIBS) $(Z_LIBS)
|
mbsync_LDADD = $(DB_LIBS) $(SSL_LIBS) $(SOCK_LIBS) $(SASL_LIBS) $(Z_LIBS) $(KEYCHAIN_LIBS)
|
||||||
noinst_HEADERS = common.h config.h driver.h sync.h socket.h
|
noinst_HEADERS = common.h config.h driver.h sync.h socket.h
|
||||||
|
|
||||||
drv_proxy.$(OBJEXT): drv_proxy.inc
|
drv_proxy.$(OBJEXT): drv_proxy.inc
|
||||||
|
|
|
@ -41,6 +41,10 @@
|
||||||
# include <sasl/saslutil.h>
|
# include <sasl/saslutil.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_MACOS_KEYCHAIN
|
||||||
|
# include <Security/Security.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef HAVE_LIBSSL
|
#ifdef HAVE_LIBSSL
|
||||||
enum { SSL_None, SSL_STARTTLS, SSL_IMAPS };
|
enum { SSL_None, SSL_STARTTLS, SSL_IMAPS };
|
||||||
#endif
|
#endif
|
||||||
|
@ -58,6 +62,9 @@ typedef struct imap_server_conf {
|
||||||
string_list_t *auth_mechs;
|
string_list_t *auth_mechs;
|
||||||
#ifdef HAVE_LIBSSL
|
#ifdef HAVE_LIBSSL
|
||||||
char ssl_type;
|
char ssl_type;
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_MACOS_KEYCHAIN
|
||||||
|
char use_keychain;
|
||||||
#endif
|
#endif
|
||||||
char failed;
|
char failed;
|
||||||
} imap_server_conf_t;
|
} imap_server_conf_t;
|
||||||
|
@ -1991,6 +1998,31 @@ ensure_password( imap_server_conf_t *srvc )
|
||||||
if (!srvc->pass) {
|
if (!srvc->pass) {
|
||||||
if (srvc->pass_cmd) {
|
if (srvc->pass_cmd) {
|
||||||
srvc->pass = cred_from_cmd( "PassCmd", srvc->pass_cmd, srvc->name );
|
srvc->pass = cred_from_cmd( "PassCmd", srvc->pass_cmd, srvc->name );
|
||||||
|
#ifdef HAVE_MACOS_KEYCHAIN
|
||||||
|
} else if (srvc->use_keychain) {
|
||||||
|
void *password_data;
|
||||||
|
UInt32 password_length;
|
||||||
|
OSStatus ret = SecKeychainFindInternetPassword(
|
||||||
|
NULL, // keychainOrArray
|
||||||
|
strlen( srvc->sconf.host ), srvc->sconf.host,
|
||||||
|
0, NULL, // securityDomain
|
||||||
|
strlen( srvc->user ), srvc->user,
|
||||||
|
0, NULL, // path
|
||||||
|
0, // port - we could use it, but it seems pointless
|
||||||
|
kSecProtocolTypeIMAP,
|
||||||
|
kSecAuthenticationTypeDefault,
|
||||||
|
&password_length, &password_data,
|
||||||
|
NULL ); // itemRef
|
||||||
|
if (ret != errSecSuccess) {
|
||||||
|
CFStringRef errmsg = SecCopyErrorMessageString( ret, NULL );
|
||||||
|
error( "Looking up Keychain failed: %s\n",
|
||||||
|
CFStringGetCStringPtr( errmsg, kCFStringEncodingUTF8 ) );
|
||||||
|
CFRelease( errmsg );
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
srvc->pass = nfstrndup( password_data, password_length );
|
||||||
|
SecKeychainItemFreeContent( NULL, password_data );
|
||||||
|
#endif /* HAVE_MACOS_KEYCHAIN */
|
||||||
} else {
|
} else {
|
||||||
flushn();
|
flushn();
|
||||||
char prompt[80];
|
char prompt[80];
|
||||||
|
@ -3293,6 +3325,10 @@ imap_parse_store( conffile_t *cfg, store_conf_t **storep )
|
||||||
server->pass = nfstrdup( cfg->val );
|
server->pass = nfstrdup( cfg->val );
|
||||||
else if (!strcasecmp( "PassCmd", cfg->cmd ))
|
else if (!strcasecmp( "PassCmd", cfg->cmd ))
|
||||||
server->pass_cmd = nfstrdup( cfg->val );
|
server->pass_cmd = nfstrdup( cfg->val );
|
||||||
|
#ifdef HAVE_MACOS_KEYCHAIN
|
||||||
|
else if (!strcasecmp( "UseKeychain", cfg->cmd ))
|
||||||
|
server->use_keychain = parse_bool( cfg );
|
||||||
|
#endif
|
||||||
else if (!strcasecmp( "Port", cfg->cmd )) {
|
else if (!strcasecmp( "Port", cfg->cmd )) {
|
||||||
int port = parse_int( cfg );
|
int port = parse_int( cfg );
|
||||||
if ((unsigned)port > 0xffff) {
|
if ((unsigned)port > 0xffff) {
|
||||||
|
@ -3462,6 +3498,13 @@ imap_parse_store( conffile_t *cfg, store_conf_t **storep )
|
||||||
cfg->err = 1;
|
cfg->err = 1;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
#ifdef HAVE_MACOS_KEYCHAIN
|
||||||
|
if (server->use_keychain && (server->pass || server->pass_cmd)) {
|
||||||
|
error( "%s '%s' has UseKeychain enabled despite specifying Pass/PassCmd\n", type, name );
|
||||||
|
cfg->err = 1;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
#ifdef HAVE_LIBSSL
|
#ifdef HAVE_LIBSSL
|
||||||
if ((use_tlsv1 & use_tlsv11 & use_tlsv12 & use_tlsv13) != -1 || use_imaps >= 0 || require_ssl >= 0) {
|
if ((use_tlsv1 & use_tlsv11 & use_tlsv12 & use_tlsv13) != -1 || use_imaps >= 0 || require_ssl >= 0) {
|
||||||
if (server->ssl_type >= 0 || server->sconf.ssl_versions >= 0) {
|
if (server->ssl_type >= 0 || server->sconf.ssl_versions >= 0) {
|
||||||
|
|
22
src/mbsync.1
22
src/mbsync.1
|
@ -341,6 +341,28 @@ Prepend \fB+\fR to the command to indicate that it produces TTY output
|
||||||
messier output.
|
messier output.
|
||||||
.
|
.
|
||||||
.TP
|
.TP
|
||||||
|
\fBUseKeychain\fR \fByes\fR|\fBno\fR
|
||||||
|
Whether to use the macOS Keychain to obtain the password.
|
||||||
|
(Default: \fBno\fR)
|
||||||
|
.IP
|
||||||
|
The neccessary keychain item can be created this way:
|
||||||
|
.RS
|
||||||
|
.IP
|
||||||
|
.nh
|
||||||
|
.B security add-internet-password \-r imap \-s
|
||||||
|
.I Host
|
||||||
|
.B \-a
|
||||||
|
.I User
|
||||||
|
.B \-w
|
||||||
|
.I password
|
||||||
|
[
|
||||||
|
.B \-T
|
||||||
|
.I /path/to/mbsync
|
||||||
|
]
|
||||||
|
.hy
|
||||||
|
.RE
|
||||||
|
.
|
||||||
|
.TP
|
||||||
\fBTunnel\fR \fIcommand\fR
|
\fBTunnel\fR \fIcommand\fR
|
||||||
Specify a command to run to establish a connection rather than opening a TCP
|
Specify a command to run to establish a connection rather than opening a TCP
|
||||||
socket. This allows you to run an IMAP session over an SSH tunnel, for
|
socket. This allows you to run an IMAP session over an SSH tunnel, for
|
||||||
|
|
|
@ -21,11 +21,6 @@ Pass xxxxxxxx
|
||||||
#PassCmd "gpg --quiet --for-your-eyes-only --decrypt $HOME/imappassword.gpg"
|
#PassCmd "gpg --quiet --for-your-eyes-only --decrypt $HOME/imappassword.gpg"
|
||||||
# Fetch password from pwmd (http://pwmd.sourceforge.net/):
|
# Fetch password from pwmd (http://pwmd.sourceforge.net/):
|
||||||
#PassCmd "echo -ne 'GET myIsp\\tpassword' | pwmc datafile"
|
#PassCmd "echo -ne 'GET myIsp\\tpassword' | pwmc datafile"
|
||||||
# On Mac OS X, run "KeyChain Access" -- File->New Password Item. Fill out form using
|
|
||||||
# "Keychain Item Name" http://IMAPSERVER (note: the "http://" is a hack)
|
|
||||||
# "Account Name" USERNAME
|
|
||||||
# "Password" PASSWORD
|
|
||||||
#PassCmd "/usr/bin/security find-internet-password -w -a USERNAME -s IMAPSERVER ~/Library/Keychains/login.keychain"
|
|
||||||
|
|
||||||
Channel work
|
Channel work
|
||||||
Master :work:
|
Master :work:
|
||||||
|
|
Loading…
Reference in New Issue
Block a user