Commit db929337 authored by johan's avatar johan

Add self signed certificate and certificate fingerprint generation

Add parsing a directory to get all certificates in it
parent 884184c8
......@@ -135,6 +135,54 @@ BELLESIP_EXPORT belle_sip_signing_key_t* belle_sip_signing_key_parse(const char*
*/
BELLESIP_EXPORT belle_sip_certificates_chain_t* belle_sip_certificates_chain_parse_file(const char* path, belle_sip_certificate_raw_format_t format);
/**
* Parse a directory for *.pem file containing a certificate and private key in PEM format or a single DER cert with subject CNAME as given
*
* @param[in] path directory to parse
* @param[in] subject subject CNAME to look for
* @param[out] certificate result certificate, NULL if not found. Is allocated by this function, caller must do a belle_sip_object_unref on it after use
* @param[out] pkey result private key, NULL if not found. Is allocated by this function, caller must do a belle_sip_object_unref on it after use
* @param[in] format either PEM or DER
* @return 0 if we found a certificate and key matching given subject common name
*/
BELLESIP_EXPORT int belle_sip_get_certificate_and_pkey_in_dir(const char *path, const char *subject, belle_sip_certificates_chain_t **certificate, belle_sip_signing_key_t **pkey, belle_sip_certificate_raw_format_t format);
/**
* Generate a self signed certificate and key and save them in a file if a path is given, file will be <subject>.pem
*
* @param[in] path If not NULL a file will be written in the given directory. filename is <subject>.pem
* @param[in] subject used in the CN= field of issuer and subject name
* @param[out] certificate the generated certificate. Must be destroyed using belle_sip_certificates_chain_destroy
* @param[out] key the generated key. Must be destroyed using belle_sip_signing_key_destroy
* @return 0 on success
*/
BELLESIP_EXPORT int belle_sip_generate_self_signed_certificate(const char* path, const char *subject, belle_sip_certificates_chain_t **certificate, belle_sip_signing_key_t **pkey);
/**
* Convert a certificate into a its PEM format string
*
* @param[in] cert The certificate to be converted into PEM format string
* @return the PEM representation of certificate. Buffer is allocated by this function and must be freed by caller
*/
BELLESIP_EXPORT unsigned char *belle_sip_get_certificates_pem(belle_sip_certificates_chain_t *cert);
/**
* Convert a key into a its PEM format string
*
* @param[in] key The key to be converted into PEM format string
* @return the PEM representation of key. Buffer is allocated by this function and must be freed by caller
*/
BELLESIP_EXPORT unsigned char *belle_sip_get_key_pem(belle_sip_signing_key_t *key);
/**
* Generate a certificate fingerprint as described in RFC4572
* Note: only SHA1 signing algo is supported for now
*
* @param[in] certificate The certificate used to generate the fingerprint
* @return The generated fingerprint formatted according to RFC4572 section 5. Is a null terminated string, must be freed by caller
*/
BELLESIP_EXPORT unsigned char *belle_sip_generate_certificate_fingerprint(belle_sip_certificates_chain_t *certificate);
/**
* Parse a pather containing either a private or public rsa key
* @param path file
......@@ -143,9 +191,6 @@ BELLESIP_EXPORT belle_sip_certificates_chain_t* belle_sip_certificates_chain_par
*/
BELLESIP_EXPORT belle_sip_signing_key_t* belle_sip_signing_key_parse_file(const char* path, const char* passwd);
BELLESIP_EXPORT belle_tls_verify_policy_t *belle_tls_verify_policy_new(void);
BELLESIP_EXPORT int belle_tls_verify_policy_set_root_ca(belle_tls_verify_policy_t *obj, const char *path);
#define BELLE_TLS_VERIFY_CN_MISMATCH (1)
......
......@@ -1017,4 +1017,23 @@ BELLE_SIP_DECLARE_CUSTOM_VPTR_END
BELLE_SIP_DECLARE_CUSTOM_VPTR_BEGIN(belle_sip_multipart_body_handler_t,belle_sip_body_handler_t)
BELLE_SIP_DECLARE_CUSTOM_VPTR_END
/**
* file manipulation
*/
/**
* Parse a directory and return all files in it.
*
* @param[in] path The directory to be parsed
* @param[in] file_type if not NULL return only the file with the given extension, must include the '.', ex:".pem"
* @return a belle_sip list containing all found file or NULL if no file were found or directory doesn't exist. List must be destroyed using belle_sip_list_free_with_data(<ret_list>, belle_sip_free)
*/
belle_sip_list_t *belle_sip_parse_directory(const char *path, const char *file_type);
/**
* create a directory if it doesn't already exists
*
* @param[in] path The directory to be created
* @return 0 in case of succes, -1 otherwise, note it returns -1 if the directory already exists
*/
int belle_sip_mkdir(const char *path);
#endif
......@@ -19,13 +19,14 @@
#define _CRT_RAND_S
#include <stdlib.h>
#include <sys/stat.h>
#include "belle_sip_internal.h"
#include "clock_gettime.h" /*for apple*/
#ifndef WIN32
#include <sys/time.h> /*for gettimeofday*/
#include <dirent.h> /* available on POSIX system only */
#endif
static FILE *__log_file=0;
......@@ -1116,3 +1117,48 @@ char* belle_sip_display_name_to_backslashed_escaped_string(const char* buff) {
output_buff[out_buff_index]='\0';
return belle_sip_strdup(output_buff);
}
belle_sip_list_t *belle_sip_parse_directory(const char *path, const char *file_type) {
#ifdef WIN32
/* TODO: implement this function for non POSIX compiler */
return NULL;
#else /* WIN 32 */
DIR *dir;
struct dirent *ent;
belle_sip_list_t* file_list = NULL;
if ((dir = opendir(path)) != NULL) {
/* create a string containing the path, adding a final / */
char *name_with_path = (char *)belle_sip_malloc(strlen(path)+256); /* max filename is 256 bytes in dirent structure */
int path_length = strlen(path);
memcpy(name_with_path, path, strlen(path));
name_with_path[path_length] = '/';
path_length++;
/* loop on all directory files */
while ((ent = readdir (dir)) != NULL) { /* loop on all files present in the given dir */
/* filter on file type if given */
if (file_type==NULL
|| (strncmp(ent->d_name+strlen(ent->d_name)-strlen(file_type), file_type, strlen(file_type))==0) ) {
memcpy(name_with_path+path_length, ent->d_name, strlen(ent->d_name)+1); /* +1 to get the null termination */
/* append the filename to the current list */
file_list = belle_sip_list_append(file_list, belle_sip_strdup(name_with_path));
}
}
belle_sip_free(name_with_path);
closedir(dir);
return file_list;
} else { /* unable to open dir */
printf("non on l'a pas ouvert avec succes\n");
return NULL;
}
#endif /* !WIN32 */
}
int belle_sip_mkdir(const char *path) {
#ifdef WIN32
/* TODO: implement this function for non POSIX compiler */
return -1;
#else /* WIN 32 */
return mkdir(path, 0700);
#endif
}
This diff is collapsed.
......@@ -74,11 +74,74 @@ static void test_proxy_authentication(void) {
}
#define TEMPORARY_CERTIFICATE_DIR "/belle_sip_tester_crt"
static void test_generate_and_parse_certificates(void) {
/* function not available on windows yet - need to add the create and parse directory */
#ifndef WIN32
belle_sip_certificates_chain_t *certificate, *parsed_certificate;
belle_sip_signing_key_t *key, *parsed_key;
unsigned char *pem_certificate, *pem_parsed_certificate, *pem_key, *pem_parsed_key;
int ret = 0;
char *belle_sip_certificate_temporary_dir=belle_sip_malloc(strlen(belle_sip_tester_writable_dir_prefix)+strlen(TEMPORARY_CERTIFICATE_DIR)+1);
strcpy(belle_sip_certificate_temporary_dir, belle_sip_tester_writable_dir_prefix);
memcpy(belle_sip_certificate_temporary_dir+strlen(belle_sip_tester_writable_dir_prefix), TEMPORARY_CERTIFICATE_DIR, strlen(TEMPORARY_CERTIFICATE_DIR)+1);
/* create 2 certificates in ./belle_sip_crt_test directory (TODO : set the directory in a absolute path?? where?)*/
ret = belle_sip_generate_self_signed_certificate(belle_sip_certificate_temporary_dir, "test_certificate1", &certificate, &key);
CU_ASSERT_EQUAL_FATAL(0, ret);
ret = belle_sip_generate_self_signed_certificate(belle_sip_certificate_temporary_dir, "test_certificate2", &certificate, &key);
CU_ASSERT_EQUAL_FATAL(0, ret);
/* parse directory to get the certificate2 */
ret = belle_sip_get_certificate_and_pkey_in_dir(belle_sip_certificate_temporary_dir, "test_certificate2", &parsed_certificate, &parsed_key, BELLE_SIP_CERTIFICATE_RAW_FORMAT_PEM);
belle_sip_free(belle_sip_certificate_temporary_dir);
CU_ASSERT_EQUAL_FATAL(0, ret);
/* get pem version of generated and parsed certificate and compare them */
pem_certificate = belle_sip_get_certificates_pem(certificate);
CU_ASSERT_TRUE_FATAL(pem_certificate!=NULL);
pem_parsed_certificate = belle_sip_get_certificates_pem(parsed_certificate);
CU_ASSERT_TRUE_FATAL(pem_parsed_certificate!=NULL);
CU_ASSERT_STRING_EQUAL(pem_certificate, pem_parsed_certificate);
/* get pem version of generated and parsed key and compare them */
pem_key = belle_sip_get_key_pem(key);
CU_ASSERT_TRUE_FATAL(pem_key!=NULL);
pem_parsed_key = belle_sip_get_key_pem(parsed_key);
CU_ASSERT_TRUE_FATAL(pem_parsed_key!=NULL);
CU_ASSERT_STRING_EQUAL(pem_key, pem_parsed_key);
belle_sip_free(pem_certificate);
belle_sip_free(pem_parsed_certificate);
belle_sip_free(pem_key);
belle_sip_free(pem_parsed_key);
belle_sip_object_unref(certificate);
belle_sip_object_unref(parsed_certificate);
belle_sip_object_unref(key);
belle_sip_object_unref(parsed_key);
#endif /* WIN32 */
}
static void test_certificate_fingerprint(void) {
unsigned char *fingerprint;
/* parse certificate defined in belle_sip_register_tester.c */
belle_sip_certificates_chain_t* cert = belle_sip_certificates_chain_parse(belle_sip_tester_client_cert,strlen(belle_sip_tester_client_cert),BELLE_SIP_CERTIFICATE_RAW_FORMAT_PEM);
/* generate fingerprint */
fingerprint = belle_sip_generate_certificate_fingerprint(cert);
CU_ASSERT_STRING_EQUAL(fingerprint, belle_sip_tester_client_cert_fingerprint);
free(fingerprint);
belle_sip_object_unref(cert);
}
test_t authentication_helper_tests[] = {
{ "Proxy-Authenticate", test_proxy_authentication },
{ "WWW-Authenticate", test_authentication },
{ "WWW-Authenticate (with qop)", test_authentication_qop_auth }
{ "WWW-Authenticate (with qop)", test_authentication_qop_auth },
{ "generate and parse self signed certificates", test_generate_and_parse_certificates},
{ "generate certificate fingerprint", test_certificate_fingerprint}
};
test_suite_t authentication_helper_test_suite = {
......
......@@ -139,6 +139,9 @@ const char* belle_sip_tester_client_cert = /*for URI:sip:tester@client.example.o
"oEncRDdPOA==\n"
"-----END CERTIFICATE-----";
/* fingerprint of certificate generated using openssl x509 -fingerprint */
const char* belle_sip_tester_client_cert_fingerprint =
"SHA-1 79:2F:9E:8B:28:CC:38:53:90:1D:71:DC:8F:70:66:75:E5:34:CE:C4";
const char* belle_sip_tester_private_key =
"-----BEGIN ENCRYPTED PRIVATE KEY-----\n"
......
......@@ -22,6 +22,7 @@
#include <stdio.h>
#include "CUnit/Basic.h"
#include "CUnit/MyMem.h"
#ifdef HAVE_CU_CURSES
#include "CUnit/CUCurses.h"
#endif
......@@ -35,6 +36,12 @@ static test_suite_t **test_suite = NULL;
static int nb_test_suites = 0;
static int belle_sip_tester_use_log_file=0;
#ifdef ANDROID
const char *belle_sip_tester_writable_dir_prefix = "/data/data/org.linphone.tester/cache";
#else
const char *belle_sip_tester_writable_dir_prefix = ".";
#endif
#ifdef HAVE_CU_CURSES
static unsigned char curses = 0;
#endif
......@@ -186,8 +193,13 @@ static void test_complete_message_handler(const CU_pTest pTest,
static void test_all_tests_complete_message_handler(const CU_pFailureRecord pFailure) {
char *result_string;
if (belle_sip_tester_use_log_file) belle_sip_warning("\n\n %s",CU_get_run_results_string());
printf("\n\n %s",CU_get_run_results_string());
result_string = CU_get_run_results_string();
if (result_string != NULL) {
printf("\n\n %s",result_string);
CU_FREE(result_string);
}
}
static void test_suite_init_failure_message_handler(const CU_pSuite pSuite) {
......
......@@ -69,7 +69,9 @@ extern const char * belle_sip_tester_get_root_ca_path(void);
extern void belle_sip_tester_set_root_ca_path(const char *root_ca_path);
extern int belle_sip_tester_run_tests(const char *suite_name, const char *test_name);
extern const char *belle_sip_tester_writable_dir_prefix;
extern const char* belle_sip_tester_client_cert;
extern const char* belle_sip_tester_client_cert_fingerprint;
extern const char* belle_sip_tester_private_key;
extern const char* belle_sip_tester_private_key_passwd;
......
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