summaryrefslogtreecommitdiffstats
path: root/common/userpref.c
diff options
context:
space:
mode:
Diffstat (limited to 'common/userpref.c')
-rw-r--r--common/userpref.c684
1 files changed, 333 insertions, 351 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}