Skip to content

Instantly share code, notes, and snippets.

@franzwong
Last active November 12, 2022 08:31
Show Gist options
  • Save franzwong/447611f46e6714cf2f1a082e3879c0f0 to your computer and use it in GitHub Desktop.
Save franzwong/447611f46e6714cf2f1a082e3879c0f0 to your computer and use it in GitHub Desktop.
Get generic password from MacOS Keychain with C
// Build: gcc -framework Security -framework Foundation -o get_generic_password get_generic_password.c
// Usage: ./get_generic_password <service name>
#include <CoreFoundation/CoreFoundation.h>
#include <Security/Security.h>
OSStatus getCredentialByServiceName(const char *serviceName, CFTypeRef *credential) {
CFStringRef cfServiceName = CFStringCreateWithCString(kCFAllocatorDefault, serviceName, kCFStringEncodingUTF8);
const void* keys[] = { kSecClass, kSecAttrService, kSecReturnAttributes, kSecReturnData, kSecMatchLimit };
const void* values[] = { kSecClassGenericPassword, cfServiceName, kCFBooleanTrue, kCFBooleanTrue, kSecMatchLimitOne };
CFDictionaryRef query = CFDictionaryCreate(kCFAllocatorDefault, (const void**) keys, (const void**) values, 5, NULL, NULL);
OSStatus result = SecItemCopyMatching(query, credential);
CFRelease(cfServiceName);
CFRelease(query);
return result;
}
void getString(CFStringRef cfString, char **buffer) {
const char *str = CFStringGetCStringPtr(cfString, kCFStringEncodingUTF8);
if (str != NULL) {
*buffer = malloc(strlen(str) + 1);
strcpy(*buffer, str);
} else {
CFIndex length = CFStringGetLength(cfString);
CFIndex stringLength = length * sizeof(UniChar) + 1;
*buffer = malloc(stringLength);
CFStringGetCString(cfString, *buffer, stringLength, kCFStringEncodingUTF8);
}
}
int main(int argc, const char* argv[]) {
if (argc < 2) {
fprintf(stderr, "Usage: ./get_generic_password <service name>");
return 1;
}
const char *serviceName = argv[1];
CFTypeRef credential = NULL;
OSStatus result = getCredentialByServiceName(serviceName, &credential);
if (result == errSecSuccess) {
CFStringRef cfAccount = (CFStringRef) CFDictionaryGetValue(credential, kSecAttrAccount);
if (cfAccount != NULL) {
char *account = NULL;
getString(cfAccount, &account);
printf("Account: %s\n", account);
free(account);
}
CFDataRef cfPassword = (CFDataRef) CFDictionaryGetValue(credential, kSecValueData);
if (cfPassword != NULL) {
long length = CFDataGetLength(cfPassword);
uint8_t *buffer = malloc(length);
CFDataGetBytes(cfPassword, CFRangeMake(0, length), buffer);
printf("Password: %.*s\n", (int)length, buffer);
free(buffer);
buffer = NULL;
}
CFRelease(credential);
}
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment