summaryrefslogtreecommitdiffstats
path: root/common
diff options
context:
space:
mode:
authorGravatar Martin Szulecki2013-08-18 05:28:53 +0200
committerGravatar Martin Szulecki2013-09-17 11:43:33 +0200
commitec720cc1c30ac3f9b7996575e835565f60ce2b3e (patch)
treef92476e06ce36ab56348544fb9ae614ec10d904c /common
parent36e636a727ecbae7083878ceb493b26046a47179 (diff)
downloadlibimobiledevice-ec720cc1c30ac3f9b7996575e835565f60ce2b3e.tar.gz
libimobiledevice-ec720cc1c30ac3f9b7996575e835565f60ce2b3e.tar.bz2
Refactor userpref logic to use plist format and implement trust dialog handling
iOS 7 introduced a new pairing workflow which increases security by showing a trust dialog to the user before pairing with the host is allowed. The userpref system was refactored to use the native plist format, too. Configuration files of the native implementations are used on each platform. Former configuration files are no longer in use and can be deleted.
Diffstat (limited to 'common')
-rw-r--r--common/userpref.c684
-rw-r--r--common/userpref.h36
2 files changed, 361 insertions, 359 deletions
diff --git a/common/userpref.c b/common/userpref.c
index 23fe583..41ce9b9 100644
--- a/common/userpref.c
+++ b/common/userpref.c
@@ -58,14 +58,6 @@
58#include "debug.h" 58#include "debug.h"
59#include "utils.h" 59#include "utils.h"
60 60
61#define LIBIMOBILEDEVICE_CONF_DIR "libimobiledevice"
62#define LIBIMOBILEDEVICE_CONF_FILE "libimobiledevicerc"
63
64#define LIBIMOBILEDEVICE_ROOT_PRIVKEY "RootPrivateKey.pem"
65#define LIBIMOBILEDEVICE_HOST_PRIVKEY "HostPrivateKey.pem"
66#define LIBIMOBILEDEVICE_ROOT_CERTIF "RootCertificate.pem"
67#define LIBIMOBILEDEVICE_HOST_CERTIF "HostCertificate.pem"
68
69#ifdef WIN32 61#ifdef WIN32
70#define DIR_SEP '\\' 62#define DIR_SEP '\\'
71#define DIR_SEP_S "\\" 63#define DIR_SEP_S "\\"
@@ -74,6 +66,19 @@
74#define DIR_SEP_S "/" 66#define DIR_SEP_S "/"
75#endif 67#endif
76 68
69#define USERPREF_CONFIG_EXTENSION ".plist"
70
71#ifndef __APPLE__
72#define USERPREF_CONFIG_DIR "libimobiledevice"
73#else
74#ifdef WIN32
75#define USERPREF_CONFIG_DIR "Apple"DIR_SEP_S"Lockdown"
76#else
77#define USERPREF_CONFIG_DIR "lockdown"
78#endif
79#endif
80#define USERPREF_CONFIG_FILE "SystemConfiguration"USERPREF_CONFIG_EXTENSION
81
77static char *__config_dir = NULL; 82static char *__config_dir = NULL;
78 83
79#ifdef WIN32 84#ifdef WIN32
@@ -172,7 +177,7 @@ static const char *userpref_get_config_dir()
172 LPITEMIDLIST pidl = NULL; 177 LPITEMIDLIST pidl = NULL;
173 BOOL b = FALSE; 178 BOOL b = FALSE;
174 179
175 hr = SHGetSpecialFolderLocation (NULL, CSIDL_LOCAL_APPDATA, &pidl); 180 hr = SHGetSpecialFolderLocation (NULL, CSIDL_COMMON_APPDATA, &pidl);
176 if (hr == S_OK) { 181 if (hr == S_OK) {
177 b = SHGetPathFromIDListW (pidl, path); 182 b = SHGetPathFromIDListW (pidl, path);
178 if (b) { 183 if (b) {
@@ -183,6 +188,10 @@ static const char *userpref_get_config_dir()
183 188
184 use_dot_config = 0; 189 use_dot_config = 0;
185#else 190#else
191#ifdef __APPLE__
192 base_config_dir = strdup("/var/db");
193 use_dot_config = 0;
194#else
186 const char *cdir = getenv("XDG_CONFIG_HOME"); 195 const char *cdir = getenv("XDG_CONFIG_HOME");
187 if (!cdir) { 196 if (!cdir) {
188 cdir = getenv("HOME"); 197 cdir = getenv("HOME");
@@ -200,11 +209,12 @@ static const char *userpref_get_config_dir()
200 use_dot_config = 0; 209 use_dot_config = 0;
201 } 210 }
202#endif 211#endif
212#endif
203 213
204 if (use_dot_config) 214 if (use_dot_config)
205 __config_dir = string_concat(base_config_dir, DIR_SEP_S, ".config", DIR_SEP_S, LIBIMOBILEDEVICE_CONF_DIR, NULL); 215 __config_dir = string_concat(base_config_dir, DIR_SEP_S, ".config", DIR_SEP_S, USERPREF_CONFIG_DIR, NULL);
206 else 216 else
207 __config_dir = string_concat(base_config_dir, DIR_SEP_S, LIBIMOBILEDEVICE_CONF_DIR, NULL); 217 __config_dir = string_concat(base_config_dir, DIR_SEP_S, USERPREF_CONFIG_DIR, NULL);
208 218
209 if (__config_dir) { 219 if (__config_dir) {
210 int i = strlen(__config_dir)-1; 220 int i = strlen(__config_dir)-1;
@@ -215,6 +225,8 @@ static const char *userpref_get_config_dir()
215 225
216 free(base_config_dir); 226 free(base_config_dir);
217 227
228 debug_info("initialized config_dir to %s", __config_dir);
229
218 return __config_dir; 230 return __config_dir;
219} 231}
220 232
@@ -250,131 +262,6 @@ static int mkdir_with_parents(const char *dir, int mode)
250 return res; 262 return res;
251} 263}
252 264
253static int config_write(const char *cfgfile, plist_t dict)
254{
255 if (!cfgfile || !dict || (plist_get_node_type(dict) != PLIST_DICT)) {
256 return -1;
257 }
258 int res = -1;
259
260#if 1 // old style config
261 plist_t hostid = plist_dict_get_item(dict, "HostID");
262 if (hostid && (plist_get_node_type(hostid) == PLIST_STRING)) {
263 char *hostidstr = NULL;
264 plist_get_string_val(hostid, &hostidstr);
265 if (hostidstr) {
266 FILE *fd = fopen(cfgfile, "wb");
267 if (fd) {
268 fprintf(fd, "\n[Global]\nHostID=%s\n", hostidstr);
269 fclose(fd);
270 res = 0;
271 } else {
272 debug_info("could not open '%s' for writing: %s", cfgfile, strerror(errno));
273 }
274 free(hostidstr);
275 }
276 }
277#endif
278#if 0
279 char *xml = NULL;
280 uint32_t length = 0;
281
282 plist_to_xml(dict, &xml, &length);
283 if (!xml) {
284 return res;
285 }
286
287 FILE *fd = fopen(cfgfile, "wb");
288 if (!fd) {
289 free(xml);
290 return res;
291 }
292
293 if (fwrite(xml, 1, length, fd) == length) {
294 res = 0;
295 } else {
296 fprintf(stderr, "%s: ERROR: failed to write configuration to '%s'\n", __func__, cfgfile);
297 }
298 fclose(fd);
299
300 free(xml);
301#endif
302 return res;
303}
304
305static int config_read(const char *cfgfile, plist_t *dict)
306{
307 if (!cfgfile || !dict) {
308 return -1;
309 }
310
311 int res = -1;
312 FILE *fd = fopen(cfgfile, "rb");
313 if (!fd) {
314 debug_info("could not open '%s' for reading: %s", cfgfile, strerror(errno));
315 return -1;
316 }
317
318 fseek(fd, 0, SEEK_END);
319 unsigned long int size = ftell(fd);
320 fseek(fd, 0, SEEK_SET);
321 unsigned char *contents = NULL;
322
323 contents = malloc(size);
324 if (fread(contents, 1, size, fd) != size) {
325 free(contents);
326 fclose(fd);
327 return -1;
328 }
329 plist_t plist = NULL;
330
331 if (!memcmp(contents, "bplist00", 8)) {
332 plist_from_bin((const char*)contents, (uint32_t)size, &plist);
333 fclose(fd);
334 } else {
335 if (memchr(contents, '<', size)) {
336 plist_from_xml((const char*)contents, (uint32_t)size, &plist);
337 }
338 if (plist) {
339 fclose(fd);
340 } else {
341 // try parsing old format config file
342 char line[256];
343 fseek(fd, 0, SEEK_SET);
344 while (fgets(line, 256, fd)) {
345 char *p = &line[0];
346 size_t llen = strlen(p)-1;
347 while ((llen > 0) && ((p[llen] == '\n') || (p[llen] == '\r'))) {
348 p[llen] = '\0';
349 llen--;
350 }
351 if (llen == 0) continue;
352 while ((p[0] == '\n') || (p[0] == '\r')) {
353 p++;
354 }
355 if (!strncmp(p, "HostID=", 7)) {
356 plist = plist_new_dict();
357 plist_dict_insert_item(plist, "HostID", plist_new_string(p+7));
358 break;
359 }
360 }
361 fclose(fd);
362#if 0
363 if (plist) {
364 // write new format config
365 config_write(cfgfile, plist);
366 }
367#endif
368 }
369 }
370 free(contents);
371 if (plist) {
372 *dict = plist;
373 res = 0;
374 }
375 return res;
376}
377
378/** 265/**
379 * Creates a freedesktop compatible configuration directory. 266 * Creates a freedesktop compatible configuration directory.
380 */ 267 */
@@ -398,12 +285,12 @@ static int get_rand(int min, int max)
398 * 285 *
399 * @return A null terminated string containing a valid HostID. 286 * @return A null terminated string containing a valid HostID.
400 */ 287 */
401static char *userpref_generate_host_id() 288static char *userpref_generate_host_id(int index)
402{ 289{
403 /* HostID's are just UUID's, and UUID's are 36 characters long */ 290 /* HostID's are just UUID's, and UUID's are 36 characters long */
404 char *hostid = (char *) malloc(sizeof(char) * 37); 291 char *hostid = (char *) malloc(sizeof(char) * 37);
405 const char *chars = "ABCDEF0123456789"; 292 const char *chars = "ABCDEF0123456789";
406 srand(time(NULL)); 293 srand(time(NULL) - index);
407 int i = 0; 294 int i = 0;
408 295
409 for (i = 0; i < 36; i++) { 296 for (i = 0; i < 36; i++) {
@@ -420,88 +307,193 @@ static char *userpref_generate_host_id()
420} 307}
421 308
422/** 309/**
423 * Store HostID in config file. 310 * Generates a valid BUID for this system (which is actually a UUID).
424 * 311 *
425 * @param host_id A null terminated string containing a valid HostID. 312 * @return A null terminated string containing a valid BUID.
426 */ 313 */
427static int userpref_set_host_id(const char *host_id) 314static char *userpref_generate_system_buid()
428{ 315{
429 const char *config_path; 316 return userpref_generate_host_id(1);
430 char *config_file; 317}
431 318
432 if (!host_id) 319static int internal_set_value(const char *config_file, const char *key, plist_t value)
320{
321 if (!config_file)
433 return 0; 322 return 0;
434 323
435 /* Make sure config directory exists */ 324 /* read file into plist */
436 userpref_create_config_dir();
437
438 config_path = userpref_get_config_dir();
439 config_file = (char*)malloc(strlen(config_path)+1+strlen(LIBIMOBILEDEVICE_CONF_FILE)+1);
440 strcpy(config_file, config_path);
441 strcat(config_file, DIR_SEP_S);
442 strcat(config_file, LIBIMOBILEDEVICE_CONF_FILE);
443
444 /* Now parse file to get the HostID */
445 plist_t config = NULL; 325 plist_t config = NULL;
446 config_read(config_file, &config); 326
327 plist_read_from_filename(&config, config_file);
447 if (!config) { 328 if (!config) {
448 config = plist_new_dict(); 329 config = plist_new_dict();
449 plist_dict_insert_item(config, "HostID", plist_new_string(host_id)); 330 plist_dict_insert_item(config, key, value);
450 } else { 331 } else {
451 plist_t n = plist_dict_get_item(config, "HostID"); 332 plist_t n = plist_dict_get_item(config, key);
452 if (n) { 333 if (n) {
453 plist_set_string_val(n, host_id); 334 plist_dict_remove_item(config, key);
454 } else {
455 plist_dict_insert_item(config, "HostID", plist_new_string(host_id));
456 } 335 }
336 plist_dict_insert_item(config, key, value);
337 remove(config_file);
338 }
339
340 /* store in config file */
341 char *value_string = NULL;
342 if (plist_get_node_type(value) == PLIST_STRING) {
343 plist_get_string_val(value, &value_string);
344 debug_info("setting key %s to %s in config_file %s", key, value_string, config_file);
345 } else {
346 debug_info("setting key %s in config_file %s", key, config_file);
457 } 347 }
458 348
459 /* Store in config file */ 349 plist_write_to_filename(config, config_file, PLIST_FORMAT_XML);
460 debug_info("setting hostID to %s", host_id);
461 350
462 config_write(config_file, config);
463 plist_free(config); 351 plist_free(config);
464 352
465 free(config_file);
466 return 1; 353 return 1;
467} 354}
468 355
469/** 356int userpref_set_value(const char *key, plist_t value)
470 * Reads the HostID from a previously generated configuration file.
471 *
472 * @note It is the responsibility of the calling function to free the returned host_id
473 *
474 * @return The string containing the HostID or NULL
475 */
476void userpref_get_host_id(char **host_id)
477{ 357{
478 const char *config_path; 358 const char *config_path = NULL;
479 char *config_file; 359 char *config_file = NULL;
360
361 /* Make sure config directory exists */
362 userpref_create_config_dir();
480 363
481 config_path = userpref_get_config_dir(); 364 config_path = userpref_get_config_dir();
482 config_file = (char*)malloc(strlen(config_path)+1+strlen(LIBIMOBILEDEVICE_CONF_FILE)+1); 365 config_file = string_concat(config_path, DIR_SEP_S, USERPREF_CONFIG_FILE, NULL);
483 strcpy(config_file, config_path); 366
484 strcat(config_file, DIR_SEP_S); 367 int result = internal_set_value(config_file, key, value);
485 strcat(config_file, LIBIMOBILEDEVICE_CONF_FILE); 368
369 free(config_file);
370
371 return result;
372}
373
374int userpref_device_record_set_value(const char *udid, const char *key, plist_t value)
375{
376 const char *config_path = NULL;
377 char *config_file = NULL;
378
379 /* Make sure config directory exists */
380 userpref_create_config_dir();
486 381
487 /* now parse file to get the HostID */ 382 config_path = userpref_get_config_dir();
383 config_file = string_concat(config_path, DIR_SEP_S, udid, USERPREF_CONFIG_EXTENSION, NULL);
384
385 int result = internal_set_value(config_file, key, value);
386
387 free(config_file);
388
389 return result;
390}
391
392static int internal_get_value(const char* config_file, const char *key, plist_t *value)
393{
394 *value = NULL;
395
396 /* now parse file to get the SystemBUID */
488 plist_t config = NULL; 397 plist_t config = NULL;
489 if (config_read(config_file, &config) == 0) { 398 if (plist_read_from_filename(&config, config_file)) {
490 plist_t n_host_id = plist_dict_get_item(config, "HostID"); 399 debug_info("reading key %s from config_file %s", key, config_file);
491 if (n_host_id && (plist_get_node_type(n_host_id) == PLIST_STRING)) { 400 plist_t n = plist_dict_get_item(config, key);
492 plist_get_string_val(n_host_id, host_id); 401 if (n) {
402 *value = plist_copy(n);
403 plist_free(n);
404 n = NULL;
493 } 405 }
494 } 406 }
495 plist_free(config); 407 plist_free(config);
408
409 return 1;
410}
411
412int userpref_get_value(const char *key, plist_t *value)
413{
414 const char *config_path = NULL;
415 char *config_file = NULL;
416
417 config_path = userpref_get_config_dir();
418 config_file = string_concat(config_path, DIR_SEP_S, USERPREF_CONFIG_FILE, NULL);
419
420 int result = internal_get_value(config_file, key, value);
421
422 free(config_file);
423
424 return result;
425}
426
427int userpref_device_record_get_value(const char *udid, const char *key, plist_t *value)
428{
429 const char *config_path = NULL;
430 char *config_file = NULL;
431
432 config_path = userpref_get_config_dir();
433 config_file = string_concat(config_path, DIR_SEP_S, udid, USERPREF_CONFIG_EXTENSION, NULL);
434
435 int result = internal_get_value(config_file, key, value);
436
496 free(config_file); 437 free(config_file);
497 438
439 return result;
440}
441
442/**
443 * Store SystemBUID in config file.
444 *
445 * @param host_id A null terminated string containing a valid SystemBUID.
446 */
447static int userpref_set_system_buid(const char *system_buid)
448{
449 return userpref_set_value(USERPREF_SYSTEM_BUID_KEY, plist_new_string(system_buid));
450}
451
452/**
453 * Reads the BUID from a previously generated configuration file.
454 *
455 * @note It is the responsibility of the calling function to free the returned system_buid
456 *
457 * @return The string containing the BUID or NULL
458 */
459void userpref_get_system_buid(char **system_buid)
460{
461 plist_t value = NULL;
462
463 userpref_get_value(USERPREF_SYSTEM_BUID_KEY, &value);
464
465 if (value && (plist_get_node_type(value) == PLIST_STRING)) {
466 plist_get_string_val(value, system_buid);
467 debug_info("got %s %s", USERPREF_SYSTEM_BUID_KEY, *system_buid);
468 }
469
470 if (!*system_buid) {
471 /* no config, generate system_buid */
472 debug_info("no previous %s found", USERPREF_SYSTEM_BUID_KEY);
473 *system_buid = userpref_generate_system_buid();
474 userpref_set_system_buid(*system_buid);
475 }
476
477 debug_info("using %s as %s", *system_buid, USERPREF_SYSTEM_BUID_KEY);
478}
479
480void userpref_device_record_get_host_id(const char *udid, char **host_id)
481{
482 plist_t value = NULL;
483
484 userpref_device_record_get_value(udid, USERPREF_HOST_ID_KEY, &value);
485
486 if (value && (plist_get_node_type(value) == PLIST_STRING)) {
487 plist_get_string_val(value, host_id);
488 }
489
498 if (!*host_id) { 490 if (!*host_id) {
499 /* no config, generate host_id */ 491 /* no config, generate host_id */
500 *host_id = userpref_generate_host_id(); 492 *host_id = userpref_generate_host_id(0);
501 userpref_set_host_id(*host_id); 493 userpref_device_record_set_value(udid, USERPREF_HOST_ID_KEY, plist_new_string(*host_id));
502 } 494 }
503 495
504 debug_info("Using %s as HostID", *host_id); 496 debug_info("using %s as %s", *host_id, USERPREF_HOST_ID_KEY);
505} 497}
506 498
507/** 499/**
@@ -512,26 +504,24 @@ void userpref_get_host_id(char **host_id)
512 * @return 1 if the device has been connected previously to this configuration 504 * @return 1 if the device has been connected previously to this configuration
513 * or 0 otherwise. 505 * or 0 otherwise.
514 */ 506 */
515int userpref_has_device_public_key(const char *udid) 507int userpref_has_device_record(const char *udid)
516{ 508{
517 int ret = 0; 509 int ret = 0;
518 const char *config_path; 510 const char *config_path = NULL;
519 char *config_file; 511 char *config_file = NULL;
520 struct stat st; 512 struct stat st;
521 513
522 if (!udid) return 0; 514 if (!udid) return 0;
523 515
524 /* first get config file */ 516 /* first get config file */
525 config_path = userpref_get_config_dir(); 517 config_path = userpref_get_config_dir();
526 config_file = (char*)malloc(strlen(config_path)+1+strlen(udid)+4+1); 518 config_file = string_concat(config_path, DIR_SEP_S, udid, USERPREF_CONFIG_EXTENSION, NULL);
527 strcpy(config_file, config_path);
528 strcat(config_file, DIR_SEP_S);
529 strcat(config_file, udid);
530 strcat(config_file, ".pem");
531 519
532 if ((stat(config_file, &st) == 0) && S_ISREG(st.st_mode)) 520 if ((stat(config_file, &st) == 0) && S_ISREG(st.st_mode))
533 ret = 1; 521 ret = 1;
522
534 free(config_file); 523 free(config_file);
524
535 return ret; 525 return ret;
536} 526}
537 527
@@ -557,7 +547,7 @@ userpref_error_t userpref_get_paired_udids(char ***list, unsigned int *count)
557 void *next; 547 void *next;
558 }; 548 };
559 DIR *config_dir; 549 DIR *config_dir;
560 const char *config_path; 550 const char *config_path = NULL;
561 struct slist_t *udids = NULL; 551 struct slist_t *udids = NULL;
562 unsigned int i; 552 unsigned int i;
563 unsigned int found = 0; 553 unsigned int found = 0;
@@ -577,8 +567,8 @@ userpref_error_t userpref_get_paired_udids(char ***list, unsigned int *count)
577 struct dirent *entry; 567 struct dirent *entry;
578 struct slist_t *listp = udids; 568 struct slist_t *listp = udids;
579 while ((entry = readdir(config_dir))) { 569 while ((entry = readdir(config_dir))) {
580 char *ext = strstr(entry->d_name, ".pem"); 570 char *ext = strstr(entry->d_name, USERPREF_CONFIG_EXTENSION);
581 if (ext && ((ext - entry->d_name) == 40) && (strlen(entry->d_name) == 44)) { 571 if (ext && ((ext - entry->d_name) == 40) && (strlen(entry->d_name) == (40 + strlen(ext)))) {
582 struct slist_t *ne = (struct slist_t*)malloc(sizeof(struct slist_t)); 572 struct slist_t *ne = (struct slist_t*)malloc(sizeof(struct slist_t));
583 ne->name = (char*)malloc(41); 573 ne->name = (char*)malloc(41);
584 strncpy(ne->name, entry->d_name, 40); 574 strncpy(ne->name, entry->d_name, 40);
@@ -614,75 +604,77 @@ userpref_error_t userpref_get_paired_udids(char ***list, unsigned int *count)
614} 604}
615 605
616/** 606/**
617 * Mark the device (as represented by the key) as having connected to this 607 * Mark the device as having connected to this configuration.
618 * configuration.
619 * 608 *
620 * @param udid The device UDID as given by the device 609 * @param udid The device UDID as given by the device
621 * @param public_key The public key given by the device 610 * @param device_record The device record with full configuration
622 * 611 *
623 * @return 1 on success and 0 if no public key is given or if it has already 612 * @return 1 on success and 0 if no device record is given or if it has already
624 * been marked as connected previously. 613 * been marked as connected previously.
625 */ 614 */
626userpref_error_t userpref_set_device_public_key(const char *udid, key_data_t public_key) 615userpref_error_t userpref_set_device_record(const char *udid, plist_t device_record)
627{ 616{
628 if (NULL == public_key.data)
629 return USERPREF_E_INVALID_ARG;
630
631 if (userpref_has_device_public_key(udid))
632 return USERPREF_E_SUCCESS;
633
634 /* ensure config directory exists */ 617 /* ensure config directory exists */
635 userpref_create_config_dir(); 618 userpref_create_config_dir();
636 619
637 /* build file path */ 620 /* build file path */
638 const char *config_path = userpref_get_config_dir(); 621 const char *config_path = userpref_get_config_dir();
639 char *pem = (char*)malloc(strlen(config_path)+1+strlen(udid)+4+1); 622 char *device_record_file = string_concat(config_path, DIR_SEP_S, udid, USERPREF_CONFIG_EXTENSION, NULL);
640 strcpy(pem, config_path); 623
641 strcat(pem, DIR_SEP_S); 624 remove(device_record_file);
642 strcat(pem, udid);
643 strcat(pem, ".pem");
644 625
645 /* store file */ 626 /* store file */
646 FILE *pFile = fopen(pem, "wb"); 627 if (!plist_write_to_filename(device_record, device_record_file, PLIST_FORMAT_XML)) {
647 if (pFile) { 628 debug_info("could not open '%s' for writing: %s", device_record_file, strerror(errno));
648 fwrite(public_key.data, 1, public_key.size, pFile); 629 }
649 fclose(pFile); 630 free(device_record_file);
650 } else { 631
651 debug_info("could not open '%s' for writing: %s", pem, strerror(errno)); 632 return USERPREF_E_SUCCESS;
633}
634
635userpref_error_t userpref_get_device_record(const char *udid, plist_t *device_record)
636{
637 /* ensure config directory exists */
638 userpref_create_config_dir();
639
640 /* build file path */
641 const char *config_path = userpref_get_config_dir();
642 char *device_record_file = string_concat(config_path, DIR_SEP_S, udid, USERPREF_CONFIG_EXTENSION, NULL);
643
644 /* read file */
645 if (!plist_read_from_filename(device_record, device_record_file)) {
646 debug_info("could not open '%s' for reading: %s", device_record_file, strerror(errno));
652 } 647 }
653 free(pem); 648 free(device_record_file);
654 649
655 return USERPREF_E_SUCCESS; 650 return USERPREF_E_SUCCESS;
656} 651}
657 652
658/** 653/**
659 * Remove the public key stored for the device with udid from this host. 654 * Remove the pairing record stored for a device from this host.
660 * 655 *
661 * @param udid The udid of the device 656 * @param udid The udid of the device
662 * 657 *
663 * @return USERPREF_E_SUCCESS on success. 658 * @return USERPREF_E_SUCCESS on success.
664 */ 659 */
665userpref_error_t userpref_remove_device_public_key(const char *udid) 660userpref_error_t userpref_remove_device_record(const char *udid)
666{ 661{
667 if (!userpref_has_device_public_key(udid)) 662 if (!userpref_has_device_record(udid))
668 return USERPREF_E_SUCCESS; 663 return USERPREF_E_SUCCESS;
669 664
670 /* build file path */ 665 /* build file path */
671 const char *config_path = userpref_get_config_dir(); 666 const char *config_path = userpref_get_config_dir();
672 char *pem = (char*)malloc(strlen(config_path)+1+strlen(udid)+4+1); 667 char *device_record_file = string_concat(config_path, DIR_SEP_S, udid, USERPREF_CONFIG_EXTENSION, NULL);
673 strcpy(pem, config_path);
674 strcat(pem, DIR_SEP_S);
675 strcat(pem, udid);
676 strcat(pem, ".pem");
677 668
678 /* remove file */ 669 /* remove file */
679 remove(pem); 670 remove(device_record_file);
680 671
681 free(pem); 672 free(device_record_file);
682 673
683 return USERPREF_E_SUCCESS; 674 return USERPREF_E_SUCCESS;
684} 675}
685 676
677#if 0
686/** 678/**
687 * Private function which reads the given file into a key_data_t structure. 679 * Private function which reads the given file into a key_data_t structure.
688 * 680 *
@@ -696,7 +688,7 @@ static int userpref_get_file_contents(const char *file, key_data_t * data)
696 int success = 0; 688 int success = 0;
697 unsigned long int size = 0; 689 unsigned long int size = 0;
698 unsigned char *content = NULL; 690 unsigned char *content = NULL;
699 const char *config_path; 691 const char *config_path = NULL;
700 char *filepath; 692 char *filepath;
701 FILE *fd; 693 FILE *fd;
702 694
@@ -705,10 +697,7 @@ static int userpref_get_file_contents(const char *file, key_data_t * data)
705 697
706 /* Read file */ 698 /* Read file */
707 config_path = userpref_get_config_dir(); 699 config_path = userpref_get_config_dir();
708 filepath = (char*)malloc(strlen(config_path)+1+strlen(file)+1); 700 filepath = string_concat(config_path, DIR_SEP_S, file, NULL);
709 strcpy(filepath, config_path);
710 strcat(filepath, DIR_SEP_S);
711 strcat(filepath, file);
712 701
713 fd = fopen(filepath, "rb"); 702 fd = fopen(filepath, "rb");
714 if (fd) { 703 if (fd) {
@@ -746,13 +735,14 @@ static int userpref_get_file_contents(const char *file, key_data_t * data)
746 735
747 return success; 736 return success;
748} 737}
738#endif
749 739
750/** 740/**
751 * Private function which generate private keys and certificates. 741 * Private function which generate private keys and certificates.
752 * 742 *
753 * @return 1 if keys were successfully generated, 0 otherwise 743 * @return 1 if keys were successfully generated, 0 otherwise
754 */ 744 */
755static userpref_error_t userpref_gen_keys_and_cert(void) 745static userpref_error_t userpref_device_record_gen_keys_and_cert(const char* udid)
756{ 746{
757 userpref_error_t ret = USERPREF_E_SSL_ERROR; 747 userpref_error_t ret = USERPREF_E_SSL_ERROR;
758 748
@@ -761,7 +751,7 @@ static userpref_error_t userpref_gen_keys_and_cert(void)
761 key_data_t host_key_pem = { NULL, 0 }; 751 key_data_t host_key_pem = { NULL, 0 };
762 key_data_t host_cert_pem = { NULL, 0 }; 752 key_data_t host_cert_pem = { NULL, 0 };
763 753
764 debug_info("Generating keys and certificates"); 754 debug_info("generating keys and certificates");
765#ifdef HAVE_OPENSSL 755#ifdef HAVE_OPENSSL
766 RSA* root_keypair = RSA_generate_key(2048, 65537, NULL, NULL); 756 RSA* root_keypair = RSA_generate_key(2048, 65537, NULL, NULL);
767 RSA* host_keypair = RSA_generate_key(2048, 65537, NULL, NULL); 757 RSA* host_keypair = RSA_generate_key(2048, 65537, NULL, NULL);
@@ -880,7 +870,7 @@ static userpref_error_t userpref_gen_keys_and_cert(void)
880 gnutls_global_deinit(); 870 gnutls_global_deinit();
881 gnutls_global_init(); 871 gnutls_global_init();
882 872
883 //use less secure random to speed up key generation 873 /* use less secure random to speed up key generation */
884 gcry_control(GCRYCTL_ENABLE_QUICK_RANDOM); 874 gcry_control(GCRYCTL_ENABLE_QUICK_RANDOM);
885 875
886 gnutls_x509_privkey_init(&root_privkey); 876 gnutls_x509_privkey_init(&root_privkey);
@@ -940,7 +930,7 @@ static userpref_error_t userpref_gen_keys_and_cert(void)
940 gnutls_x509_crt_export(host_cert, GNUTLS_X509_FMT_PEM, host_cert_pem.data, &host_cert_export_size); 930 gnutls_x509_crt_export(host_cert, GNUTLS_X509_FMT_PEM, host_cert_pem.data, &host_cert_export_size);
941 host_cert_pem.size = host_cert_export_size; 931 host_cert_pem.size = host_cert_export_size;
942 932
943 //restore gnutls env 933 /* restore gnutls env */
944 gnutls_global_deinit(); 934 gnutls_global_deinit();
945 gnutls_global_init(); 935 gnutls_global_init();
946#endif 936#endif
@@ -949,7 +939,7 @@ static userpref_error_t userpref_gen_keys_and_cert(void)
949 ret = USERPREF_E_SUCCESS; 939 ret = USERPREF_E_SUCCESS;
950 940
951 /* store values in config file */ 941 /* store values in config file */
952 userpref_set_keys_and_certs( &root_key_pem, &root_cert_pem, &host_key_pem, &host_cert_pem); 942 userpref_device_record_set_keys_and_certs(udid, &root_key_pem, &root_cert_pem, &host_key_pem, &host_cert_pem);
953 943
954 if (root_key_pem.data) 944 if (root_key_pem.data)
955 free(root_key_pem.data); 945 free(root_key_pem.data);
@@ -966,15 +956,15 @@ static userpref_error_t userpref_gen_keys_and_cert(void)
966/** 956/**
967 * Private function which import the given key into a gnutls structure. 957 * Private function which import the given key into a gnutls structure.
968 * 958 *
969 * @param key_name The filename of the private key to import. 959 * @param name The name of the private key to import.
970 * @param key the gnutls key structure. 960 * @param key the gnutls key structure.
971 * 961 *
972 * @return 1 if the key was successfully imported. 962 * @return 1 if the key was successfully imported.
973 */ 963 */
974#ifdef HAVE_OPENSSL 964#ifdef HAVE_OPENSSL
975static userpref_error_t userpref_import_key(const char* key_name, key_data_t* key) 965static userpref_error_t userpref_device_record_import_key(const char* udid, const char* name, key_data_t* key)
976#else 966#else
977static userpref_error_t userpref_import_key(const char* key_name, gnutls_x509_privkey_t key) 967static userpref_error_t userpref_device_record_import_key(const char* udid, const char* name, gnutls_x509_privkey_t key)
978#endif 968#endif
979{ 969{
980#ifdef HAVE_OPENSSL 970#ifdef HAVE_OPENSSL
@@ -982,37 +972,49 @@ static userpref_error_t userpref_import_key(const char* key_name, gnutls_x509_pr
982 return USERPREF_E_SUCCESS; 972 return USERPREF_E_SUCCESS;
983#endif 973#endif
984 userpref_error_t ret = USERPREF_E_INVALID_CONF; 974 userpref_error_t ret = USERPREF_E_INVALID_CONF;
985 key_data_t pem_key = { NULL, 0 }; 975 char* buffer = NULL;
986 if (userpref_get_file_contents(key_name, &pem_key)) { 976 uint64_t length = 0;
977
978 plist_t crt = NULL;
979 if (userpref_device_record_get_value(udid, name, &crt)) {
980 if (crt && plist_get_node_type(crt) == PLIST_DATA) {
981 plist_get_data_val(crt, &buffer, &length);
987#ifdef HAVE_OPENSSL 982#ifdef HAVE_OPENSSL
988 key->data = (unsigned char*)malloc(pem_key.size); 983 key->data = (unsigned char*)malloc(length);
989 memcpy(key->data, pem_key.data, pem_key.size); 984 memcpy(key->data, buffer, length);
990 key->size = pem_key.size; 985 key->size = length;
991 ret = USERPREF_E_SUCCESS;
992#else
993 if (GNUTLS_E_SUCCESS == gnutls_x509_privkey_import(key, &pem_key, GNUTLS_X509_FMT_PEM))
994 ret = USERPREF_E_SUCCESS; 986 ret = USERPREF_E_SUCCESS;
995 else 987#else
996 ret = USERPREF_E_SSL_ERROR; 988 key_data_t pem = { buffer, length };
989 if (GNUTLS_E_SUCCESS == gnutls_x509_privkey_import(key, &pem, GNUTLS_X509_FMT_PEM))
990 ret = USERPREF_E_SUCCESS;
991 else
992 ret = USERPREF_E_SSL_ERROR;
997#endif 993#endif
994 }
998 } 995 }
999 if (pem_key.data) 996
1000 free(pem_key.data); 997 if (crt)
998 plist_free(crt);
999
1000 if (buffer)
1001 free(buffer);
1002
1001 return ret; 1003 return ret;
1002} 1004}
1003 1005
1004/** 1006/**
1005 * Private function which import the given certificate into a gnutls structure. 1007 * Private function which import the given certificate into a gnutls structure.
1006 * 1008 *
1007 * @param crt_name The filename of the certificate to import. 1009 * @param name The name of the certificate to import.
1008 * @param cert the gnutls certificate structure. 1010 * @param cert the gnutls certificate structure.
1009 * 1011 *
1010 * @return IDEVICE_E_SUCCESS if the certificate was successfully imported. 1012 * @return IDEVICE_E_SUCCESS if the certificate was successfully imported.
1011 */ 1013 */
1012#ifdef HAVE_OPENSSL 1014#ifdef HAVE_OPENSSL
1013static userpref_error_t userpref_import_crt(const char* crt_name, key_data_t* cert) 1015static userpref_error_t userpref_device_record_import_crt(const char* udid, const char* name, key_data_t* cert)
1014#else 1016#else
1015static userpref_error_t userpref_import_crt(const char* crt_name, gnutls_x509_crt_t cert) 1017static userpref_error_t userpref_device_record_import_crt(const char* udid, const char* name, gnutls_x509_crt_t cert)
1016#endif 1018#endif
1017{ 1019{
1018#ifdef HAVE_OPENSSL 1020#ifdef HAVE_OPENSSL
@@ -1020,23 +1022,34 @@ static userpref_error_t userpref_import_crt(const char* crt_name, gnutls_x509_cr
1020 return USERPREF_E_SUCCESS; 1022 return USERPREF_E_SUCCESS;
1021#endif 1023#endif
1022 userpref_error_t ret = USERPREF_E_INVALID_CONF; 1024 userpref_error_t ret = USERPREF_E_INVALID_CONF;
1023 key_data_t pem_cert = { NULL, 0 }; 1025 char* buffer = NULL;
1026 uint64_t length = 0;
1024 1027
1025 if (userpref_get_file_contents(crt_name, &pem_cert)) { 1028 plist_t crt = NULL;
1029 if (userpref_device_record_get_value(udid, name, &crt)) {
1030 if (crt && plist_get_node_type(crt) == PLIST_DATA) {
1031 plist_get_data_val(crt, &buffer, &length);
1026#ifdef HAVE_OPENSSL 1032#ifdef HAVE_OPENSSL
1027 cert->data = (unsigned char*)malloc(pem_cert.size); 1033 cert->data = (unsigned char*)malloc(length);
1028 memcpy(cert->data, pem_cert.data, pem_cert.size); 1034 memcpy(cert->data, buffer, length);
1029 cert->size = pem_cert.size; 1035 cert->size = length;
1030 ret = USERPREF_E_SUCCESS;
1031#else
1032 if (GNUTLS_E_SUCCESS == gnutls_x509_crt_import(cert, &pem_cert, GNUTLS_X509_FMT_PEM))
1033 ret = USERPREF_E_SUCCESS; 1036 ret = USERPREF_E_SUCCESS;
1034 else 1037#else
1035 ret = USERPREF_E_SSL_ERROR; 1038 key_data_t pem = { buffer, length };
1039 if (GNUTLS_E_SUCCESS == gnutls_x509_crt_import(cert, &pem, GNUTLS_X509_FMT_PEM))
1040 ret = USERPREF_E_SUCCESS;
1041 else
1042 ret = USERPREF_E_SSL_ERROR;
1036#endif 1043#endif
1044 }
1037 } 1045 }
1038 if (pem_cert.data) 1046
1039 free(pem_cert.data); 1047 if (crt)
1048 plist_free(crt);
1049
1050 if (buffer)
1051 free(buffer);
1052
1040 return ret; 1053 return ret;
1041} 1054}
1042 1055
@@ -1054,41 +1067,40 @@ static userpref_error_t userpref_import_crt(const char* crt_name, gnutls_x509_cr
1054 * @return 1 if the keys and certificates were successfully retrieved, 0 otherwise 1067 * @return 1 if the keys and certificates were successfully retrieved, 0 otherwise
1055 */ 1068 */
1056#ifdef HAVE_OPENSSL 1069#ifdef HAVE_OPENSSL
1057userpref_error_t userpref_get_keys_and_certs(key_data_t* root_privkey, key_data_t* root_crt, key_data_t* host_privkey, key_data_t* host_crt) 1070userpref_error_t userpref_device_record_get_keys_and_certs(const char *udid, key_data_t* root_privkey, key_data_t* root_crt, key_data_t* host_privkey, key_data_t* host_crt)
1058#else 1071#else
1059userpref_error_t userpref_get_keys_and_certs(gnutls_x509_privkey_t root_privkey, gnutls_x509_crt_t root_crt, gnutls_x509_privkey_t host_privkey, gnutls_x509_crt_t host_crt) 1072userpref_error_t userpref_device_record_get_keys_and_certs(const char *udid, gnutls_x509_privkey_t root_privkey, gnutls_x509_crt_t root_crt, gnutls_x509_privkey_t host_privkey, gnutls_x509_crt_t host_crt)
1060#endif 1073#endif
1061{ 1074{
1062 userpref_error_t ret = USERPREF_E_SUCCESS; 1075 userpref_error_t ret = USERPREF_E_SUCCESS;
1063 1076
1064 if (ret == USERPREF_E_SUCCESS) 1077 if (ret == USERPREF_E_SUCCESS)
1065 ret = userpref_import_key(LIBIMOBILEDEVICE_ROOT_PRIVKEY, root_privkey); 1078 ret = userpref_device_record_import_key(udid, USERPREF_ROOT_PRIVATE_KEY_KEY, root_privkey);
1066 1079
1067 if (ret == USERPREF_E_SUCCESS) 1080 if (ret == USERPREF_E_SUCCESS)
1068 ret = userpref_import_key(LIBIMOBILEDEVICE_HOST_PRIVKEY, host_privkey); 1081 ret = userpref_device_record_import_key(udid, USERPREF_HOST_PRIVATE_KEY_KEY, host_privkey);
1069 1082
1070 if (ret == USERPREF_E_SUCCESS) 1083 if (ret == USERPREF_E_SUCCESS)
1071 ret = userpref_import_crt(LIBIMOBILEDEVICE_ROOT_CERTIF, root_crt); 1084 ret = userpref_device_record_import_crt(udid, USERPREF_ROOT_CERTIFICATE_KEY, root_crt);
1072 1085
1073 if (ret == USERPREF_E_SUCCESS) 1086 if (ret == USERPREF_E_SUCCESS)
1074 ret = userpref_import_crt(LIBIMOBILEDEVICE_HOST_CERTIF, host_crt); 1087 ret = userpref_device_record_import_crt(udid, USERPREF_HOST_CERTIFICATE_KEY, host_crt);
1075 1088
1076 if (USERPREF_E_SUCCESS != ret) { 1089 if (USERPREF_E_SUCCESS != ret) {
1077 //we had problem reading or importing root cert 1090 /* we had problem reading or importing root cert, try with new ones */
1078 //try with a new ones. 1091 ret = userpref_device_record_gen_keys_and_cert(udid);
1079 ret = userpref_gen_keys_and_cert();
1080 1092
1081 if (ret == USERPREF_E_SUCCESS) 1093 if (ret == USERPREF_E_SUCCESS)
1082 ret = userpref_import_key(LIBIMOBILEDEVICE_ROOT_PRIVKEY, root_privkey); 1094 ret = userpref_device_record_import_key(udid, USERPREF_ROOT_PRIVATE_KEY_KEY, root_privkey);
1083 1095
1084 if (ret == USERPREF_E_SUCCESS) 1096 if (ret == USERPREF_E_SUCCESS)
1085 ret = userpref_import_key(LIBIMOBILEDEVICE_HOST_PRIVKEY, host_privkey); 1097 ret = userpref_device_record_import_key(udid, USERPREF_HOST_PRIVATE_KEY_KEY, host_privkey);
1086 1098
1087 if (ret == USERPREF_E_SUCCESS) 1099 if (ret == USERPREF_E_SUCCESS)
1088 ret = userpref_import_crt(LIBIMOBILEDEVICE_ROOT_CERTIF, root_crt); 1100 ret = userpref_device_record_import_crt(udid, USERPREF_ROOT_CERTIFICATE_KEY, root_crt);
1089 1101
1090 if (ret == USERPREF_E_SUCCESS) 1102 if (ret == USERPREF_E_SUCCESS)
1091 ret = userpref_import_crt(LIBIMOBILEDEVICE_HOST_CERTIF, host_crt); 1103 ret = userpref_device_record_import_crt(udid, USERPREF_ROOT_CERTIFICATE_KEY, host_crt);
1092 } 1104 }
1093 1105
1094 return ret; 1106 return ret;
@@ -1102,14 +1114,36 @@ userpref_error_t userpref_get_keys_and_certs(gnutls_x509_privkey_t root_privkey,
1102 * 1114 *
1103 * @return 1 if the certificates were successfully retrieved, 0 otherwise 1115 * @return 1 if the certificates were successfully retrieved, 0 otherwise
1104 */ 1116 */
1105userpref_error_t userpref_get_certs_as_pem(key_data_t *pem_root_cert, key_data_t *pem_host_cert) 1117userpref_error_t userpref_device_record_get_certs_as_pem(const char *udid, key_data_t *pem_root_cert, key_data_t *pem_host_cert)
1106{ 1118{
1107 if (!pem_root_cert || !pem_host_cert) 1119 if (!udid || !pem_root_cert || !pem_host_cert)
1108 return USERPREF_E_INVALID_ARG; 1120 return USERPREF_E_INVALID_ARG;
1109 1121
1110 if (userpref_get_file_contents(LIBIMOBILEDEVICE_ROOT_CERTIF, pem_root_cert) && userpref_get_file_contents(LIBIMOBILEDEVICE_HOST_CERTIF, pem_host_cert)) 1122 char* buffer = NULL;
1123 uint64_t length = 0;
1124 plist_t root_cert = NULL;
1125 plist_t host_cert = NULL;
1126 if (userpref_device_record_get_value(udid, USERPREF_HOST_CERTIFICATE_KEY, &host_cert) &&
1127 userpref_device_record_get_value(udid, USERPREF_ROOT_CERTIFICATE_KEY, &root_cert)) {
1128 if (host_cert && plist_get_node_type(host_cert) == PLIST_DATA) {
1129 plist_get_data_val(host_cert, &buffer, &length);
1130 pem_host_cert->data = (unsigned char*)malloc(length);
1131 memcpy(pem_host_cert->data, buffer, length);
1132 pem_host_cert->size = length;
1133 free(buffer);
1134 buffer = NULL;
1135 }
1136 if (root_cert && plist_get_node_type(root_cert) == PLIST_DATA) {
1137 plist_get_data_val(root_cert, &buffer, &length);
1138 pem_root_cert->data = (unsigned char*)malloc(length);
1139 memcpy(pem_root_cert->data, buffer, length);
1140 pem_root_cert->size = length;
1141 free(buffer);
1142 buffer = NULL;
1143 }
1144
1111 return USERPREF_E_SUCCESS; 1145 return USERPREF_E_SUCCESS;
1112 else { 1146 } else {
1113 if (pem_root_cert->data) { 1147 if (pem_root_cert->data) {
1114 free(pem_root_cert->data); 1148 free(pem_root_cert->data);
1115 pem_root_cert->size = 0; 1149 pem_root_cert->size = 0;
@@ -1119,7 +1153,9 @@ userpref_error_t userpref_get_certs_as_pem(key_data_t *pem_root_cert, key_data_t
1119 pem_host_cert->size = 0; 1153 pem_host_cert->size = 0;
1120 } 1154 }
1121 } 1155 }
1156
1122 debug_info("configuration invalid"); 1157 debug_info("configuration invalid");
1158
1123 return USERPREF_E_INVALID_CONF; 1159 return USERPREF_E_INVALID_CONF;
1124} 1160}
1125 1161
@@ -1135,81 +1171,27 @@ userpref_error_t userpref_get_certs_as_pem(key_data_t *pem_root_cert, key_data_t
1135 * 1171 *
1136 * @return 1 on success and 0 otherwise. 1172 * @return 1 on success and 0 otherwise.
1137 */ 1173 */
1138userpref_error_t userpref_set_keys_and_certs(key_data_t * root_key, key_data_t * root_cert, key_data_t * host_key, key_data_t * host_cert) 1174userpref_error_t userpref_device_record_set_keys_and_certs(const char* udid, key_data_t * root_key, key_data_t * root_cert, key_data_t * host_key, key_data_t * host_cert)
1139{ 1175{
1140 FILE *pFile;
1141 char *pem;
1142 const char *config_path;
1143 userpref_error_t ret = USERPREF_E_SUCCESS; 1176 userpref_error_t ret = USERPREF_E_SUCCESS;
1144 1177
1145 debug_info("saving keys and certs"); 1178 debug_info("saving keys and certs for udid %s", udid);
1146 1179
1147 if (!root_key || !host_key || !root_cert || !host_cert) { 1180 if (!root_key || !host_key || !root_cert || !host_cert) {
1148 debug_info("missing key or cert (root_key=%p, host_key=%p, root=cert=%p, host_cert=%p", root_key, host_key, root_cert, host_cert); 1181 debug_info("missing key or cert (root_key=%p, host_key=%p, root=cert=%p, host_cert=%p", root_key, host_key, root_cert, host_cert);
1149 return USERPREF_E_INVALID_ARG; 1182 return USERPREF_E_INVALID_ARG;
1150 } 1183 }
1151 1184
1152 /* Make sure config directory exists */ 1185 /* now write keys and certificates to disk */
1153 userpref_create_config_dir(); 1186 if (userpref_device_record_set_value(udid, USERPREF_HOST_PRIVATE_KEY_KEY, plist_new_data((char*)host_key->data, host_key->size)) &&
1154 1187 userpref_device_record_set_value(udid, USERPREF_HOST_CERTIFICATE_KEY, plist_new_data((char*)host_cert->data, host_cert->size)) &&
1155 config_path = userpref_get_config_dir(); 1188 userpref_device_record_set_value(udid, USERPREF_ROOT_PRIVATE_KEY_KEY, plist_new_data((char*)root_key->data, root_key->size)) &&
1156 1189 userpref_device_record_set_value(udid, USERPREF_ROOT_CERTIFICATE_KEY, plist_new_data((char*)root_cert->data, root_cert->size)))
1157 /* Now write keys and certificates to disk */ 1190 {
1158 pem = (char*)malloc(strlen(config_path)+1+strlen(LIBIMOBILEDEVICE_ROOT_PRIVKEY)+1); 1191 ret = USERPREF_E_SUCCESS;
1159 strcpy(pem, config_path);
1160 strcat(pem, DIR_SEP_S);
1161 strcat(pem, LIBIMOBILEDEVICE_ROOT_PRIVKEY);
1162 pFile = fopen(pem, "wb");
1163 if (pFile) {
1164 fwrite(root_key->data, 1, root_key->size, pFile);
1165 fclose(pFile);
1166 } else {
1167 debug_info("could not open '%s' for writing: %s", pem, strerror(errno));
1168 ret = USERPREF_E_WRITE_ERROR;
1169 }
1170 free(pem);
1171
1172 pem = (char*)malloc(strlen(config_path)+1+strlen(LIBIMOBILEDEVICE_HOST_PRIVKEY)+1);
1173 strcpy(pem, config_path);
1174 strcat(pem, DIR_SEP_S);
1175 strcat(pem, LIBIMOBILEDEVICE_HOST_PRIVKEY);
1176 pFile = fopen(pem, "wb");
1177 if (pFile) {
1178 fwrite(host_key->data, 1, host_key->size, pFile);
1179 fclose(pFile);
1180 } else {
1181 debug_info("could not open '%s' for writing: %s", pem, strerror(errno));
1182 ret = USERPREF_E_WRITE_ERROR;
1183 }
1184 free(pem);
1185
1186 pem = (char*)malloc(strlen(config_path)+1+strlen(LIBIMOBILEDEVICE_ROOT_CERTIF)+1);
1187 strcpy(pem, config_path);
1188 strcat(pem, DIR_SEP_S);
1189 strcat(pem, LIBIMOBILEDEVICE_ROOT_CERTIF);
1190 pFile = fopen(pem, "wb");
1191 if (pFile) {
1192 fwrite(root_cert->data, 1, root_cert->size, pFile);
1193 fclose(pFile);
1194 } else {
1195 debug_info("could not open '%s' for writing: %s", pem, strerror(errno));
1196 ret = USERPREF_E_WRITE_ERROR;
1197 }
1198 free(pem);
1199
1200 pem = (char*)malloc(strlen(config_path)+1+strlen(LIBIMOBILEDEVICE_HOST_CERTIF)+1);
1201 strcpy(pem, config_path);
1202 strcat(pem, DIR_SEP_S);
1203 strcat(pem, LIBIMOBILEDEVICE_HOST_CERTIF);
1204 pFile = fopen(pem, "wb");
1205 if (pFile) {
1206 fwrite(host_cert->data, 1, host_cert->size, pFile);
1207 fclose(pFile);
1208 } else { 1192 } else {
1209 debug_info("could not open '%s' for writing: %s", pem, strerror(errno)); 1193 ret = 1;
1210 ret = USERPREF_E_WRITE_ERROR;
1211 } 1194 }
1212 free(pem);
1213 1195
1214 return ret; 1196 return ret;
1215} 1197}
diff --git a/common/userpref.h b/common/userpref.h
index 14db985..f59e5fe 100644
--- a/common/userpref.h
+++ b/common/userpref.h
@@ -37,6 +37,17 @@ typedef gnutls_datum_t key_data_t;
37#endif 37#endif
38 38
39#include <stdint.h> 39#include <stdint.h>
40#include <plist/plist.h>
41
42#define USERPREF_DEVICE_CERTIFICATE_KEY "DeviceCertificate"
43#define USERPREF_ESCROW_BAG_KEY "EscrowBag"
44#define USERPREF_HOST_CERTIFICATE_KEY "HostCertificate"
45#define USERPREF_ROOT_CERTIFICATE_KEY "RootCertificate"
46#define USERPREF_HOST_PRIVATE_KEY_KEY "HostPrivateKey"
47#define USERPREF_ROOT_PRIVATE_KEY_KEY "RootPrivateKey"
48#define USERPREF_HOST_ID_KEY "HostID"
49#define USERPREF_SYSTEM_BUID_KEY "SystemBUID"
50#define USERPREF_WIFI_MAC_ADDRESS_KEY "WiFiMACAddress"
40 51
41#ifndef LIBIMOBILEDEVICE_INTERNAL 52#ifndef LIBIMOBILEDEVICE_INTERNAL
42#ifdef WIN32 53#ifdef WIN32
@@ -58,16 +69,25 @@ typedef gnutls_datum_t key_data_t;
58typedef int16_t userpref_error_t; 69typedef int16_t userpref_error_t;
59 70
60#ifdef HAVE_OPENSSL 71#ifdef HAVE_OPENSSL
61LIBIMOBILEDEVICE_INTERNAL userpref_error_t userpref_get_keys_and_certs(key_data_t* root_privkey, key_data_t* root_crt, key_data_t* host_privkey, key_data_t* host_crt); 72LIBIMOBILEDEVICE_INTERNAL userpref_error_t userpref_device_record_get_keys_and_certs(const char *udid, key_data_t* root_privkey, key_data_t* root_crt, key_data_t* host_privkey, key_data_t* host_crt);
62#else 73#else
63LIBIMOBILEDEVICE_INTERNAL userpref_error_t userpref_get_keys_and_certs(gnutls_x509_privkey_t root_privkey, gnutls_x509_crt_t root_crt, gnutls_x509_privkey_t host_privkey, gnutls_x509_crt_t host_crt); 74LIBIMOBILEDEVICE_INTERNAL userpref_error_t userpref_device_record_get_keys_and_certs(const char *udid, gnutls_x509_privkey_t root_privkey, gnutls_x509_crt_t root_crt, gnutls_x509_privkey_t host_privkey, gnutls_x509_crt_t host_crt);
64#endif 75#endif
65LIBIMOBILEDEVICE_INTERNAL userpref_error_t userpref_set_keys_and_certs(key_data_t * root_key, key_data_t * root_cert, key_data_t * host_key, key_data_t * host_cert); 76LIBIMOBILEDEVICE_INTERNAL userpref_error_t userpref_device_record_set_keys_and_certs(const char *udid, key_data_t * root_key, key_data_t * root_cert, key_data_t * host_key, key_data_t * host_cert);
66LIBIMOBILEDEVICE_INTERNAL userpref_error_t userpref_get_certs_as_pem(key_data_t *pem_root_cert, key_data_t *pem_host_cert); 77LIBIMOBILEDEVICE_INTERNAL userpref_error_t userpref_device_record_get_certs_as_pem(const char *udid, key_data_t *pem_root_cert, key_data_t *pem_host_cert);
67LIBIMOBILEDEVICE_INTERNAL userpref_error_t userpref_set_device_public_key(const char *udid, key_data_t public_key); 78
68userpref_error_t userpref_remove_device_public_key(const char *udid); 79LIBIMOBILEDEVICE_INTERNAL userpref_error_t userpref_set_device_record(const char *udid, plist_t device_record);
69LIBIMOBILEDEVICE_INTERNAL int userpref_has_device_public_key(const char *udid); 80userpref_error_t userpref_remove_device_record(const char *udid);
81LIBIMOBILEDEVICE_INTERNAL int userpref_has_device_record(const char *udid);
82
70userpref_error_t userpref_get_paired_udids(char ***list, unsigned int *count); 83userpref_error_t userpref_get_paired_udids(char ***list, unsigned int *count);
71void userpref_get_host_id(char **host_id); 84void userpref_device_record_get_host_id(const char *udid, char **host_id);
85void userpref_get_system_buid(char **system_buid);
86
87userpref_error_t userpref_get_device_record(const char *udid, plist_t *device_record);
88int userpref_get_value(const char *key, plist_t *value);
89int userpref_set_value(const char *key, plist_t value);
90int userpref_device_record_get_value(const char *udid, const char *key, plist_t *value);
91int userpref_device_record_set_value(const char *udid, const char *key, plist_t value);
72 92
73#endif 93#endif