#include "securityd_service.h"
#include <stdio.h>
#include <xpc/xpc.h>
#include <dispatch/dispatch.h>
#include <AssertMacros.h>
#include <CoreFoundation/CoreFoundation.h>
#include <Security/SecKeychainPriv.h>
static inline char *
hextostr(const uint8_t *buf, size_t len, char *hexbuf)
{
char *s = hexbuf;
size_t i;
static const char hexdigits[] = "0123456789abcdef";
for (i = 0; i < len; i++) {
*s++ = hexdigits[buf[i]>>4];
*s++ = hexdigits[buf[i]&0xf];
}
*s = '\0';
return hexbuf;
}
int main(int argc, const char * argv[])
{
uint64_t action = 0;
OSStatus status = noErr;
uint8_t testkey[128] = "\xde\xad\xbe\xef\xde\xad\xbe\xef\xde\xad\xbe\xef\xde\xad\xbe\xef";
xpc_connection_t connection = xpc_connection_create_mach_service(SECURITYD_SERVICE_NAME, NULL, XPC_CONNECTION_MACH_SERVICE_PRIVILEGED);
xpc_connection_set_event_handler(connection, ^(xpc_object_t event) {
if (xpc_get_type(event) == XPC_TYPE_ERROR) {
printf("XPC error\n");
}
});
xpc_connection_resume(connection);
if (argc != 2) {
printf("Usage: securityservicectrl < get | set | stash | login | loginstash >\n");
return 1;
}
if (strcmp(argv[1], "get") == 0) {
action = SERVICE_STASH_GET_KEY;
printf("Get key\n");
} else if (strcmp(argv[1], "set") == 0) {
action = SERVICE_STASH_SET_KEY;
printf("Set key\n");
} else if (strcmp(argv[1], "stash") == 0) {
action = SERVICE_STASH_BLOB;
printf("Stash\n");
} else if (strcmp(argv[1], "login") == 0) {
printf("SecKeychainLogin() null passwd\n");
status = SecKeychainLogin((uint32) strlen("test"), "test", 0, NULL);
printf("Returned: %i\n", status);
return status ? 1 : 0;
} else if (strcmp(argv[1], "loginstash") == 0) {
printf("SecKeychainStash()\n");
status = SecKeychainStash();
printf("Returned: %i\n", status);
return status ? 1 : 0;
} else {
printf("%s not known\n", argv[1]);
return 1;
}
xpc_object_t message = xpc_dictionary_create(NULL, NULL, 0);
xpc_dictionary_set_uint64(message, SERVICE_XPC_REQUEST, action);
if (action == SERVICE_STASH_SET_KEY)
xpc_dictionary_set_data(message, SERVICE_XPC_KEY, testkey, 16);
xpc_object_t reply = xpc_connection_send_message_with_reply_sync(connection, message);
require_action(reply != NULL, done, status = -1);
require_action(xpc_get_type(reply) != XPC_TYPE_ERROR, done, status = -1);
if (action == SERVICE_STASH_GET_KEY) {
size_t len = 0;
const uint8_t *keydata = xpc_dictionary_get_data(reply, SERVICE_XPC_KEY, &len);
if (keydata) {
char buf[sizeof(testkey) + 1];
printf("\tkey = %s\n", hextostr(keydata, len > sizeof(testkey) ? sizeof(testkey) : len, buf));
}
}
status = (OSStatus)xpc_dictionary_get_int64(reply, SERVICE_XPC_RC);
done:
if (message)
xpc_release(message);
if (reply)
xpc_release(reply);
if (connection)
xpc_release(connection);
printf("Returned: %i\n", status);
return status ? 1 : 0;
}