git.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
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

  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).