diff options
Diffstat (limited to 'src/userpref.c')
| -rw-r--r-- | src/userpref.c | 492 |
1 files changed, 404 insertions, 88 deletions
diff --git a/src/userpref.c b/src/userpref.c index 4aab67b..d44d5aa 100644 --- a/src/userpref.c +++ b/src/userpref.c | |||
| @@ -19,9 +19,6 @@ | |||
| 19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | 19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
| 20 | */ | 20 | */ |
| 21 | 21 | ||
| 22 | #include <glib.h> | ||
| 23 | #include <glib/gstdio.h> | ||
| 24 | #include <glib/gprintf.h> | ||
| 25 | #include <stdio.h> | 22 | #include <stdio.h> |
| 26 | #include <stdint.h> | 23 | #include <stdint.h> |
| 27 | #include <stdlib.h> | 24 | #include <stdlib.h> |
| @@ -30,6 +27,15 @@ | |||
| 30 | #include <gnutls/x509.h> | 27 | #include <gnutls/x509.h> |
| 31 | #include <gcrypt.h> | 28 | #include <gcrypt.h> |
| 32 | 29 | ||
| 30 | #include <dirent.h> | ||
| 31 | #include <libgen.h> | ||
| 32 | #include <sys/stat.h> | ||
| 33 | #include <errno.h> | ||
| 34 | |||
| 35 | #ifdef WIN32 | ||
| 36 | #include <shlobj.h> | ||
| 37 | #endif | ||
| 38 | |||
| 33 | #include "userpref.h" | 39 | #include "userpref.h" |
| 34 | #include "debug.h" | 40 | #include "debug.h" |
| 35 | 41 | ||
| @@ -41,18 +47,239 @@ | |||
| 41 | #define LIBIMOBILEDEVICE_ROOT_CERTIF "RootCertificate.pem" | 47 | #define LIBIMOBILEDEVICE_ROOT_CERTIF "RootCertificate.pem" |
| 42 | #define LIBIMOBILEDEVICE_HOST_CERTIF "HostCertificate.pem" | 48 | #define LIBIMOBILEDEVICE_HOST_CERTIF "HostCertificate.pem" |
| 43 | 49 | ||
| 50 | #ifdef WIN32 | ||
| 51 | #define DIR_SEP '\\' | ||
| 52 | #define DIR_SEP_S "\\" | ||
| 53 | #else | ||
| 54 | #define DIR_SEP '/' | ||
| 55 | #define DIR_SEP_S "/" | ||
| 56 | #endif | ||
| 57 | |||
| 58 | static char __config_dir[512] = {0, }; | ||
| 59 | |||
| 60 | #ifdef WIN32 | ||
| 61 | static char *userpref_utf16_to_utf8(wchar_t *unistr, long len, long *items_read, long *items_written) | ||
| 62 | { | ||
| 63 | if (!unistr || (len <= 0)) return NULL; | ||
| 64 | char *outbuf = (char*)malloc(3*(len+1)); | ||
| 65 | int p = 0; | ||
| 66 | int i = 0; | ||
| 67 | |||
| 68 | wchar_t wc; | ||
| 69 | |||
| 70 | while (i < len) { | ||
| 71 | wc = unistr[i++]; | ||
| 72 | if (wc >= 0x800) { | ||
| 73 | outbuf[p++] = (char)(0xE0 + ((wc >> 12) & 0xF)); | ||
| 74 | outbuf[p++] = (char)(0x80 + ((wc >> 6) & 0x3F)); | ||
| 75 | outbuf[p++] = (char)(0x80 + (wc & 0x3F)); | ||
| 76 | } else if (wc >= 0x80) { | ||
| 77 | outbuf[p++] = (char)(0xC0 + ((wc >> 6) & 0x1F)); | ||
| 78 | outbuf[p++] = (char)(0x80 + (wc & 0x3F)); | ||
| 79 | } else { | ||
| 80 | outbuf[p++] = (char)(wc & 0x7F); | ||
| 81 | } | ||
| 82 | } | ||
| 83 | if (items_read) { | ||
| 84 | *items_read = i; | ||
| 85 | } | ||
| 86 | if (items_written) { | ||
| 87 | *items_written = p; | ||
| 88 | } | ||
| 89 | outbuf[p] = 0; | ||
| 90 | |||
| 91 | return outbuf; | ||
| 92 | } | ||
| 93 | #endif | ||
| 94 | |||
| 95 | static const char *userpref_get_config_dir() | ||
| 96 | { | ||
| 97 | if (__config_dir[0]) return __config_dir; | ||
| 98 | #ifdef WIN32 | ||
| 99 | wchar_t path[MAX_PATH+1]; | ||
| 100 | HRESULT hr; | ||
| 101 | LPITEMIDLIST pidl = NULL; | ||
| 102 | BOOL b = FALSE; | ||
| 103 | |||
| 104 | hr = SHGetSpecialFolderLocation (NULL, CSIDL_LOCAL_APPDATA, &pidl); | ||
| 105 | if (hr == S_OK) { | ||
| 106 | b = SHGetPathFromIDListW (pidl, path); | ||
| 107 | if (b) { | ||
| 108 | char *cdir = userpref_utf16_to_utf8 (path, wcslen(path), NULL, NULL); | ||
| 109 | strcpy(__config_dir, cdir); | ||
| 110 | free(cdir); | ||
| 111 | CoTaskMemFree (pidl); | ||
| 112 | } | ||
| 113 | } | ||
| 114 | #else | ||
| 115 | const char *cdir = getenv("XDG_CONFIG_HOME"); | ||
| 116 | if (!cdir) { | ||
| 117 | cdir = getenv("HOME"); | ||
| 118 | strcpy(__config_dir, cdir); | ||
| 119 | strcat(__config_dir, DIR_SEP_S); | ||
| 120 | strcat(__config_dir, ".config"); | ||
| 121 | } else { | ||
| 122 | strcpy(__config_dir, cdir); | ||
| 123 | } | ||
| 124 | #endif | ||
| 125 | strcat(__config_dir, DIR_SEP_S); | ||
| 126 | strcat(__config_dir, LIBIMOBILEDEVICE_CONF_DIR); | ||
| 127 | |||
| 128 | int i = strlen(__config_dir)-1; | ||
| 129 | while ((i > 0) && (__config_dir[i] == DIR_SEP)) { | ||
| 130 | __config_dir[i--] = '\0'; | ||
| 131 | } | ||
| 132 | |||
| 133 | return __config_dir; | ||
| 134 | } | ||
| 135 | |||
| 136 | static int mkdir_with_parents(const char *dir, int mode) | ||
| 137 | { | ||
| 138 | if (!dir) return -1; | ||
| 139 | if (mkdir(dir, mode) == 0) { | ||
| 140 | return 0; | ||
| 141 | } else { | ||
| 142 | if (errno == EEXIST) return 0; | ||
| 143 | } | ||
| 144 | int res; | ||
| 145 | char *parent = strdup(dir); | ||
| 146 | parent = dirname(parent); | ||
| 147 | if (parent) { | ||
| 148 | res = mkdir_with_parents(parent, mode); | ||
| 149 | } else { | ||
| 150 | res = -1; | ||
| 151 | } | ||
| 152 | free(parent); | ||
| 153 | if (res == 0) { | ||
| 154 | mkdir_with_parents(dir, mode); | ||
| 155 | } | ||
| 156 | return res; | ||
| 157 | } | ||
| 158 | |||
| 159 | static int config_write(const char *cfgfile, plist_t dict) | ||
| 160 | { | ||
| 161 | if (!cfgfile || !dict || (plist_get_node_type(dict) != PLIST_DICT)) { | ||
| 162 | return -1; | ||
| 163 | } | ||
| 164 | int res = -1; | ||
| 165 | |||
| 166 | #if 1 // old style config | ||
| 167 | plist_t hostid = plist_dict_get_item(dict, "HostID"); | ||
| 168 | if (hostid && (plist_get_node_type(hostid) == PLIST_STRING)) { | ||
| 169 | char *hostidstr = NULL; | ||
| 170 | plist_get_string_val(hostid, &hostidstr); | ||
| 171 | if (hostidstr) { | ||
| 172 | FILE *fd = fopen(cfgfile, "w"); | ||
| 173 | if (fd) { | ||
| 174 | fprintf(fd, "\n[Global]\nHostID=%s\n", hostidstr); | ||
| 175 | fclose(fd); | ||
| 176 | res = 0; | ||
| 177 | } | ||
| 178 | free(hostidstr); | ||
| 179 | } | ||
| 180 | } | ||
| 181 | #endif | ||
| 182 | #if 0 | ||
| 183 | char *xml = NULL; | ||
| 184 | uint32_t length = 0; | ||
| 185 | |||
| 186 | plist_to_xml(dict, &xml, &length); | ||
| 187 | if (!xml) { | ||
| 188 | return res; | ||
| 189 | } | ||
| 190 | |||
| 191 | FILE *fd = fopen(cfgfile, "w"); | ||
| 192 | if (!fd) { | ||
| 193 | free(xml); | ||
| 194 | return res; | ||
| 195 | } | ||
| 196 | |||
| 197 | if (fwrite(xml, 1, length, fd) == length) { | ||
| 198 | res = 0; | ||
| 199 | } else { | ||
| 200 | fprintf(stderr, "%s: ERROR: failed to write configuration to '%s'\n", __func__, cfgfile); | ||
| 201 | } | ||
| 202 | fclose(fd); | ||
| 203 | |||
| 204 | free(xml); | ||
| 205 | #endif | ||
| 206 | return res; | ||
| 207 | } | ||
| 208 | |||
| 209 | static int config_read(const char *cfgfile, plist_t *dict) | ||
| 210 | { | ||
| 211 | if (!cfgfile || !dict) { | ||
| 212 | return -1; | ||
| 213 | } | ||
| 214 | |||
| 215 | int res = -1; | ||
| 216 | FILE *fd = fopen(cfgfile, "r+"); | ||
| 217 | if (!fd) { | ||
| 218 | return -1; | ||
| 219 | } | ||
| 220 | |||
| 221 | fseek(fd, 0, SEEK_END); | ||
| 222 | unsigned long int size = ftell(fd); | ||
| 223 | fseek(fd, 0, SEEK_SET); | ||
| 224 | unsigned char *contents = NULL; | ||
| 225 | |||
| 226 | contents = malloc(size); | ||
| 227 | if (fread(contents, 1, size, fd) != size) { | ||
| 228 | free(contents); | ||
| 229 | fclose(fd); | ||
| 230 | return -1; | ||
| 231 | } | ||
| 232 | plist_t plist = NULL; | ||
| 233 | |||
| 234 | if (!memcmp(contents, "bplist00", 8)) { | ||
| 235 | plist_from_bin((const char*)contents, (uint32_t)size, &plist); | ||
| 236 | fclose(fd); | ||
| 237 | } else { | ||
| 238 | if (memchr(contents, '<', size)) { | ||
| 239 | plist_from_xml((const char*)contents, (uint32_t)size, &plist); | ||
| 240 | } | ||
| 241 | if (plist) { | ||
| 242 | fclose(fd); | ||
| 243 | } else { | ||
| 244 | // try parsing old format config file | ||
| 245 | char line[256]; | ||
| 246 | fseek(fd, 0, SEEK_SET); | ||
| 247 | while (fgets(line, 256, fd)) { | ||
| 248 | size_t llen = strlen(line)-1; | ||
| 249 | while ((llen > 0) && ((line[llen] == '\n') || (line[llen] == '\r'))) { | ||
| 250 | line[llen] = '\0'; | ||
| 251 | } | ||
| 252 | if (!strncmp(line, "HostID=", 7)) { | ||
| 253 | plist = plist_new_dict(); | ||
| 254 | plist_dict_insert_item(plist, "HostID", plist_new_string(line+7)); | ||
| 255 | break; | ||
| 256 | } | ||
| 257 | } | ||
| 258 | fclose(fd); | ||
| 259 | if (plist) { | ||
| 260 | // write new format config | ||
| 261 | config_write(cfgfile, plist); | ||
| 262 | } | ||
| 263 | } | ||
| 264 | } | ||
| 265 | free(contents); | ||
| 266 | if (plist) { | ||
| 267 | *dict = plist; | ||
| 268 | res = 0; | ||
| 269 | } | ||
| 270 | return res; | ||
| 271 | } | ||
| 44 | 272 | ||
| 45 | /** | 273 | /** |
| 46 | * Creates a freedesktop compatible configuration directory. | 274 | * Creates a freedesktop compatible configuration directory. |
| 47 | */ | 275 | */ |
| 48 | static void userpref_create_config_dir(void) | 276 | static void userpref_create_config_dir(void) |
| 49 | { | 277 | { |
| 50 | gchar *config_dir = g_build_path(G_DIR_SEPARATOR_S, g_get_user_config_dir(), LIBIMOBILEDEVICE_CONF_DIR, NULL); | 278 | const char *config_path = userpref_get_config_dir(); |
| 51 | 279 | struct stat st; | |
| 52 | if (!g_file_test(config_dir, (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR))) | 280 | if (stat(config_path, &st) != 0) { |
| 53 | g_mkdir_with_parents(config_dir, 0755); | 281 | mkdir_with_parents(config_path, 0755); |
| 54 | 282 | } | |
| 55 | g_free(config_dir); | ||
| 56 | } | 283 | } |
| 57 | 284 | ||
| 58 | static int get_rand(int min, int max) | 285 | static int get_rand(int min, int max) |
| @@ -94,10 +321,8 @@ static char *userpref_generate_host_id() | |||
| 94 | */ | 321 | */ |
| 95 | static int userpref_set_host_id(const char *host_id) | 322 | static int userpref_set_host_id(const char *host_id) |
| 96 | { | 323 | { |
| 97 | GKeyFile *key_file; | 324 | const char *config_path; |
| 98 | gsize length; | 325 | char *config_file; |
| 99 | gchar *buf, *config_file; | ||
| 100 | GIOChannel *file; | ||
| 101 | 326 | ||
| 102 | if (!host_id) | 327 | if (!host_id) |
| 103 | return 0; | 328 | return 0; |
| @@ -105,24 +330,34 @@ static int userpref_set_host_id(const char *host_id) | |||
| 105 | /* Make sure config directory exists */ | 330 | /* Make sure config directory exists */ |
| 106 | userpref_create_config_dir(); | 331 | userpref_create_config_dir(); |
| 107 | 332 | ||
| 333 | config_path = userpref_get_config_dir(); | ||
| 334 | config_file = (char*)malloc(strlen(config_path)+1+strlen(LIBIMOBILEDEVICE_CONF_FILE)+1); | ||
| 335 | strcpy(config_file, config_path); | ||
| 336 | strcat(config_file, DIR_SEP_S); | ||
| 337 | strcat(config_file, LIBIMOBILEDEVICE_CONF_FILE); | ||
| 338 | |||
| 108 | /* Now parse file to get the HostID */ | 339 | /* Now parse file to get the HostID */ |
| 109 | key_file = g_key_file_new(); | 340 | plist_t config = NULL; |
| 341 | config_read(config_file, &config); | ||
| 342 | if (!config) { | ||
| 343 | config = plist_new_dict(); | ||
| 344 | plist_dict_insert_item(config, "HostID", plist_new_string(host_id)); | ||
| 345 | } else { | ||
| 346 | plist_t n = plist_dict_get_item(config, "HostID"); | ||
| 347 | if (n) { | ||
| 348 | plist_set_string_val(n, host_id); | ||
| 349 | } else { | ||
| 350 | plist_dict_insert_item(config, "HostID", plist_new_string(host_id)); | ||
| 351 | } | ||
| 352 | } | ||
| 110 | 353 | ||
| 111 | /* Store in config file */ | 354 | /* Store in config file */ |
| 112 | debug_info("setting hostID to %s", host_id); | 355 | debug_info("setting hostID to %s", host_id); |
| 113 | g_key_file_set_value(key_file, "Global", "HostID", host_id); | 356 | |
| 114 | 357 | config_write(config_file, config); | |
| 115 | /* Write config file on disk */ | 358 | plist_free(config); |
| 116 | buf = g_key_file_to_data(key_file, &length, NULL); | 359 | |
| 117 | config_file = | 360 | free(config_file); |
| 118 | g_build_path(G_DIR_SEPARATOR_S, g_get_user_config_dir(), LIBIMOBILEDEVICE_CONF_DIR, LIBIMOBILEDEVICE_CONF_FILE, NULL); | ||
| 119 | file = g_io_channel_new_file(config_file, "w", NULL); | ||
| 120 | g_free(config_file); | ||
| 121 | g_io_channel_write_chars(file, buf, length, NULL, NULL); | ||
| 122 | g_io_channel_shutdown(file, TRUE, NULL); | ||
| 123 | g_io_channel_unref(file); | ||
| 124 | |||
| 125 | g_key_file_free(key_file); | ||
| 126 | return 1; | 361 | return 1; |
| 127 | } | 362 | } |
| 128 | 363 | ||
| @@ -135,23 +370,25 @@ static int userpref_set_host_id(const char *host_id) | |||
| 135 | */ | 370 | */ |
| 136 | void userpref_get_host_id(char **host_id) | 371 | void userpref_get_host_id(char **host_id) |
| 137 | { | 372 | { |
| 138 | gchar *config_file; | 373 | const char *config_path; |
| 139 | GKeyFile *key_file; | 374 | char *config_file; |
| 140 | gchar *loc_host_id; | ||
| 141 | 375 | ||
| 142 | config_file = | 376 | config_path = userpref_get_config_dir(); |
| 143 | g_build_path(G_DIR_SEPARATOR_S, g_get_user_config_dir(), LIBIMOBILEDEVICE_CONF_DIR, LIBIMOBILEDEVICE_CONF_FILE, NULL); | 377 | config_file = (char*)malloc(strlen(config_path)+1+strlen(LIBIMOBILEDEVICE_CONF_FILE)+1); |
| 378 | strcpy(config_file, config_path); | ||
| 379 | strcat(config_file, DIR_SEP_S); | ||
| 380 | strcat(config_file, LIBIMOBILEDEVICE_CONF_FILE); | ||
| 144 | 381 | ||
| 145 | /* now parse file to get the HostID */ | 382 | /* now parse file to get the HostID */ |
| 146 | key_file = g_key_file_new(); | 383 | plist_t config = NULL; |
| 147 | if (g_key_file_load_from_file(key_file, config_file, G_KEY_FILE_KEEP_COMMENTS, NULL)) { | 384 | if (config_read(config_file, &config) == 0) { |
| 148 | loc_host_id = g_key_file_get_value(key_file, "Global", "HostID", NULL); | 385 | plist_t n_host_id = plist_dict_get_item(config, "HostID"); |
| 149 | if (loc_host_id) | 386 | if (n_host_id && (plist_get_node_type(n_host_id) == PLIST_STRING)) { |
| 150 | *host_id = strdup((char *) loc_host_id); | 387 | plist_get_string_val(n_host_id, host_id); |
| 151 | g_free(loc_host_id); | 388 | } |
| 152 | } | 389 | } |
| 153 | g_key_file_free(key_file); | 390 | plist_free(config); |
| 154 | g_free(config_file); | 391 | free(config_file); |
| 155 | 392 | ||
| 156 | if (!*host_id) { | 393 | if (!*host_id) { |
| 157 | /* no config, generate host_id */ | 394 | /* no config, generate host_id */ |
| @@ -173,15 +410,23 @@ void userpref_get_host_id(char **host_id) | |||
| 173 | int userpref_has_device_public_key(const char *uuid) | 410 | int userpref_has_device_public_key(const char *uuid) |
| 174 | { | 411 | { |
| 175 | int ret = 0; | 412 | int ret = 0; |
| 176 | gchar *config_file; | 413 | const char *config_path; |
| 414 | char *config_file; | ||
| 415 | struct stat st; | ||
| 416 | |||
| 417 | if (!uuid) return 0; | ||
| 177 | 418 | ||
| 178 | /* first get config file */ | 419 | /* first get config file */ |
| 179 | gchar *device_file = g_strconcat(uuid, ".pem", NULL); | 420 | config_path = userpref_get_config_dir(); |
| 180 | config_file = g_build_path(G_DIR_SEPARATOR_S, g_get_user_config_dir(), LIBIMOBILEDEVICE_CONF_DIR, device_file, NULL); | 421 | config_file = (char*)malloc(strlen(config_path)+1+strlen(uuid)+4+1); |
| 181 | if (g_file_test(config_file, (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_REGULAR))) | 422 | strcpy(config_file, config_path); |
| 423 | strcat(config_file, DIR_SEP_S); | ||
| 424 | strcat(config_file, uuid); | ||
| 425 | strcat(config_file, ".pem"); | ||
| 426 | |||
| 427 | if ((stat(config_file, &st) == 0) && S_ISREG(st.st_mode)) | ||
| 182 | ret = 1; | 428 | ret = 1; |
| 183 | g_free(config_file); | 429 | free(config_file); |
| 184 | g_free(device_file); | ||
| 185 | return ret; | 430 | return ret; |
| 186 | } | 431 | } |
| 187 | 432 | ||
| @@ -202,10 +447,13 @@ int userpref_has_device_public_key(const char *uuid) | |||
| 202 | */ | 447 | */ |
| 203 | userpref_error_t userpref_get_paired_uuids(char ***list, unsigned int *count) | 448 | userpref_error_t userpref_get_paired_uuids(char ***list, unsigned int *count) |
| 204 | { | 449 | { |
| 205 | GDir *config_dir; | 450 | struct slist_t { |
| 206 | gchar *config_path; | 451 | char *name; |
| 207 | const gchar *dir_file; | 452 | void *next; |
| 208 | GList *uuids = NULL; | 453 | }; |
| 454 | DIR *config_dir; | ||
| 455 | const char *config_path; | ||
| 456 | struct slist_t *uuids = NULL; | ||
| 209 | unsigned int i; | 457 | unsigned int i; |
| 210 | unsigned int found = 0; | 458 | unsigned int found = 0; |
| 211 | 459 | ||
| @@ -218,29 +466,44 @@ userpref_error_t userpref_get_paired_uuids(char ***list, unsigned int *count) | |||
| 218 | *count = 0; | 466 | *count = 0; |
| 219 | } | 467 | } |
| 220 | 468 | ||
| 221 | config_path = g_build_path(G_DIR_SEPARATOR_S, g_get_user_config_dir(), LIBIMOBILEDEVICE_CONF_DIR, NULL); | 469 | config_path = userpref_get_config_dir(); |
| 222 | 470 | config_dir = opendir(config_path); | |
| 223 | config_dir = g_dir_open(config_path,0,NULL); | ||
| 224 | if (config_dir) { | 471 | if (config_dir) { |
| 225 | while ((dir_file = g_dir_read_name(config_dir))) { | 472 | struct dirent *entry; |
| 226 | if (g_str_has_suffix(dir_file, ".pem") && (strlen(dir_file) == 44)) { | 473 | struct slist_t *listp = uuids; |
| 227 | uuids = g_list_append(uuids, g_strndup(dir_file, strlen(dir_file)-4)); | 474 | while ((entry = readdir(config_dir))) { |
| 475 | char *ext = strstr(entry->d_name, ".pem"); | ||
| 476 | if (ext && ((ext - entry->d_name) == 40) && (strlen(entry->d_name) == 44)) { | ||
| 477 | struct slist_t *ne = (struct slist_t*)malloc(sizeof(struct slist_t)); | ||
| 478 | ne->name = (char*)malloc(41); | ||
| 479 | strncpy(ne->name, entry->d_name, 40); | ||
| 480 | ne->name[40] = 0; | ||
| 481 | ne->next = NULL; | ||
| 482 | if (!listp) { | ||
| 483 | listp = ne; | ||
| 484 | uuids = listp; | ||
| 485 | } else { | ||
| 486 | listp->next = ne; | ||
| 487 | listp = listp->next; | ||
| 488 | } | ||
| 228 | found++; | 489 | found++; |
| 229 | } | 490 | } |
| 230 | } | 491 | } |
| 231 | g_dir_close(config_dir); | 492 | closedir(config_dir); |
| 232 | } | 493 | } |
| 233 | *list = (char**)malloc(sizeof(char*) * (found+1)); | 494 | *list = (char**)malloc(sizeof(char*) * (found+1)); |
| 234 | for (i = 0; i < found; i++) { | 495 | i = 0; |
| 235 | (*list)[i] = g_list_nth_data(uuids, i); | 496 | while (uuids) { |
| 497 | (*list)[i++] = uuids->name; | ||
| 498 | struct slist_t *old = uuids; | ||
| 499 | uuids = uuids->next; | ||
| 500 | free(old); | ||
| 236 | } | 501 | } |
| 237 | (*list)[i] = NULL; | 502 | (*list)[i] = NULL; |
| 238 | 503 | ||
| 239 | if (count) { | 504 | if (count) { |
| 240 | *count = found; | 505 | *count = found; |
| 241 | } | 506 | } |
| 242 | g_list_free(uuids); | ||
| 243 | g_free(config_path); | ||
| 244 | 507 | ||
| 245 | return USERPREF_E_SUCCESS; | 508 | return USERPREF_E_SUCCESS; |
| 246 | } | 509 | } |
| @@ -266,15 +529,18 @@ userpref_error_t userpref_set_device_public_key(const char *uuid, gnutls_datum_t | |||
| 266 | userpref_create_config_dir(); | 529 | userpref_create_config_dir(); |
| 267 | 530 | ||
| 268 | /* build file path */ | 531 | /* build file path */ |
| 269 | gchar *device_file = g_strconcat(uuid, ".pem", NULL); | 532 | const char *config_path = userpref_get_config_dir(); |
| 270 | gchar *pem = g_build_path(G_DIR_SEPARATOR_S, g_get_user_config_dir(), LIBIMOBILEDEVICE_CONF_DIR, device_file, NULL); | 533 | char *pem = (char*)malloc(strlen(config_path)+1+strlen(uuid)+4+1); |
| 534 | strcpy(pem, config_path); | ||
| 535 | strcat(pem, DIR_SEP_S); | ||
| 536 | strcat(pem, uuid); | ||
| 537 | strcat(pem, ".pem"); | ||
| 271 | 538 | ||
| 272 | /* store file */ | 539 | /* store file */ |
| 273 | FILE *pFile = fopen(pem, "wb"); | 540 | FILE *pFile = fopen(pem, "wb"); |
| 274 | fwrite(public_key.data, 1, public_key.size, pFile); | 541 | fwrite(public_key.data, 1, public_key.size, pFile); |
| 275 | fclose(pFile); | 542 | fclose(pFile); |
| 276 | g_free(pem); | 543 | free(pem); |
| 277 | g_free(device_file); | ||
| 278 | 544 | ||
| 279 | return USERPREF_E_SUCCESS; | 545 | return USERPREF_E_SUCCESS; |
| 280 | } | 546 | } |
| @@ -292,14 +558,17 @@ userpref_error_t userpref_remove_device_public_key(const char *uuid) | |||
| 292 | return USERPREF_E_SUCCESS; | 558 | return USERPREF_E_SUCCESS; |
| 293 | 559 | ||
| 294 | /* build file path */ | 560 | /* build file path */ |
| 295 | gchar *device_file = g_strconcat(uuid, ".pem", NULL); | 561 | const char *config_path = userpref_get_config_dir(); |
| 296 | gchar *pem = g_build_path(G_DIR_SEPARATOR_S, g_get_user_config_dir(), LIBIMOBILEDEVICE_CONF_DIR, device_file, NULL); | 562 | char *pem = (char*)malloc(strlen(config_path)+1+strlen(uuid)+4+1); |
| 563 | strcpy(pem, config_path); | ||
| 564 | strcat(pem, DIR_SEP_S); | ||
| 565 | strcat(pem, uuid); | ||
| 566 | strcat(pem, ".pem"); | ||
| 297 | 567 | ||
| 298 | /* remove file */ | 568 | /* remove file */ |
| 299 | g_remove(pem); | 569 | remove(pem); |
| 300 | 570 | ||
| 301 | g_free(pem); | 571 | free(pem); |
| 302 | g_free(device_file); | ||
| 303 | 572 | ||
| 304 | return USERPREF_E_SUCCESS; | 573 | return USERPREF_E_SUCCESS; |
| 305 | } | 574 | } |
| @@ -314,18 +583,50 @@ userpref_error_t userpref_remove_device_public_key(const char *uuid) | |||
| 314 | */ | 583 | */ |
| 315 | static int userpref_get_file_contents(const char *file, gnutls_datum_t * data) | 584 | static int userpref_get_file_contents(const char *file, gnutls_datum_t * data) |
| 316 | { | 585 | { |
| 317 | gboolean success; | 586 | int success; |
| 318 | gsize size; | 587 | unsigned long int size = 0; |
| 319 | char *content; | 588 | unsigned char *content = NULL; |
| 320 | gchar *filepath; | 589 | const char *config_path; |
| 590 | char *filepath; | ||
| 591 | FILE *fd; | ||
| 321 | 592 | ||
| 322 | if (NULL == file || NULL == data) | 593 | if (NULL == file || NULL == data) |
| 323 | return 0; | 594 | return 0; |
| 324 | 595 | ||
| 325 | /* Read file */ | 596 | /* Read file */ |
| 326 | filepath = g_build_path(G_DIR_SEPARATOR_S, g_get_user_config_dir(), LIBIMOBILEDEVICE_CONF_DIR, file, NULL); | 597 | config_path = userpref_get_config_dir(); |
| 327 | success = g_file_get_contents(filepath, &content, &size, NULL); | 598 | filepath = (char*)malloc(strlen(config_path)+1+strlen(file)+1); |
| 328 | g_free(filepath); | 599 | strcpy(filepath, config_path); |
| 600 | strcat(filepath, DIR_SEP_S); | ||
| 601 | strcat(filepath, file); | ||
| 602 | |||
| 603 | fd = fopen(filepath, "rb"); | ||
| 604 | if (fd) { | ||
| 605 | fseek(fd, 0, SEEK_END); | ||
| 606 | size = ftell(fd); | ||
| 607 | fseek(fd, 0, SEEK_SET); | ||
| 608 | |||
| 609 | // prevent huge files | ||
| 610 | if (size > 0xFFFFFF) { | ||
| 611 | fprintf(stderr, "%s: file is too big (> 16MB). Refusing to read the contents to memory!", __func__); | ||
| 612 | } else { | ||
| 613 | size_t p = 0; | ||
| 614 | content = (unsigned char*)malloc(size); | ||
| 615 | while (!feof(fd)) { | ||
| 616 | p += fread(content+p, 1, size-p, fd); | ||
| 617 | if (ferror(fd) != 0) { | ||
| 618 | break; | ||
| 619 | } | ||
| 620 | if (p >= size) { | ||
| 621 | success = 1; | ||
| 622 | break; | ||
| 623 | } | ||
| 624 | } | ||
| 625 | } | ||
| 626 | fclose(fd); | ||
| 627 | } | ||
| 628 | |||
| 629 | free(filepath); | ||
| 329 | 630 | ||
| 330 | /* Add it to the gnutls_datnum_t structure */ | 631 | /* Add it to the gnutls_datnum_t structure */ |
| 331 | if (success) { | 632 | if (success) { |
| @@ -549,8 +850,8 @@ userpref_error_t userpref_get_certs_as_pem(gnutls_datum_t *pem_root_cert, gnutls | |||
| 549 | if (userpref_get_file_contents(LIBIMOBILEDEVICE_ROOT_CERTIF, pem_root_cert) && userpref_get_file_contents(LIBIMOBILEDEVICE_HOST_CERTIF, pem_host_cert)) | 850 | if (userpref_get_file_contents(LIBIMOBILEDEVICE_ROOT_CERTIF, pem_root_cert) && userpref_get_file_contents(LIBIMOBILEDEVICE_HOST_CERTIF, pem_host_cert)) |
| 550 | return USERPREF_E_SUCCESS; | 851 | return USERPREF_E_SUCCESS; |
| 551 | else { | 852 | else { |
| 552 | g_free(pem_root_cert->data); | 853 | gnutls_free(pem_root_cert->data); |
| 553 | g_free(pem_host_cert->data); | 854 | gnutls_free(pem_host_cert->data); |
| 554 | } | 855 | } |
| 555 | return USERPREF_E_INVALID_CONF; | 856 | return USERPREF_E_INVALID_CONF; |
| 556 | } | 857 | } |
| @@ -570,7 +871,8 @@ userpref_error_t userpref_get_certs_as_pem(gnutls_datum_t *pem_root_cert, gnutls | |||
| 570 | userpref_error_t userpref_set_keys_and_certs(gnutls_datum_t * root_key, gnutls_datum_t * root_cert, gnutls_datum_t * host_key, gnutls_datum_t * host_cert) | 871 | userpref_error_t userpref_set_keys_and_certs(gnutls_datum_t * root_key, gnutls_datum_t * root_cert, gnutls_datum_t * host_key, gnutls_datum_t * host_cert) |
| 571 | { | 872 | { |
| 572 | FILE *pFile; | 873 | FILE *pFile; |
| 573 | gchar *pem; | 874 | char *pem; |
| 875 | const char *config_path; | ||
| 574 | 876 | ||
| 575 | if (!root_key || !host_key || !root_cert || !host_cert) | 877 | if (!root_key || !host_key || !root_cert || !host_cert) |
| 576 | return USERPREF_E_INVALID_ARG; | 878 | return USERPREF_E_INVALID_ARG; |
| @@ -578,30 +880,44 @@ userpref_error_t userpref_set_keys_and_certs(gnutls_datum_t * root_key, gnutls_d | |||
| 578 | /* Make sure config directory exists */ | 880 | /* Make sure config directory exists */ |
| 579 | userpref_create_config_dir(); | 881 | userpref_create_config_dir(); |
| 580 | 882 | ||
| 883 | config_path = userpref_get_config_dir(); | ||
| 884 | |||
| 581 | /* Now write keys and certificates to disk */ | 885 | /* Now write keys and certificates to disk */ |
| 582 | pem = g_build_path(G_DIR_SEPARATOR_S, g_get_user_config_dir(), LIBIMOBILEDEVICE_CONF_DIR, LIBIMOBILEDEVICE_ROOT_PRIVKEY, NULL); | 886 | pem = (char*)malloc(strlen(config_path)+1+strlen(LIBIMOBILEDEVICE_ROOT_PRIVKEY)+1); |
| 887 | strcpy(pem, config_path); | ||
| 888 | strcat(pem, DIR_SEP_S); | ||
| 889 | strcat(pem, LIBIMOBILEDEVICE_ROOT_PRIVKEY); | ||
| 583 | pFile = fopen(pem, "wb"); | 890 | pFile = fopen(pem, "wb"); |
| 584 | fwrite(root_key->data, 1, root_key->size, pFile); | 891 | fwrite(root_key->data, 1, root_key->size, pFile); |
| 585 | fclose(pFile); | 892 | fclose(pFile); |
| 586 | g_free(pem); | 893 | free(pem); |
| 587 | 894 | ||
| 588 | pem = g_build_path(G_DIR_SEPARATOR_S, g_get_user_config_dir(), LIBIMOBILEDEVICE_CONF_DIR, LIBIMOBILEDEVICE_HOST_PRIVKEY, NULL); | 895 | pem = (char*)malloc(strlen(config_path)+1+strlen(LIBIMOBILEDEVICE_HOST_PRIVKEY)+1); |
| 896 | strcpy(pem, config_path); | ||
| 897 | strcat(pem, DIR_SEP_S); | ||
| 898 | strcat(pem, LIBIMOBILEDEVICE_HOST_PRIVKEY); | ||
| 589 | pFile = fopen(pem, "wb"); | 899 | pFile = fopen(pem, "wb"); |
| 590 | fwrite(host_key->data, 1, host_key->size, pFile); | 900 | fwrite(host_key->data, 1, host_key->size, pFile); |
| 591 | fclose(pFile); | 901 | fclose(pFile); |
| 592 | g_free(pem); | 902 | free(pem); |
| 593 | 903 | ||
| 594 | pem = g_build_path(G_DIR_SEPARATOR_S, g_get_user_config_dir(), LIBIMOBILEDEVICE_CONF_DIR, LIBIMOBILEDEVICE_ROOT_CERTIF, NULL); | 904 | pem = (char*)malloc(strlen(config_path)+1+strlen(LIBIMOBILEDEVICE_ROOT_CERTIF)+1); |
| 905 | strcpy(pem, config_path); | ||
| 906 | strcat(pem, DIR_SEP_S); | ||
| 907 | strcat(pem, LIBIMOBILEDEVICE_ROOT_CERTIF); | ||
| 595 | pFile = fopen(pem, "wb"); | 908 | pFile = fopen(pem, "wb"); |
| 596 | fwrite(root_cert->data, 1, root_cert->size, pFile); | 909 | fwrite(root_cert->data, 1, root_cert->size, pFile); |
| 597 | fclose(pFile); | 910 | fclose(pFile); |
| 598 | g_free(pem); | 911 | free(pem); |
| 599 | 912 | ||
| 600 | pem = g_build_path(G_DIR_SEPARATOR_S, g_get_user_config_dir(), LIBIMOBILEDEVICE_CONF_DIR, LIBIMOBILEDEVICE_HOST_CERTIF, NULL); | 913 | pem = (char*)malloc(strlen(config_path)+1+strlen(LIBIMOBILEDEVICE_HOST_CERTIF)+1); |
| 914 | strcpy(pem, config_path); | ||
| 915 | strcat(pem, DIR_SEP_S); | ||
| 916 | strcat(pem, LIBIMOBILEDEVICE_HOST_CERTIF); | ||
| 601 | pFile = fopen(pem, "wb"); | 917 | pFile = fopen(pem, "wb"); |
| 602 | fwrite(host_cert->data, 1, host_cert->size, pFile); | 918 | fwrite(host_cert->data, 1, host_cert->size, pFile); |
| 603 | fclose(pFile); | 919 | fclose(pFile); |
| 604 | g_free(pem); | 920 | free(pem); |
| 605 | 921 | ||
| 606 | return USERPREF_E_SUCCESS; | 922 | return USERPREF_E_SUCCESS; |
| 607 | } | 923 | } |
