Skip to content
Snippets Groups Projects
Commit 34afae28 authored by drkleena's avatar drkleena
Browse files

initial commit

parent c2a63b88
No related branches found
No related tags found
No related merge requests found
{
"transport": "scp",
"uploadOnSave": true,
"useAtomicWrites": true,
"deleteLocal": false,
"hostname": "ubuntu@115.146.95.37",
"ignore": [
".remote-sync.json",
".git/**"
],
"watch": [],
"keyfile": "~/Desktop/private.txt",
"passphrase": "j0nas13"
}
\ No newline at end of file
File added
......@@ -3,70 +3,173 @@
gcc -o certexample certexample.c -lssl -lcrypto
*/
#include <openssl/x509.h>
#include <openssl/asn1.h>
#include <openssl/crypto.h>
#include <openssl/asn1t.h>
#include <openssl/x509v3.h>
#include <openssl/bio.h>
#include <openssl/pem.h>
#include <openssl/err.h>
#include <stdio.h>
#include <string.h>
#include <assert.h>
#include <time.h>
#include <openssl/asn1_mac.h>
int main()
{
const ASN1_TIME *X509_get0_notBefore(const X509 *x);
char** str_split(const char* a_str, const char a_delim);
char* concat(char *s1, char *s2);
char* get_basic_constraints(X509 *cert);
char* get_key_usage(X509 *cert);
char* compare_not_before(X509 *cert);
char* compare_not_after(X509 *cert);
char* get_SAN(X509 *cert);
char *get_domain_name(X509 *cert);
int matches_subject_alternative_name(const char *hostname, X509 *server_cert);
int get_public_key_length(X509 *cert);
int validate_basic_constraints(char* basic_constraints);
int validate_key_usage(char* key_usage);
int validate_key_length(int length);
int validate_CN(const char* hostname, char*cn);
int validate_wildcard_string(const char *hostname, char*hostname_with_wildcard);
int validate_CN_and_SAN(const char *url, X509 *cert);
int validate_not_before(X509 *cert);
int validate_not_after(X509 *cert);
int validate_certificate(const char *url, X509 *cert);
const char test_cert_example[] = "./cert-file2.pem";
int main(int argc, char **argv){
int LINE_BUFFER=100;
char line[LINE_BUFFER];
FILE *csv_input = fopen(concat("./sample_certs/",argv[1]), "r");
FILE *csv_output = fopen("output_test.csv" ,"w");
//for each line in the csv file, process each certificate
OpenSSL_add_all_algorithms();
ERR_load_BIO_strings();
ERR_load_crypto_strings();
int n = 0;
while (fgets(line, LINE_BUFFER, csv_input) != NULL){
printf("CSV LINE # %d\n", n);
BIO *certificate_bio = NULL;
X509 *cert = NULL;
X509_NAME *cert_issuer = NULL;
X509_CINF *cert_inf = NULL;
STACK_OF(X509_EXTENSION) * ext_list;
certificate_bio = BIO_new(BIO_s_file());
//here we are able to access each line
line[strlen(line)-1] = '\0';
//initialise openSSL
OpenSSL_add_all_algorithms();
ERR_load_BIO_strings();
ERR_load_crypto_strings();
//create BIO object to read certificate
certificate_bio = BIO_new(BIO_s_file());
char **csv_row_elements = str_split(line, ',');
printf("\tFILE: %s\n",csv_row_elements[0]);
printf("\tURL: %s\n",csv_row_elements[1]);
char *certificate_file = concat("./sample_certs/", csv_row_elements[0]);
//Read certificate into BIO
if (!(BIO_read_filename(certificate_bio, test_cert_example)))
{
const char *url = csv_row_elements[1];
//for some reason splitting keeps mututating the original string
char *unchanged_url = csv_row_elements[1];
FILE *fp = fopen(certificate_file, "r");
if (!(BIO_read_filename(certificate_bio, certificate_file))){
fprintf(stderr, "Error in reading cert BIO filename");
exit(EXIT_FAILURE);
}
if (!(cert = PEM_read_bio_X509(certificate_bio, NULL, 0, NULL)))
{
//load certiifcate
if (!(cert = PEM_read_bio_X509(certificate_bio, NULL, 0, NULL))){
fprintf(stderr, "Error in loading certificate");
exit(EXIT_FAILURE);
}
// printf ("\tBASIC CONSTRAINT: %s\n",get_basic_constraints(cert));
// printf ("\tBASIC CONSTRAINT VALIDATION: %d\n",validate_basic_constraints(get_basic_constraints(cert)));
//
// // printf ("\tKEY USAGE: %s\n",get_key_usage(cert));
// printf ("\tKEY USAGE VALIDATION: %d\n",validate_key_usage(get_key_usage(cert)));
//
// // printf ("\tKEY LENGTH BITS: %d\n",get_public_key_length(cert));
//
// printf ("\tKEY LENGTH VALIDATION: %d\n",validate_key_length(get_public_key_length(cert)));
//
// // printf ("\tNot Before compared to Current: %s\n",compare_not_before(cert));
// // printf ("\tNot After compared to Current: %s\n",compare_not_after(cert));
// printf("\tNOT BEFORE VALIDATION %d\n", validate_not_before(cert));
// printf("\tNOT AFTER VALIDATION %d\n", validate_not_after(cert));
// // printf ("\tCommon Name: %s\n",get_domain_name(cert));
//
// printf("\tCOMMON NAME AND SAN VALIDATION %d\n", validate_CN_and_SAN(url, cert));
// printf ("%d", 0 || 1);
// printf("FINAL VALIDATION %d\n", validate_certificate(url, cert));
// printf("\t%s\n", unchanged_url);
fprintf(csv_output,"%s,", csv_row_elements[0]);
fprintf(csv_output,"%s,", unchanged_url);
fprintf(csv_output,"%d\n", validate_certificate(url, cert));
//cert contains the x509 certificate and can be used to analyse the certificate
// printf ("\tCOMMON NAME VALIDATION: %d\n",);
// printf ("\tMatches Subject Alternative Name Result: %d\n",);
// printf("URL: %s\n",url);
//*********************
// Example code of accessing certificate values
//*********************
//
// printf("URL: %s\n",url);
n++;
cert_issuer = X509_get_issuer_name(cert);
char issuer_cn[256] = "Issuer CN NOT FOUND";
X509_NAME_get_text_by_NID(cert_issuer, NID_commonName, issuer_cn, 256);
printf("Issuer CommonName:%s\n", issuer_cn);
}
exit(0);
}
char* get_basic_constraints(X509 *cert){
X509_EXTENSION *ex = X509_get_ext(cert, X509_get_ext_by_NID(cert, NID_basic_constraints, -1));
//List of extensions available at https://www.openssl.org/docs/man1.1.0/crypto/X509_REVOKED_get0_extensions.html
//Need to check extension exists and is not null
X509_EXTENSION *ex = X509_get_ext(cert, X509_get_ext_by_NID(cert, NID_subject_key_identifier, -1));
ASN1_OBJECT *obj = X509_EXTENSION_get_object(ex);
char buff[1024];
OBJ_obj2txt(buff, 1024, obj, 0);
printf("Extension:%s\n", buff);
//printf("Extension: %s, ", buff);
BUF_MEM *bptr = NULL;
char *buf = NULL;
BIO *bio = BIO_new(BIO_s_mem());
if (!X509V3_EXT_print(bio, ex, 0, 0))
{
fprintf(stderr, "Error in reading extensions");
X509V3_EXT_print(bio, ex, 0, 0);
BIO_flush(bio);
BIO_get_mem_ptr(bio, &bptr);
//bptr->data is not NULL terminated - add null character
buf = (char *)malloc((bptr->length + 1) * sizeof(char));
memcpy(buf, bptr->data, bptr->length);
buf[bptr->length] = '\0';
BIO_flush(bio);
//Can print or parse value
return buf;
}
char* get_key_usage(X509 *cert){
X509_EXTENSION *ex = X509_get_ext(cert, X509_get_ext_by_NID(cert, NID_ext_key_usage, -1));
ASN1_OBJECT *obj = X509_EXTENSION_get_object(ex);
char buff[1024];
OBJ_obj2txt(buff, 1024, obj, 0);
//printf("Extension: %s, ", buff);
BUF_MEM *bptr = NULL;
char *buf = NULL;
BIO *bio = BIO_new(BIO_s_mem());
X509V3_EXT_print(bio, ex, 0, 0);
BIO_flush(bio);
BIO_get_mem_ptr(bio, &bptr);
......@@ -76,15 +179,273 @@ int main()
buf[bptr->length] = '\0';
//Can print or parse value
printf("%s\n", buf);
//*********************
// End of Example code
//*********************
return buf;
}
int get_public_key_length(X509 *cert){
X509_free(cert);
BIO_free_all(certificate_bio);
BIO_free_all(bio);
free(buf);
exit(0);
EVP_PKEY *public_key = X509_get_pubkey(cert);
RSA *rsa_key = EVP_PKEY_get1_RSA(public_key);
int key_length_bytes = RSA_size(rsa_key);
return (key_length_bytes*8);
}
char* get_domain_name(X509 *cert){
X509_NAME *x509_name = X509_get_subject_name(cert);
char *cert_cn = X509_NAME_oneline(x509_name, 0, 0);
cert_cn =(cert_cn+1);
char **chain = str_split(cert_cn, '/');
char *domain = chain[5];
char **domain_clean = str_split(domain, '=');
return domain_clean[1];
}
char* compare_not_before(X509 *cert){
int day, sec;
const ASN1_TIME *not_before = X509_get_notBefore(cert);
if (!ASN1_TIME_diff(&day, &sec, NULL, not_before)){
/* Invalid time format */
printf("what the fuck do now\n");
}
if (day > 0 || sec > 0){
return "Later";
}
else if (day < 0 || sec < 0){
return "Sooner";
}
else{
return "Same";
}
return "invalid?";
}
char* compare_not_after(X509 *cert){
int day, sec;
const ASN1_TIME *not_after = X509_get_notAfter(cert);
if (!ASN1_TIME_diff(&day, &sec, NULL, not_after)){
/* Invalid time format */
printf("what the fuck do now\n");
}
if (day > 0 || sec > 0){
return "Later";
}
else if (day < 0 || sec < 0){
return "Sooner";
}
else{
return "Same";
}
return "invalid?";
}
char* concat(char *s1, char *s2){
//concats two strings
char *result = malloc(strlen(s1)+strlen(s2)+1);
strcpy(result, s1);
strcat(result, s2);
return result;
}
char** str_split(const char* a_str, const char a_delim){
char** result = 0;
size_t count = 0;
char* tmp = (char *)a_str;
char* copy = (char *)a_str;
char* last_comma = 0;
char delim[2];
delim[0] = a_delim;
delim[1] = 0;
/* Count how many elements will be extracted. */
while (*tmp){
if (a_delim == *tmp){
count++;
last_comma = tmp;
}
tmp++;
}
/* Add space for trailing token. */
count += last_comma < (a_str + strlen(a_str) - 1);
/* Add space for terminating null string so caller
knows where the list of returned strings ends. */
count++;
result = malloc(sizeof(char*) * count);
if (result){
size_t idx = 0;
char* token = strtok(copy, delim);
while (token){
assert(idx < count);
*(result + idx++) = strdup(token);
token = strtok(0, delim);
}
assert(idx == count - 1);
*(result + idx) = 0;
}
return result;
}
int matches_subject_alternative_name(const char *hostname, X509 *server_cert) {
int i;
int san_names_nb = -1;
STACK_OF(GENERAL_NAME) *san_names = NULL;
// Try to extract the names within the SAN extension from the certificate
san_names = X509_get_ext_d2i(server_cert, NID_subject_alt_name, NULL, NULL);
if (san_names == NULL) {
return 0;
}
san_names_nb = sk_GENERAL_NAME_num(san_names);
// Check each name within the extension
for (i=0; i<san_names_nb; i++) {
const GENERAL_NAME *current_name = sk_GENERAL_NAME_value(san_names, i);
if (current_name->type == GEN_DNS) {
// Current name is a DNS name, let's check it
char *dns_name = (char *) ASN1_STRING_data(current_name->d.dNSName);
printf ("\t%s\n", dns_name);
// Make sure there isn't an embedded NUL character in the DNS name
if (ASN1_STRING_length(current_name->d.dNSName) != strlen(dns_name)) {
return 0;
break;
}
else { // Compare expected hostname with the DNS name
if (validate_wildcard_string(hostname, dns_name) == 1) {
return 1;
break;
}
}
}
}
sk_GENERAL_NAME_pop_free(san_names, GENERAL_NAME_free);
return 0;
}
int validate_key_usage(char* key_usage){
//key usage may be a bunch of strings, need to get first one if this is the case
if(strlen("TLS Web Server Authentication")!=strlen(key_usage)){
char **key_usage_clean = str_split(key_usage, ',');
if(strcmp(key_usage_clean[0], "TLS Web Server Authentication") == 0){
return 1;
}
return 0;
}
else{
if(strcmp(key_usage, "TLS Web Server Authentication") == 0){
return 1;
}
return 0;
}
}
int validate_basic_constraints(char* basic_constraints){
if(strcmp(basic_constraints, "CA:FALSE")==0){
// printf("\tBASIC CONSTRAINT PASS\n");
return 1;
}
return 0;
}
int validate_wildcard_string(const char *hostname, char*hostname_with_wildcard){
char **hostname_with_wildcard_split = str_split(hostname_with_wildcard, '.');
char **hostname_split = str_split(hostname, '.');
const char *hostname_with_wildcard_right = hostname_with_wildcard_split[1];
const char *hostname_split_right = hostname_split[1];
if(strcasecmp(hostname_split_right, hostname_with_wildcard_right)==0){
printf("\t\tWILDCARD FUNCTION\t\t%s == %s\n", hostname_split_right, hostname_with_wildcard_right);
return 1;
}
return 0;
}
int validate_key_length(int length){
if (length==2048){
return 1;
}
return 0;
}
int validate_CN(const char* hostname, char*cn){
if(cn[0]=='*'){
return (validate_wildcard_string(hostname, cn));
}
else{
if(strcasecmp(cn, hostname)==0){
return 1;
}
else{
return 0;
}
}
return 0;
}
int validate_CN_and_SAN(const char *url, X509 *cert){
if(validate_CN(url, get_domain_name(cert)) || matches_subject_alternative_name(url, cert)){
return 1;
}
else{return 0;}
}
int validate_not_before(X509 *cert){
if(strcmp(compare_not_before(cert), "Sooner")==0){
return 1;
}
return 0;
}
int validate_not_after(X509 *cert){
if(strcmp(compare_not_after(cert), "Later")==0){
return 1;
}
return 0;
}
int validate_certificate(const char *url, X509 *cert){
// printf ("\tBASIC CONSTRAINT VALIDATION: %d\n",validate_basic_constraints(get_basic_constraints(cert)));
// printf ("\tKEY USAGE VALIDATION: %d\n",validate_key_usage(get_key_usage(cert)));
// printf ("\tKEY LENGTH VALIDATION: %d\n",validate_key_length(get_public_key_length(cert)));
// printf("\tNOT BEFORE VALIDATION %d\n", validate_not_before(cert));
// printf("\tNOT AFTER VALIDATION %d\n", validate_not_after(cert));
// printf("\tCOMMON NAME AND SAN VALIDATION %d\n", validate_CN_and_SAN(url, cert));
int a = validate_basic_constraints(get_basic_constraints(cert));
int b = validate_key_usage(get_key_usage(cert));
int c = validate_key_length(get_public_key_length(cert));
int d = validate_not_before(cert);
int e = validate_not_after(cert);
// printf("%s\n", url);
int f = validate_CN_and_SAN(url, cert);
// & b & c & d & e & f
if(a&b & c & d & e& f){
return 1;
}
else{
return 0;
}
}
#!/bin/bash
all: certexample.c
gcc -I /usr/local/opt/openssl/include -L /usr/local/opt/openssl/lib -o certexample certexample.c -lssl -lcrypto
testone.crt,www.example.com,0
testtwo.crt,www.mydomain.com,1
testthree.crt,www.test.com,0
testfour.crt,www.oldsite.com,0
testfive.crt,www.unimelb.com,0
testsix.crt,www.codetest.com,0
testseven.crt,www.example.com,1
testeight.crt,www.comp30023.com,1
testnine.crt,www.certtest.com,1
testten.crt,www.victoria.com,1
testeleven.crt,freeca.com,0
testtwo.crt,www.example.com,0
testseven.crt,example.com,0
testeight.crt,www.comp30023.com
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment