Yet Another Intercepting Proxy
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

180 lines
4.7 KiB

#include "ssl.h"
SSL_CTX* InitServerCTX(Config *config) {
const SSL_METHOD *method;
SSL_CTX *ctx;
OpenSSL_add_all_algorithms(); /* load & register all cryptos, etc. */
SSL_load_error_strings(); /* load all error messages */
method = TLS_server_method(); /* create new server-method instance */
ctx = SSL_CTX_new(method); /* create new context from method */
if ( ctx == NULL ) {
ERR_print_errors_fp(stderr);
abort();
}
//set the local certificate from CertFile
if ( SSL_CTX_use_certificate_file(ctx, config->certfile, SSL_FILETYPE_PEM) <= 0 ){
ERR_print_errors_fp(stderr);
abort();
}
//set the private key from KeyFile (may be the same as CertFile)
if ( SSL_CTX_use_PrivateKey_file(ctx, config->keyfile, SSL_FILETYPE_PEM) <= 0 ){
ERR_print_errors_fp(stderr);
abort();
}
//verify private key
if ( !SSL_CTX_check_private_key(ctx) )
{
fprintf(stderr, "Private key does not match the public certificate\n");
abort();
}
return ctx;
}
// Generates a 2048-bit RSA key.
// Largely stolen from here: https://gist.github.com/nathan-osman/5041136
EVP_PKEY* generate_ca_key() {
// Allocate memory for the EVP_PKEY structure.
EVP_PKEY *pkey = EVP_PKEY_new();
if(!pkey) {
perror("Unable to create EVP_PKEY structure.\n");
return NULL;
}
// Generate the RSA key and assign it to pkey.
RSA *rsa = RSA_new();
BIGNUM *bn = BN_new();
BN_set_word(bn, RSA_F4);
RSA_generate_key_ex(rsa, 2048, bn, NULL );
if(!EVP_PKEY_assign_RSA(pkey, rsa)) {
perror("Unable to generate 2048-bit RSA key.\n");
EVP_PKEY_free(pkey);
return NULL;
}
// The key has been generated, return it.
return pkey;
}
// Generates a self-signed x509 certificate.
// Largely stolen from here: https://gist.github.com/nathan-osman/5041136
X509* generate_ca_cert(EVP_PKEY * pkey) {
// Allocate memory for the X509 structure.
X509 *x509 = X509_new();
if(!x509) {
perror( "Unable to create X509 structure.\n");
return NULL;
}
// Set the serial number.
ASN1_INTEGER_set(X509_get_serialNumber(x509), 1);
// This certificate is valid from now until exactly one year from now.
X509_gmtime_adj(X509_get_notBefore(x509), 0);
X509_gmtime_adj(X509_get_notAfter(x509), 31536000L);
// Set the public key for our certificate.
X509_set_pubkey(x509, pkey);
// We want to copy the subject name to the issuer name.
X509_NAME *name = X509_get_subject_name(x509);
// Set the country code and common name.
X509_NAME_add_entry_by_txt(name, "C", MBSTRING_ASC, (unsigned char *)"UK", -1, -1, 0);
X509_NAME_add_entry_by_txt(name, "O", MBSTRING_ASC, (unsigned char *)"Yet Another Intercepting Proxy", -1, -1, 0);
X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_ASC, (unsigned char *)"jn.hn", -1, -1, 0);
// Now set the issuer name.
X509_set_issuer_name(x509, name);
// TODO: mitmproxy adds some extensions. I don' tknow if I need those
// https://github.com/mitmproxy/mitmproxy/blob/3cb89069b9f70c198cc89337bd5a9b1bbf3a69d0/mitmproxy/certs.py#L190-L204
// Actually sign the certificate with our key.
if(!X509_sign(x509, pkey, EVP_sha1()))
{
perror( "Error signing certificate.\n");
X509_free(x509);
return NULL;
}
return x509;
}
bool create_and_save_key(char keyfile[]) {
// Generate the key
EVP_PKEY *pkey = generate_ca_key();
if ( pkey == NULL ){
fprintf(stderr, "Unable to open generate key\n");
return false;
}
// Open the PEM file for writing the key to disk.
FILE * pkey_file = fopen(keyfile, "wb");
if(!pkey_file) {
fprintf(stderr, "Unable to open \"%s\" for writing.\n", keyfile);
return false;
}
// Write the key to disk.
bool ret = PEM_write_PrivateKey(pkey_file, pkey, NULL, NULL, 0, NULL, NULL);
fclose(pkey_file);
if(!ret) {
perror("Unable to write private key to disk.\n");
return false;
}
return true;
}
EVP_PKEY* read_private_key(char keyfile[]){
FILE *fp;
EVP_PKEY *pkey;
if (! (fp = fopen(keyfile, "r"))){
perror("Error cant open certificate private key file.\n");
return NULL;
}
pkey = PEM_read_PrivateKey( fp, NULL, NULL, NULL );
if ( pkey == NULL ){
perror("Error cant read certificate private key file.\n");
}
return pkey;
}
bool create_and_save_cert(char certfile[], EVP_PKEY *pkey) {
// Open the PEM file for writing the certificate to disk.
FILE * x509_file = fopen(certfile, "wb");
if(!x509_file) {
fprintf(stderr, "Unable to open \"%s\" for writing.\n", certfile);
return false;
}
X509 *x509 = generate_ca_cert(pkey);
if ( x509 == NULL ){
fprintf(stderr, "Unable to open generate cert\n");
return false;
}
// Write the certificate to disk.
int ret = PEM_write_X509(x509_file, x509);
fclose(x509_file);
if(!ret) {
perror("Unable to write certificate to disk.\n");
return false;
}
return true;
}