~ubuntu-branches/ubuntu/trusty/libimobiledevice/trusty-proposed

« back to all changes in this revision

Viewing changes to .pc/CVE-2013-2142.patch/src/userpref.c

  • Committer: Package Import Robot
  • Author(s): Timo Jyrinki, Matthias Niess, Timo Jyrinki
  • Date: 2014-03-14 08:44:15 UTC
  • mfrom: (1.1.10)
  • Revision ID: package-import@ubuntu.com-20140314084415-twglhjx6bqzmir8v
Tags: 1.1.5+git20140313.bafe6a9e-0ubuntu1
[ Matthias Niess ]
* Replace a duplicate 'backup' util man page with the one for 'crashreport'

[ Timo Jyrinki ]
* New upstream snapshot. (LP: #1207812)
* Drop patches include in the upstream snapshot:
  - debian/patches/CVE-2013-2142.patch
  - debian/patches/git_explicitly_cast_ssl_enabled.patch
* Drop the python patch, new upstream method seems to work:
  - debian/patches/09_use_python_config.patch
* Refreshed remaining patches:
  - debian/patches/01-libs.private.patch
  - debian/patches/02-fix-link-errors.patch
* Drop libimobiledevice-doc, the git does not include html documentation
* Updated libimobiledevice4.symbols 
* Add missing man page for the 'idevicename' util

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * userpref.c
3
 
 * contains methods to access user specific certificates IDs and more.
4
 
 *
5
 
 * Copyright (c) 2008 Jonathan Beck All Rights Reserved.
6
 
 *
7
 
 * This library is free software; you can redistribute it and/or
8
 
 * modify it under the terms of the GNU Lesser General Public
9
 
 * License as published by the Free Software Foundation; either
10
 
 * version 2.1 of the License, or (at your option) any later version.
11
 
 *
12
 
 * This library is distributed in the hope that it will be useful,
13
 
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15
 
 * Lesser General Public License for more details.
16
 
 *
17
 
 * You should have received a copy of the GNU Lesser General Public
18
 
 * License along with this library; if not, write to the Free Software
19
 
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
20
 
 */
21
 
 
22
 
#ifdef HAVE_CONFIG_H
23
 
#include <config.h>
24
 
#endif
25
 
#include <stdio.h>
26
 
#include <stdint.h>
27
 
#include <stdlib.h>
28
 
#include <string.h>
29
 
#ifdef HAVE_OPENSSL
30
 
#include <openssl/pem.h>
31
 
#include <openssl/rsa.h>
32
 
#include <openssl/x509.h>
33
 
#include <openssl/x509v3.h>
34
 
#else
35
 
#include <gnutls/gnutls.h>
36
 
#include <gnutls/x509.h>
37
 
#include <gcrypt.h>
38
 
#endif
39
 
 
40
 
#include <dirent.h>
41
 
#include <libgen.h>
42
 
#include <sys/stat.h>
43
 
#include <errno.h>
44
 
 
45
 
#ifdef WIN32
46
 
#include <shlobj.h>
47
 
#endif
48
 
 
49
 
#include "userpref.h"
50
 
#include "debug.h"
51
 
 
52
 
#define LIBIMOBILEDEVICE_CONF_DIR  "libimobiledevice"
53
 
#define LIBIMOBILEDEVICE_CONF_FILE "libimobiledevicerc"
54
 
 
55
 
#define LIBIMOBILEDEVICE_ROOT_PRIVKEY "RootPrivateKey.pem"
56
 
#define LIBIMOBILEDEVICE_HOST_PRIVKEY "HostPrivateKey.pem"
57
 
#define LIBIMOBILEDEVICE_ROOT_CERTIF "RootCertificate.pem"
58
 
#define LIBIMOBILEDEVICE_HOST_CERTIF "HostCertificate.pem"
59
 
 
60
 
#ifdef WIN32
61
 
#define DIR_SEP '\\'
62
 
#define DIR_SEP_S "\\"
63
 
#else
64
 
#define DIR_SEP '/'
65
 
#define DIR_SEP_S "/"
66
 
#endif
67
 
 
68
 
static char __config_dir[512] = {0, };
69
 
 
70
 
#ifdef WIN32
71
 
static char *userpref_utf16_to_utf8(wchar_t *unistr, long len, long *items_read, long *items_written)
72
 
{
73
 
        if (!unistr || (len <= 0)) return NULL;
74
 
        char *outbuf = (char*)malloc(3*(len+1));
75
 
        int p = 0;
76
 
        int i = 0;
77
 
 
78
 
        wchar_t wc;
79
 
 
80
 
        while (i < len) {
81
 
                wc = unistr[i++];
82
 
                if (wc >= 0x800) {
83
 
                        outbuf[p++] = (char)(0xE0 + ((wc >> 12) & 0xF));
84
 
                        outbuf[p++] = (char)(0x80 + ((wc >> 6) & 0x3F));
85
 
                        outbuf[p++] = (char)(0x80 + (wc & 0x3F));
86
 
                } else if (wc >= 0x80) {
87
 
                        outbuf[p++] = (char)(0xC0 + ((wc >> 6) & 0x1F));
88
 
                        outbuf[p++] = (char)(0x80 + (wc & 0x3F));
89
 
                } else {
90
 
                        outbuf[p++] = (char)(wc & 0x7F);
91
 
                }
92
 
        }
93
 
        if (items_read) {
94
 
                *items_read = i;
95
 
        }
96
 
        if (items_written) {
97
 
                *items_written = p;
98
 
        }
99
 
        outbuf[p] = 0;
100
 
 
101
 
        return outbuf;
102
 
}
103
 
#endif
104
 
 
105
 
static const char *userpref_get_tmp_dir()
106
 
{
107
 
        const char *cdir = getenv("TMPDIR");
108
 
        if (cdir && cdir[0])
109
 
                return cdir;
110
 
        cdir = getenv("TMP");
111
 
        if (cdir && cdir[0])
112
 
                return cdir;
113
 
        cdir = getenv("TEMP");
114
 
        if (cdir && cdir[0])
115
 
                return cdir;
116
 
        return "/tmp";
117
 
}
118
 
 
119
 
static const char *userpref_get_config_dir()
120
 
{
121
 
        if (__config_dir[0]) return __config_dir;
122
 
#ifdef WIN32
123
 
        wchar_t path[MAX_PATH+1];
124
 
        HRESULT hr;
125
 
        LPITEMIDLIST pidl = NULL;
126
 
        BOOL b = FALSE;
127
 
 
128
 
        hr = SHGetSpecialFolderLocation (NULL, CSIDL_LOCAL_APPDATA, &pidl);
129
 
        if (hr == S_OK) {
130
 
                b = SHGetPathFromIDListW (pidl, path);
131
 
                if (b) {
132
 
                        char *cdir = userpref_utf16_to_utf8 (path, wcslen(path), NULL, NULL);
133
 
                        strcpy(__config_dir, cdir);
134
 
                        free(cdir);
135
 
                        CoTaskMemFree (pidl);
136
 
                }
137
 
        }
138
 
#else
139
 
        const char *cdir = getenv("XDG_CONFIG_HOME");
140
 
        if (!cdir) {
141
 
                cdir = getenv("HOME");
142
 
                if (!cdir || !cdir[0]) {
143
 
                        const char *tdir = userpref_get_tmp_dir();
144
 
                        strcpy(__config_dir, tdir);
145
 
                        strcat(__config_dir, DIR_SEP_S);
146
 
                        strcat(__config_dir, "root");
147
 
                } else {
148
 
                        strcpy(__config_dir, cdir);
149
 
                }
150
 
                strcat(__config_dir, DIR_SEP_S);
151
 
                strcat(__config_dir, ".config");
152
 
        } else {
153
 
                strcpy(__config_dir, cdir);
154
 
        }
155
 
#endif
156
 
        strcat(__config_dir, DIR_SEP_S);
157
 
        strcat(__config_dir, LIBIMOBILEDEVICE_CONF_DIR);
158
 
 
159
 
        int i = strlen(__config_dir)-1; 
160
 
        while ((i > 0) && (__config_dir[i] == DIR_SEP)) {
161
 
                __config_dir[i--] = '\0';
162
 
        }
163
 
 
164
 
        return __config_dir;
165
 
}
166
 
 
167
 
static int __mkdir(const char *dir, int mode)
168
 
{
169
 
#ifdef WIN32
170
 
        return mkdir(dir);
171
 
#else
172
 
        return mkdir(dir, mode);
173
 
#endif
174
 
}
175
 
 
176
 
static int mkdir_with_parents(const char *dir, int mode)
177
 
{
178
 
        if (!dir) return -1;
179
 
        if (__mkdir(dir, mode) == 0) {
180
 
                return 0;
181
 
        } else {
182
 
                if (errno == EEXIST) return 0;  
183
 
        }
184
 
        int res;
185
 
        char *parent = strdup(dir);
186
 
        parent = dirname(parent);
187
 
        if (parent) {
188
 
                res = mkdir_with_parents(parent, mode);
189
 
        } else {
190
 
                res = -1;       
191
 
        }
192
 
        free(parent);
193
 
        if (res == 0) {
194
 
                mkdir_with_parents(dir, mode);
195
 
        }
196
 
        return res;
197
 
}
198
 
 
199
 
static int config_write(const char *cfgfile, plist_t dict)
200
 
{
201
 
        if (!cfgfile || !dict || (plist_get_node_type(dict) != PLIST_DICT)) {
202
 
                return -1;
203
 
        }
204
 
        int res = -1;
205
 
 
206
 
#if 1 // old style config
207
 
        plist_t hostid = plist_dict_get_item(dict, "HostID");
208
 
        if (hostid && (plist_get_node_type(hostid) == PLIST_STRING)) {
209
 
                char *hostidstr = NULL;
210
 
                plist_get_string_val(hostid, &hostidstr);
211
 
                if (hostidstr) {
212
 
                        FILE *fd = fopen(cfgfile, "wb");
213
 
                        if (fd) {
214
 
                                fprintf(fd, "\n[Global]\nHostID=%s\n", hostidstr);
215
 
                                fclose(fd);
216
 
                                res = 0;
217
 
                        } else {
218
 
                                debug_info("could not open '%s' for writing: %s", cfgfile, strerror(errno));
219
 
                        }
220
 
                        free(hostidstr);
221
 
                }
222
 
        }
223
 
#endif
224
 
#if 0
225
 
        char *xml = NULL;
226
 
        uint32_t length = 0;
227
 
 
228
 
        plist_to_xml(dict, &xml, &length);
229
 
        if (!xml) {
230
 
                return res;
231
 
        }
232
 
 
233
 
        FILE *fd = fopen(cfgfile, "wb");
234
 
        if (!fd) {
235
 
                free(xml);
236
 
                return res;
237
 
        }
238
 
 
239
 
        if (fwrite(xml, 1, length, fd) == length) {
240
 
                res = 0;
241
 
        } else {
242
 
                fprintf(stderr, "%s: ERROR: failed to write configuration to '%s'\n", __func__, cfgfile);
243
 
        }
244
 
        fclose(fd);
245
 
 
246
 
        free(xml);
247
 
#endif
248
 
        return res;
249
 
}
250
 
 
251
 
static int config_read(const char *cfgfile, plist_t *dict)
252
 
{
253
 
        if (!cfgfile || !dict) {
254
 
                return -1;
255
 
        }
256
 
 
257
 
        int res = -1;
258
 
        FILE *fd = fopen(cfgfile, "rb");
259
 
        if (!fd) {
260
 
                debug_info("could not open '%s' for reading: %s", cfgfile, strerror(errno));
261
 
                return -1;
262
 
        }
263
 
 
264
 
        fseek(fd, 0, SEEK_END);
265
 
        unsigned long int size = ftell(fd);
266
 
        fseek(fd, 0, SEEK_SET);
267
 
        unsigned char *contents = NULL;
268
 
 
269
 
        contents = malloc(size);
270
 
        if (fread(contents, 1, size, fd) != size) {
271
 
                free(contents);
272
 
                fclose(fd);
273
 
                return -1;
274
 
        }
275
 
        plist_t plist = NULL;
276
 
 
277
 
        if (!memcmp(contents, "bplist00", 8)) {
278
 
                plist_from_bin((const char*)contents, (uint32_t)size, &plist);
279
 
                fclose(fd);
280
 
        } else {
281
 
                if (memchr(contents, '<', size)) {
282
 
                        plist_from_xml((const char*)contents, (uint32_t)size, &plist);
283
 
                }
284
 
                if (plist) {
285
 
                        fclose(fd);
286
 
                } else {
287
 
                        // try parsing old format config file
288
 
                        char line[256];
289
 
                        fseek(fd, 0, SEEK_SET);
290
 
                        while (fgets(line, 256, fd)) {
291
 
                                char *p = &line[0];
292
 
                                size_t llen = strlen(p)-1;
293
 
                                while ((llen > 0) && ((p[llen] == '\n') || (p[llen] == '\r'))) {
294
 
                                        p[llen] = '\0';
295
 
                                        llen--;
296
 
                                }
297
 
                                if (llen == 0) continue;
298
 
                                while ((p[0] == '\n') || (p[0] == '\r')) {
299
 
                                        p++;
300
 
                                }
301
 
                                if (!strncmp(p, "HostID=", 7)) {
302
 
                                        plist = plist_new_dict();
303
 
                                        plist_dict_insert_item(plist, "HostID", plist_new_string(p+7));
304
 
                                        break;
305
 
                                }
306
 
                        }
307
 
                        fclose(fd);
308
 
#if 0
309
 
                        if (plist) {
310
 
                                // write new format config
311
 
                                config_write(cfgfile, plist);
312
 
                        }
313
 
#endif
314
 
                }
315
 
        }
316
 
        free(contents);
317
 
        if (plist) {
318
 
                *dict = plist;
319
 
                res = 0;
320
 
        }
321
 
        return res;
322
 
}
323
 
 
324
 
/**
325
 
 * Creates a freedesktop compatible configuration directory.
326
 
 */
327
 
static void userpref_create_config_dir(void)
328
 
{
329
 
        const char *config_path = userpref_get_config_dir();
330
 
        struct stat st;
331
 
        if (stat(config_path, &st) != 0) {
332
 
                mkdir_with_parents(config_path, 0755);
333
 
        }
334
 
}
335
 
 
336
 
static int get_rand(int min, int max)
337
 
{
338
 
        int retval = (rand() % (max - min)) + min;
339
 
        return retval;
340
 
}
341
 
 
342
 
/**
343
 
 * Generates a valid HostID (which is actually a UUID).
344
 
 *
345
 
 * @return A null terminated string containing a valid HostID.
346
 
 */
347
 
static char *userpref_generate_host_id()
348
 
{
349
 
        /* HostID's are just UUID's, and UUID's are 36 characters long */
350
 
        char *hostid = (char *) malloc(sizeof(char) * 37);
351
 
        const char *chars = "ABCDEF0123456789";
352
 
        srand(time(NULL));
353
 
        int i = 0;
354
 
 
355
 
        for (i = 0; i < 36; i++) {
356
 
                if (i == 8 || i == 13 || i == 18 || i == 23) {
357
 
                        hostid[i] = '-';
358
 
                        continue;
359
 
                } else {
360
 
                        hostid[i] = chars[get_rand(0, 16)];
361
 
                }
362
 
        }
363
 
        /* make it a real string */
364
 
        hostid[36] = '\0';
365
 
        return hostid;
366
 
}
367
 
 
368
 
/**
369
 
 * Store HostID in config file.
370
 
 *
371
 
 * @param host_id A null terminated string containing a valid HostID.
372
 
 */
373
 
static int userpref_set_host_id(const char *host_id)
374
 
{
375
 
        const char *config_path;
376
 
        char *config_file;
377
 
 
378
 
        if (!host_id)
379
 
                return 0;
380
 
 
381
 
        /* Make sure config directory exists */
382
 
        userpref_create_config_dir();
383
 
 
384
 
        config_path = userpref_get_config_dir();
385
 
        config_file = (char*)malloc(strlen(config_path)+1+strlen(LIBIMOBILEDEVICE_CONF_FILE)+1);
386
 
        strcpy(config_file, config_path);
387
 
        strcat(config_file, DIR_SEP_S);
388
 
        strcat(config_file, LIBIMOBILEDEVICE_CONF_FILE);
389
 
 
390
 
        /* Now parse file to get the HostID */
391
 
        plist_t config = NULL;
392
 
        config_read(config_file, &config);
393
 
        if (!config) {
394
 
                config = plist_new_dict();
395
 
                plist_dict_insert_item(config, "HostID", plist_new_string(host_id));
396
 
        } else {
397
 
                plist_t n = plist_dict_get_item(config, "HostID");
398
 
                if (n) {
399
 
                        plist_set_string_val(n, host_id);
400
 
                } else {
401
 
                        plist_dict_insert_item(config, "HostID", plist_new_string(host_id));
402
 
                }
403
 
        }
404
 
 
405
 
        /* Store in config file */
406
 
        debug_info("setting hostID to %s", host_id);
407
 
 
408
 
        config_write(config_file, config);
409
 
        plist_free(config);
410
 
 
411
 
        free(config_file);
412
 
        return 1;
413
 
}
414
 
 
415
 
/**
416
 
 * Reads the HostID from a previously generated configuration file.
417
 
 *
418
 
 * @note It is the responsibility of the calling function to free the returned host_id
419
 
 *
420
 
 * @return The string containing the HostID or NULL
421
 
 */
422
 
void userpref_get_host_id(char **host_id)
423
 
{
424
 
        const char *config_path;
425
 
        char *config_file;
426
 
 
427
 
        config_path = userpref_get_config_dir();
428
 
        config_file = (char*)malloc(strlen(config_path)+1+strlen(LIBIMOBILEDEVICE_CONF_FILE)+1);
429
 
        strcpy(config_file, config_path);
430
 
        strcat(config_file, DIR_SEP_S);
431
 
        strcat(config_file, LIBIMOBILEDEVICE_CONF_FILE);
432
 
 
433
 
        /* now parse file to get the HostID */
434
 
        plist_t config = NULL;
435
 
        if (config_read(config_file, &config) == 0) {
436
 
                plist_t n_host_id = plist_dict_get_item(config, "HostID");
437
 
                if (n_host_id && (plist_get_node_type(n_host_id) == PLIST_STRING)) {
438
 
                        plist_get_string_val(n_host_id, host_id);
439
 
                }
440
 
        }
441
 
        plist_free(config);
442
 
        free(config_file);
443
 
 
444
 
        if (!*host_id) {
445
 
                /* no config, generate host_id */
446
 
                *host_id = userpref_generate_host_id();
447
 
                userpref_set_host_id(*host_id);
448
 
        }
449
 
 
450
 
        debug_info("Using %s as HostID", *host_id);
451
 
}
452
 
 
453
 
/**
454
 
 * Determines whether this device has been connected to this system before.
455
 
 *
456
 
 * @param udid The device UDID as given by the device.
457
 
 *
458
 
 * @return 1 if the device has been connected previously to this configuration
459
 
 *         or 0 otherwise.
460
 
 */
461
 
int userpref_has_device_public_key(const char *udid)
462
 
{
463
 
        int ret = 0;
464
 
        const char *config_path;
465
 
        char *config_file;
466
 
        struct stat st;
467
 
 
468
 
        if (!udid) return 0;
469
 
 
470
 
        /* first get config file */
471
 
        config_path = userpref_get_config_dir();
472
 
        config_file = (char*)malloc(strlen(config_path)+1+strlen(udid)+4+1);
473
 
        strcpy(config_file, config_path);
474
 
        strcat(config_file, DIR_SEP_S);
475
 
        strcat(config_file, udid);
476
 
        strcat(config_file, ".pem");
477
 
 
478
 
        if ((stat(config_file, &st) == 0) && S_ISREG(st.st_mode))
479
 
                ret = 1;
480
 
        free(config_file);
481
 
        return ret;
482
 
}
483
 
 
484
 
/**
485
 
 * Fills a list with UDIDs of devices that have been connected to this
486
 
 * system before, i.e. for which a public key file exists.
487
 
 *
488
 
 * @param list A pointer to a char** initially pointing to NULL that will
489
 
 *        hold a newly allocated list of UDIDs upon successful return.
490
 
 *        The caller is responsible for freeing the memory. Note that if
491
 
 *        no public key file was found the list has to be freed too as it
492
 
 *        points to a terminating NULL element.
493
 
 * @param count The number of UDIDs found. This parameter can be NULL if it
494
 
 *        is not required.
495
 
 *
496
 
 * @return USERPREF_E_SUCCESS on success, or USERPREF_E_INVALID_ARG if the 
497
 
 *         list parameter is not pointing to NULL.
498
 
 */
499
 
userpref_error_t userpref_get_paired_udids(char ***list, unsigned int *count)
500
 
{
501
 
        struct slist_t {
502
 
                char *name;
503
 
                void *next;
504
 
        };
505
 
        DIR *config_dir;
506
 
        const char *config_path;
507
 
        struct slist_t *udids = NULL;
508
 
        unsigned int i;
509
 
        unsigned int found = 0;
510
 
 
511
 
        if (!list || (list && *list)) {
512
 
                debug_info("ERROR: The list parameter needs to point to NULL!");
513
 
                return USERPREF_E_INVALID_ARG;
514
 
        }
515
 
 
516
 
        if (count) {
517
 
                *count = 0;
518
 
        }
519
 
 
520
 
        config_path = userpref_get_config_dir();
521
 
        config_dir = opendir(config_path);
522
 
        if (config_dir) {
523
 
                struct dirent *entry;
524
 
                struct slist_t *listp = udids;
525
 
                while ((entry = readdir(config_dir))) {
526
 
                        char *ext = strstr(entry->d_name, ".pem");
527
 
                        if (ext && ((ext - entry->d_name) == 40) && (strlen(entry->d_name) == 44)) {
528
 
                                struct slist_t *ne = (struct slist_t*)malloc(sizeof(struct slist_t));
529
 
                                ne->name = (char*)malloc(41);
530
 
                                strncpy(ne->name, entry->d_name, 40);
531
 
                                ne->name[40] = 0;
532
 
                                ne->next = NULL;
533
 
                                if (!listp) {
534
 
                                        listp = ne;
535
 
                                        udids = listp;
536
 
                                } else {
537
 
                                        listp->next = ne;
538
 
                                        listp = listp->next;
539
 
                                }
540
 
                                found++;
541
 
                        }
542
 
                }
543
 
                closedir(config_dir);
544
 
        }
545
 
        *list = (char**)malloc(sizeof(char*) * (found+1));
546
 
        i = 0;
547
 
        while (udids) {
548
 
                (*list)[i++] = udids->name;
549
 
                struct slist_t *old = udids;
550
 
                udids = udids->next;
551
 
                free(old);
552
 
        }
553
 
        (*list)[i] = NULL;
554
 
 
555
 
        if (count) {
556
 
                *count = found;
557
 
        }
558
 
 
559
 
        return USERPREF_E_SUCCESS;
560
 
}
561
 
 
562
 
/**
563
 
 * Mark the device (as represented by the key) as having connected to this
564
 
 * configuration.
565
 
 *
566
 
 * @param udid The device UDID as given by the device
567
 
 * @param public_key The public key given by the device
568
 
 *
569
 
 * @return 1 on success and 0 if no public key is given or if it has already
570
 
 *         been marked as connected previously.
571
 
 */
572
 
userpref_error_t userpref_set_device_public_key(const char *udid, key_data_t public_key)
573
 
{
574
 
        if (NULL == public_key.data)
575
 
                return USERPREF_E_INVALID_ARG;
576
 
        
577
 
        if (userpref_has_device_public_key(udid))
578
 
                return USERPREF_E_SUCCESS;
579
 
 
580
 
        /* ensure config directory exists */
581
 
        userpref_create_config_dir();
582
 
 
583
 
        /* build file path */
584
 
        const char *config_path = userpref_get_config_dir();
585
 
        char *pem = (char*)malloc(strlen(config_path)+1+strlen(udid)+4+1);
586
 
        strcpy(pem, config_path);
587
 
        strcat(pem, DIR_SEP_S);
588
 
        strcat(pem, udid);
589
 
        strcat(pem, ".pem");
590
 
 
591
 
        /* store file */
592
 
        FILE *pFile = fopen(pem, "wb");
593
 
        if (pFile) {
594
 
                fwrite(public_key.data, 1, public_key.size, pFile);
595
 
                fclose(pFile);
596
 
        } else {
597
 
                debug_info("could not open '%s' for writing: %s", pem, strerror(errno));
598
 
        }
599
 
        free(pem);
600
 
 
601
 
        return USERPREF_E_SUCCESS;
602
 
}
603
 
 
604
 
/**
605
 
 * Remove the public key stored for the device with udid from this host.
606
 
 *
607
 
 * @param udid The udid of the device
608
 
 *
609
 
 * @return USERPREF_E_SUCCESS on success.
610
 
 */
611
 
userpref_error_t userpref_remove_device_public_key(const char *udid)
612
 
{
613
 
        if (!userpref_has_device_public_key(udid))
614
 
                return USERPREF_E_SUCCESS;
615
 
 
616
 
        /* build file path */
617
 
        const char *config_path = userpref_get_config_dir();
618
 
        char *pem = (char*)malloc(strlen(config_path)+1+strlen(udid)+4+1);
619
 
        strcpy(pem, config_path);
620
 
        strcat(pem, DIR_SEP_S);
621
 
        strcat(pem, udid);
622
 
        strcat(pem, ".pem");
623
 
 
624
 
        /* remove file */
625
 
        remove(pem);
626
 
 
627
 
        free(pem);
628
 
 
629
 
        return USERPREF_E_SUCCESS;
630
 
}
631
 
 
632
 
/**
633
 
 * Private function which reads the given file into a key_data_t structure.
634
 
 *
635
 
 * @param file The filename of the file to read
636
 
 * @param data The pointer at which to store the data.
637
 
 *
638
 
 * @return 1 if the file contents where read successfully and 0 otherwise.
639
 
 */
640
 
static int userpref_get_file_contents(const char *file, key_data_t * data)
641
 
{
642
 
        int success = 0;
643
 
        unsigned long int size = 0;
644
 
        unsigned char *content = NULL;
645
 
        const char *config_path;
646
 
        char *filepath;
647
 
        FILE *fd;
648
 
 
649
 
        if (NULL == file || NULL == data)
650
 
                return 0;
651
 
 
652
 
        /* Read file */
653
 
        config_path = userpref_get_config_dir();
654
 
        filepath = (char*)malloc(strlen(config_path)+1+strlen(file)+1);
655
 
        strcpy(filepath, config_path);
656
 
        strcat(filepath, DIR_SEP_S);
657
 
        strcat(filepath, file);
658
 
 
659
 
        fd = fopen(filepath, "rb");
660
 
        if (fd) {
661
 
                fseek(fd, 0, SEEK_END);
662
 
                size = ftell(fd);
663
 
                fseek(fd, 0, SEEK_SET);
664
 
 
665
 
                // prevent huge files
666
 
                if (size > 0xFFFFFF) {
667
 
                        fprintf(stderr, "%s: file is too big (> 16MB). Refusing to read the contents to memory!", __func__);
668
 
                } else {
669
 
                        size_t p = 0;
670
 
                        content = (unsigned char*)malloc(size);
671
 
                        while (!feof(fd)) {
672
 
                                p += fread(content+p, 1, size-p, fd);
673
 
                                if (ferror(fd) != 0) {
674
 
                                        break;
675
 
                                }
676
 
                                if (p >= size) {
677
 
                                        success = 1;
678
 
                                        break;
679
 
                                }
680
 
                        }
681
 
                }
682
 
                fclose(fd);
683
 
        }
684
 
 
685
 
        free(filepath);
686
 
 
687
 
        /* Add it to the key_data_t structure */
688
 
        if (success) {
689
 
                data->data = (uint8_t*) content;
690
 
                data->size = size;
691
 
        }
692
 
 
693
 
        return success;
694
 
}
695
 
 
696
 
/**
697
 
 * Private function which generate private keys and certificates.
698
 
 *
699
 
 * @return 1 if keys were successfully generated, 0 otherwise
700
 
 */
701
 
static userpref_error_t userpref_gen_keys_and_cert(void)
702
 
{
703
 
        userpref_error_t ret = USERPREF_E_SSL_ERROR;
704
 
 
705
 
        key_data_t root_key_pem = { NULL, 0 };
706
 
        key_data_t root_cert_pem = { NULL, 0 };
707
 
        key_data_t host_key_pem = { NULL, 0 };
708
 
        key_data_t host_cert_pem = { NULL, 0 };
709
 
 
710
 
        debug_info("Generating keys and certificates");
711
 
#ifdef HAVE_OPENSSL
712
 
        RSA* root_keypair = RSA_generate_key(2048, 65537, NULL, NULL);
713
 
        RSA* host_keypair = RSA_generate_key(2048, 65537, NULL, NULL);
714
 
 
715
 
        EVP_PKEY* root_pkey = EVP_PKEY_new();
716
 
        EVP_PKEY_assign_RSA(root_pkey, root_keypair);
717
 
 
718
 
        EVP_PKEY* host_pkey = EVP_PKEY_new();
719
 
        EVP_PKEY_assign_RSA(host_pkey, host_keypair);
720
 
 
721
 
        /* generate root certificate */
722
 
        X509* root_cert = X509_new();
723
 
        {
724
 
                /* set serial number */
725
 
                ASN1_INTEGER* sn = ASN1_INTEGER_new();
726
 
                ASN1_INTEGER_set(sn, 0);
727
 
                X509_set_serialNumber(root_cert, sn);
728
 
                ASN1_INTEGER_free(sn);
729
 
 
730
 
                /* set version */
731
 
                X509_set_version(root_cert, 2);
732
 
 
733
 
                /* set x509v3 basic constraints */
734
 
                X509_EXTENSION* ext;
735
 
                if (!(ext = X509V3_EXT_conf_nid(NULL, NULL, NID_basic_constraints, (char*)"critical,CA:TRUE"))) {
736
 
                        debug_info("ERROR: X509V3_EXT_conf_nid failed");
737
 
                }
738
 
                X509_add_ext(root_cert, ext, -1);
739
 
 
740
 
                /* set key validity */
741
 
                ASN1_TIME* asn1time = ASN1_TIME_new();
742
 
                ASN1_TIME_set(asn1time, time(NULL));
743
 
                X509_set_notBefore(root_cert, asn1time);
744
 
                ASN1_TIME_set(asn1time, time(NULL) + (60 * 60 * 24 * 365 * 10));
745
 
                X509_set_notAfter(root_cert, asn1time);
746
 
                ASN1_TIME_free(asn1time);
747
 
 
748
 
                /* use root public key for root cert */
749
 
                X509_set_pubkey(root_cert, root_pkey);
750
 
                /* sign root cert with root private key */
751
 
                X509_sign(root_cert, root_pkey, EVP_sha1());
752
 
        }
753
 
 
754
 
        /* create host certificate */
755
 
        X509* host_cert = X509_new();
756
 
        {
757
 
                /* set serial number */
758
 
                ASN1_INTEGER* sn = ASN1_INTEGER_new();
759
 
                ASN1_INTEGER_set(sn, 0);
760
 
                X509_set_serialNumber(host_cert, sn);
761
 
                ASN1_INTEGER_free(sn);
762
 
 
763
 
                /* set version */
764
 
                X509_set_version(host_cert, 2);
765
 
 
766
 
                /* set x509v3 basic constraints */
767
 
                X509_EXTENSION* ext;
768
 
                if (!(ext = X509V3_EXT_conf_nid(NULL, NULL, NID_basic_constraints, (char*)"critical,CA:FALSE"))) {
769
 
                        debug_info("ERROR: X509V3_EXT_conf_nid failed");
770
 
                }
771
 
                X509_add_ext(host_cert, ext, -1);
772
 
 
773
 
                /* set x509v3 key usage */
774
 
                if (!(ext = X509V3_EXT_conf_nid(NULL, NULL, NID_key_usage, (char*)"digitalSignature,keyEncipherment"))) {
775
 
                        debug_info("ERROR: X509V3_EXT_conf_nid failed");
776
 
                }
777
 
                X509_add_ext(host_cert, ext, -1);
778
 
 
779
 
                /* set key validity */
780
 
                ASN1_TIME* asn1time = ASN1_TIME_new();
781
 
                ASN1_TIME_set(asn1time, time(NULL));
782
 
                X509_set_notBefore(host_cert, asn1time);
783
 
                ASN1_TIME_set(asn1time, time(NULL) + (60 * 60 * 24 * 365 * 10));
784
 
                X509_set_notAfter(host_cert, asn1time);
785
 
                ASN1_TIME_free(asn1time);
786
 
 
787
 
                /* use host public key for host cert */ 
788
 
                X509_set_pubkey(host_cert, host_pkey);
789
 
 
790
 
                /* sign host cert with root private key */
791
 
                X509_sign(host_cert, root_pkey, EVP_sha1());
792
 
        }
793
 
 
794
 
        if (root_cert && root_pkey && host_cert && host_pkey) {
795
 
                BIO* membp;
796
 
 
797
 
                membp = BIO_new(BIO_s_mem());
798
 
                if (PEM_write_bio_X509(membp, root_cert) > 0) {
799
 
                        root_cert_pem.size = BIO_get_mem_data(membp, &root_cert_pem.data);
800
 
                }
801
 
                membp = BIO_new(BIO_s_mem());
802
 
                if (PEM_write_bio_PrivateKey(membp, root_pkey, NULL, NULL, 0, 0, NULL) > 0) {
803
 
                        root_key_pem.size = BIO_get_mem_data(membp, &root_key_pem.data);
804
 
                }
805
 
                membp = BIO_new(BIO_s_mem());
806
 
                if (PEM_write_bio_X509(membp, host_cert) > 0) {
807
 
                        host_cert_pem.size = BIO_get_mem_data(membp, &host_cert_pem.data);
808
 
                }
809
 
                membp = BIO_new(BIO_s_mem());
810
 
                if (PEM_write_bio_PrivateKey(membp, host_pkey, NULL, NULL, 0, 0, NULL) > 0) {
811
 
                        host_key_pem.size = BIO_get_mem_data(membp, &host_key_pem.data);
812
 
                }
813
 
        }
814
 
 
815
 
        EVP_PKEY_free(root_pkey);
816
 
        EVP_PKEY_free(host_pkey);
817
 
 
818
 
        X509_free(host_cert);
819
 
        X509_free(root_cert);
820
 
#else
821
 
        gnutls_x509_privkey_t root_privkey;
822
 
        gnutls_x509_crt_t root_cert;
823
 
        gnutls_x509_privkey_t host_privkey;
824
 
        gnutls_x509_crt_t host_cert;
825
 
 
826
 
        gnutls_global_deinit();
827
 
        gnutls_global_init();
828
 
 
829
 
        //use less secure random to speed up key generation
830
 
        gcry_control(GCRYCTL_ENABLE_QUICK_RANDOM);
831
 
 
832
 
        gnutls_x509_privkey_init(&root_privkey);
833
 
        gnutls_x509_privkey_init(&host_privkey);
834
 
 
835
 
        gnutls_x509_crt_init(&root_cert);
836
 
        gnutls_x509_crt_init(&host_cert);
837
 
 
838
 
        /* generate root key */
839
 
        gnutls_x509_privkey_generate(root_privkey, GNUTLS_PK_RSA, 2048, 0);
840
 
        gnutls_x509_privkey_generate(host_privkey, GNUTLS_PK_RSA, 2048, 0);
841
 
 
842
 
        /* generate certificates */
843
 
        gnutls_x509_crt_set_key(root_cert, root_privkey);
844
 
        gnutls_x509_crt_set_serial(root_cert, "\x00", 1);
845
 
        gnutls_x509_crt_set_version(root_cert, 3);
846
 
        gnutls_x509_crt_set_ca_status(root_cert, 1);
847
 
        gnutls_x509_crt_set_activation_time(root_cert, time(NULL));
848
 
        gnutls_x509_crt_set_expiration_time(root_cert, time(NULL) + (60 * 60 * 24 * 365 * 10));
849
 
        gnutls_x509_crt_sign(root_cert, root_cert, root_privkey);
850
 
 
851
 
        gnutls_x509_crt_set_key(host_cert, host_privkey);
852
 
        gnutls_x509_crt_set_serial(host_cert, "\x00", 1);
853
 
        gnutls_x509_crt_set_version(host_cert, 3);
854
 
        gnutls_x509_crt_set_ca_status(host_cert, 0);
855
 
        gnutls_x509_crt_set_key_usage(host_cert, GNUTLS_KEY_KEY_ENCIPHERMENT | GNUTLS_KEY_DIGITAL_SIGNATURE);
856
 
        gnutls_x509_crt_set_activation_time(host_cert, time(NULL));
857
 
        gnutls_x509_crt_set_expiration_time(host_cert, time(NULL) + (60 * 60 * 24 * 365 * 10));
858
 
        gnutls_x509_crt_sign(host_cert, root_cert, root_privkey);
859
 
 
860
 
        /* export to PEM format */
861
 
        size_t root_key_export_size = 0;
862
 
        size_t host_key_export_size = 0;
863
 
 
864
 
        gnutls_x509_privkey_export(root_privkey, GNUTLS_X509_FMT_PEM, NULL, &root_key_export_size);
865
 
        gnutls_x509_privkey_export(host_privkey, GNUTLS_X509_FMT_PEM, NULL, &host_key_export_size);
866
 
 
867
 
        root_key_pem.data = gnutls_malloc(root_key_export_size);
868
 
        host_key_pem.data = gnutls_malloc(host_key_export_size);
869
 
 
870
 
        gnutls_x509_privkey_export(root_privkey, GNUTLS_X509_FMT_PEM, root_key_pem.data, &root_key_export_size);
871
 
        root_key_pem.size = root_key_export_size;
872
 
        gnutls_x509_privkey_export(host_privkey, GNUTLS_X509_FMT_PEM, host_key_pem.data, &host_key_export_size);
873
 
        host_key_pem.size = host_key_export_size;
874
 
 
875
 
        size_t root_cert_export_size = 0;
876
 
        size_t host_cert_export_size = 0;
877
 
 
878
 
        gnutls_x509_crt_export(root_cert, GNUTLS_X509_FMT_PEM, NULL, &root_cert_export_size);
879
 
        gnutls_x509_crt_export(host_cert, GNUTLS_X509_FMT_PEM, NULL, &host_cert_export_size);
880
 
 
881
 
        root_cert_pem.data = gnutls_malloc(root_cert_export_size);
882
 
        host_cert_pem.data = gnutls_malloc(host_cert_export_size);
883
 
 
884
 
        gnutls_x509_crt_export(root_cert, GNUTLS_X509_FMT_PEM, root_cert_pem.data, &root_cert_export_size);
885
 
        root_cert_pem.size = root_cert_export_size;
886
 
        gnutls_x509_crt_export(host_cert, GNUTLS_X509_FMT_PEM, host_cert_pem.data, &host_cert_export_size);
887
 
        host_cert_pem.size = host_cert_export_size;
888
 
 
889
 
        //restore gnutls env
890
 
        gnutls_global_deinit();
891
 
        gnutls_global_init();
892
 
#endif
893
 
        if (NULL != root_cert_pem.data && 0 != root_cert_pem.size &&
894
 
                NULL != host_cert_pem.data && 0 != host_cert_pem.size)
895
 
                ret = USERPREF_E_SUCCESS;
896
 
 
897
 
        /* store values in config file */
898
 
        userpref_set_keys_and_certs( &root_key_pem, &root_cert_pem, &host_key_pem, &host_cert_pem);
899
 
 
900
 
        if (root_key_pem.data)
901
 
                free(root_key_pem.data);
902
 
        if (root_cert_pem.data)
903
 
                free(root_cert_pem.data);
904
 
        if (host_key_pem.data)
905
 
                free(host_key_pem.data);
906
 
        if (host_cert_pem.data)
907
 
                free(host_cert_pem.data);
908
 
 
909
 
        return ret;
910
 
}
911
 
 
912
 
/**
913
 
 * Private function which import the given key into a gnutls structure.
914
 
 *
915
 
 * @param key_name The filename of the private key to import.
916
 
 * @param key the gnutls key structure.
917
 
 *
918
 
 * @return 1 if the key was successfully imported.
919
 
 */
920
 
#ifdef HAVE_OPENSSL
921
 
static userpref_error_t userpref_import_key(const char* key_name, key_data_t* key)
922
 
#else
923
 
static userpref_error_t userpref_import_key(const char* key_name, gnutls_x509_privkey_t key)
924
 
#endif
925
 
{
926
 
#ifdef HAVE_OPENSSL
927
 
        if (!key)
928
 
                return USERPREF_E_SUCCESS;
929
 
#endif
930
 
        userpref_error_t ret = USERPREF_E_INVALID_CONF;
931
 
        key_data_t pem_key = { NULL, 0 };
932
 
        if (userpref_get_file_contents(key_name, &pem_key)) {
933
 
#ifdef HAVE_OPENSSL
934
 
                key->data = (unsigned char*)malloc(pem_key.size);
935
 
                memcpy(key->data, pem_key.data, pem_key.size);
936
 
                key->size = pem_key.size;
937
 
                ret = USERPREF_E_SUCCESS;
938
 
#else
939
 
                if (GNUTLS_E_SUCCESS == gnutls_x509_privkey_import(key, &pem_key, GNUTLS_X509_FMT_PEM))
940
 
                        ret = USERPREF_E_SUCCESS;
941
 
                else
942
 
                        ret = USERPREF_E_SSL_ERROR;
943
 
#endif
944
 
        }
945
 
        if (pem_key.data)
946
 
                free(pem_key.data);
947
 
        return ret;
948
 
}
949
 
 
950
 
/**
951
 
 * Private function which import the given certificate into a gnutls structure.
952
 
 *
953
 
 * @param crt_name The filename of the certificate to import.
954
 
 * @param cert the gnutls certificate structure.
955
 
 *
956
 
 * @return IDEVICE_E_SUCCESS if the certificate was successfully imported.
957
 
 */
958
 
#ifdef HAVE_OPENSSL
959
 
static userpref_error_t userpref_import_crt(const char* crt_name, key_data_t* cert)
960
 
#else
961
 
static userpref_error_t userpref_import_crt(const char* crt_name, gnutls_x509_crt_t cert)
962
 
#endif
963
 
{
964
 
#ifdef HAVE_OPENSSL
965
 
        if (!cert)
966
 
                return USERPREF_E_SUCCESS;
967
 
#endif
968
 
        userpref_error_t ret = USERPREF_E_INVALID_CONF;
969
 
        key_data_t pem_cert = { NULL, 0 };
970
 
 
971
 
        if (userpref_get_file_contents(crt_name, &pem_cert)) {
972
 
#ifdef HAVE_OPENSSL
973
 
                cert->data = (unsigned char*)malloc(pem_cert.size);
974
 
                memcpy(cert->data, pem_cert.data, pem_cert.size);
975
 
                cert->size = pem_cert.size;
976
 
                ret = USERPREF_E_SUCCESS;
977
 
#else
978
 
                if (GNUTLS_E_SUCCESS == gnutls_x509_crt_import(cert, &pem_cert, GNUTLS_X509_FMT_PEM))
979
 
                        ret = USERPREF_E_SUCCESS;
980
 
                else
981
 
                        ret = USERPREF_E_SSL_ERROR;
982
 
#endif
983
 
        }
984
 
        if (pem_cert.data)
985
 
                free(pem_cert.data);
986
 
        return ret;
987
 
}
988
 
 
989
 
/**
990
 
 * Function to retrieve host keys and certificates.
991
 
 * This function trigger key generation if they do not exists yet or are invalid.
992
 
 *
993
 
 * @note This function can take few seconds to complete (typically 5 seconds)
994
 
 *
995
 
 * @param root_privkey The root private key.
996
 
 * @param root_crt The root certificate.
997
 
 * @param host_privkey The host private key.
998
 
 * @param host_crt The host certificate.
999
 
 *
1000
 
 * @return 1 if the keys and certificates were successfully retrieved, 0 otherwise
1001
 
 */
1002
 
#ifdef HAVE_OPENSSL
1003
 
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)
1004
 
#else
1005
 
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)
1006
 
#endif
1007
 
{
1008
 
        userpref_error_t ret = USERPREF_E_SUCCESS;
1009
 
 
1010
 
        if (ret == USERPREF_E_SUCCESS)
1011
 
                ret = userpref_import_key(LIBIMOBILEDEVICE_ROOT_PRIVKEY, root_privkey);
1012
 
 
1013
 
        if (ret == USERPREF_E_SUCCESS)
1014
 
                ret = userpref_import_key(LIBIMOBILEDEVICE_HOST_PRIVKEY, host_privkey);
1015
 
 
1016
 
        if (ret == USERPREF_E_SUCCESS)
1017
 
                ret = userpref_import_crt(LIBIMOBILEDEVICE_ROOT_CERTIF, root_crt);
1018
 
 
1019
 
        if (ret == USERPREF_E_SUCCESS)
1020
 
                ret = userpref_import_crt(LIBIMOBILEDEVICE_HOST_CERTIF, host_crt);
1021
 
 
1022
 
        if (USERPREF_E_SUCCESS != ret) {
1023
 
                //we had problem reading or importing root cert
1024
 
                //try with a new ones.
1025
 
                ret = userpref_gen_keys_and_cert();
1026
 
 
1027
 
                if (ret == USERPREF_E_SUCCESS)
1028
 
                        ret = userpref_import_key(LIBIMOBILEDEVICE_ROOT_PRIVKEY, root_privkey);
1029
 
 
1030
 
                if (ret == USERPREF_E_SUCCESS)
1031
 
                        ret = userpref_import_key(LIBIMOBILEDEVICE_HOST_PRIVKEY, host_privkey);
1032
 
 
1033
 
                if (ret == USERPREF_E_SUCCESS)
1034
 
                        ret = userpref_import_crt(LIBIMOBILEDEVICE_ROOT_CERTIF, root_crt);
1035
 
 
1036
 
                if (ret == USERPREF_E_SUCCESS)
1037
 
                        ret = userpref_import_crt(LIBIMOBILEDEVICE_HOST_CERTIF, host_crt);
1038
 
        }
1039
 
 
1040
 
        return ret;
1041
 
}
1042
 
 
1043
 
