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

initial commit

parent c2a63b88
Branches
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 @@ ...@@ -3,70 +3,173 @@
gcc -o certexample certexample.c -lssl -lcrypto gcc -o certexample certexample.c -lssl -lcrypto
*/ */
#include <openssl/x509.h> #include <openssl/x509.h>
#include <openssl/asn1.h>
#include <openssl/crypto.h>
#include <openssl/asn1t.h>
#include <openssl/x509v3.h> #include <openssl/x509v3.h>
#include <openssl/bio.h> #include <openssl/bio.h>
#include <openssl/pem.h> #include <openssl/pem.h>
#include <openssl/err.h> #include <openssl/err.h>
#include <stdio.h> #include <stdio.h>
#include <string.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; BIO *certificate_bio = NULL;
X509 *cert = NULL; X509 *cert = NULL;
X509_NAME *cert_issuer = NULL; X509_NAME *cert_issuer = NULL;
X509_CINF *cert_inf = NULL; X509_CINF *cert_inf = NULL;
STACK_OF(X509_EXTENSION) * ext_list; 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 char **csv_row_elements = str_split(line, ',');
certificate_bio = BIO_new(BIO_s_file());
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 const char *url = csv_row_elements[1];
if (!(BIO_read_filename(certificate_bio, test_cert_example))) //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"); fprintf(stderr, "Error in reading cert BIO filename");
exit(EXIT_FAILURE); 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"); fprintf(stderr, "Error in loading certificate");
exit(EXIT_FAILURE); 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"; exit(0);
X509_NAME_get_text_by_NID(cert_issuer, NID_commonName, issuer_cn, 256); }
printf("Issuer CommonName:%s\n", issuer_cn); 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); ASN1_OBJECT *obj = X509_EXTENSION_get_object(ex);
char buff[1024]; char buff[1024];
OBJ_obj2txt(buff, 1024, obj, 0); OBJ_obj2txt(buff, 1024, obj, 0);
printf("Extension:%s\n", buff); //printf("Extension: %s, ", buff);
BUF_MEM *bptr = NULL; BUF_MEM *bptr = NULL;
char *buf = NULL; char *buf = NULL;
BIO *bio = BIO_new(BIO_s_mem()); BIO *bio = BIO_new(BIO_s_mem());
if (!X509V3_EXT_print(bio, ex, 0, 0))
{ X509V3_EXT_print(bio, ex, 0, 0);
fprintf(stderr, "Error in reading extensions");
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_flush(bio);
BIO_get_mem_ptr(bio, &bptr); BIO_get_mem_ptr(bio, &bptr);
...@@ -76,15 +179,273 @@ int main() ...@@ -76,15 +179,273 @@ int main()
buf[bptr->length] = '\0'; buf[bptr->length] = '\0';
//Can print or parse value //Can print or parse value
printf("%s\n", buf);
//********************* return buf;
// End of Example code }
//********************* int get_public_key_length(X509 *cert){
X509_free(cert); EVP_PKEY *public_key = X509_get_pubkey(cert);
BIO_free_all(certificate_bio);
BIO_free_all(bio); RSA *rsa_key = EVP_PKEY_get1_RSA(public_key);
free(buf);
exit(0); 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