Commit 4b558a53 authored by Jonathan Beck's avatar Jonathan Beck Committed by Matt Colyer

Store certificates and private keys as PEM files instead of storing them in...

Store certificates and private keys as PEM files instead of storing them in config file. Added functions to generate proper pairing request.
Signed-off-by: 's avatarMatt Colyer <matt@colyer.name>
parent 20a6f879
...@@ -93,25 +93,15 @@ int main(int argc, char *argv[]) { ...@@ -93,25 +93,15 @@ int main(int argc, char *argv[]) {
gnutls_x509_crt_export (root_cert, GNUTLS_X509_FMT_PEM, root_cert_pem.data, &root_cert_pem.size); gnutls_x509_crt_export (root_cert, GNUTLS_X509_FMT_PEM, root_cert_pem.data, &root_cert_pem.size);
gnutls_x509_crt_export (host_cert, GNUTLS_X509_FMT_PEM, host_cert_pem.data, &host_cert_pem.size); gnutls_x509_crt_export (host_cert, GNUTLS_X509_FMT_PEM, host_cert_pem.data, &host_cert_pem.size);
/* encode in base64 for storage */
char* root_key_b64 = g_base64_encode (root_key_pem.data,root_key_pem.size);
char* host_key_b64 = g_base64_encode (host_key_pem.data,host_key_pem.size);
char* root_cert_b64 = g_base64_encode (root_cert_pem.data,root_cert_pem.size);
char* host_cert_b64 = g_base64_encode (host_cert_pem.data,host_cert_pem.size);
/* store values in config file */ /* store values in config file */
init_config_file(host_id, root_key_b64, host_key_b64, root_cert_b64, host_cert_b64); init_config_file(host_id, &root_key_pem, &host_key_pem, &root_cert_pem, &host_cert_pem);
gnutls_free(root_key_pem.data); gnutls_free(root_key_pem.data);
gnutls_free(host_key_pem.data); gnutls_free(host_key_pem.data);
gnutls_free(root_cert_pem.data); gnutls_free(root_cert_pem.data);
gnutls_free(host_cert_pem.data); gnutls_free(host_cert_pem.data);
g_free(root_key_b64);
g_free(host_key_b64);
g_free(root_cert_b64);
g_free(host_cert_b64);
return 0; return 0;
} }
......
...@@ -263,8 +263,8 @@ int lockdownd_pair_device(lockdownd_client *control, char *public_key_b64, char ...@@ -263,8 +263,8 @@ int lockdownd_pair_device(lockdownd_client *control, char *public_key_b64, char
/* Setup Pair request plist */ /* Setup Pair request plist */
dict = add_child_to_plist(plist, "dict", "\n", NULL, 0); dict = add_child_to_plist(plist, "dict", "\n", NULL, 0);
add_key_str_dict_element(plist, dict, "Key", "PairRecord", 1); dictRecord = add_key_dict_node(plist, dict, "PairRecord", "\n", 1);
dictRecord = add_child_to_plist(plist, "dict", "\n", NULL, 1); //dictRecord = add_child_to_plist(plist, "dict", "\n", NULL, 1);
add_key_data_dict_element(plist, dictRecord, "DeviceCertificate", device_cert_b64, 2); add_key_data_dict_element(plist, dictRecord, "DeviceCertificate", device_cert_b64, 2);
add_key_data_dict_element(plist, dictRecord, "HostCertificate", host_cert_b64, 2); add_key_data_dict_element(plist, dictRecord, "HostCertificate", host_cert_b64, 2);
add_key_str_dict_element(plist, dictRecord, "HostID", host_id, 2); add_key_str_dict_element(plist, dictRecord, "HostID", host_id, 2);
...@@ -273,6 +273,8 @@ int lockdownd_pair_device(lockdownd_client *control, char *public_key_b64, char ...@@ -273,6 +273,8 @@ int lockdownd_pair_device(lockdownd_client *control, char *public_key_b64, char
xmlDocDumpMemory(plist, (xmlChar**)&XML_content, &length); xmlDocDumpMemory(plist, (xmlChar**)&XML_content, &length);
printf("XML Pairing request : %s\n",XML_content);
/* send to iPhone */ /* send to iPhone */
bytes = lockdownd_send(control, XML_content, length); bytes = lockdownd_send(control, XML_content, length);
...@@ -366,34 +368,34 @@ int lockdownd_gen_pair_cert(char *public_key_b64, char **device_cert_b64, char * ...@@ -366,34 +368,34 @@ int lockdownd_gen_pair_cert(char *public_key_b64, char **device_cert_b64, char *
gnutls_datum_t essentially_null = {strdup("abababababababab"), strlen("abababababababab")}; gnutls_datum_t essentially_null = {strdup("abababababababab"), strlen("abababababababab")};
gnutls_x509_privkey_t fake_privkey, root_privkey; gnutls_x509_privkey_t fake_privkey, root_privkey;
gnutls_x509_crt_t dev_cert, root_cert; gnutls_x509_crt_t dev_cert, root_cert, host_cert;
gnutls_x509_privkey_init(&fake_privkey); gnutls_x509_privkey_init(&fake_privkey);
gnutls_x509_crt_init(&dev_cert); gnutls_x509_crt_init(&dev_cert);
gnutls_x509_crt_init(&root_cert); gnutls_x509_crt_init(&root_cert);
gnutls_x509_crt_init(&host_cert);
if ( GNUTLS_E_SUCCESS == gnutls_x509_privkey_import_rsa_raw(fake_privkey, &modulus, &exponent, &essentially_null, &essentially_null, &essentially_null, &essentially_null) ) { if ( GNUTLS_E_SUCCESS == gnutls_x509_privkey_import_rsa_raw(fake_privkey, &modulus, &exponent, &essentially_null, &essentially_null, &essentially_null, &essentially_null) ) {
gnutls_x509_privkey_init(&root_privkey); gnutls_x509_privkey_init(&root_privkey);
/* get certificate stored in config */ /* get root cert */
*host_cert_b64 = get_host_certificate();
*root_cert_b64 = get_root_certificate();
gnutls_datum_t pem_root_cert = {NULL, 0}; gnutls_datum_t pem_root_cert = {NULL, 0};
pem_root_cert.data = g_base64_decode (*root_cert_b64, &pem_root_cert.size); ret = get_root_certificate(&pem_root_cert);
ret = gnutls_x509_crt_import (root_cert, &pem_root_cert, GNUTLS_X509_FMT_PEM); ret = gnutls_x509_crt_import (root_cert, &pem_root_cert, GNUTLS_X509_FMT_PEM);
gnutls_free(pem_root_cert.data);
/* get host cert */
gnutls_datum_t pem_host_cert = {NULL, 0};
ret = get_host_certificate(&pem_host_cert);
ret = gnutls_x509_crt_import (host_cert, &pem_host_cert, GNUTLS_X509_FMT_PEM);
/* get root private key */ /* get root private key */
char *root_priv_b64 = get_root_private_key();
gnutls_datum_t pem_root_priv = {NULL, 0}; gnutls_datum_t pem_root_priv = {NULL, 0};
pem_root_priv.data = g_base64_decode (root_priv_b64, &pem_root_priv.size); ret = get_root_private_key(&pem_root_priv);
ret = gnutls_x509_privkey_import (root_privkey, &pem_root_priv, GNUTLS_X509_FMT_PEM); ret = gnutls_x509_privkey_import (root_privkey, &pem_root_priv, GNUTLS_X509_FMT_PEM);
gnutls_free(pem_root_priv.data);
/* generate device certificate */ /* generate device certificate */
...@@ -418,8 +420,13 @@ int lockdownd_gen_pair_cert(char *public_key_b64, char **device_cert_b64, char * ...@@ -418,8 +420,13 @@ int lockdownd_gen_pair_cert(char *public_key_b64, char **device_cert_b64, char *
/* now encode certificates for output */ /* now encode certificates for output */
*device_cert_b64 = g_base64_encode(dev_pem.data, dev_pem.size); *device_cert_b64 = g_base64_encode(dev_pem.data, dev_pem.size);
*host_cert_b64 = g_base64_encode(pem_host_cert.data, pem_host_cert.size);
*root_cert_b64 = g_base64_encode(pem_root_cert.data, pem_root_cert.size);
ret = 1; ret = 1;
} }
gnutls_free(pem_root_priv.data);
gnutls_free(pem_root_cert.data);
gnutls_free(pem_host_cert.data);
} }
} }
......
...@@ -29,6 +29,29 @@ const char *plist_base = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\ ...@@ -29,6 +29,29 @@ const char *plist_base = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\
<plist version=\"1.0\">\n\ <plist version=\"1.0\">\n\
</plist>\0"; </plist>\0";
char* format_string(char* buf, int cols, int depth)
{
int colw = depth + cols + 1; //new buf cols width
int len = strlen(buf);
//int nlines = ceil((float)len / (float)cols);
int nlines = len / cols + 1;
char* new_buf = (char*)malloc(nlines * colw + depth + 1);
int i = 0;
int j = 0;
for (i = 0; i < nlines; i++){
new_buf[i * colw] = '\n';
for (j = 0; j < depth; j++)
new_buf[i * colw + 1 + j] = '\t';
memcpy(new_buf + i * colw + 1 + depth, buf + i * cols, cols);
}
new_buf[len+(1+depth)*nlines] = '\n';
for (j = 0; j < depth; j++)
new_buf[len+(1+depth)*nlines + 1 + j] = '\t';
new_buf[len+(1+depth)*nlines+depth+1] = '\0';
free(buf);
return new_buf;
}
xmlDocPtr new_plist() { xmlDocPtr new_plist() {
char *plist = strdup(plist_base); char *plist = strdup(plist_base);
xmlDocPtr plist_xml = xmlReadMemory(plist, strlen(plist), NULL, NULL, 0); xmlDocPtr plist_xml = xmlReadMemory(plist, strlen(plist), NULL, NULL, 0);
...@@ -62,10 +85,17 @@ xmlNode *add_key_str_dict_element(xmlDocPtr plist, xmlNode *dict, const char *ke ...@@ -62,10 +85,17 @@ xmlNode *add_key_str_dict_element(xmlDocPtr plist, xmlNode *dict, const char *ke
return keyPtr; return keyPtr;
} }
xmlNode *add_key_dict_node(xmlDocPtr plist, xmlNode *dict, const char *key, const char *value, int depth) {
xmlNode *child;
add_child_to_plist(plist, "key", key, dict, depth);
child = add_child_to_plist(plist, "dict", value, dict, depth);
return child;
}
xmlNode *add_key_data_dict_element(xmlDocPtr plist, xmlNode *dict, const char *key, const char *value, int depth) { xmlNode *add_key_data_dict_element(xmlDocPtr plist, xmlNode *dict, const char *key, const char *value, int depth) {
xmlNode *keyPtr; xmlNode *keyPtr;
keyPtr = add_child_to_plist(plist, "key", key, dict, depth); keyPtr = add_child_to_plist(plist, "key", key, dict, depth);
add_child_to_plist(plist, "data", value, dict, depth); add_child_to_plist(plist, "data", format_string(value, 60, depth), dict, depth);
return keyPtr; return keyPtr;
} }
......
...@@ -25,6 +25,7 @@ ...@@ -25,6 +25,7 @@
#include <libxml/parser.h> #include <libxml/parser.h>
#include <libxml/tree.h> #include <libxml/tree.h>
xmlNode *add_key_dict_node(xmlDocPtr plist, xmlNode *dict, const char *key, const char *value, int depth);
xmlNode *add_key_str_dict_element(xmlDocPtr plist, xmlNode *dict, const char *key, const char *value, int depth); xmlNode *add_key_str_dict_element(xmlDocPtr plist, xmlNode *dict, const char *key, const char *value, int depth);
xmlNode *add_key_data_dict_element(xmlDocPtr plist, xmlNode *dict, const char *key, const char *value, int depth); xmlNode *add_key_data_dict_element(xmlDocPtr plist, xmlNode *dict, const char *key, const char *value, int depth);
xmlNode *add_child_to_plist(xmlDocPtr plist, const char *name, const char *content, xmlNode *to_node, int depth); xmlNode *add_child_to_plist(xmlDocPtr plist, const char *name, const char *content, xmlNode *to_node, int depth);
......
...@@ -24,9 +24,16 @@ ...@@ -24,9 +24,16 @@
#include <string.h> #include <string.h>
#include "userpref.h" #include "userpref.h"
#define LIBIPHONE_CONF_DIR "libiphone" #define LIBIPHONE_CONF_DIR "libiphone"
#define LIBIPHONE_CONF_FILE "libiphonerc" #define LIBIPHONE_CONF_FILE "libiphonerc"
#define LIBIPHONE_ROOT_PRIVKEY "RootPrivateKey.pem"
#define LIBIPHONE_HOST_PRIVKEY "HostPrivateKey.pem"
#define LIBIPHONE_ROOT_CERTIF "RootCertificate.pem"
#define LIBIPHONE_HOST_CERTIF "HostCertificate.pem"
extern int debug; extern int debug;
inline void create_config_dir() { inline void create_config_dir() {
...@@ -145,99 +152,59 @@ int store_device_public_key(char* public_key) ...@@ -145,99 +152,59 @@ int store_device_public_key(char* public_key)
return 1; return 1;
} }
int read_file_in_confdir(char* file, gnutls_datum_t* data)
char* get_root_private_key()
{ {
char* private_key = NULL; if (NULL == file || NULL == data)
return 0;
/* first get config file */
gchar* config_file = g_build_path(G_DIR_SEPARATOR_S, g_get_user_config_dir(), LIBIPHONE_CONF_DIR, LIBIPHONE_CONF_FILE, NULL);
if (g_file_test(config_file, (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_REGULAR))) {
/* now parse file to get knwon devices list */
GKeyFile* key_file = g_key_file_new ();
if( g_key_file_load_from_file (key_file, config_file, G_KEY_FILE_KEEP_COMMENTS, NULL) ) {
gchar* loc_private_key = g_key_file_get_value(key_file, "Global", "RootPrivateKey", NULL); gchar* filepath = g_build_path(G_DIR_SEPARATOR_S, g_get_user_config_dir(), LIBIPHONE_CONF_DIR, file, NULL);
if (loc_private_key) if (g_file_test(filepath, (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_REGULAR))) {
private_key = strdup((char*)loc_private_key);
g_free(loc_private_key); FILE * pFile;
} long lSize;
g_key_file_free(key_file);
pFile = fopen ( filepath , "rb" );
if (pFile==NULL)
return 0;
fseek (pFile , 0 , SEEK_END);
data->size = ftell (pFile);
rewind (pFile);
data->data = (char*)gnutls_malloc(data->size);
if (data->data == NULL)
return 0;
// copy the file into the buffer:
fread (data->data,1,data->size,pFile);
fclose (pFile);
} }
return private_key; return 1;
} }
char* get_host_private_key() int get_root_private_key(gnutls_datum_t* root_privkey)
{ {
char* private_key = NULL; return read_file_in_confdir(LIBIPHONE_ROOT_PRIVKEY, root_privkey);
/* first get config file */
gchar* config_file = g_build_path(G_DIR_SEPARATOR_S, g_get_user_config_dir(), LIBIPHONE_CONF_DIR, LIBIPHONE_CONF_FILE, NULL);
if (g_file_test(config_file, (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_REGULAR))) {
/* now parse file to get knwon devices list */
GKeyFile* key_file = g_key_file_new ();
if( g_key_file_load_from_file (key_file, config_file, G_KEY_FILE_KEEP_COMMENTS, NULL) ) {
gchar* loc_private_key = g_key_file_get_value(key_file, "Global", "HostPrivateKey", NULL);
if (loc_private_key)
private_key = strdup((char*)loc_private_key);
g_free(loc_private_key);
}
g_key_file_free(key_file);
}
return private_key;
} }
int get_host_private_key(gnutls_datum_t* host_privkey)
char* get_root_certificate()
{ {
char* cert = NULL; return read_file_in_confdir(LIBIPHONE_HOST_PRIVKEY, host_privkey);
/* first get config file */
gchar* config_file = g_build_path(G_DIR_SEPARATOR_S, g_get_user_config_dir(), LIBIPHONE_CONF_DIR, LIBIPHONE_CONF_FILE, NULL);
if (g_file_test(config_file, (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_REGULAR))) {
/* now parse file to get knwon devices list */
GKeyFile* key_file = g_key_file_new ();
if( g_key_file_load_from_file (key_file, config_file, G_KEY_FILE_KEEP_COMMENTS, NULL) ) {
gchar* loc_cert = g_key_file_get_value(key_file, "Global", "RootCertificate", NULL);
if (loc_cert)
cert = strdup((char*)loc_cert);
g_free(loc_cert);
}
g_key_file_free(key_file);
}
return cert;
} }
char* get_host_certificate() int get_root_certificate(gnutls_datum_t* root_cert)
{ {
char* cert = NULL; return read_file_in_confdir(LIBIPHONE_ROOT_CERTIF, root_cert);
}
/* first get config file */
gchar* config_file = g_build_path(G_DIR_SEPARATOR_S, g_get_user_config_dir(), LIBIPHONE_CONF_DIR, LIBIPHONE_CONF_FILE, NULL);
if (g_file_test(config_file, (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_REGULAR))) {
/* now parse file to get knwon devices list */
GKeyFile* key_file = g_key_file_new ();
if( g_key_file_load_from_file (key_file, config_file, G_KEY_FILE_KEEP_COMMENTS, NULL) ) {
gchar* loc_cert = g_key_file_get_value(key_file, "Global", "HostCertificate", NULL); int get_host_certificate(gnutls_datum_t* host_cert)
if (loc_cert) {
cert = strdup((char*)loc_cert); return read_file_in_confdir(LIBIPHONE_HOST_CERTIF, host_cert);
g_free(loc_cert);
}
g_key_file_free(key_file);
}
return cert;
} }
int init_config_file(char* host_id, char* root_private_key, char* host_private_key, char* root_cert, char* host_cert) int 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)
{ {
if (!host_id || !root_private_key || !host_private_key || !root_cert || !host_cert) if (!host_id || !root_key || !host_key || !root_cert || !host_cert)
return 0; return 0;
gchar* config_file = g_build_path(G_DIR_SEPARATOR_S, g_get_user_config_dir(), LIBIPHONE_CONF_DIR, LIBIPHONE_CONF_FILE, NULL); gchar* config_file = g_build_path(G_DIR_SEPARATOR_S, g_get_user_config_dir(), LIBIPHONE_CONF_DIR, LIBIPHONE_CONF_FILE, NULL);
...@@ -249,10 +216,6 @@ int init_config_file(char* host_id, char* root_private_key, char* host_private_k ...@@ -249,10 +216,6 @@ int init_config_file(char* host_id, char* root_private_key, char* host_private_k
/* store in config file */ /* store in config file */
g_key_file_set_value (key_file, "Global", "HostID", host_id); g_key_file_set_value (key_file, "Global", "HostID", host_id);
g_key_file_set_value (key_file, "Global", "RootPrivateKey", root_private_key);
g_key_file_set_value (key_file, "Global", "HostPrivateKey", host_private_key);
g_key_file_set_value (key_file, "Global", "RootCertificate", root_cert);
g_key_file_set_value (key_file, "Global", "HostCertificate", host_cert);
/* write config file on disk */ /* write config file on disk */
gsize length; gsize length;
...@@ -263,5 +226,28 @@ int init_config_file(char* host_id, char* root_private_key, char* host_private_k ...@@ -263,5 +226,28 @@ int init_config_file(char* host_id, char* root_private_key, char* host_private_k
g_key_file_free(key_file); g_key_file_free(key_file);
//now write keys and certifs to disk
FILE * pFile;
gchar* pem;
pem = g_build_path(G_DIR_SEPARATOR_S, g_get_user_config_dir(), LIBIPHONE_CONF_DIR, LIBIPHONE_ROOT_PRIVKEY, NULL);
pFile = fopen ( pem , "wb" );
fwrite ( root_key->data, 1 , root_key->size , pFile );
fclose (pFile);
pem = g_build_path(G_DIR_SEPARATOR_S, g_get_user_config_dir(), LIBIPHONE_CONF_DIR, LIBIPHONE_HOST_PRIVKEY, NULL);
pFile = fopen ( pem , "wb" );
fwrite ( host_key->data, 1 , host_key->size , pFile );
fclose (pFile);
pem = g_build_path(G_DIR_SEPARATOR_S, g_get_user_config_dir(), LIBIPHONE_CONF_DIR, LIBIPHONE_ROOT_CERTIF, NULL);
pFile = fopen ( pem , "wb" );
fwrite ( root_cert->data, 1 , root_cert->size , pFile );
fclose (pFile);
pem = g_build_path(G_DIR_SEPARATOR_S, g_get_user_config_dir(), LIBIPHONE_CONF_DIR, LIBIPHONE_HOST_CERTIF, NULL);
pFile = fopen ( pem , "wb" );
fwrite ( host_cert->data, 1 , host_cert->size , pFile );
fclose (pFile);
return 1; return 1;
} }
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
#ifndef USERPREF_H #ifndef USERPREF_H
#define USERPREF_H #define USERPREF_H
#include <gnutls/gnutls.h>
/** /**
* \fn char* get_host_id() * \fn char* get_host_id()
* method to get user's HostID. Caller must free returned buffer. * method to get user's HostID. Caller must free returned buffer.
...@@ -43,34 +44,34 @@ int is_device_known(char* public_key); ...@@ -43,34 +44,34 @@ int is_device_known(char* public_key);
int store_device_public_key(char* public_key); int store_device_public_key(char* public_key);
/** /**
* \fn char* get_root_private_key() * \fn int get_root_private_key(gnutls_datum_t* root_privkey)
* \return RootPrivateKey if exists. Returns NULL otherwise. * \return 1 if everything went well. Returns 0 otherwise.
*/ */
char* get_root_private_key(); int get_root_private_key(gnutls_datum_t* root_privkey);
/** /**
* \fn char* get_host_private_key() * \fn int get_host_private_key(gnutls_datum_t* host_privkey)
* \return HostPrivateKey if exists. Returns NULL otherwise. * \return 1 if everything went well. Returns 0 otherwise.
*/ */
char* get_host_private_key(); int get_host_private_key(gnutls_datum_t* host_privkey);
/** /**
* \fn char* get_root_certificate() * \fn int get_root_certificate(gnutls_datum_t* root_cert)
* \return RootCertificate if exists. Returns NULL otherwise. * \return 1 if everything went well. Returns 0 otherwise.
*/ */
char* get_root_certificate(); int get_root_certificate(gnutls_datum_t* root_cert);
/** /**
* \fn char* get_host_certificate() * \fn int get_host_certificate(gnutls_datum_t* host_cert)
* \return HostCertificate if exists. Returns NULL otherwise. * \return 1 if everything went well. Returns 0 otherwise.
*/ */
char* get_host_certificate(); int get_host_certificate(gnutls_datum_t* host_cert);
/** /**
* \fn int init_config_file(char* host_id, char* root_private_key, char* host_private_key, char* root_cert, char* host_cert) * \fn int 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)
* setup a brand new config file. * setup a brand new config file.
* \return 1 if everything went well. Returns 0 otherwise. * \return 1 if everything went well. Returns 0 otherwise.
*/ */
int init_config_file(char* host_id, char* root_private_key, char* host_private_key, char* root_cert, char* host_cert); int 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);
#endif #endif
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment