diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/lockdown.c | 44 | ||||
| -rw-r--r-- | src/lockdown.h | 2 | ||||
| -rw-r--r-- | src/userpref.c | 143 | ||||
| -rw-r--r-- | src/userpref.h | 4 |
4 files changed, 70 insertions, 123 deletions
diff --git a/src/lockdown.c b/src/lockdown.c index 6ba7e18..c8275eb 100644 --- a/src/lockdown.c +++ b/src/lockdown.c | |||
| @@ -320,21 +320,21 @@ int lockdownd_init(iPhone *phone, lockdownd_client **control) | |||
| 320 | fprintf(stderr, "Hello failed in the lockdownd client.\n"); | 320 | fprintf(stderr, "Hello failed in the lockdownd client.\n"); |
| 321 | } | 321 | } |
| 322 | 322 | ||
| 323 | char *public_key = NULL; | 323 | char *uid = NULL; |
| 324 | if(!lockdownd_get_device_public_key(*control, &public_key)){ | 324 | if(!lockdownd_get_device_uid(*control, &uid)){ |
| 325 | fprintf(stderr, "Device refused to send public key.\n"); | 325 | fprintf(stderr, "Device refused to send public key.\n"); |
| 326 | } | 326 | } |
| 327 | 327 | ||
| 328 | host_id = get_host_id(); | 328 | host_id = get_host_id(); |
| 329 | 329 | ||
| 330 | if (!is_device_known(public_key)) | 330 | if (!is_device_known(uid)) |
| 331 | ret = lockdownd_pair_device(*control, public_key, host_id); | 331 | ret = lockdownd_pair_device(*control, uid, host_id); |
| 332 | else | 332 | else |
| 333 | ret = 1; | 333 | ret = 1; |
| 334 | 334 | ||
| 335 | if (public_key) { | 335 | if (uid) { |
| 336 | free(public_key); | 336 | free(uid); |
| 337 | public_key = NULL; | 337 | uid = NULL; |
| 338 | } | 338 | } |
| 339 | 339 | ||
| 340 | if (ret && host_id && lockdownd_start_SSL_session(*control, host_id)) { | 340 | if (ret && host_id && lockdownd_start_SSL_session(*control, host_id)) { |
| @@ -359,7 +359,7 @@ int lockdownd_init(iPhone *phone, lockdownd_client **control) | |||
| 359 | * | 359 | * |
| 360 | * @return 1 on success and 0 on failure | 360 | * @return 1 on success and 0 on failure |
| 361 | */ | 361 | */ |
| 362 | int lockdownd_pair_device(lockdownd_client *control, char *public_key_b64, char *host_id) | 362 | int lockdownd_pair_device(lockdownd_client *control, char *uid, char *host_id) |
| 363 | { | 363 | { |
| 364 | int ret = 0; | 364 | int ret = 0; |
| 365 | xmlDocPtr plist = new_plist(); | 365 | xmlDocPtr plist = new_plist(); |
| @@ -373,8 +373,16 @@ int lockdownd_pair_device(lockdownd_client *control, char *public_key_b64, char | |||
| 373 | char* device_cert_b64 = NULL; | 373 | char* device_cert_b64 = NULL; |
| 374 | char* host_cert_b64 = NULL; | 374 | char* host_cert_b64 = NULL; |
| 375 | char* root_cert_b64 = NULL; | 375 | char* root_cert_b64 = NULL; |
| 376 | char *public_key_b64 = NULL; | ||
| 377 | |||
| 378 | if(!lockdownd_get_device_public_key(control, &public_key_b64)){ | ||
| 379 | fprintf(stderr, "Device refused to send public key.\n"); | ||
| 380 | return 0; | ||
| 381 | } | ||
| 382 | |||
| 376 | 383 | ||
| 377 | if(!lockdownd_gen_pair_cert(public_key_b64, &device_cert_b64, &host_cert_b64, &root_cert_b64)){ | 384 | if(!lockdownd_gen_pair_cert(public_key_b64, &device_cert_b64, &host_cert_b64, &root_cert_b64)){ |
| 385 | free(public_key_b64); | ||
| 378 | return 0; | 386 | return 0; |
| 379 | } | 387 | } |
| 380 | 388 | ||
| @@ -408,12 +416,18 @@ int lockdownd_pair_device(lockdownd_client *control, char *public_key_b64, char | |||
| 408 | } | 416 | } |
| 409 | 417 | ||
| 410 | plist = xmlReadMemory(XML_content, bytes, NULL, NULL, 0); | 418 | plist = xmlReadMemory(XML_content, bytes, NULL, NULL, 0); |
| 411 | if (!plist) return 0; | 419 | if (!plist) { |
| 420 | free(public_key_b64); | ||
| 421 | return 0; | ||
| 422 | } | ||
| 412 | dict = xmlDocGetRootElement(plist); | 423 | dict = xmlDocGetRootElement(plist); |
| 413 | for (dict = dict->children; dict; dict = dict->next) { | 424 | for (dict = dict->children; dict; dict = dict->next) { |
| 414 | if (!xmlStrcmp(dict->name, "dict")) break; | 425 | if (!xmlStrcmp(dict->name, "dict")) break; |
| 415 | } | 426 | } |
| 416 | if (!dict) return 0; | 427 | if (!dict) { |
| 428 | free(public_key_b64); | ||
| 429 | return 0; | ||
| 430 | } | ||
| 417 | 431 | ||
| 418 | /* Parse xml to check success and to find public key */ | 432 | /* Parse xml to check success and to find public key */ |
| 419 | dictionary = read_dict_element_strings(dict); | 433 | dictionary = read_dict_element_strings(dict); |
| @@ -435,11 +449,12 @@ int lockdownd_pair_device(lockdownd_client *control, char *public_key_b64, char | |||
| 435 | /* store public key in config if pairing succeeded */ | 449 | /* store public key in config if pairing succeeded */ |
| 436 | if (success) { | 450 | if (success) { |
| 437 | if (debug) printf("lockdownd_pair_device: pair success\n"); | 451 | if (debug) printf("lockdownd_pair_device: pair success\n"); |
| 438 | store_device_public_key(public_key_b64); | 452 | store_device_public_key(uid, public_key_b64); |
| 439 | ret = 1; | 453 | ret = 1; |
| 440 | } else { | 454 | } else { |
| 441 | if (debug) printf("lockdownd_pair_device: pair failure\n"); | 455 | if (debug) printf("lockdownd_pair_device: pair failure\n"); |
| 442 | } | 456 | } |
| 457 | free(public_key_b64); | ||
| 443 | return ret; | 458 | return ret; |
| 444 | } | 459 | } |
| 445 | 460 | ||
| @@ -542,12 +557,9 @@ int lockdownd_gen_pair_cert(char *public_key_b64, char **device_cert_b64, char * | |||
| 542 | if (!error) { | 557 | if (!error) { |
| 543 | /* if everything went well, export in PEM format */ | 558 | /* if everything went well, export in PEM format */ |
| 544 | gnutls_datum_t dev_pem = {NULL, 0}; | 559 | gnutls_datum_t dev_pem = {NULL, 0}; |
| 545 | size_t crt_size; | 560 | gnutls_x509_crt_export(dev_cert, GNUTLS_X509_FMT_PEM, NULL, &dev_pem.size); |
| 546 | gnutls_x509_crt_export(dev_cert, GNUTLS_X509_FMT_PEM, NULL, &crt_size); | ||
| 547 | dev_pem.size = crt_size; | ||
| 548 | dev_pem.data = gnutls_malloc(dev_pem.size); | 561 | dev_pem.data = gnutls_malloc(dev_pem.size); |
| 549 | gnutls_x509_crt_export(dev_cert, GNUTLS_X509_FMT_PEM, dev_pem.data, &crt_size); | 562 | gnutls_x509_crt_export(dev_cert, GNUTLS_X509_FMT_PEM, dev_pem.data, &dev_pem.size); |
| 550 | dev_pem.size = crt_size; | ||
| 551 | 563 | ||
| 552 | /* now encode certificates for output */ | 564 | /* now encode certificates for output */ |
| 553 | *device_cert_b64 = g_base64_encode(dev_pem.data, dev_pem.size); | 565 | *device_cert_b64 = g_base64_encode(dev_pem.data, dev_pem.size); |
diff --git a/src/lockdown.h b/src/lockdown.h index df70bbd..c542d65 100644 --- a/src/lockdown.h +++ b/src/lockdown.h | |||
| @@ -44,7 +44,7 @@ int lockdownd_hello(lockdownd_client *control); | |||
| 44 | int lockdownd_get_device_uid(lockdownd_client *control, char **uid); | 44 | int lockdownd_get_device_uid(lockdownd_client *control, char **uid); |
| 45 | int lockdownd_get_device_public_key(lockdownd_client *control, char **public_key); | 45 | int lockdownd_get_device_public_key(lockdownd_client *control, char **public_key); |
| 46 | int lockdownd_gen_pair_cert(char *public_key_b64, char **device_cert_b64, char **host_cert_b64, char **root_cert_b64); | 46 | int lockdownd_gen_pair_cert(char *public_key_b64, char **device_cert_b64, char **host_cert_b64, char **root_cert_b64); |
| 47 | int lockdownd_pair_device(lockdownd_client *control, char *public_key, char *host_id); | 47 | int lockdownd_pair_device(lockdownd_client *control, char *uid, char *host_id); |
| 48 | int lockdownd_recv(lockdownd_client *control, char **dump_data); | 48 | int lockdownd_recv(lockdownd_client *control, char **dump_data); |
| 49 | int lockdownd_send(lockdownd_client *control, char *raw_data, uint32 length); | 49 | int lockdownd_send(lockdownd_client *control, char *raw_data, uint32 length); |
| 50 | void lockdownd_close(lockdownd_client *control); | 50 | void lockdownd_close(lockdownd_client *control); |
diff --git a/src/userpref.c b/src/userpref.c index 41b11bc..5b53775 100644 --- a/src/userpref.c +++ b/src/userpref.c | |||
| @@ -25,7 +25,7 @@ | |||
| 25 | #include <string.h> | 25 | #include <string.h> |
| 26 | #include "userpref.h" | 26 | #include "userpref.h" |
| 27 | #include <string.h> | 27 | #include <string.h> |
| 28 | #include <stdio.h> | 28 | #include <stdlib.h> |
| 29 | 29 | ||
| 30 | #define LIBIPHONE_CONF_DIR "libiphone" | 30 | #define LIBIPHONE_CONF_DIR "libiphone" |
| 31 | #define LIBIPHONE_CONF_FILE "libiphonerc" | 31 | #define LIBIPHONE_CONF_FILE "libiphonerc" |
| @@ -37,6 +37,18 @@ | |||
| 37 | 37 | ||
| 38 | extern int debug; | 38 | extern int debug; |
| 39 | 39 | ||
| 40 | /** Creates a freedesktop compatible configuration directory for libiphone. | ||
| 41 | */ | ||
| 42 | inline void create_config_dir() { | ||
| 43 | gchar* config_dir = g_build_path(G_DIR_SEPARATOR_S, g_get_user_config_dir(), LIBIPHONE_CONF_DIR, NULL); | ||
| 44 | |||
| 45 | if (!g_file_test(config_dir, (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR) )) | ||
| 46 | g_mkdir_with_parents(config_dir, 0755); | ||
| 47 | |||
| 48 | g_free(config_dir); | ||
| 49 | } | ||
| 50 | |||
| 51 | |||
| 40 | /** Reads the HostID from a previously generated configuration file. | 52 | /** Reads the HostID from a previously generated configuration file. |
| 41 | * | 53 | * |
| 42 | * @note It is the responsibility of the calling function to free the returned host_id | 54 | * @note It is the responsibility of the calling function to free the returned host_id |
| @@ -68,12 +80,12 @@ char* get_host_id() { | |||
| 68 | 80 | ||
| 69 | /** Determines whether this iPhone has been connected to this system before. | 81 | /** Determines whether this iPhone has been connected to this system before. |
| 70 | * | 82 | * |
| 71 | * @param public_key The public key as given by the iPhone. | 83 | * @param uid The device uid as given by the iPhone. |
| 72 | * | 84 | * |
| 73 | * @return 1 if the iPhone has been connected previously to this configuration | 85 | * @return 1 if the iPhone has been connected previously to this configuration |
| 74 | * or 0 otherwise. | 86 | * or 0 otherwise. |
| 75 | */ | 87 | */ |
| 76 | int is_device_known(char* public_key) { | 88 | int is_device_known(char* uid) { |
| 77 | int ret = 0; | 89 | int ret = 0; |
| 78 | gchar *config_file; | 90 | gchar *config_file; |
| 79 | GKeyFile *key_file; | 91 | GKeyFile *key_file; |
| @@ -81,41 +93,12 @@ int is_device_known(char* public_key) { | |||
| 81 | GIOChannel *keyfile; | 93 | GIOChannel *keyfile; |
| 82 | 94 | ||
| 83 | /* first get config file */ | 95 | /* first get config file */ |
| 84 | config_file = g_build_path(G_DIR_SEPARATOR_S, g_get_user_config_dir(), LIBIPHONE_CONF_DIR, LIBIPHONE_CONF_FILE, NULL); | 96 | gchar* device_file = g_strconcat(uid, ".pem", NULL); |
| 85 | if (g_file_test(config_file, (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_REGULAR))) { | 97 | config_file = g_build_path(G_DIR_SEPARATOR_S, g_get_user_config_dir(), LIBIPHONE_CONF_DIR, device_file, NULL); |
| 86 | 98 | if (g_file_test(config_file, (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_REGULAR))) | |
| 87 | /* now parse file to get knwon devices list */ | 99 | ret = 1; |
| 88 | key_file = g_key_file_new (); | 100 | g_free(config_file); |
| 89 | if(g_key_file_load_from_file(key_file, config_file, G_KEY_FILE_KEEP_COMMENTS, NULL)) { | 101 | g_free(device_file); |
| 90 | |||
| 91 | devices_list = g_key_file_get_string_list (key_file, "Global", "DevicesList", NULL, NULL); | ||
| 92 | if (devices_list) { | ||
| 93 | pcur = devices_list; | ||
| 94 | while(*pcur && !ret) { | ||
| 95 | /* open associated base64 encoded key */ | ||
| 96 | keyfilepath = g_build_path(G_DIR_SEPARATOR_S, g_get_user_config_dir(), LIBIPHONE_CONF_DIR, *pcur, NULL); | ||
| 97 | if (g_file_test(keyfilepath, (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_REGULAR))) { | ||
| 98 | keyfile = g_io_channel_new_file (keyfilepath, "r", NULL); | ||
| 99 | |||
| 100 | stored_key = NULL; | ||
| 101 | g_io_channel_read_to_end (keyfile, &stored_key, NULL, NULL); | ||
| 102 | |||
| 103 | /* now compare to input */ | ||
| 104 | if (strcmp(public_key, stored_key) == 2 || !strcmp(public_key, stored_key)) | ||
| 105 | ret = 1; | ||
| 106 | g_free(stored_key); | ||
| 107 | g_io_channel_shutdown(keyfile, FALSE, NULL); | ||
| 108 | g_io_channel_unref(keyfile); | ||
| 109 | pcur++; | ||
| 110 | } | ||
| 111 | g_free(keyfilepath); | ||
| 112 | } | ||
| 113 | } | ||
| 114 | g_strfreev(devices_list); | ||
| 115 | } | ||
| 116 | g_key_file_free(key_file); | ||
| 117 | g_free(config_file); | ||
| 118 | } | ||
| 119 | return ret; | 102 | return ret; |
| 120 | } | 103 | } |
| 121 | 104 | ||
| @@ -127,65 +110,28 @@ int is_device_known(char* public_key) { | |||
| 127 | * @return 1 on success and 0 if no public key is given or if it has already | 110 | * @return 1 on success and 0 if no public key is given or if it has already |
| 128 | * been marked as connected previously. | 111 | * been marked as connected previously. |
| 129 | */ | 112 | */ |
| 130 | int store_device_public_key(char* public_key) { | 113 | int store_device_public_key(char* uid, char* public_key) { |
| 131 | gchar *config_file; | ||
| 132 | GKeyFile *key_file; | ||
| 133 | gchar **devices_list; | ||
| 134 | guint len = 0; | ||
| 135 | guint wlength = 0; | ||
| 136 | gchar dev_file[20]; | ||
| 137 | int i; | ||
| 138 | const gchar** new_devices_list; | ||
| 139 | gsize length; | ||
| 140 | gchar *buf; | ||
| 141 | GIOChannel *file; | ||
| 142 | gchar* device_file; | ||
| 143 | 114 | ||
| 144 | if (NULL == public_key || is_device_known(public_key)) | 115 | if (NULL == public_key || is_device_known(uid)) |
| 145 | return 0; | 116 | return 0; |
| 146 | 117 | ||
| 147 | /* first get config file */ | 118 | /* ensure config directory exists */ |
| 148 | config_file = g_build_path(G_DIR_SEPARATOR_S, g_get_user_config_dir(), LIBIPHONE_CONF_DIR, LIBIPHONE_CONF_FILE, NULL); | 119 | create_config_dir(); |
| 149 | if (g_file_test(config_file, (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_REGULAR))) { | 120 | |
| 150 | key_file = g_key_file_new(); | 121 | /* build file path */ |
| 151 | if(g_key_file_load_from_file (key_file, config_file, G_KEY_FILE_KEEP_COMMENTS, NULL)) { | 122 | gchar* device_file = g_strconcat(uid, ".pem", NULL); |
| 152 | 123 | gchar* pem = g_build_path(G_DIR_SEPARATOR_S, g_get_user_config_dir(), LIBIPHONE_CONF_DIR, device_file, NULL); | |
| 153 | /* Determine device name */ | ||
| 154 | devices_list = g_key_file_get_string_list (key_file, "Global", "DevicesList", NULL, NULL); | ||
| 155 | if (devices_list) | ||
| 156 | len = g_strv_length(devices_list); | ||
| 157 | g_strfreev(devices_list); | ||
| 158 | g_sprintf(dev_file, "Device%i", len); | ||
| 159 | |||
| 160 | /* Write device file to disk */ | ||
| 161 | device_file = g_build_path(G_DIR_SEPARATOR_S, g_get_user_config_dir(), LIBIPHONE_CONF_DIR, dev_file, NULL); | ||
| 162 | file = g_io_channel_new_file (device_file, "w", NULL); | ||
| 163 | g_free(device_file); | ||
| 164 | wlength = strlen(public_key); // why this wasn't discovered before... ugh | ||
| 165 | g_io_channel_write_chars(file, public_key, wlength, NULL, NULL); | ||
| 166 | g_io_channel_shutdown(file, TRUE, NULL); | ||
| 167 | g_io_channel_unref(file); | ||
| 168 | |||
| 169 | /* Append device to list */ | ||
| 170 | new_devices_list = (const gchar**)g_malloc(sizeof(gchar*)* (len + 2)); | ||
| 171 | for( i = 0; i < len; i++) | ||
| 172 | new_devices_list[i] = devices_list[i]; | ||
| 173 | new_devices_list[len] = dev_file; | ||
| 174 | new_devices_list[len+1] = NULL; | ||
| 175 | g_key_file_set_string_list(key_file,"Global", "DevicesList", new_devices_list, len+1); | ||
| 176 | g_free(new_devices_list); | ||
| 177 | |||
| 178 | } | ||
| 179 | |||
| 180 | /* Write config file to disk */ | ||
| 181 | buf = g_key_file_to_data(key_file, &length, NULL); | ||
| 182 | file = g_io_channel_new_file(config_file, "w", NULL); | ||
| 183 | g_io_channel_write_chars(file, buf, length, NULL, NULL); | ||
| 184 | g_io_channel_shutdown(file, TRUE, NULL); | ||
| 185 | g_io_channel_unref(file); | ||
| 186 | g_key_file_free(key_file); | ||
| 187 | } | ||
| 188 | 124 | ||
| 125 | /* decode public key for storing */ | ||
| 126 | gsize decoded_size; | ||
| 127 | gchar* data = g_base64_decode (public_key, &decoded_size); | ||
| 128 | /* store file */ | ||
| 129 | FILE* pFile = fopen(pem , "wb"); | ||
| 130 | fwrite(data, 1, decoded_size, pFile); | ||
| 131 | fclose(pFile); | ||
| 132 | g_free(pem); | ||
| 133 | g_free(data); | ||
| 134 | g_free(device_file); | ||
| 189 | return 1; | 135 | return 1; |
| 190 | } | 136 | } |
| 191 | 137 | ||
| @@ -257,17 +203,6 @@ int get_host_certificate(gnutls_datum_t* host_cert) { | |||
| 257 | return read_file_in_confdir(LIBIPHONE_HOST_CERTIF, host_cert); | 203 | return read_file_in_confdir(LIBIPHONE_HOST_CERTIF, host_cert); |
| 258 | } | 204 | } |
| 259 | 205 | ||
| 260 | /** Creates a freedesktop compatible configuration directory for libiphone. | ||
| 261 | */ | ||
| 262 | inline void create_config_dir() { | ||
| 263 | gchar* config_dir = g_build_path(G_DIR_SEPARATOR_S, g_get_user_config_dir(), LIBIPHONE_CONF_DIR, NULL); | ||
| 264 | |||
| 265 | if (!g_file_test(config_dir, (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR) )) | ||
| 266 | g_mkdir_with_parents(config_dir, 0755); | ||
| 267 | |||
| 268 | g_free(config_dir); | ||
| 269 | } | ||
| 270 | |||
| 271 | /** Create and save a configuration file containing the given data. | 206 | /** Create and save a configuration file containing the given data. |
| 272 | * | 207 | * |
| 273 | * @note: All fields must specified and be non-null | 208 | * @note: All fields must specified and be non-null |
diff --git a/src/userpref.h b/src/userpref.h index c437e52..553c5df 100644 --- a/src/userpref.h +++ b/src/userpref.h | |||
| @@ -35,12 +35,12 @@ char* get_host_id(); | |||
| 35 | * | 35 | * |
| 36 | * @return 1 if device is already paired. Returns 0 otherwise. | 36 | * @return 1 if device is already paired. Returns 0 otherwise. |
| 37 | */ | 37 | */ |
| 38 | int is_device_known(char* public_key); | 38 | int is_device_known(char* uid); |
| 39 | 39 | ||
| 40 | /** | 40 | /** |
| 41 | * @return 1 if everything went well. Returns 0 otherwise. | 41 | * @return 1 if everything went well. Returns 0 otherwise. |
| 42 | */ | 42 | */ |
| 43 | int store_device_public_key(char* public_key); | 43 | int store_device_public_key(char* uid, char* public_key); |
| 44 | 44 | ||
| 45 | /** | 45 | /** |
| 46 | * @return 1 if everything went well. Returns 0 otherwise. | 46 | * @return 1 if everything went well. Returns 0 otherwise. |