/**
1044
 
 * Function to retrieve certificates encoded in PEM format.
1045
 
 *
1046
 
 * @param pem_root_cert The root certificate.
1047
 
 * @param pem_host_cert The host certificate.
1048
 
 *
1049
 
 * @return 1 if the certificates were successfully retrieved, 0 otherwise
1050
 
 */
1051
 
userpref_error_t userpref_get_certs_as_pem(key_data_t *pem_root_cert, key_data_t *pem_host_cert)
1052
 
{
1053
 
        if (!pem_root_cert || !pem_host_cert)
1054
 
                return USERPREF_E_INVALID_ARG;
1055
 
 
1056
 
        if (userpref_get_file_contents(LIBIMOBILEDEVICE_ROOT_CERTIF, pem_root_cert) && userpref_get_file_contents(LIBIMOBILEDEVICE_HOST_CERTIF, pem_host_cert))
1057
 
                return USERPREF_E_SUCCESS;
1058
 
        else {
1059
 
                if (pem_root_cert->data) {
1060
 
                        free(pem_root_cert->data);
1061
 
                        pem_root_cert->size = 0;
1062
 
                }
1063
 
                if (pem_host_cert->data) {
1064
 
                        free(pem_host_cert->data);
1065
 
                        pem_host_cert->size = 0;
1066
 
                }
1067
 
        }
1068
 
        debug_info("configuration invalid");
1069
 
        return USERPREF_E_INVALID_CONF;
1070
 
}
1071
 
 
1072
 
