From: Jay Soffian <jaysoffian@gmail.com>
To: git@vger.kernel.org
Cc: Jay Soffian <jaysoffian@gmail.com>,
Junio C Hamano <gitster@pobox.com>, Jeff King <peff@peff.net>,
John Szakmeister <john@szakmeister.net>
Subject: [PATCH] credential-osxkeychain: load Security framework dynamically
Date: Wed, 14 Sep 2011 18:55:26 -0400 [thread overview]
Message-ID: <1316040926-89429-1-git-send-email-jaysoffian@gmail.com> (raw)
In-Reply-To: <1316023117-84755-1-git-send-email-jaysoffian@gmail.com>
Use dlopen() / dysym() instead of dynmically linking to the
Security framework. A followup commit will refactor things such
that git-credential-osxkeychain can be hardlinked to git.
Signed-off-by: Jay Soffian <jaysoffian@gmail.com>
---
> Hmm, maybe it can be if I dlopen the security framework instead of linking
> against it.
Something like this. I'm going to pause here for feedback. Is the (not yet
existant) followup commit referenced above allowing git-credential-osxkeychain
to be a hard link to git a worthwhile endeavor? Or would a better approach be
to make git-credential-osxkeychain.c not use any git code?
contrib/credential-osxkeychain/Makefile | 12 +++-
.../credential-osxkeychain/generate_security.py | 73 ++++++++++++++++++++
2 files changed, 82 insertions(+), 3 deletions(-)
create mode 100755 contrib/credential-osxkeychain/generate_security.py
diff --git a/contrib/credential-osxkeychain/Makefile b/contrib/credential-osxkeychain/Makefile
index dc6bbbc3f9..001d695cb8 100644
--- a/contrib/credential-osxkeychain/Makefile
+++ b/contrib/credential-osxkeychain/Makefile
@@ -25,11 +25,17 @@ ifndef V
endif
endif
-git-credential-osxkeychain: git-credential-osxkeychain.o $(GIT_LIBS)
- $(QUIET_LINK)$(CC) -o $@ $< $(LIBS) -Wl,-framework -Wl,Security
+git-credential-osxkeychain: git-credential-osxkeychain.o security.o $(GIT_LIBS)
+ $(QUIET_LINK)$(CC) -o $@ $< security.o $(LIBS)
git-credential-osxkeychain.o: git-credential-osxkeychain.c
$(QUIET_CC)$(CC) -c $(CFLAGS) $<
+security.o: security.c
+ $(QUIET_CC)$(CC) -c $(CFLAGS) $<
+
+security.c: generate_security.py
+ python generate_security.py
+
clean:
- $(RM) git-credential-osxkeychain git-credential-osxkeychain.o
+ $(RM) git-credential-osxkeychain git-credential-osxkeychain.o security.?
diff --git a/contrib/credential-osxkeychain/generate_security.py b/contrib/credential-osxkeychain/generate_security.py
new file mode 100755
index 0000000000..db94672e95
--- /dev/null
+++ b/contrib/credential-osxkeychain/generate_security.py
@@ -0,0 +1,73 @@
+#!/usr/bin/python
+
+import re
+
+func_decls = """
+OSStatus SecKeychainAddInternetPassword(SecKeychainRef keychain, UInt32 serverNameLength, const char *serverName, UInt32 securityDomainLength, const char *securityDomain, UInt32 accountNameLength, const char *accountName, UInt32 pathLength, const char *path, UInt16 port, SecProtocolType protocol, SecAuthenticationType authenticationType, UInt32 passwordLength, const void *passwordData, SecKeychainItemRef *itemRef);
+OSStatus SecKeychainFindInternetPassword(CFTypeRef keychainOrArray, UInt32 serverNameLength, const char *serverName, UInt32 securityDomainLength, const char *securityDomain, UInt32 accountNameLength, const char *accountName, UInt32 pathLength, const char *path, UInt16 port, SecProtocolType protocol, SecAuthenticationType authenticationType, UInt32 *passwordLength, void **passwordData, SecKeychainItemRef *itemRef);
+OSStatus SecKeychainItemCopyContent(SecKeychainItemRef itemRef, SecItemClass *itemClass, SecKeychainAttributeList *attrList, UInt32 *length, void **outData);
+OSStatus SecKeychainItemDelete(SecKeychainItemRef itemRef);
+OSStatus SecKeychainItemFreeContent(SecKeychainAttributeList *attrList, void *data);
+OSStatus SecKeychainItemModifyContent(SecKeychainItemRef itemRef, const SecKeychainAttributeList *attrList, UInt32 length, const void *data);
+"""
+
+header = r"""
+#include <dlfcn.h>
+#include <Security/Security.h>
+#include "cache.h"
+
+const char *security_framework =
+ "/System/Library/Frameworks/Security.framework/Security";
+
+void *load_security()
+{
+ static void *security;
+ if (!security) {
+ if (!(security = dlopen(security_framework, RTLD_LAZY)))
+ die(_("dlopen(\"%s\") failed: %s"),
+ security_framework, dlerror());
+ }
+ return security;
+}
+"""
+
+func_tmpl = """
+%(func_decl)s
+{
+ %(func_rv)s (*func)(%(arg_types)s) =
+ dlsym(load_security(), "%(func_name)s");
+ if (!func)
+ die(_("dlsym(%(func_name)s) failed: %%s"), dlerror());
+ return func(%(arg_names)s);
+}
+"""
+
+def generate_func(decl):
+ func_rv, func_name, func_args = re.search(
+ r'^(.*?)\s+([^(]+)\((.*)\);$', decl).groups()
+ func_args = [s.strip() for s in func_args.split(',')]
+ arg_types = []
+ arg_names = []
+ for arg in func_args:
+ arg_type, arg_name = re.search(r'^(.*?)([a-zA-Z]+)$', arg).groups()
+ arg_types.append(arg_type.strip())
+ arg_names.append(arg_name.strip())
+ return func_tmpl % dict(
+ func_decl=decl.rstrip(';'),
+ func_name=func_name,
+ func_rv=func_rv,
+ arg_types=', '.join(arg_types),
+ arg_names=', '.join(arg_names),
+ )
+
+def main():
+ f = open('security.c', 'w')
+ f.write(header)
+ for decl in func_decls.splitlines():
+ decl = decl.strip()
+ if decl:
+ f.write(generate_func(decl))
+ f.close()
+
+if __name__ == '__main__':
+ main()
--
1.7.7.rc1.1.g011e1
next prev parent reply other threads:[~2011-09-14 22:55 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2011-09-14 17:58 [PATCH] contrib: add a credential helper for Mac OS X's keychain Jay Soffian
2011-09-14 18:19 ` Jay Soffian
2011-09-14 22:55 ` Jay Soffian [this message]
2011-09-14 23:08 ` [PATCH] credential-osxkeychain: load Security framework dynamically Jeff King
2011-09-14 23:56 ` Jay Soffian
2011-09-15 0:16 ` Jeff King
2011-09-14 23:18 ` Junio C Hamano
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1316040926-89429-1-git-send-email-jaysoffian@gmail.com \
--to=jaysoffian@gmail.com \
--cc=git@vger.kernel.org \
--cc=gitster@pobox.com \
--cc=john@szakmeister.net \
--cc=peff@peff.net \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).