It is useful to segregate OS-specific code where appropriate for better
readability and easier debugging.  Logic regarding the macOS keychain is
macOS-specific (obviously), and was intermixed with the
ensure_password() function.

Move the logic relating to searching the macOS keychain into a
self-contained search_macos_keychain() function, adding a clearer
separation between macOS-specific and OS-agnostic code in the
ensure_password() function (since the macOS-specific code is just a
single function call).
---
 src/drv_imap.c | 64 +++++++++++++++++++++++++++++++++-----------------
 1 file changed, 42 insertions(+), 22 deletions(-)

diff --git a/src/drv_imap.c b/src/drv_imap.c
index 9b170ab74311..bbc6f43b290c 100644
--- a/src/drv_imap.c
+++ b/src/drv_imap.c
@@ -2332,36 +2332,56 @@ ensure_user( imap_server_conf_t *srvc )
        return srvc->user;
 }
 
+#ifdef HAVE_MACOS_KEYCHAIN
+/*
+ * Searches the macOS file-based keychain for an appropriate password.  If
+ * found, returns a newly allocated copy of the password (which should later be
+ * freed).  Otherwise, returns NULL.
+ *
+ * A password is deemed appropriate if its protocol is IMAP, and its server 
name
+ * and account name match the given host and user, respectively.  If multiple
+ * such passwords exist, the first found by the Security framework is returned.
+ */
+static char *
+search_macos_keychain( const char *host, const char *user )
+{
+       void *password_data;
+       UInt32 password_length;
+
+       OSStatus ret = SecKeychainFindInternetPassword(
+                       NULL,  // keychainOrArray
+                       strlen( host ), host,
+                       0, NULL,  // securityDomain
+                       strlen( user ), 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;
+       }
+
+       char *password_copy = nfstrndup( password_data, password_length );
+       SecKeychainItemFreeContent( NULL, password_data );
+       return password_copy;
+}
+#endif /* HAVE_MACOS_KEYCHAIN */
+
 static const char *
 ensure_password( imap_server_conf_t *srvc )
 {
        if (!srvc->pass) {
                if (srvc->pass_cmd) {
                        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 );
+                       srvc->pass = search_macos_keychain( srvc->sconf.host, 
srvc->user );
 #endif /* HAVE_MACOS_KEYCHAIN */
                } else {
                        flushn();
-- 
2.50.1 (Apple Git-155)



_______________________________________________
isync-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/isync-devel

Reply via email to