/**
1073
 
 * Create and save a configuration file containing the given data.
1074
 
 *
1075
 
 * @note: All fields must specified and be non-null
1076
 
 *
1077
 
 * @param root_key The root key
1078
 
 * @param root_cert The root certificate
1079
 
 * @param host_key The host key
1080
 
 * @param host_cert The host certificate
1081
 
 *
1082
 
 * @return 1 on success and 0 otherwise.
1083
 
 */
1084
 
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)
1085
 
{
1086
 
        FILE *pFile;
1087
 
        char *pem;
1088
 
        const char *config_path;
1089
 
        userpref_error_t ret = USERPREF_E_SUCCESS;
1090
 
 
1091
 
        debug_info("saving keys and certs");
1092
 
 
1093
 
        if (!root_key || !host_key || !root_cert || !host_cert) {
1094
 
                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);
1095
 
                return USERPREF_E_INVALID_ARG;
1096
 
        }
1097
 
 
1098
 
        /* Make sure config directory exists */
1099
 
        userpref_create_config_dir();
1100
 
 
1101
 
        config_path = userpref_get_config_dir();
1102
 
 
1103
 
        /* Now write keys and certificates to disk */
1104
 
        pem = (char*)malloc(strlen(config_path)+1+strlen(LIBIMOBILEDEVICE_ROOT_PRIVKEY)+1);
