diff options
| -rw-r--r-- | configure.ac | 2 | ||||
| -rw-r--r-- | src/Makefile.am | 1 | ||||
| -rw-r--r-- | src/conf.c | 499 | ||||
| -rw-r--r-- | src/conf.h | 40 | ||||
| -rw-r--r-- | src/main.c | 7 | ||||
| -rw-r--r-- | src/preflight.c | 11 | ||||
| -rw-r--r-- | src/utils.c | 144 | ||||
| -rw-r--r-- | src/utils.h | 17 |
8 files changed, 709 insertions, 12 deletions
diff --git a/configure.ac b/configure.ac index 9e113d7..6737f6f 100644 --- a/configure.ac +++ b/configure.ac | |||
| @@ -57,7 +57,7 @@ AC_TYPE_UINT8_T | |||
| 57 | # Checks for library functions. | 57 | # Checks for library functions. |
| 58 | AC_FUNC_MALLOC | 58 | AC_FUNC_MALLOC |
| 59 | AC_FUNC_REALLOC | 59 | AC_FUNC_REALLOC |
| 60 | AC_CHECK_FUNCS([strcasecmp strdup strerror strndup]) | 60 | AC_CHECK_FUNCS([strcasecmp strdup strerror strndup stpcpy]) |
| 61 | 61 | ||
| 62 | # Check for operating system | 62 | # Check for operating system |
| 63 | AC_MSG_CHECKING([whether to enable WIN32 build settings]) | 63 | AC_MSG_CHECKING([whether to enable WIN32 build settings]) |
diff --git a/src/Makefile.am b/src/Makefile.am index 883f1d8..38858c4 100644 --- a/src/Makefile.am +++ b/src/Makefile.am | |||
| @@ -9,6 +9,7 @@ usbmuxd_SOURCES = client.c client.h \ | |||
| 9 | log.c log.h \ | 9 | log.c log.h \ |
| 10 | usb-linux.c usb.h \ | 10 | usb-linux.c usb.h \ |
| 11 | utils.c utils.h \ | 11 | utils.c utils.h \ |
| 12 | conf.c conf.h \ | ||
| 12 | main.c | 13 | main.c |
| 13 | usbmuxd_CFLAGS = $(AM_CFLAGS) | 14 | usbmuxd_CFLAGS = $(AM_CFLAGS) |
| 14 | usbmuxd_LDFLAGS = $(AM_LDFLAGS) | 15 | usbmuxd_LDFLAGS = $(AM_LDFLAGS) |
diff --git a/src/conf.c b/src/conf.c new file mode 100644 index 0000000..780a7c4 --- /dev/null +++ b/src/conf.c | |||
| @@ -0,0 +1,499 @@ | |||
| 1 | /* | ||
| 2 | usbmuxd - iPhone/iPod Touch USB multiplex server daemon | ||
| 3 | |||
| 4 | Copyright (C) 2013 Nikias Bassen <nikias@gmx.li> | ||
| 5 | |||
| 6 | This program is free software; you can redistribute it and/or modify | ||
| 7 | it under the terms of the GNU General Public License as published by | ||
| 8 | the Free Software Foundation, either version 2 or version 3. | ||
| 9 | |||
| 10 | This program is distributed in the hope that it will be useful, | ||
| 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 13 | GNU General Public License for more details. | ||
| 14 | |||
| 15 | You should have received a copy of the GNU General Public License | ||
| 16 | along with this program; if not, write to the Free Software | ||
| 17 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | ||
| 18 | |||
| 19 | */ | ||
| 20 | |||
| 21 | #ifdef HAVE_CONFIG_H | ||
| 22 | #include <config.h> | ||
| 23 | #endif | ||
| 24 | |||
| 25 | #include <stdio.h> | ||
| 26 | #include <stdint.h> | ||
| 27 | #include <stdlib.h> | ||
| 28 | #include <string.h> | ||
| 29 | #include <time.h> | ||
| 30 | #ifdef HAVE_SYS_TYPES_H | ||
| 31 | #include <sys/types.h> | ||
| 32 | #endif | ||
| 33 | |||
| 34 | #include <dirent.h> | ||
| 35 | #include <libgen.h> | ||
| 36 | #include <sys/stat.h> | ||
| 37 | #include <errno.h> | ||
| 38 | |||
| 39 | #ifdef WIN32 | ||
| 40 | #include <shlobj.h> | ||
| 41 | #endif | ||
| 42 | |||
| 43 | #include "conf.h" | ||
| 44 | #include "utils.h" | ||
| 45 | #include "log.h" | ||
| 46 | |||
| 47 | #ifdef WIN32 | ||
| 48 | #define DIR_SEP '\\' | ||
| 49 | #define DIR_SEP_S "\\" | ||
| 50 | #else | ||
| 51 | #define DIR_SEP '/' | ||
| 52 | #define DIR_SEP_S "/" | ||
| 53 | #endif | ||
| 54 | |||
| 55 | #define CONFIG_SYSTEM_BUID_KEY "SystemBUID" | ||
| 56 | #define CONFIG_HOST_ID_KEY "HostID" | ||
| 57 | |||
| 58 | #define CONFIG_EXT ".plist" | ||
| 59 | |||
| 60 | #ifdef WIN32 | ||
| 61 | #define CONFIG_DIR "Apple"DIR_SEP_S"Lockdown" | ||
| 62 | #else | ||
| 63 | #define CONFIG_DIR "lockdown" | ||
| 64 | #endif | ||
| 65 | |||
| 66 | #define CONFIG_FILE "SystemConfiguration"CONFIG_EXT | ||
| 67 | |||
| 68 | static char *__config_dir = NULL; | ||
| 69 | |||
| 70 | #ifdef WIN32 | ||
| 71 | static char *config_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 | const char *config_get_config_dir() | ||
| 106 | { | ||
| 107 | char *base_config_dir = NULL; | ||
| 108 | |||
| 109 | if (__config_dir) | ||
| 110 | return __config_dir; | ||
| 111 | |||
| 112 | #ifdef WIN32 | ||
| 113 | wchar_t path[MAX_PATH+1]; | ||
| 114 | HRESULT hr; | ||
| 115 | LPITEMIDLIST pidl = NULL; | ||
| 116 | BOOL b = FALSE; | ||
| 117 | |||
| 118 | hr = SHGetSpecialFolderLocation (NULL, CSIDL_COMMON_APPDATA, &pidl); | ||
| 119 | if (hr == S_OK) { | ||
| 120 | b = SHGetPathFromIDListW (pidl, path); | ||
| 121 | if (b) { | ||
| 122 | base_config_dir = config_utf16_to_utf8 (path, wcslen(path), NULL, NULL); | ||
| 123 | CoTaskMemFree (pidl); | ||
| 124 | } | ||
| 125 | } | ||
| 126 | #else | ||
| 127 | #ifdef __APPLE__ | ||
| 128 | base_config_dir = strdup("/var/db"); | ||
| 129 | #else | ||
| 130 | base_config_dir = strdup("/var/lib"); | ||
| 131 | #endif | ||
| 132 | #endif | ||
| 133 | __config_dir = string_concat(base_config_dir, DIR_SEP_S, CONFIG_DIR, NULL); | ||
| 134 | |||
| 135 | if (__config_dir) { | ||
| 136 | int i = strlen(__config_dir)-1; | ||
| 137 | while ((i > 0) && (__config_dir[i] == DIR_SEP)) { | ||
| 138 | __config_dir[i--] = '\0'; | ||
| 139 | } | ||
| 140 | } | ||
| 141 | |||
| 142 | free(base_config_dir); | ||
| 143 | |||
| 144 | usbmuxd_log(LL_DEBUG, "initialized config_dir to %s", __config_dir); | ||
| 145 | |||
| 146 | return __config_dir; | ||
| 147 | } | ||
| 148 | |||
| 149 | static int __mkdir(const char *dir, int mode) | ||
| 150 | { | ||
| 151 | #ifdef WIN32 | ||
| 152 | return mkdir(dir); | ||
| 153 | #else | ||
| 154 | return mkdir(dir, mode); | ||
| 155 | #endif | ||
| 156 | } | ||
| 157 | |||
| 158 | static int mkdir_with_parents(const char *dir, int mode) | ||
| 159 | { | ||
| 160 | if (!dir) return -1; | ||
| 161 | if (__mkdir(dir, mode) == 0) { | ||
| 162 | return 0; | ||
| 163 | } else { | ||
| 164 | if (errno == EEXIST) return 0; | ||
| 165 | } | ||
| 166 | int res; | ||
| 167 | char *parent = strdup(dir); | ||
| 168 | char* parentdir = dirname(parent); | ||
| 169 | if (parentdir) { | ||
| 170 | res = mkdir_with_parents(parentdir, mode); | ||
| 171 | } else { | ||
| 172 | res = -1; | ||
| 173 | } | ||
| 174 | free(parent); | ||
| 175 | return res; | ||
| 176 | } | ||
| 177 | |||
| 178 | /** | ||
| 179 | * Creates a freedesktop compatible configuration directory. | ||
| 180 | */ | ||
| 181 | static void config_create_config_dir(void) | ||
| 182 | { | ||
| 183 | const char *config_path = config_get_config_dir(); | ||
| 184 | struct stat st; | ||
| 185 | if (stat(config_path, &st) != 0) { | ||
| 186 | mkdir_with_parents(config_path, 0755); | ||
| 187 | } | ||
| 188 | } | ||
| 189 | |||
| 190 | static int get_rand(int min, int max) | ||
| 191 | { | ||
| 192 | int retval = (rand() % (max - min)) + min; | ||
| 193 | return retval; | ||
| 194 | } | ||
| 195 | |||
| 196 | static char *config_generate_uuid(int idx) | ||
| 197 | { | ||
| 198 | char *uuid = (char *) malloc(sizeof(char) * 37); | ||
| 199 | const char *chars = "ABCDEF0123456789"; | ||
| 200 | srand(time(NULL) - idx); | ||
| 201 | int i = 0; | ||
| 202 | |||
| 203 | for (i = 0; i < 36; i++) { | ||
| 204 | if (i == 8 || i == 13 || i == 18 || i == 23) { | ||
| 205 | uuid[i] = '-'; | ||
| 206 | continue; | ||
| 207 | } else { | ||
| 208 | uuid[i] = chars[get_rand(0, 16)]; | ||
| 209 | } | ||
| 210 | } | ||
| 211 | /* make it a real string */ | ||
| 212 | uuid[36] = '\0'; | ||
| 213 | return uuid; | ||
| 214 | } | ||
| 215 | |||
| 216 | /** | ||
| 217 | * Generates a valid BUID for this system (which is actually a UUID). | ||
| 218 | * | ||
| 219 | * @return A null terminated string containing a valid BUID. | ||
| 220 | */ | ||
| 221 | static char *config_generate_system_buid() | ||
| 222 | { | ||
| 223 | return config_generate_uuid(1); | ||
| 224 | } | ||
| 225 | |||
| 226 | static int internal_set_value(const char *config_file, const char *key, plist_t value) | ||
| 227 | { | ||
| 228 | if (!config_file) | ||
| 229 | return 0; | ||
| 230 | |||
| 231 | /* read file into plist */ | ||
| 232 | plist_t config = NULL; | ||
| 233 | |||
| 234 | plist_read_from_filename(&config, config_file); | ||
| 235 | if (!config) { | ||
| 236 | config = plist_new_dict(); | ||
| 237 | plist_dict_insert_item(config, key, value); | ||
| 238 | } else { | ||
| 239 | plist_t n = plist_dict_get_item(config, key); | ||
| 240 | if (n) { | ||
| 241 | plist_dict_remove_item(config, key); | ||
| 242 | } | ||
| 243 | plist_dict_insert_item(config, key, value); | ||
| 244 | remove(config_file); | ||
| 245 | } | ||
| 246 | |||
| 247 | /* store in config file */ | ||
| 248 | char *value_string = NULL; | ||
| 249 | if (plist_get_node_type(value) == PLIST_STRING) { | ||
| 250 | plist_get_string_val(value, &value_string); | ||
| 251 | usbmuxd_log(LL_DEBUG, "setting key %s to %s in config_file %s", key, value_string, config_file); | ||
| 252 | if (value_string) | ||
| 253 | free(value_string); | ||
| 254 | } else { | ||
| 255 | usbmuxd_log(LL_DEBUG, "setting key %s in config_file %s", key, config_file); | ||
| 256 | } | ||
| 257 | |||
| 258 | plist_write_to_filename(config, config_file, PLIST_FORMAT_XML); | ||
| 259 | |||
| 260 | plist_free(config); | ||
| 261 | |||
| 262 | return 1; | ||
| 263 | } | ||
| 264 | |||
| 265 | static int config_set_value(const char *key, plist_t value) | ||
| 266 | { | ||
| 267 | const char *config_path = NULL; | ||
| 268 | char *config_file = NULL; | ||
| 269 | |||
| 270 | /* Make sure config directory exists */ | ||
| 271 | config_create_config_dir(); | ||
| 272 | |||
| 273 | config_path = config_get_config_dir(); | ||
| 274 | config_file = string_concat(config_path, DIR_SEP_S, CONFIG_FILE, NULL); | ||
| 275 | |||
| 276 | int result = internal_set_value(config_file, key, value); | ||
| 277 | |||
| 278 | free(config_file); | ||
| 279 | |||
| 280 | return result; | ||
| 281 | } | ||
| 282 | |||
| 283 | static int internal_get_value(const char* config_file, const char *key, plist_t *value) | ||
| 284 | { | ||
| 285 | *value = NULL; | ||
| 286 | |||
| 287 | /* now parse file to get the SystemBUID */ | ||
| 288 | plist_t config = NULL; | ||
| 289 | if (plist_read_from_filename(&config, config_file)) { | ||
| 290 | usbmuxd_log(LL_DEBUG, "reading key %s from config_file %s", key, config_file); | ||
| 291 | plist_t n = plist_dict_get_item(config, key); | ||
| 292 | if (n) { | ||
| 293 | *value = plist_copy(n); | ||
| 294 | plist_free(n); | ||
| 295 | n = NULL; | ||
| 296 | } | ||
| 297 | } | ||
| 298 | plist_free(config); | ||
| 299 | |||
| 300 | return 1; | ||
| 301 | } | ||
| 302 | |||
| 303 | static int config_get_value(const char *key, plist_t *value) | ||
| 304 | { | ||
| 305 | const char *config_path = NULL; | ||
| 306 | char *config_file = NULL; | ||
| 307 | |||
| 308 | config_path = config_get_config_dir(); | ||
| 309 | config_file = string_concat(config_path, DIR_SEP_S, CONFIG_FILE, NULL); | ||
| 310 | |||
| 311 | int result = internal_get_value(config_file, key, value); | ||
| 312 | |||
| 313 | free(config_file); | ||
| 314 | |||
| 315 | return result; | ||
| 316 | } | ||
| 317 | |||
| 318 | /** | ||
| 319 | * Store SystemBUID in config file. | ||
| 320 | * | ||
| 321 | * @param system_buid A null terminated string containing a valid SystemBUID. | ||
| 322 | */ | ||
| 323 | static int config_set_system_buid(const char *system_buid) | ||
| 324 | { | ||
| 325 | return config_set_value(CONFIG_SYSTEM_BUID_KEY, plist_new_string(system_buid)); | ||
| 326 | } | ||
| 327 | |||
| 328 | /** | ||
| 329 | * Reads the BUID from a previously generated configuration file. | ||
| 330 | * | ||
| 331 | * @param system_buid pointer to a variable that will be set to point to a | ||
| 332 | * newly allocated string containing the BUID. | ||
| 333 | * | ||
| 334 | * @note It is the responsibility of the calling function to free the returned system_buid | ||
| 335 | */ | ||
| 336 | void config_get_system_buid(char **system_buid) | ||
| 337 | { | ||
| 338 | plist_t value = NULL; | ||
| 339 | |||
| 340 | config_get_value(CONFIG_SYSTEM_BUID_KEY, &value); | ||
| 341 | |||
| 342 | if (value && (plist_get_node_type(value) == PLIST_STRING)) { | ||
| 343 | plist_get_string_val(value, system_buid); | ||
| 344 | usbmuxd_log(LL_DEBUG, "got %s %s", CONFIG_SYSTEM_BUID_KEY, *system_buid); | ||
| 345 | } | ||
| 346 | |||
| 347 | if (value) | ||
| 348 | plist_free(value); | ||
| 349 | |||
| 350 | if (!*system_buid) { | ||
| 351 | /* no config, generate system_buid */ | ||
| 352 | usbmuxd_log(LL_DEBUG, "no previous %s found", CONFIG_SYSTEM_BUID_KEY); | ||
| 353 | *system_buid = config_generate_system_buid(); | ||
| 354 | config_set_system_buid(*system_buid); | ||
| 355 | } | ||
| 356 | |||
| 357 | usbmuxd_log(LL_DEBUG, "using %s as %s", *system_buid, CONFIG_SYSTEM_BUID_KEY); | ||
| 358 | } | ||
| 359 | |||
| 360 | /** | ||
| 361 | * Store a pairing record for the given device identifier. | ||
| 362 | * | ||
| 363 | * @param udid device identifier | ||
| 364 | * @param record_data buffer containing a pairing record | ||
| 365 | * @param record_size size of buffer passed in record_data | ||
| 366 | * | ||
| 367 | * @return 0 on success or a negative errno otherwise. | ||
| 368 | */ | ||
| 369 | int config_set_device_record(const char *udid, char* record_data, uint64_t record_size) | ||
| 370 | { | ||
| 371 | int res = 0; | ||
| 372 | |||
| 373 | if (!udid || record_data || record_size < 8) | ||
| 374 | return -EINVAL; | ||
| 375 | |||
| 376 | plist_t plist = NULL; | ||
| 377 | if (memcmp(record_data, "bplist00", 8) == 0) { | ||
| 378 | plist_from_bin(record_data, record_size, &plist); | ||
| 379 | } else { | ||
| 380 | plist_from_xml(record_data, record_size, &plist); | ||
| 381 | } | ||
| 382 | |||
| 383 | if (!plist || plist_get_node_type(plist) != PLIST_DICT) { | ||
| 384 | if (plist) | ||
| 385 | plist_free(plist); | ||
| 386 | return -EINVAL; | ||
| 387 | } | ||
| 388 | |||
| 389 | /* ensure config directory exists */ | ||
| 390 | config_create_config_dir(); | ||
| 391 | |||
| 392 | /* build file path */ | ||
| 393 | const char *config_path = config_get_config_dir(); | ||
| 394 | char *device_record_file = string_concat(config_path, DIR_SEP_S, udid, CONFIG_EXT, NULL); | ||
| 395 | |||
| 396 | remove(device_record_file); | ||
| 397 | |||
| 398 | /* store file */ | ||
| 399 | if (!plist_write_to_filename(plist, device_record_file, PLIST_FORMAT_XML)) { | ||
| 400 | usbmuxd_log(LL_DEBUG, "could not open '%s' for writing: %s", device_record_file, strerror(errno)); | ||
| 401 | res = -ENOENT; | ||
| 402 | } | ||
| 403 | free(device_record_file); | ||
| 404 | if (plist) | ||
| 405 | plist_free(plist); | ||
| 406 | |||
| 407 | return res; | ||
| 408 | } | ||
| 409 | |||
| 410 | /** | ||
| 411 | * Retrieve a pairing record for the given device identifier | ||
| 412 | * | ||
| 413 | * @param udid device identifier | ||
| 414 | * @param record_data pointer to a variable that will be set to point to a | ||
| 415 | * newly allocated buffer holding the pairing record | ||
| 416 | * @param record_size pointer to a variable that will be set to the size | ||
| 417 | * of the buffer given in record_data. | ||
| 418 | * | ||
| 419 | * @return 0 on success or a negative errno otherwise. | ||
| 420 | */ | ||
| 421 | int config_get_device_record(const char *udid, char **record_data, uint64_t *record_size) | ||
| 422 | { | ||
| 423 | int res = 0; | ||
| 424 | |||
| 425 | /* ensure config directory exists */ | ||
| 426 | config_create_config_dir(); | ||
| 427 | |||
| 428 | /* build file path */ | ||
| 429 | const char *config_path = config_get_config_dir(); | ||
| 430 | char *device_record_file = string_concat(config_path, DIR_SEP_S, udid, CONFIG_EXT, NULL); | ||
| 431 | |||
| 432 | /* read file */ | ||
| 433 | buffer_read_from_filename(device_record_file, record_data, record_size); if (!*record_data) { | ||
| 434 | usbmuxd_log(LL_ERROR, "%s: failed to read '%s': %s", __func__, device_record_file, strerror(errno)); | ||
| 435 | res = -ENOENT; | ||
| 436 | } | ||
| 437 | free(device_record_file); | ||
| 438 | |||
| 439 | return res; | ||
| 440 | } | ||
| 441 | |||
| 442 | /** | ||
| 443 | * Remove the pairing record stored for a device from this host. | ||
| 444 | * | ||
| 445 | * @param udid The udid of the device | ||
| 446 | * | ||
| 447 | * @return 0 on success or a negative errno otherwise. | ||
| 448 | */ | ||
| 449 | int config_remove_device_record(const char *udid) | ||
| 450 | { | ||
| 451 | int res = 0; | ||
| 452 | |||
| 453 | /* build file path */ | ||
| 454 | const char *config_path = config_get_config_dir(); | ||
| 455 | char *device_record_file = string_concat(config_path, DIR_SEP_S, udid, CONFIG_EXT, NULL); | ||
| 456 | |||
| 457 | /* remove file */ | ||
| 458 | if (remove(device_record_file) != 0) { | ||
| 459 | res = -errno; | ||
| 460 | usbmuxd_log(LL_DEBUG, "could not remove %s: %s", device_record_file, strerror(errno)); | ||
| 461 | } | ||
| 462 | |||
| 463 | free(device_record_file); | ||
| 464 | |||
| 465 | return res; | ||
| 466 | } | ||
| 467 | |||
| 468 | static int config_device_record_get_value(const char *udid, const char *key, plist_t *value) | ||
| 469 | { | ||
| 470 | const char *config_path = NULL; | ||
| 471 | char *config_file = NULL; | ||
| 472 | |||
| 473 | config_path = config_get_config_dir(); | ||
| 474 | config_file = string_concat(config_path, DIR_SEP_S, udid, CONFIG_EXT, NULL); | ||
| 475 | |||
| 476 | int result = internal_get_value(config_file, key, value); | ||
| 477 | |||
| 478 | free(config_file); | ||
| 479 | |||
| 480 | return result; | ||
| 481 | } | ||
| 482 | |||
| 483 | void config_device_record_get_host_id(const char *udid, char **host_id) | ||
| 484 | { | ||
| 485 | plist_t value = NULL; | ||
| 486 | |||
| 487 | config_device_record_get_value(udid, CONFIG_HOST_ID_KEY, &value); | ||
| 488 | |||
| 489 | if (value && (plist_get_node_type(value) == PLIST_STRING)) { | ||
| 490 | plist_get_string_val(value, host_id); | ||
| 491 | } | ||
| 492 | |||
| 493 | if (value) | ||
| 494 | plist_free(value); | ||
| 495 | |||
| 496 | if (!*host_id) { | ||
| 497 | usbmuxd_log(LL_ERROR, "%s: ERROR couldn't get HostID from pairing record for udid %s\n", __func__, udid); | ||
| 498 | } | ||
| 499 | } | ||
diff --git a/src/conf.h b/src/conf.h new file mode 100644 index 0000000..a104185 --- /dev/null +++ b/src/conf.h | |||
| @@ -0,0 +1,40 @@ | |||
| 1 | /* | ||
| 2 | usbmuxd - iPhone/iPod Touch USB multiplex server daemon | ||
| 3 | |||
| 4 | Copyright (C) 2013 Nikias Bassen <nikias@gmx.li> | ||
| 5 | |||
| 6 | This program is free software; you can redistribute it and/or modify | ||
| 7 | it under the terms of the GNU General Public License as published by | ||
| 8 | the Free Software Foundation, either version 2 or version 3. | ||
| 9 | |||
| 10 | This program is distributed in the hope that it will be useful, | ||
| 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 13 | GNU General Public License for more details. | ||
| 14 | |||
| 15 | You should have received a copy of the GNU General Public License | ||
| 16 | along with this program; if not, write to the Free Software | ||
| 17 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | ||
| 18 | |||
| 19 | */ | ||
| 20 | |||
| 21 | #ifndef __CONF_H__ | ||
| 22 | #define __CONF_H__ | ||
| 23 | |||
| 24 | #ifdef HAVE_CONFIG_H | ||
| 25 | #include <config.h> | ||
| 26 | #endif | ||
| 27 | |||
| 28 | #include <plist/plist.h> | ||
| 29 | |||
| 30 | const char *config_get_config_dir(); | ||
| 31 | |||
| 32 | void config_get_system_buid(char **system_buid); | ||
| 33 | |||
| 34 | int config_get_device_record(const char *udid, char **record_data, uint64_t *record_size); | ||
| 35 | int config_set_device_record(const char *udid, char* record_data, uint64_t record_size); | ||
| 36 | int config_remove_device_record(const char *udid); | ||
| 37 | |||
| 38 | void config_device_record_get_host_id(const char *udid, char **host_id); | ||
| 39 | |||
| 40 | #endif | ||
| @@ -46,10 +46,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |||
| 46 | #include "usb.h" | 46 | #include "usb.h" |
| 47 | #include "device.h" | 47 | #include "device.h" |
| 48 | #include "client.h" | 48 | #include "client.h" |
| 49 | 49 | #include "conf.h" | |
| 50 | #ifdef HAVE_LIBIMOBILEDEVICE | ||
| 51 | extern const char* userpref_get_config_dir(); | ||
| 52 | #endif | ||
| 53 | 50 | ||
| 54 | static const char *socket_path = "/var/run/usbmuxd"; | 51 | static const char *socket_path = "/var/run/usbmuxd"; |
| 55 | static const char *lockfile = "/var/run/usbmuxd.pid"; | 52 | static const char *lockfile = "/var/run/usbmuxd.pid"; |
| @@ -534,7 +531,7 @@ int main(int argc, char *argv[]) | |||
| 534 | goto terminate; | 531 | goto terminate; |
| 535 | 532 | ||
| 536 | #ifdef HAVE_LIBIMOBILEDEVICE | 533 | #ifdef HAVE_LIBIMOBILEDEVICE |
| 537 | const char* userprefdir = userpref_get_config_dir(); | 534 | const char* userprefdir = config_get_config_dir(); |
| 538 | struct stat fst; | 535 | struct stat fst; |
| 539 | memset(&fst, '\0', sizeof(struct stat)); | 536 | memset(&fst, '\0', sizeof(struct stat)); |
| 540 | if (stat(userprefdir, &fst) < 0) { | 537 | if (stat(userprefdir, &fst) < 0) { |
diff --git a/src/preflight.c b/src/preflight.c index def6a82..283c6d9 100644 --- a/src/preflight.c +++ b/src/preflight.c | |||
| @@ -36,6 +36,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |||
| 36 | 36 | ||
| 37 | #include "preflight.h" | 37 | #include "preflight.h" |
| 38 | #include "client.h" | 38 | #include "client.h" |
| 39 | #include "conf.h" | ||
| 39 | #include "log.h" | 40 | #include "log.h" |
| 40 | 41 | ||
| 41 | #ifdef HAVE_LIBIMOBILEDEVICE | 42 | #ifdef HAVE_LIBIMOBILEDEVICE |
| @@ -55,12 +56,10 @@ struct cb_data { | |||
| 55 | int is_device_connected; | 56 | int is_device_connected; |
| 56 | }; | 57 | }; |
| 57 | 58 | ||
| 58 | extern uint16_t userpref_remove_device_record(const char* udid); | ||
| 59 | |||
| 60 | static void lockdownd_set_untrusted_host_buid(lockdownd_client_t lockdown) | 59 | static void lockdownd_set_untrusted_host_buid(lockdownd_client_t lockdown) |
| 61 | { | 60 | { |
| 62 | char* system_buid = NULL; | 61 | char* system_buid = NULL; |
| 63 | userpref_get_system_buid(&system_buid); | 62 | config_get_system_buid(&system_buid); |
| 64 | usbmuxd_log(LL_DEBUG, "%s: Setting UntrustedHostBUID to %s", __func__, system_buid); | 63 | usbmuxd_log(LL_DEBUG, "%s: Setting UntrustedHostBUID to %s", __func__, system_buid); |
| 65 | lockdownd_set_value(lockdown, NULL, "UntrustedHostBUID", plist_new_string(system_buid)); | 64 | lockdownd_set_value(lockdown, NULL, "UntrustedHostBUID", plist_new_string(system_buid)); |
| 66 | free(system_buid); | 65 | free(system_buid); |
| @@ -162,7 +161,7 @@ retry: | |||
| 162 | 161 | ||
| 163 | int is_device_paired = 0; | 162 | int is_device_paired = 0; |
| 164 | char *host_id = NULL; | 163 | char *host_id = NULL; |
| 165 | userpref_device_record_get_host_id(dev->udid, &host_id); | 164 | config_device_record_get_host_id(dev->udid, &host_id); |
| 166 | lerr = lockdownd_start_session(lockdown, host_id, NULL, NULL); | 165 | lerr = lockdownd_start_session(lockdown, host_id, NULL, NULL); |
| 167 | free(host_id); | 166 | free(host_id); |
| 168 | if (lerr == LOCKDOWN_E_SUCCESS) { | 167 | if (lerr == LOCKDOWN_E_SUCCESS) { |
| @@ -179,7 +178,7 @@ retry: | |||
| 179 | break; | 178 | break; |
| 180 | case LOCKDOWN_E_SSL_ERROR: | 179 | case LOCKDOWN_E_SSL_ERROR: |
| 181 | usbmuxd_log(LL_ERROR, "%s: The stored pair record for device %s is invalid. Removing.", __func__, _dev->udid); | 180 | usbmuxd_log(LL_ERROR, "%s: The stored pair record for device %s is invalid. Removing.", __func__, _dev->udid); |
| 182 | if (userpref_remove_device_record(_dev->udid) == 0) { | 181 | if (config_remove_device_record(_dev->udid) == 0) { |
| 183 | lockdownd_client_free(lockdown); | 182 | lockdownd_client_free(lockdown); |
| 184 | lockdown = NULL; | 183 | lockdown = NULL; |
| 185 | goto retry; | 184 | goto retry; |
| @@ -293,7 +292,7 @@ retry: | |||
| 293 | } | 292 | } |
| 294 | 293 | ||
| 295 | host_id = NULL; | 294 | host_id = NULL; |
| 296 | userpref_device_record_get_host_id(dev->udid, &host_id); | 295 | config_device_record_get_host_id(dev->udid, &host_id); |
| 297 | lerr = lockdownd_start_session(lockdown, host_id, NULL, NULL); | 296 | lerr = lockdownd_start_session(lockdown, host_id, NULL, NULL); |
| 298 | free(host_id); | 297 | free(host_id); |
| 299 | if (lerr != LOCKDOWN_E_SUCCESS) { | 298 | if (lerr != LOCKDOWN_E_SUCCESS) { |
diff --git a/src/utils.c b/src/utils.c index ceef535..475a921 100644 --- a/src/utils.c +++ b/src/utils.c | |||
| @@ -3,6 +3,7 @@ | |||
| 3 | 3 | ||
| 4 | Copyright (C) 2009 Hector Martin "marcan" <hector@marcansoft.com> | 4 | Copyright (C) 2009 Hector Martin "marcan" <hector@marcansoft.com> |
| 5 | Copyright (C) 2009 Nikias Bassen <nikias@gmx.li> | 5 | Copyright (C) 2009 Nikias Bassen <nikias@gmx.li> |
| 6 | Copyright (c) 2013 Federico Mena Quintero | ||
| 6 | 7 | ||
| 7 | This library is free software; you can redistribute it and/or modify | 8 | This library is free software; you can redistribute it and/or modify |
| 8 | it under the terms of the GNU Lesser General Public License as | 9 | it under the terms of the GNU Lesser General Public License as |
| @@ -27,6 +28,8 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |||
| 27 | #include <stdlib.h> | 28 | #include <stdlib.h> |
| 28 | #include <string.h> | 29 | #include <string.h> |
| 29 | #include <stdio.h> | 30 | #include <stdio.h> |
| 31 | #include <stdarg.h> | ||
| 32 | |||
| 30 | #include "utils.h" | 33 | #include "utils.h" |
| 31 | 34 | ||
| 32 | #include "log.h" | 35 | #include "log.h" |
| @@ -118,3 +121,144 @@ int collection_count(struct collection *col) | |||
| 118 | } | 121 | } |
| 119 | return cnt; | 122 | return cnt; |
| 120 | } | 123 | } |
| 124 | |||
| 125 | #ifndef HAVE_STPCPY | ||
| 126 | /** | ||
| 127 | * Copy characters from one string into another | ||
| 128 | * | ||
| 129 | * @note: The strings should not overlap, as the behavior is undefined. | ||
| 130 | * | ||
| 131 | * @s1: The source string. | ||
| 132 | * @s2: The destination string. | ||
| 133 | * | ||
| 134 | * @return a pointer to the terminating `\0' character of @s1, | ||
| 135 | * or NULL if @s1 or @s2 is NULL. | ||
| 136 | */ | ||
| 137 | char *stpcpy(char * s1, const char * s2) | ||
| 138 | { | ||
| 139 | if (s1 == NULL || s2 == NULL) | ||
| 140 | return NULL; | ||
| 141 | |||
| 142 | strcpy(s1, s2); | ||
| 143 | |||
| 144 | return s1 + strlen(s2); | ||
| 145 | } | ||
| 146 | #endif | ||
| 147 | |||
| 148 | /** | ||
| 149 | * Concatenate strings into a newly allocated string | ||
| 150 | * | ||
| 151 | * @note: Specify NULL for the last string in the varargs list | ||
| 152 | * | ||
| 153 | * @str: The first string in the list | ||
| 154 | * @...: Subsequent strings. Use NULL for the last item. | ||
| 155 | * | ||
| 156 | * @return a newly allocated string, or NULL if @str is NULL. This will also | ||
| 157 | * return NULL and set errno to ENOMEM if memory is exhausted. | ||
| 158 | */ | ||
| 159 | char *string_concat(const char *str, ...) | ||
| 160 | { | ||
| 161 | size_t len; | ||
| 162 | va_list args; | ||
| 163 | char *s; | ||
| 164 | char *result; | ||
| 165 | char *dest; | ||
| 166 | |||
| 167 | if (!str) | ||
| 168 | return NULL; | ||
| 169 | |||
| 170 | /* Compute final length */ | ||
| 171 | |||
| 172 | len = strlen(str) + 1; /* plus 1 for the null terminator */ | ||
| 173 | |||
| 174 | va_start(args, str); | ||
| 175 | s = va_arg(args, char *); | ||
| 176 | while (s) { | ||
| 177 | len += strlen(s); | ||
| 178 | s = va_arg(args, char*); | ||
| 179 | } | ||
| 180 | va_end(args); | ||
| 181 | |||
| 182 | /* Concat each string */ | ||
| 183 | |||
| 184 | result = malloc(len); | ||
| 185 | if (!result) | ||
| 186 | return NULL; /* errno remains set */ | ||
| 187 | |||
| 188 | dest = result; | ||
| 189 | |||
| 190 | dest = stpcpy(dest, str); | ||
| 191 | |||
| 192 | va_start(args, str); | ||
| 193 | s = va_arg(args, char *); | ||
| 194 | while (s) { | ||
| 195 | dest = stpcpy(dest, s); | ||
| 196 | s = va_arg(args, char *); | ||
| 197 | } | ||
| 198 | va_end(args); | ||
| 199 | |||
| 200 | return result; | ||
| 201 | } | ||
| 202 | |||
| 203 | void buffer_read_from_filename(const char *filename, char **buffer, uint64_t *length) | ||
| 204 | { | ||
| 205 | FILE *f; | ||
| 206 | uint64_t size; | ||
| 207 | |||
| 208 | *length = 0; | ||
| 209 | |||
| 210 | f = fopen(filename, "rb"); | ||
| 211 | if (!f) { | ||
| 212 | return; | ||
| 213 | } | ||
| 214 | |||
| 215 | fseek(f, 0, SEEK_END); | ||
| 216 | size = ftell(f); | ||
| 217 | rewind(f); | ||
| 218 | |||
| 219 | if (size == 0) { | ||
| 220 | fclose(f); | ||
| 221 | return; | ||
| 222 | } | ||
| 223 | |||
| 224 | *buffer = (char*)malloc(sizeof(char)*(size+1)); | ||
| 225 | if (fread(*buffer, sizeof(char), size, f) != size) { | ||
| 226 | usbmuxd_log(LL_ERROR, "%s: ERROR: couldn't read %d bytes from %s\n", __func__, (int)size, filename); | ||
| 227 | } | ||
| 228 | fclose(f); | ||
| 229 | |||
| 230 | *length = size; | ||
| 231 | } | ||
| 232 | |||
| 233 | void buffer_write_to_filename(const char *filename, const char *buffer, uint64_t length) | ||
| 234 | { | ||
| 235 | FILE *f; | ||
| 236 | |||
| 237 | f = fopen(filename, "wb"); | ||
| 238 | if (f) { | ||
| 239 | fwrite(buffer, sizeof(char), length, f); | ||
| 240 | fclose(f); | ||
| 241 | } | ||
| 242 | } | ||
| 243 | |||
| 244 | int plist_write_to_filename(plist_t plist, const char *filename, enum plist_format_t format) | ||
| 245 | { | ||
| 246 | char *buffer = NULL; | ||
| 247 | uint32_t length; | ||
| 248 | |||
| 249 | if (!plist || !filename) | ||
| 250 | return 0; | ||
| 251 | |||
| 252 | if (format == PLIST_FORMAT_XML) | ||
| 253 | plist_to_xml(plist, &buffer, &length); | ||
| 254 | else if (format == PLIST_FORMAT_BINARY) | ||
| 255 | plist_to_bin(plist, &buffer, &length); | ||
| 256 | else | ||
| 257 | return 0; | ||
| 258 | |||
| 259 | buffer_write_to_filename(filename, buffer, length); | ||
| 260 | |||
| 261 | free(buffer); | ||
| 262 | |||
| 263 | return 1; | ||
| 264 | } | ||
diff --git a/src/utils.h b/src/utils.h index 69a4259..730fbad 100644 --- a/src/utils.h +++ b/src/utils.h | |||
| @@ -24,6 +24,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |||
| 24 | #define __UTILS_H__ | 24 | #define __UTILS_H__ |
| 25 | 25 | ||
| 26 | #include <poll.h> | 26 | #include <poll.h> |
| 27 | #include <plist/plist.h> | ||
| 27 | 28 | ||
| 28 | enum fdowner { | 29 | enum fdowner { |
| 29 | FD_LISTEN, | 30 | FD_LISTEN, |
| @@ -69,4 +70,20 @@ void collection_free(struct collection *col); | |||
| 69 | } \ | 70 | } \ |
| 70 | } while(0); | 71 | } while(0); |
| 71 | 72 | ||
| 73 | #ifndef HAVE_STPCPY | ||
| 74 | char *stpcpy(char * s1, const char * s2); | ||
| 75 | #endif | ||
| 76 | char *string_concat(const char *str, ...); | ||
| 77 | |||
| 78 | void buffer_read_from_filename(const char *filename, char **buffer, uint64_t *length); | ||
| 79 | void buffer_write_to_filename(const char *filename, const char *buffer, uint64_t length); | ||
| 80 | |||
| 81 | enum plist_format_t { | ||
| 82 | PLIST_FORMAT_XML, | ||
| 83 | PLIST_FORMAT_BINARY | ||
| 84 | }; | ||
| 85 | |||
| 86 | int plist_read_from_filename(plist_t *plist, const char *filename); | ||
| 87 | int plist_write_to_filename(plist_t plist, const char *filename, enum plist_format_t format); | ||
| 88 | |||
| 72 | #endif | 89 | #endif |
