Ticket #14189: 0001-Support-for-Mac-OS-X-keychain.patch

File 0001-Support-for-Mac-OS-X-keychain.patch, 3.6 KB (added by jaysoffian@…, 17 years ago)
  • configure.ac

    From 5b892d8374e27edfbf9d2902cd7c26d0b54c67bd Mon Sep 17 00:00:00 2001
    From: Jay Soffian <jaysoffian@gmail.com>
    Date: Tue, 5 Feb 2008 03:36:48 -0500
    Subject: [PATCH] Support for Mac OS X keychain
    
    The Mac OS X keychain provides a more secure mechanism for storing passwords
    than a plaintext file such as .netrc or .msmtprc. The attached patch allows
    msmtp to retrieve its account passwords from the keychain.
    
    To make use of the functionality, an OS X user creates a keychain item with
    tje Keychain Access GUI application. The "account name" is simply the value of
    the msmtp "user" argument. However, the "keychain item name" is
    "smtp://<hostname>" where "<hostname>" matches the msmtp host argument. Using
    "smtp://" is needed so that the item is created of kind "Internet password."
    For example, selecting "File -> Get Info" on a keychain item that corresponds
    to "host smtp.freemail.example" and "user joe.smith" will show:
    
        Name: smtp.freemail.example
        Kind: Internet password
     Account: joe.smith
       Where: smtp://smtp.freemail.example
    
    Signed-off-by: Jay Soffian <jaysoffian@gmail.com>
    ---
     configure.ac |   16 ++++++++++++++++
     src/msmtp.c  |   31 +++++++++++++++++++++++++++++--
     2 files changed, 45 insertions(+), 2 deletions(-)
    
    diff --git a/configure.ac b/configure.ac
    index eeaa734..97a202d 100644
    a b if test "$libidn" != "no"; then 
    179179    fi
    180180fi
    181181
     182dnl MacOS X Keychain Services (Security Framework)
     183AC_CACHE_CHECK([for SecKeychainGetVersion],
     184    ac_cv_func_SecKeychainGetVersion,
     185    [ac_save_LIBS="$LIBS"
     186    LIBS="$LIBS -Wl,-framework -Wl,Security"
     187    AC_TRY_LINK([#include <Security/Security.h>],
     188        [SecKeychainGetVersion(NULL);],
     189        [ac_cv_func_SecKeychainGetVersion=yes],
     190        [ac_cv_func_SecKeychainGetVersion=no])
     191    LIBS="$ac_save_LIBS"])
     192if test $ac_cv_func_SecKeychainGetVersion = yes; then
     193    AC_DEFINE([HAVE_KEYCHAIN], 1,
     194        [Define to 1 if you have the MacOS X Keychain Services API.])
     195    LIBS="$LIBS -Wl,-framework -Wl,Security"
     196fi
     197
    182198dnl Global #defines for all source files
    183199AH_VERBATIM([UNUSED],
    184200[/* Let gcc know about unused variables to suppress warnings.
  • src/msmtp.c

    diff --git a/src/msmtp.c b/src/msmtp.c
    index fef0f5c..f0e30b7 100644
    a b extern int optind; 
    5656#include <netdb.h>
    5757#include <arpa/inet.h>
    5858#endif
    59 
     59#ifdef HAVE_KEYCHAIN
     60#include <Security/Security.h>
     61#endif
    6062#include "getpass.h"
    6163#include "gettext.h"
    6264#include "xalloc.h"
    char *msmtp_password_callback(const char *hostname, const char *user) 
    284286    char *prompt;
    285287    char *gpw;
    286288    char *password = NULL;
     289#ifdef HAVE_KEYCHAIN
     290    void *passwordData;
     291    UInt32 passwordLength;
     292    OSStatus status;
     293#endif
    287294
    288295    homedir = get_homedir();
    289296    netrc_filename = get_filename(homedir, NETRCFILE);
    char *msmtp_password_callback(const char *hostname, const char *user) 
    297304        free_netrc_entry_list(netrc_hostlist);
    298305    }
    299306    free(netrc_filename);
    300    
     307
     308#ifdef HAVE_KEYCHAIN
     309    if (SecKeychainFindInternetPassword(
     310        NULL,
     311        strlen(hostname), hostname,
     312        0, NULL,
     313        strlen(user), user,
     314        0, (char *)NULL,
     315        0,
     316        kSecProtocolTypeSMTP,
     317        kSecAuthenticationTypeDefault,
     318        &passwordLength, &passwordData,
     319        NULL) == noErr)
     320    {
     321        password = xmalloc((passwordLength + 1) * sizeof(char));
     322        strncpy(password, passwordData, (size_t)passwordLength);
     323        password[passwordLength] = '\0';
     324        SecKeychainItemFreeContent(NULL, passwordData);
     325    }
     326#endif /* HAVE_KEYCHAIN */
     327
    301328    if (!password)
    302329    {
    303330        prompt = xasprintf(_("password for %s at %s: "), user, hostname);