From: Peter G. <pg...@gm...> - 2016-09-14 13:45:39
|
Hi Matthias, This patch is against 6.3.26. Would you prefer a patch against master instead? Or perhaps a pull request (not sure if GitLab supports this)? Peter On Thu, Aug 25, 2016 at 3:36 AM, 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 > - Update fetchmail.man with description of OS X Keychain item format > recognizable by fetchmail and a recipe for adding a conforming item > --- > configure.ac | 10 +++++++++ > fetchmail.c | 70 ++++++++++++++++++++++++++++++ > +++++++++++++++++++++++++++++ > fetchmail.man | 19 ++++++++++++++++ > 3 files changed, 99 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) > { > diff --git a/fetchmail.man b/fetchmail.man > index 792ada2..b60238a 100644 > --- a/fetchmail.man > +++ b/fetchmail.man > @@ -1200,6 +1200,25 @@ password en clair) whenever the server returns > AUTH=NTLM in its > capability response. Specify a user option value that looks like > \&'user@domain': the part to the left of the @ will be passed as the > username and the part to the right as the NTLM domain. > +.PP > +If your \fBfetchmail\fP was built with OS X Keychain support, the current > +user's keychain will be searched for credentials. \fBfetchmail\fP looks > for an > +entry of type "Internet password" with the "Account" field matching the > +username used for authentication, and the "Where" field a URI matching the > +protocol and server name (e.g. "imap://imap.gmail.com"). It does not > appear > +possible to create an "Internet password" entry using the \fIKeychain > Access\fP > +GUI tool; one must use the \fIsecurity(1)\fP tool. Below is an example of > using > +this tool to set up an properly-configured entry for authenticating the > user > +"pgriess" to Google's IMAP server: > + > + $ security add-internet-password \\ > + -a pgriess \\ > + -r imap \\ > + -s imap.gmail.com \\ > + -w <password> > + > +Use "-r pop3" for all POP-related \fBfetchmail\fP protocols including > POP2, > +APOP, etc. > > .SS Secure Socket Layers (SSL) and Transport Layer Security (TLS) > .PP > -- > 2.8.0-rc2 > > |