From: Peter G. <pg...@gm...> - 2016-08-25 09:18:32
|
I did not include the re-generated 'configure' and related files in my diff since they were very large (my local version of autotools is different) and not core to the change. If you need me to, I can attempt to re-generate these without such a large amount of noise but I'm not sure how easy it will be to get the proper version(s) installed on my system. Thanks, Peter On Thu, Aug 25, 2016 at 4:36 PM, Peter Griess <pg...@gm...> wrote: > - Attempt to retrieve credentials from the Mac OS X Keychain Services > framework based on the account name, server name, and protocol of the > configured query. This allows us to avoid storing passwords in the the > .fetchmailrc file and to take advantage of Keychain's ACL features to > ensure that only fetchmail and a few other select applications have > access to these credentials. > - Add a new configure --with-keychain option gating this feature > --- > configure.ac | 10 +++++++++ > fetchmail.c | 70 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ > 2 files changed, 80 insertions(+) > > diff --git a/configure.ac b/configure.ac > index 5efd8d1..78d3cf7 100644 > --- a/configure.ac > +++ b/configure.ac > @@ -527,6 +527,16 @@ if test "$fm_cv_getaddrinfo" = yes ; then > fi > fi > > +# Optionally support credential retrieval from OS X Keychain Services > +AC_ARG_WITH(keychain, > + [AS_HELP_STRING([--with-keychain], > + [use the Mac OS X keychain for credential storage])], > + [], > + [with_keychain=no]) > +AS_IF([test "x$with_keychain" = xyes], > + AC_DEFINE([HAVE_KEYCHAIN], [1], [Enable OS X Keychain integration]) > + [LIBS="$LIBS -Wl,-framework -Wl,Security -Wl,-framework -Wl,CoreFoundation"]) > + > # This version of the Kerberos 4 and 5 options addresses the follwing issues: > # > # * Build correctly under Heimdal kerberos if it is compiled with db2 and > diff --git a/fetchmail.c b/fetchmail.c > index ae30f90..9535075 100644 > --- a/fetchmail.c > +++ b/fetchmail.c > @@ -37,6 +37,10 @@ > #include <langinfo.h> > #endif > > +#ifdef HAVE_KEYCHAIN > +#include <Security/Security.h> > +#endif > + > #include "fetchmail.h" > #include "socket.h" > #include "tunable.h" > @@ -284,6 +288,9 @@ int main(int argc, char **argv) > #ifndef HAVE_RES_SEARCH > "-DNS" > #endif > +#ifdef HAVE_KEYCHAIN > + "+KEYCHAIN" > +#endif > ".\n"; > printf(GT_("This is fetchmail release %s"), VERSION); > fputs(features, stdout); > @@ -560,6 +567,69 @@ int main(int argc, char **argv) > } > } > > +#ifdef HAVE_KEYCHAIN > + /* look in the OS X keychain for remaining un-set passwords */ > + for (ctl = querylist; ctl; ctl = ctl->next) > + { > + if (!ctl->active || NO_PASSWORD(ctl) || ctl->password > + || (implicitmode && ctl->server.skip)) > + { > + continue; > + } > + > + const char *host = (ctl->server.via) ? > + ctl->server.via : > + ctl->server.pollname; > + const SecProtocolType protocol_type = > + (ctl->server.protocol == P_IMAP) ? kSecProtocolTypeIMAP : > + (ctl->server.protocol == P_POP2) ? kSecProtocolTypePOP3 : > + (ctl->server.protocol == P_POP3) ? kSecProtocolTypePOP3 : > + (ctl->server.protocol == P_APOP) ? kSecProtocolTypePOP3 : > + (ctl->server.protocol == P_RPOP) ? kSecProtocolTypePOP3 : > + kSecProtocolTypeAny; > + > + uint32_t password_len; > + void* password_bytes; > + OSStatus oss = SecKeychainFindInternetPassword( > + NULL, > + strlen(host), host, /* server */ > + 0, NULL, /* security domain */ > + strlen(ctl->remotename), ctl->remotename, /* account name */ > + 0, NULL, /* path */ > + 0, /* port */ > + protocol_type, > + kSecAuthenticationTypeDefault, > + &password_len, &password_bytes, /* password */ > + NULL /* SecKeychainItemRef */); > + > + if (oss != errSecSuccess && outlevel >= O_VERBOSE) > + { > + char errstr[512]; > + CFStringRef cferrstr = SecCopyErrorMessageString(oss, NULL); > + Boolean ok = CFStringGetCString( > + cferrstr, > + errstr, > + sizeof(errstr), > + kCFStringEncodingUTF8); > + if (!ok) > + { > + strcpy(errstr, "Unknown; CFStringGetCString() failed"); > + } > + > + report(stderr, > + "SecKeychainFindInternetPassword: %s (%d)\n", > + errstr, > + oss); > + continue; > + } > + > + ctl->password = (char*) xmalloc(password_len + 1); > + memmove(ctl->password, password_bytes, password_len); > + ctl->password[password_len] = '\0'; > + (void) SecKeychainItemFreeContent(NULL, password_bytes); > + } > +#endif > + > /* pick up interactively any passwords we need but don't have */ > for (ctl = querylist; ctl; ctl = ctl->next) > { > -- > 2.8.0-rc2 > |