summaryrefslogtreecommitdiff
path: root/vendor/github.com/docker/docker-credential-helpers/osxkeychain/osxkeychain_darwin.c
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/docker/docker-credential-helpers/osxkeychain/osxkeychain_darwin.c')
-rw-r--r--vendor/github.com/docker/docker-credential-helpers/osxkeychain/osxkeychain_darwin.c228
1 files changed, 228 insertions, 0 deletions
diff --git a/vendor/github.com/docker/docker-credential-helpers/osxkeychain/osxkeychain_darwin.c b/vendor/github.com/docker/docker-credential-helpers/osxkeychain/osxkeychain_darwin.c
new file mode 100644
index 000000000..f84d61ee5
--- /dev/null
+++ b/vendor/github.com/docker/docker-credential-helpers/osxkeychain/osxkeychain_darwin.c
@@ -0,0 +1,228 @@
+#include "osxkeychain_darwin.h"
+#include <CoreFoundation/CoreFoundation.h>
+#include <Foundation/NSValue.h>
+#include <stdio.h>
+#include <string.h>
+
+char *get_error(OSStatus status) {
+ char *buf = malloc(128);
+ CFStringRef str = SecCopyErrorMessageString(status, NULL);
+ int success = CFStringGetCString(str, buf, 128, kCFStringEncodingUTF8);
+ if (!success) {
+ strncpy(buf, "Unknown error", 128);
+ }
+ return buf;
+}
+
+char *keychain_add(struct Server *server, char *label, char *username, char *secret) {
+ SecKeychainItemRef item;
+
+ OSStatus status = SecKeychainAddInternetPassword(
+ NULL,
+ strlen(server->host), server->host,
+ 0, NULL,
+ strlen(username), username,
+ strlen(server->path), server->path,
+ server->port,
+ server->proto,
+ kSecAuthenticationTypeDefault,
+ strlen(secret), secret,
+ &item
+ );
+
+ if (status) {
+ return get_error(status);
+ }
+
+ SecKeychainAttribute attribute;
+ SecKeychainAttributeList attrs;
+ attribute.tag = kSecLabelItemAttr;
+ attribute.data = label;
+ attribute.length = strlen(label);
+ attrs.count = 1;
+ attrs.attr = &attribute;
+
+ status = SecKeychainItemModifyContent(item, &attrs, 0, NULL);
+
+ if (status) {
+ return get_error(status);
+ }
+
+ return NULL;
+}
+
+char *keychain_get(struct Server *server, unsigned int *username_l, char **username, unsigned int *secret_l, char **secret) {
+ char *tmp;
+ SecKeychainItemRef item;
+
+ OSStatus status = SecKeychainFindInternetPassword(
+ NULL,
+ strlen(server->host), server->host,
+ 0, NULL,
+ 0, NULL,
+ strlen(server->path), server->path,
+ server->port,
+ server->proto,
+ kSecAuthenticationTypeDefault,
+ secret_l, (void **)&tmp,
+ &item);
+
+ if (status) {
+ return get_error(status);
+ }
+
+ *secret = strdup(tmp);
+ SecKeychainItemFreeContent(NULL, tmp);
+
+ SecKeychainAttributeList list;
+ SecKeychainAttribute attr;
+
+ list.count = 1;
+ list.attr = &attr;
+ attr.tag = kSecAccountItemAttr;
+
+ status = SecKeychainItemCopyContent(item, NULL, &list, NULL, NULL);
+ if (status) {
+ return get_error(status);
+ }
+
+ *username = strdup(attr.data);
+ *username_l = attr.length;
+ SecKeychainItemFreeContent(&list, NULL);
+
+ return NULL;
+}
+
+char *keychain_delete(struct Server *server) {
+ SecKeychainItemRef item;
+
+ OSStatus status = SecKeychainFindInternetPassword(
+ NULL,
+ strlen(server->host), server->host,
+ 0, NULL,
+ 0, NULL,
+ strlen(server->path), server->path,
+ server->port,
+ server->proto,
+ kSecAuthenticationTypeDefault,
+ 0, NULL,
+ &item);
+
+ if (status) {
+ return get_error(status);
+ }
+
+ status = SecKeychainItemDelete(item);
+ if (status) {
+ return get_error(status);
+ }
+ return NULL;
+}
+
+char * CFStringToCharArr(CFStringRef aString) {
+ if (aString == NULL) {
+ return NULL;
+ }
+ CFIndex length = CFStringGetLength(aString);
+ CFIndex maxSize =
+ CFStringGetMaximumSizeForEncoding(length, kCFStringEncodingUTF8) + 1;
+ char *buffer = (char *)malloc(maxSize);
+ if (CFStringGetCString(aString, buffer, maxSize,
+ kCFStringEncodingUTF8)) {
+ return buffer;
+ }
+ return NULL;
+}
+
+char *keychain_list(char *credsLabel, char *** paths, char *** accts, unsigned int *list_l) {
+ CFStringRef credsLabelCF = CFStringCreateWithCString(NULL, credsLabel, kCFStringEncodingUTF8);
+ CFMutableDictionaryRef query = CFDictionaryCreateMutable (NULL, 1, NULL, NULL);
+ CFDictionaryAddValue(query, kSecClass, kSecClassInternetPassword);
+ CFDictionaryAddValue(query, kSecReturnAttributes, kCFBooleanTrue);
+ CFDictionaryAddValue(query, kSecMatchLimit, kSecMatchLimitAll);
+ CFDictionaryAddValue(query, kSecAttrLabel, credsLabelCF);
+ //Use this query dictionary
+ CFTypeRef result= NULL;
+ OSStatus status = SecItemCopyMatching(
+ query,
+ &result);
+
+ CFRelease(credsLabelCF);
+
+ //Ran a search and store the results in result
+ if (status) {
+ return get_error(status);
+ }
+ CFIndex numKeys = CFArrayGetCount(result);
+ *paths = (char **) malloc((int)sizeof(char *)*numKeys);
+ *accts = (char **) malloc((int)sizeof(char *)*numKeys);
+ //result is of type CFArray
+ for(CFIndex i=0; i<numKeys; i++) {
+ CFDictionaryRef currKey = CFArrayGetValueAtIndex(result,i);
+
+ CFStringRef protocolTmp = CFDictionaryGetValue(currKey, CFSTR("ptcl"));
+ if (protocolTmp != NULL) {
+ CFStringRef protocolStr = CFStringCreateWithFormat(NULL, NULL, CFSTR("%@"), protocolTmp);
+ if (CFStringCompare(protocolStr, CFSTR("htps"), 0) == kCFCompareEqualTo) {
+ protocolTmp = CFSTR("https://");
+ }
+ else {
+ protocolTmp = CFSTR("http://");
+ }
+ CFRelease(protocolStr);
+ }
+ else {
+ char * path = "0";
+ char * acct = "0";
+ (*paths)[i] = (char *) malloc(sizeof(char)*(strlen(path)));
+ memcpy((*paths)[i], path, sizeof(char)*(strlen(path)));
+ (*accts)[i] = (char *) malloc(sizeof(char)*(strlen(acct)));
+ memcpy((*accts)[i], acct, sizeof(char)*(strlen(acct)));
+ continue;
+ }
+
+ CFMutableStringRef str = CFStringCreateMutableCopy(NULL, 0, protocolTmp);
+ CFStringRef serverTmp = CFDictionaryGetValue(currKey, CFSTR("srvr"));
+ if (serverTmp != NULL) {
+ CFStringAppend(str, serverTmp);
+ }
+
+ CFStringRef pathTmp = CFDictionaryGetValue(currKey, CFSTR("path"));
+ if (pathTmp != NULL) {
+ CFStringAppend(str, pathTmp);
+ }
+
+ const NSNumber * portTmp = CFDictionaryGetValue(currKey, CFSTR("port"));
+ if (portTmp != NULL && portTmp.integerValue != 0) {
+ CFStringRef portStr = CFStringCreateWithFormat(NULL, NULL, CFSTR("%@"), portTmp);
+ CFStringAppend(str, CFSTR(":"));
+ CFStringAppend(str, portStr);
+ CFRelease(portStr);
+ }
+
+ CFStringRef acctTmp = CFDictionaryGetValue(currKey, CFSTR("acct"));
+ if (acctTmp == NULL) {
+ acctTmp = CFSTR("account not defined");
+ }
+
+ char * path = CFStringToCharArr(str);
+ char * acct = CFStringToCharArr(acctTmp);
+
+ //We now have all we need, username and servername. Now export this to .go
+ (*paths)[i] = (char *) malloc(sizeof(char)*(strlen(path)+1));
+ memcpy((*paths)[i], path, sizeof(char)*(strlen(path)+1));
+ (*accts)[i] = (char *) malloc(sizeof(char)*(strlen(acct)+1));
+ memcpy((*accts)[i], acct, sizeof(char)*(strlen(acct)+1));
+
+ CFRelease(str);
+ }
+ *list_l = (int)numKeys;
+ return NULL;
+}
+
+void freeListData(char *** data, unsigned int length) {
+ for(int i=0; i<length; i++) {
+ free((*data)[i]);
+ }
+ free(*data);
+}