summaryrefslogtreecommitdiffstats
path: root/src/userpref.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/userpref.c')
-rw-r--r--src/userpref.c305
1 files changed, 193 insertions, 112 deletions
diff --git a/src/userpref.c b/src/userpref.c
index 0a9086b..46e97b7 100644
--- a/src/userpref.c
+++ b/src/userpref.c
@@ -27,35 +27,34 @@
27#include <string.h> 27#include <string.h>
28#include <stdio.h> 28#include <stdio.h>
29 29
30
31#define LIBIPHONE_CONF_DIR "libiphone" 30#define LIBIPHONE_CONF_DIR "libiphone"
32#define LIBIPHONE_CONF_FILE "libiphonerc" 31#define LIBIPHONE_CONF_FILE "libiphonerc"
33 32
34#define LIBIPHONE_ROOT_PRIVKEY "RootPrivateKey.pem" 33#define LIBIPHONE_ROOT_PRIVKEY "RootPrivateKey.pem"
35#define LIBIPHONE_HOST_PRIVKEY "HostPrivateKey.pem" 34#define LIBIPHONE_HOST_PRIVKEY "HostPrivateKey.pem"
36#define LIBIPHONE_ROOT_CERTIF "RootCertificate.pem" 35#define LIBIPHONE_ROOT_CERTIF "RootCertificate.pem"
37#define LIBIPHONE_HOST_CERTIF "HostCertificate.pem" 36#define LIBIPHONE_HOST_CERTIF "HostCertificate.pem"
38
39 37
40extern int debug; 38extern int debug;
41 39
42inline void create_config_dir() { 40/** Reads the HostID from a previously generated configuration file.
43 gchar* config_dir = g_build_path(G_DIR_SEPARATOR_S, g_get_user_config_dir(), LIBIPHONE_CONF_DIR, NULL); 41 *
44 g_mkdir_with_parents (config_dir, 755); 42 * @note It is the responsibility of the calling function to free the returned host_id
45 g_free(config_dir); 43 *
46 return; 44 * @return The string containing the HostID or NULL
47} 45 */
48 46char* get_host_id() {
49char* get_host_id()
50{
51 char* host_id = NULL; 47 char* host_id = NULL;
52 gchar* config_file = g_build_path(G_DIR_SEPARATOR_S, g_get_user_config_dir(), LIBIPHONE_CONF_DIR, LIBIPHONE_CONF_FILE, NULL); 48 gchar* config_file;
49 GKeyFile* key_file;
50 gchar* loc_host_id;
53 51
54 /* now parse file to get the HostID */ 52 config_file = g_build_path(G_DIR_SEPARATOR_S, g_get_user_config_dir(), LIBIPHONE_CONF_DIR, LIBIPHONE_CONF_FILE, NULL);
55 GKeyFile* key_file = g_key_file_new ();
56 if( g_key_file_load_from_file (key_file, config_file, G_KEY_FILE_KEEP_COMMENTS, NULL) ) {
57 53
58 gchar* loc_host_id = g_key_file_get_value(key_file, "Global", "HostID", NULL); 54 /* now parse file to get the HostID */
55 key_file = g_key_file_new();
56 if(g_key_file_load_from_file(key_file, config_file, G_KEY_FILE_KEEP_COMMENTS, NULL)) {
57 loc_host_id = g_key_file_get_value(key_file, "Global", "HostID", NULL);
59 if (loc_host_id) 58 if (loc_host_id)
60 host_id = strdup((char*)loc_host_id); 59 host_id = strdup((char*)loc_host_id);
61 g_free(loc_host_id); 60 g_free(loc_host_id);
@@ -63,32 +62,42 @@ char* get_host_id()
63 g_key_file_free(key_file); 62 g_key_file_free(key_file);
64 g_free(config_file); 63 g_free(config_file);
65 64
66 if (debug) printf("Using %s as HostID\n",host_id); 65 if (debug) printf("get_host_id(): Using %s as HostID\n",host_id);
67 return host_id; 66 return host_id;
68} 67}
69 68
70int is_device_known(char* public_key) 69/** Determines whether this iPhone has been connected to this system before.
71{ 70 *
71 * @param public_key The public key as given by the iPhone.
72 *
73 * @return 1 if the iPhone has been connected previously to this configuration
74 * or 0 otherwise.
75 */
76int is_device_known(char* public_key) {
72 int ret = 0; 77 int ret = 0;
73 78 gchar *config_file;
79 GKeyFile *key_file;
80 gchar **devices_list, **pcur, *keyfilepath, *stored_key;
81 GIOChannel *keyfile;
82
74 /* first get config file */ 83 /* first get config file */
75 gchar* config_file = g_build_path(G_DIR_SEPARATOR_S, g_get_user_config_dir(), LIBIPHONE_CONF_DIR, LIBIPHONE_CONF_FILE, NULL); 84 config_file = g_build_path(G_DIR_SEPARATOR_S, g_get_user_config_dir(), LIBIPHONE_CONF_DIR, LIBIPHONE_CONF_FILE, NULL);
76 if (g_file_test(config_file, (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_REGULAR))) { 85 if (g_file_test(config_file, (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_REGULAR))) {
77 86
78 /* now parse file to get knwon devices list */ 87 /* now parse file to get knwon devices list */
79 GKeyFile* key_file = g_key_file_new (); 88 key_file = g_key_file_new ();
80 if( g_key_file_load_from_file (key_file, config_file, G_KEY_FILE_KEEP_COMMENTS, NULL) ) { 89 if(g_key_file_load_from_file(key_file, config_file, G_KEY_FILE_KEEP_COMMENTS, NULL)) {
81 90
82 gchar** devices_list = g_key_file_get_string_list (key_file, "Global", "DevicesList", NULL, NULL); 91 devices_list = g_key_file_get_string_list (key_file, "Global", "DevicesList", NULL, NULL);
83 if (devices_list) { 92 if (devices_list) {
84 gchar** pcur = devices_list; 93 pcur = devices_list;
85 while(*pcur && !ret) { 94 while(*pcur && !ret) {
86 /* open associated base64 encoded key */ 95 /* open associated base64 encoded key */
87 gchar* keyfilepath = g_build_path(G_DIR_SEPARATOR_S, g_get_user_config_dir(), LIBIPHONE_CONF_DIR, *pcur, NULL); 96 keyfilepath = g_build_path(G_DIR_SEPARATOR_S, g_get_user_config_dir(), LIBIPHONE_CONF_DIR, *pcur, NULL);
88 if (g_file_test(keyfilepath, (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_REGULAR))) { 97 if (g_file_test(keyfilepath, (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_REGULAR))) {
89 GIOChannel* keyfile = g_io_channel_new_file (keyfilepath, "r", NULL); 98 keyfile = g_io_channel_new_file (keyfilepath, "r", NULL);
90 99
91 gchar* stored_key = NULL; 100 stored_key = NULL;
92 g_io_channel_read_to_end (keyfile, &stored_key, NULL, NULL); 101 g_io_channel_read_to_end (keyfile, &stored_key, NULL, NULL);
93 102
94 /* now compare to input */ 103 /* now compare to input */
@@ -109,52 +118,67 @@ int is_device_known(char* public_key)
109 return ret; 118 return ret;
110} 119}
111 120
112int store_device_public_key(char* public_key) 121/** Mark the iPhone (as represented by the key) as having connected to this
113{ 122 * configuration.
123 *
124 * @param public_key The public key given by the iPhone
125 *
126 * @return 1 on success and 0 if no public key is given or if it has already
127 * been marked as connected previously.
128 */
129int store_device_public_key(char* public_key) {
130 gchar *config_file;
131 GKeyFile *key_file;
132 gchar **devices_list;
133 guint len = 0;
134 guint wlength = 0;
135 gchar dev_file[20];
136 int i;
137 const gchar** new_devices_list;
138 gsize length;
139 gchar *buf;
140 GIOChannel *file;
141 gchar* device_file;
142
114 if (NULL == public_key || is_device_known(public_key)) 143 if (NULL == public_key || is_device_known(public_key))
115 return 0; 144 return 0;
116 145
117 /* first get config file */ 146 /* first get config file */
118 gchar* config_file = g_build_path(G_DIR_SEPARATOR_S, g_get_user_config_dir(), LIBIPHONE_CONF_DIR, LIBIPHONE_CONF_FILE, NULL); 147 config_file = g_build_path(G_DIR_SEPARATOR_S, g_get_user_config_dir(), LIBIPHONE_CONF_DIR, LIBIPHONE_CONF_FILE, NULL);
119 if (g_file_test(config_file, (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_REGULAR))) { 148 if (g_file_test(config_file, (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_REGULAR))) {
149 key_file = g_key_file_new();
150 if(g_key_file_load_from_file (key_file, config_file, G_KEY_FILE_KEEP_COMMENTS, NULL)) {
120 151
121 152 /* Determine device name */
122 GKeyFile* key_file = g_key_file_new (); 153 devices_list = g_key_file_get_string_list (key_file, "Global", "DevicesList", NULL, NULL);
123 if( g_key_file_load_from_file (key_file, config_file, G_KEY_FILE_KEEP_COMMENTS, NULL) ) {
124
125 gchar** devices_list = g_key_file_get_string_list (key_file, "Global", "DevicesList", NULL, NULL);
126
127 guint length = 0;
128 guint wlength = 0;
129 if (devices_list) 154 if (devices_list)
130 length = g_strv_length(devices_list); 155 len = g_strv_length(devices_list);
131 g_strfreev(devices_list); 156 g_strfreev(devices_list);
157 g_sprintf(dev_file, "Device%i", len);
132 158
133 gchar dev_file[20]; 159 /* Write device file to disk */
134 g_sprintf (dev_file, "Device%i", length); 160 device_file = g_build_path(G_DIR_SEPARATOR_S, g_get_user_config_dir(), LIBIPHONE_CONF_DIR, dev_file, NULL);
135 161 file = g_io_channel_new_file (device_file, "w", NULL);
136 gchar* device_file = g_build_path(G_DIR_SEPARATOR_S, g_get_user_config_dir(), LIBIPHONE_CONF_DIR, dev_file, NULL); 162 g_free(device_file);
137 GIOChannel* file = g_io_channel_new_file (device_file, "w", NULL);
138 g_free (device_file);
139 wlength = strlen(public_key); // why this wasn't discovered before... ugh 163 wlength = strlen(public_key); // why this wasn't discovered before... ugh
140 g_io_channel_write_chars (file, public_key, wlength, NULL, NULL); 164 g_io_channel_write_chars(file, public_key, wlength, NULL, NULL);
141 g_io_channel_shutdown(file, TRUE, NULL); 165 g_io_channel_shutdown(file, TRUE, NULL);
142 166
143 /* append device to list */ 167 /* Append device to list */
144 const gchar** new_devices_list = (const gchar**)g_malloc(sizeof(gchar*)* (length + 2)); 168 new_devices_list = (const gchar**)g_malloc(sizeof(gchar*)* (len + 2));
145 int i; 169 for( i = 0; i < len; i++)
146 for( i = 0; i < length; i++)
147 new_devices_list[i] = devices_list[i]; 170 new_devices_list[i] = devices_list[i];
148 new_devices_list[length] = dev_file; 171 new_devices_list[len] = dev_file;
149 new_devices_list[length+1] = NULL; 172 new_devices_list[len+1] = NULL;
150 g_key_file_set_string_list (key_file,"Global", "DevicesList", new_devices_list, length+1); 173 g_key_file_set_string_list(key_file,"Global", "DevicesList", new_devices_list, len+1);
151 g_free(new_devices_list); 174 g_free(new_devices_list);
152 175
153 } 176 }
154 gsize length; 177
155 gchar* buf = g_key_file_to_data (key_file, &length,NULL); 178 /* Write config file to disk */
156 GIOChannel* file = g_io_channel_new_file (config_file, "w", NULL); 179 buf = g_key_file_to_data(key_file, &length, NULL);
157 g_io_channel_write_chars (file, buf, length, NULL, NULL); 180 file = g_io_channel_new_file(config_file, "w", NULL);
181 g_io_channel_write_chars(file, buf, length, NULL, NULL);
158 g_io_channel_shutdown(file, TRUE, NULL); 182 g_io_channel_shutdown(file, TRUE, NULL);
159 g_key_file_free(key_file); 183 g_key_file_free(key_file);
160 } 184 }
@@ -162,94 +186,151 @@ int store_device_public_key(char* public_key)
162 return 1; 186 return 1;
163} 187}
164 188
165int read_file_in_confdir(char* file, gnutls_datum_t* data) 189/** Private function which reads the given file into a gnutls structure.
166{ 190 *
167 if (NULL == file || NULL == data) 191 * @param file The filename of the file to read
168 return 0; 192 * @param data The pointer at which to store the data.
169 193 *
170 gchar* filepath = g_build_path(G_DIR_SEPARATOR_S, g_get_user_config_dir(), LIBIPHONE_CONF_DIR, file, NULL); 194 * @return 1 if the file contents where read successfully and 0 otherwise.
195 */
196int read_file_in_confdir(char* file, gnutls_datum_t* data) {
171 gboolean success; 197 gboolean success;
172 gsize size; 198 gsize size;
173 char *content; 199 char *content;
174 success = g_file_get_contents (filepath, &content, &size, NULL); 200 gchar *filepath;
175 g_free (filepath); 201
202 if (NULL == file || NULL == data)
203 return 0;
204
205 /* Read file */
206 filepath = g_build_path(G_DIR_SEPARATOR_S, g_get_user_config_dir(), LIBIPHONE_CONF_DIR, file, NULL);
207 success = g_file_get_contents(filepath, &content, &size, NULL);
208 g_free(filepath);
209
210 /* Add it to the gnutls_datnum_t structure */
176 data->data = content; 211 data->data = content;
177 data->size = size; 212 data->size = size;
213
178 return success; 214 return success;
179} 215}
180 216
181int get_root_private_key(gnutls_datum_t* root_privkey) 217/** Read the root private key
182{ 218 *
219 * @param root_privkey A pointer to the appropriate gnutls structure
220 *
221 * @return 1 if the file was successfully read and 0 otherwise.
222 */
223int get_root_private_key(gnutls_datum_t* root_privkey) {
183 return read_file_in_confdir(LIBIPHONE_ROOT_PRIVKEY, root_privkey); 224 return read_file_in_confdir(LIBIPHONE_ROOT_PRIVKEY, root_privkey);
184} 225}
185 226
186int get_host_private_key(gnutls_datum_t* host_privkey) 227/** Read the host private key
187{ 228 *
229 * @param host_privkey A pointer to the appropriate gnutls structure
230 *
231 * @return 1 if the file was successfully read and 0 otherwise.
232 */
233int get_host_private_key(gnutls_datum_t* host_privkey) {
188 return read_file_in_confdir(LIBIPHONE_HOST_PRIVKEY, host_privkey); 234 return read_file_in_confdir(LIBIPHONE_HOST_PRIVKEY, host_privkey);
189} 235}
190 236
191int get_root_certificate(gnutls_datum_t* root_cert) 237/** Read the root certificate
192{ 238 *
239 * @param root_privkey A pointer to the appropriate gnutls structure
240 *
241 * @return 1 if the file was successfully read and 0 otherwise.
242 */
243int get_root_certificate(gnutls_datum_t* root_cert) {
193 return read_file_in_confdir(LIBIPHONE_ROOT_CERTIF, root_cert); 244 return read_file_in_confdir(LIBIPHONE_ROOT_CERTIF, root_cert);
194} 245}
195 246
196int get_host_certificate(gnutls_datum_t* host_cert) 247/** Read the host certificate
197{ 248 *
249 * @param root_privkey A pointer to the appropriate gnutls structure
250 *
251 * @return 1 if the file was successfully read and 0 otherwise.
252 */
253int get_host_certificate(gnutls_datum_t* host_cert) {
198 return read_file_in_confdir(LIBIPHONE_HOST_CERTIF, host_cert); 254 return read_file_in_confdir(LIBIPHONE_HOST_CERTIF, host_cert);
199} 255}
200 256
201int init_config_file(char* host_id, gnutls_datum_t* root_key, gnutls_datum_t* host_key, gnutls_datum_t* root_cert, gnutls_datum_t* host_cert) 257/** Creates a freedesktop compatible configuration directory for libiphone.
202{ 258 */
259inline void create_config_dir() {
260 gchar* config_dir;
261
262 config_dir = g_build_path(G_DIR_SEPARATOR_S, g_get_user_config_dir(), LIBIPHONE_CONF_DIR, NULL);
263 g_mkdir_with_parents(config_dir, 755);
264 g_free(config_dir);
265}
266
267/** Create and save a configuration file containing the given data.
268 *
269 * @note: All fields must specified and be non-null
270 *
271 * @param host_id The UUID of the host
272 * @param root_key The root key
273 * @param host_key The host key
274 * @param root_cert The root certificate
275 * @param host_cert The host certificate
276 *
277 * @return 1 on success and 0 otherwise.
278 */
279int init_config_file(char* host_id, gnutls_datum_t* root_key, gnutls_datum_t* host_key, gnutls_datum_t* root_cert, gnutls_datum_t* host_cert) {
280 FILE * pFile;
281 gchar* pem;
282 GKeyFile* key_file;
283 gsize length;
284 gchar *buf, *config_file;
285 GIOChannel* file;
286
203 if (!host_id || !root_key || !host_key || !root_cert || !host_cert) 287 if (!host_id || !root_key || !host_key || !root_cert || !host_cert)
204 return 0; 288 return 0;
205 289
206 /* make sure config directory exists*/ 290 /* Make sure config directory exists*/
207 create_config_dir(); 291 create_config_dir();
208 292
209 /* now parse file to get the HostID */ 293 /* Now parse file to get the HostID */
210 GKeyFile* key_file = g_key_file_new (); 294 key_file = g_key_file_new();
211 295
212 /* store in config file */ 296 /* Store in config file */
213 if (debug) printf("init_config_file setting hostID to %s\n", host_id); 297 if (debug) printf("init_config_file(): setting hostID to %s\n", host_id);
214 g_key_file_set_value (key_file, "Global", "HostID", host_id); 298 g_key_file_set_value(key_file, "Global", "HostID", host_id);
215 299
216 /* write config file on disk */ 300 /* Write config file on disk */
217 gsize length; 301 buf = g_key_file_to_data(key_file, &length,NULL);
218 gchar* buf = g_key_file_to_data (key_file, &length,NULL); 302 config_file = g_build_path(G_DIR_SEPARATOR_S, g_get_user_config_dir(), LIBIPHONE_CONF_DIR, LIBIPHONE_CONF_FILE, NULL);
219 gchar* config_file = g_build_path(G_DIR_SEPARATOR_S, g_get_user_config_dir(), LIBIPHONE_CONF_DIR, LIBIPHONE_CONF_FILE, NULL); 303 file = g_io_channel_new_file(config_file, "w", NULL);
220 GIOChannel* file = g_io_channel_new_file (config_file, "w", NULL); 304 g_free(config_file);
221 g_free (config_file); 305 g_io_channel_write_chars(file, buf, length, NULL, NULL);
222 g_io_channel_write_chars (file, buf, length, NULL, NULL);
223 g_io_channel_shutdown(file, TRUE, NULL); 306 g_io_channel_shutdown(file, TRUE, NULL);
224 307
225 g_key_file_free(key_file); 308 g_key_file_free(key_file);
226 309
227 //now write keys and certifs to disk 310 /* Now write keys and certificates to disk */
228 FILE * pFile;
229 gchar* pem;
230 pem = g_build_path(G_DIR_SEPARATOR_S, g_get_user_config_dir(), LIBIPHONE_CONF_DIR, LIBIPHONE_ROOT_PRIVKEY, NULL); 311 pem = g_build_path(G_DIR_SEPARATOR_S, g_get_user_config_dir(), LIBIPHONE_CONF_DIR, LIBIPHONE_ROOT_PRIVKEY, NULL);
231 pFile = fopen ( pem , "wb" ); 312 pFile = fopen(pem , "wb");
232 fwrite ( root_key->data, 1 , root_key->size , pFile ); 313 fwrite(root_key->data, 1 , root_key->size , pFile );
233 fclose (pFile); 314 fclose(pFile);
234 g_free (pem); 315 g_free(pem);
235 316
236 pem = g_build_path(G_DIR_SEPARATOR_S, g_get_user_config_dir(), LIBIPHONE_CONF_DIR, LIBIPHONE_HOST_PRIVKEY, NULL); 317 pem = g_build_path(G_DIR_SEPARATOR_S, g_get_user_config_dir(), LIBIPHONE_CONF_DIR, LIBIPHONE_HOST_PRIVKEY, NULL);
237 pFile = fopen ( pem , "wb" ); 318 pFile = fopen(pem , "wb");
238 fwrite ( host_key->data, 1 , host_key->size , pFile ); 319 fwrite(host_key->data, 1 , host_key->size , pFile);
239 fclose (pFile); 320 fclose(pFile);
240 g_free (pem); 321 g_free(pem);
241 322
242 pem = g_build_path(G_DIR_SEPARATOR_S, g_get_user_config_dir(), LIBIPHONE_CONF_DIR, LIBIPHONE_ROOT_CERTIF, NULL); 323 pem = g_build_path(G_DIR_SEPARATOR_S, g_get_user_config_dir(), LIBIPHONE_CONF_DIR, LIBIPHONE_ROOT_CERTIF, NULL);
243 pFile = fopen ( pem , "wb" ); 324 pFile = fopen(pem , "wb");
244 fwrite ( root_cert->data, 1 , root_cert->size , pFile ); 325 fwrite(root_cert->data, 1 , root_cert->size , pFile);
245 fclose (pFile); 326 fclose(pFile);
246 g_free (pem); 327 g_free(pem);
247 328
248 pem = g_build_path(G_DIR_SEPARATOR_S, g_get_user_config_dir(), LIBIPHONE_CONF_DIR, LIBIPHONE_HOST_CERTIF, NULL); 329 pem = g_build_path(G_DIR_SEPARATOR_S, g_get_user_config_dir(), LIBIPHONE_CONF_DIR, LIBIPHONE_HOST_CERTIF, NULL);
249 pFile = fopen ( pem , "wb" ); 330 pFile = fopen(pem , "wb");
250 fwrite ( host_cert->data, 1 , host_cert->size , pFile ); 331 fwrite(host_cert->data, 1 , host_cert->size , pFile);
251 fclose (pFile); 332 fclose(pFile);
252 g_free (pem); 333 g_free(pem);
253 334
254 return 1; 335 return 1;
255} 336}