Yaip is now able to generate simple SSL certificates for a given host. I don't currently add any extensions to the certificates (such as alternative names). When I get to testing it with a browser I'll see what browsers require. However, I think I'll probably generate certificates for each host, including sub domains, to make life easier searching. I've also added a util function to count lines in a file that was used for testing some of the ssl functions.master
parent
bb62ed3b1f
commit
1beca38af6
9 changed files with 375 additions and 30 deletions
@ -1,19 +1,35 @@ |
|||||||
#ifndef SSL_H |
#ifndef SSL_H |
||||||
#define SSL_H |
#define SSL_H |
||||||
|
|
||||||
|
#include <openssl/ossl_typ.h> |
||||||
#include <openssl/ssl.h> |
#include <openssl/ssl.h> |
||||||
#include <openssl/err.h> |
#include <openssl/err.h> |
||||||
#include <openssl/x509.h> |
#include <openssl/x509.h> |
||||||
#include <openssl/pem.h> |
#include <openssl/pem.h> |
||||||
|
#include <stdlib.h> |
||||||
|
|
||||||
#include "config.h" |
#include "config.h" |
||||||
|
|
||||||
|
typedef struct CertList CertList; |
||||||
|
struct CertList { |
||||||
|
char *host; |
||||||
|
EVP_PKEY *key; |
||||||
|
X509 *cert; |
||||||
|
CertList *next; |
||||||
|
}; |
||||||
|
|
||||||
SSL_CTX* InitServerCTX(Config *config); |
SSL_CTX* InitServerCTX(Config *config); |
||||||
|
|
||||||
EVP_PKEY* generate_ca_key(); |
EVP_PKEY* generate_ca_key(); |
||||||
X509* generate_ca_cert(EVP_PKEY * pkey); |
X509* generate_ca_cert(EVP_PKEY * pkey); |
||||||
|
X509* generate_site_cert( EVP_PKEY *pkey, X509 *caCert, char *host ); |
||||||
bool create_and_save_key(char keyfile[]); |
bool create_and_save_key(char keyfile[]); |
||||||
bool create_and_save_cert(char keyfile[], EVP_PKEY *pkey); |
bool create_and_save_cert(char keyfile[], EVP_PKEY *pkey); |
||||||
EVP_PKEY* read_private_key(char keyfile[]); |
EVP_PKEY* read_private_key(char keyfile[]); |
||||||
|
|
||||||
|
CertList *newCertListItem(char *host, EVP_PKEY *key, X509 *cert); |
||||||
|
CertList *getLastCertListItem(CertList *item); |
||||||
|
unsigned int countCertListItems(CertList *item); |
||||||
|
CertList *findCertListItem( CertList *first, char *hostname ); |
||||||
|
|
||||||
#endif /* ifndef SSL_ */ |
#endif /* ifndef SSL_ */ |
||||||
|
@ -0,0 +1,206 @@ |
|||||||
|
#ifndef SSL_TEST |
||||||
|
#define SSL_TEST |
||||||
|
|
||||||
|
#include "munit/munit.h" |
||||||
|
#include "../src/ssl.h" |
||||||
|
#include "../src/util.h" |
||||||
|
|
||||||
|
|
||||||
|
MunitResult testNewRsaKeySave(const MunitParameter params[], |
||||||
|
void* user_data_or_fixture){ |
||||||
|
char keyFile[] = "/tmp/yaip-test-keyfile"; |
||||||
|
create_and_save_key( keyFile ); |
||||||
|
//TODO: make better tests.
|
||||||
|
// For now checking there is at least 3 lines seems ok
|
||||||
|
munit_assert_int( 3, <, countLines(keyFile) ); |
||||||
|
remove(keyFile); |
||||||
|
|
||||||
|
return MUNIT_OK; |
||||||
|
} |
||||||
|
|
||||||
|
MunitResult testNewCACertificate(const MunitParameter params[], |
||||||
|
void* user_data_or_fixture){ |
||||||
|
EVP_PKEY *key = generate_ca_key(); |
||||||
|
const char *nameEntry =munit_parameters_get(params, "Name Entry" ); |
||||||
|
|
||||||
|
X509 *x509 = generate_ca_cert(key); |
||||||
|
munit_assert_not_null( x509 ); |
||||||
|
|
||||||
|
X509_NAME *name = X509_get_subject_name(x509); |
||||||
|
munit_assert_not_null( name ); |
||||||
|
|
||||||
|
char buff[200] = {'\0'}; |
||||||
|
|
||||||
|
if ( strcmp( nameEntry, "C" ) == 0 ){ |
||||||
|
X509_NAME_get_text_by_NID( name, NID_countryName, buff, 200 ); |
||||||
|
munit_assert_string_equal( buff, "UK"); |
||||||
|
} else if ( strcmp( nameEntry, "O" ) == 0 ){ |
||||||
|
X509_NAME_get_text_by_NID( name, NID_organizationName, buff, 200 ); |
||||||
|
munit_assert_string_equal( buff, "Yet Another Intercepting Proxy"); |
||||||
|
} else if ( strcmp( nameEntry, "CN" ) == 0 ){ |
||||||
|
X509_NAME_get_text_by_NID( name, NID_commonName, buff, 200 ); |
||||||
|
munit_assert_string_equal( buff, "yaip.yaip"); |
||||||
|
} |
||||||
|
|
||||||
|
return MUNIT_OK; |
||||||
|
} |
||||||
|
|
||||||
|
MunitResult testNewCertificateSave(const MunitParameter params[], |
||||||
|
void* user_data_or_fixture){ |
||||||
|
char certFile[] = "/tmp/yaip-test-certfile"; |
||||||
|
EVP_PKEY *key = generate_ca_key(); |
||||||
|
create_and_save_cert( certFile, key ); |
||||||
|
//TODO: make better tests.
|
||||||
|
// For now checking there is at least 3 lines seems ok
|
||||||
|
munit_assert_int( 3, <, countLines(certFile) ); |
||||||
|
remove( certFile ); |
||||||
|
|
||||||
|
return MUNIT_OK; |
||||||
|
} |
||||||
|
|
||||||
|
MunitResult testCerlistCount(const MunitParameter params[], |
||||||
|
void* user_data_or_fixture){ |
||||||
|
CertList *head = NULL; |
||||||
|
CertList *last = head; |
||||||
|
|
||||||
|
unsigned int count = atoi(munit_parameters_get(params, "Count" )); |
||||||
|
for ( unsigned int i = 0; i < count; i++ ){ |
||||||
|
CertList *newItem = malloc(sizeof( CertList )); |
||||||
|
newItem->next = NULL; |
||||||
|
if ( head == NULL ){ |
||||||
|
head = newItem; |
||||||
|
last = newItem; |
||||||
|
} else { |
||||||
|
last->next = newItem; |
||||||
|
last = last->next; |
||||||
|
} |
||||||
|
} |
||||||
|
munit_assert_int( countCertListItems(head), ==, count ); |
||||||
|
|
||||||
|
return MUNIT_OK; |
||||||
|
} |
||||||
|
|
||||||
|
MunitResult testCerlistLast(const MunitParameter params[], |
||||||
|
void* user_data_or_fixture){ |
||||||
|
|
||||||
|
const char *countstr = munit_parameters_get(params, "Count" ); |
||||||
|
//const char *countstr = "2";
|
||||||
|
const unsigned int count = atoi(countstr); |
||||||
|
|
||||||
|
CertList *head = NULL; |
||||||
|
CertList *last = head; |
||||||
|
|
||||||
|
for ( unsigned int i = 0; i < count; i++ ){ |
||||||
|
CertList *newItem = malloc(sizeof( CertList )); |
||||||
|
char str[5] = {'\0'}; |
||||||
|
sprintf(str, "%d", i+1); |
||||||
|
newItem->next = NULL; |
||||||
|
newItem->host = strdup(str); |
||||||
|
if ( head == NULL ){ |
||||||
|
head = newItem; |
||||||
|
last = newItem; |
||||||
|
} else { |
||||||
|
last->next = newItem; |
||||||
|
last = last->next; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
CertList *lastCert = getLastCertListItem(head); |
||||||
|
if ( count == 0 ){ |
||||||
|
munit_assert_null( lastCert ); |
||||||
|
} else { |
||||||
|
munit_assert_int( countCertListItems(head), ==, count ); |
||||||
|
munit_assert_string_equal( countstr, lastCert->host ); |
||||||
|
} |
||||||
|
return MUNIT_OK; |
||||||
|
} |
||||||
|
|
||||||
|
MunitResult testNewHostCertificate(const MunitParameter params[], |
||||||
|
void* user_data_or_fixture){ |
||||||
|
|
||||||
|
EVP_PKEY *key = generate_ca_key(); |
||||||
|
X509 *x509 = generate_ca_cert(key); |
||||||
|
X509 *siteCert = generate_site_cert( key, x509, "example.com" ); |
||||||
|
const char *nameType = munit_parameters_get(params, "Name" ); |
||||||
|
X509_NAME *name; |
||||||
|
|
||||||
|
char buff[200] = {'\0'}; |
||||||
|
|
||||||
|
if ( strcmp( nameType, "subject" ) ){ |
||||||
|
name = X509_get_subject_name(siteCert); |
||||||
|
X509_NAME_get_text_by_NID( name, NID_commonName, buff, 200 ); |
||||||
|
munit_assert_string_equal( buff, "example.com" ); |
||||||
|
} else if ( strcmp( nameType, "issuer" ) ){ |
||||||
|
name = X509_get_issuer_name(siteCert); |
||||||
|
X509_NAME_get_text_by_NID( name, NID_commonName, buff, 200 ); |
||||||
|
munit_assert_string_equal( buff, "yaip.yaip" ); |
||||||
|
} else { |
||||||
|
return MUNIT_ERROR; |
||||||
|
} |
||||||
|
//FILE * pkey_file = fopen("examplecert.pem", "wb");
|
||||||
|
//// Write the cert to disk.
|
||||||
|
//PEM_write_X509( pkey_file, siteCert );
|
||||||
|
//fclose(pkey_file);
|
||||||
|
|
||||||
|
return MUNIT_OK; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
static char* count_parameters[] = { |
||||||
|
"0", "1", "2", "10", "50", NULL |
||||||
|
}; |
||||||
|
|
||||||
|
static char* x509_name_parameters[] = { |
||||||
|
"C", "O", "CN", NULL |
||||||
|
}; |
||||||
|
|
||||||
|
static char* x509_issuer_subject_parameters[] = { |
||||||
|
"issuer", "subject", NULL |
||||||
|
}; |
||||||
|
|
||||||
|
static MunitParameterEnum count_params[] = { |
||||||
|
{ "Count", count_parameters }, |
||||||
|
{ NULL, NULL }, |
||||||
|
}; |
||||||
|
|
||||||
|
static MunitParameterEnum x509_name_params[] = { |
||||||
|
{ "Name Entry", x509_name_parameters }, |
||||||
|
{ NULL, NULL }, |
||||||
|
}; |
||||||
|
|
||||||
|
static MunitParameterEnum x509_issuer_subject_params[] = { |
||||||
|
{ "Name", x509_issuer_subject_parameters }, |
||||||
|
{ NULL, NULL }, |
||||||
|
}; |
||||||
|
|
||||||
|
static MunitTest ssl_tests[] = { |
||||||
|
// name test setup tear_down options parameters
|
||||||
|
{ "/ca/rsa_key/save", testNewRsaKeySave, NULL, NULL, MUNIT_TEST_OPTION_NONE, NULL }, |
||||||
|
{ "/ca/cert/new", testNewCACertificate, NULL, NULL, MUNIT_TEST_OPTION_NONE, x509_name_params }, |
||||||
|
{ "/ca/cert/save", testNewCertificateSave, NULL, NULL, MUNIT_TEST_OPTION_NONE, NULL }, |
||||||
|
{ "/CertList/count", testCerlistCount, NULL, NULL, MUNIT_TEST_OPTION_NONE, count_params }, |
||||||
|
{ "/CertList/last", testCerlistLast, NULL, NULL, MUNIT_TEST_OPTION_NONE, count_params }, |
||||||
|
{ "/hostcert/new", testNewHostCertificate, NULL, NULL, MUNIT_TEST_OPTION_NONE, x509_issuer_subject_params }, |
||||||
|
/* Mark the end of the array with an entry where the test
|
||||||
|
* function is NULL */ |
||||||
|
{ NULL, NULL, NULL, NULL, MUNIT_TEST_OPTION_NONE, NULL } |
||||||
|
}; |
||||||
|
|
||||||
|
MunitSuite ssl_test_suite = { |
||||||
|
"/ssl", /* name */ |
||||||
|
ssl_tests, /* tests */ |
||||||
|
NULL, /* suites */ |
||||||
|
1, /* iterations */ |
||||||
|
MUNIT_SUITE_OPTION_NONE /* options */ |
||||||
|
}; |
||||||
|
|
||||||
|
#ifndef MAINTEST |
||||||
|
#define MAINTEST |
||||||
|
|
||||||
|
int main (int argc, char* argv[]) { |
||||||
|
return munit_suite_main(&ssl_test_suite, NULL, argc, argv); |
||||||
|
} |
||||||
|
|
||||||
|
#endif /* ifndef MAINTEST */ |
||||||
|
|
||||||
|
#endif |
Loading…
Reference in new issue