1105
 
        strcpy(pem, config_path);
1106
 
        strcat(pem, DIR_SEP_S);
1107
 
        strcat(pem, LIBIMOBILEDEVICE_ROOT_PRIVKEY);
1108
 
        pFile = fopen(pem, "wb");
1109
 
        if (pFile) {
1110
 
                fwrite(root_key->data, 1, root_key->size, pFile);
1111
 
                fclose(pFile);
1112
 
        } else {
1113
 
                debug_info("could not open '%s' for writing: %s", pem, strerror(errno));
1114
 
                ret = USERPREF_E_WRITE_ERROR;
1115
 
        }
1116
 
        free(pem);
1117
 
 
1118
 
        pem = (char*)malloc(strlen(config_path)+1+strlen(LIBIMOBILEDEVICE_HOST_PRIVKEY)+1);
1119
 
        strcpy(pem, config_path);
1120
 
        strcat(pem, DIR_SEP_S);
1121
 
        strcat(pem, LIBIMOBILEDEVICE_HOST_PRIVKEY);
1122
 
        pFile = fopen(pem, "wb");
1123
 
        if (pFile) {
1124
 
                fwrite(host_key->data, 1, host_key->size, pFile);
1125
 
                fclose(pFile);
1126
 
        } else {
1127
 
                debug_info("could not open '%s' for writing: %s", pem, strerror(errno));
1128
 
                ret = USERPREF_E_WRITE_ERROR;
1129
 
        }
1130
 
        free(pem);
1131
 
 
1132
 
        pem = (char*)malloc(strlen(config_path)+1+strlen(LIBIMOBILEDEVICE_ROOT_CERTIF)+1);
1133
 
        strcpy(pem, config_path);
1134
 
        strcat(pem, DIR_SEP_S);
1135
 
        strcat(pem, LIBIMOBILEDEVICE_ROOT_CERTIF);
1136
 
        pFile = fopen(pem, "wb");
1137
 
        if (pFile) {
1138
 
                fwrite(root_cert->data, 1, root_cert->size, pFile);
1139
 
                fclose(pFile);
1140
 
        } else {
1141
 
                debug_info("could not open '%s' for writing: %s", pem, strerror(errno));
1142
 
                ret = USERPREF_E_WRITE_ERROR;
1143
 
        }
1144
 
        free(pem);
1145
 
 
1146
 
        pem = (char*)malloc(strlen(config_path)+1+strlen(LIBIMOBILEDEVICE_HOST_CERTIF)+1);
1147
 
        strcpy(pem, config_path);
1148
 
        strcat(pem, DIR_SEP_S);
1149
 
        strcat(pem, LIBIMOBILEDEVICE_HOST_CERTIF);
1150
 
        pFile = fopen(pem, "wb");
1151
 
        if (pFile) {
1152
 
                fwrite(host_cert->data, 1, host_cert->size, pFile);
1153
 
                fclose(pFile);
1154
 
        } else {
1155
 
                debug_info("could not open '%s' for writing: %s", pem, strerror(errno));
1156
 
                ret = USERPREF_E_WRITE_ERROR;
1157
 
        }
1158
 
        free(pem);
1159
 
 
1160
 
        return ret;
1161
 
}