main.c
  1  //
  2  //  main.c
  3  //  securitydservicectrl
  4  //
  5  //  Created by Wade Benson on 12/2/12.
  6  //  Copyright (c) 2012 Apple. All rights reserved.
  7  //
  8  
  9  #include "securityd_service.h"
 10  #include "securityd_service_client.h"
 11  
 12  #include <stdio.h>
 13  #include <xpc/xpc.h>
 14  #include <dispatch/dispatch.h>
 15  #include <AssertMacros.h>
 16  #include <CoreFoundation/CoreFoundation.h>
 17  #include <Security/SecKeychainPriv.h>
 18  
 19  static inline char *
 20  hextostr(const uint8_t *buf, size_t len, char *hexbuf)
 21  {
 22      char *s = hexbuf;
 23      size_t i;
 24      static const char hexdigits[] = "0123456789abcdef";
 25      for (i = 0; i < len; i++) {
 26          *s++ = hexdigits[buf[i]>>4];
 27          *s++ = hexdigits[buf[i]&0xf];
 28      }
 29      *s = '\0';
 30      return hexbuf;
 31  }
 32  
 33  int main(int argc, const char * argv[])
 34  {
 35      uint64_t action = 0;
 36      OSStatus status = noErr;
 37      uint8_t testkey[128] = "\xde\xad\xbe\xef\xde\xad\xbe\xef\xde\xad\xbe\xef\xde\xad\xbe\xef";
 38      xpc_connection_t connection = xpc_connection_create_mach_service(SECURITYD_SERVICE_NAME, NULL, XPC_CONNECTION_MACH_SERVICE_PRIVILEGED);
 39      xpc_object_t message = NULL, reply = NULL;
 40  
 41      xpc_connection_set_event_handler(connection, ^(xpc_object_t event) {
 42          if (xpc_get_type(event) == XPC_TYPE_ERROR) {
 43              printf("XPC error\n");
 44          }
 45      });
 46      xpc_connection_resume(connection);
 47  
 48      if (argc < 2) {
 49          printf("Usage: securityservicectrl < get | set | stash | login | loginstash | unload | load <uid> >\n");
 50          return 1;
 51      }
 52  
 53      if (strcmp(argv[1], "get") == 0) {
 54          action = SERVICE_STASH_GET_KEY;
 55          printf("Get key\n");
 56  
 57      } else if (strcmp(argv[1], "set") == 0) {
 58          action = SERVICE_STASH_SET_KEY;
 59          printf("Set key\n");
 60  
 61      } else if (strcmp(argv[1], "stash") == 0) {
 62          action = SERVICE_STASH_BLOB;
 63          printf("Stash\n");
 64  
 65      } else if (strcmp(argv[1], "login") == 0) {
 66          printf("SecKeychainLogin() null passwd\n");
 67          status = SecKeychainLogin((uint32) strlen("test"), "test", 0, NULL);
 68          printf("Returned: %i\n", status);
 69          return status ? 1 : 0;
 70  
 71      } else if (strcmp(argv[1], "loginstash") == 0) {
 72          printf("SecKeychainStash()\n");
 73          status = SecKeychainStash();
 74          printf("Returned: %i\n", status);
 75          return status ? 1 : 0;
 76  
 77      } else if (strcmp(argv[1], "unload") == 0) {
 78          return service_client_kb_unload(NULL);
 79      } else if (strcmp(argv[1], "load") == 0) {
 80          require_action(argc == 3, done, printf("missing <uid>\n"));
 81          uid_t uid = atoi(argv[2]);
 82          return service_client_kb_load_uid(uid);
 83      } else {
 84          printf("%s not known\n", argv[1]);
 85          return 1;
 86      }
 87  
 88      // Send
 89      message = xpc_dictionary_create(NULL, NULL, 0);
 90      xpc_dictionary_set_uint64(message, SERVICE_XPC_REQUEST, action);
 91  
 92      if (action == SERVICE_STASH_SET_KEY)
 93          xpc_dictionary_set_data(message, SERVICE_XPC_KEY, testkey, 16);
 94  
 95      reply = xpc_connection_send_message_with_reply_sync(connection, message);
 96      require_action(reply != NULL, done, status = -1);
 97      require_action(xpc_get_type(reply) != XPC_TYPE_ERROR, done, status = -1);
 98  
 99      if (action == SERVICE_STASH_GET_KEY) {
100          size_t len = 0;
101          const uint8_t *keydata = xpc_dictionary_get_data(reply, SERVICE_XPC_KEY, &len);
102          if (keydata) {
103              char buf[sizeof(testkey) + 1];
104              printf("\tkey = %s\n", hextostr(keydata, len > sizeof(testkey) ? sizeof(testkey) : len, buf));
105          }
106      }
107  
108      status = (OSStatus)xpc_dictionary_get_int64(reply, SERVICE_XPC_RC);
109  
110  done:
111      if (message)
112          xpc_release(message);
113      if (reply)
114          xpc_release(reply);
115      if (connection)
116          xpc_release(connection);
117  
118      printf("Returned: %i\n", status);
119  
120      return status ? 1 : 0;
121  }
122