[PATCH] credential-osxkeychain: load Security framework dynamically

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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@xxxxxxxxx>
---
> 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

--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux Kernel Development]     [Gcc Help]     [IETF Annouce]     [DCCP]     [Netdev]     [Networking]     [Security]     [V4L]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux SCSI]     [Fedora Users]