diff --git a/certexample b/certexample index adcbba2d1dfb87c18b47852663885bcac745763a..5116c853a62f66da0077a0d486d236fc868bea46 100755 Binary files a/certexample and b/certexample differ diff --git a/certexample.c b/certexample.c index 2f40704b1ca1a02a5b346b361bbf1a292ec38f8d..f638312f73429c767e5dded319a28d101de087c8 100644 --- a/certexample.c +++ b/certexample.c @@ -16,6 +16,8 @@ #include <time.h> #include <openssl/asn1_mac.h> #define DEBUG 0 +#define LINE_BUFFER 100 + 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); @@ -39,13 +41,10 @@ int validate_certificate(const char *url, X509 *cert); int find_first_instanceof(const char *str, char delim); char *str_slice_to_end(const char *str, int begin); - - - int main(int argc, char **argv){ - int LINE_BUFFER=100; char line[LINE_BUFFER]; + //open the file, create the file to write to FILE *csv_input = fopen(argv[1], "r"); FILE *csv_output = fopen("output_test.csv" ,"w"); //for each line in the csv file, process each certificate @@ -60,6 +59,7 @@ int main(int argc, char **argv){ printf("CSV LINE # %d\n", n); } + //init all the things we use to describe a certificate BIO *certificate_bio = NULL; X509 *cert = NULL; X509_NAME *cert_issuer = NULL; @@ -71,6 +71,7 @@ int main(int argc, char **argv){ //get rid of newline line[strlen(line)-1] = '\0'; + //split the csv line up into its elements char **csv_row_elements = str_split(line, ','); if(DEBUG){ @@ -84,6 +85,7 @@ int main(int argc, char **argv){ //for some reason splitting keeps mututating the original string char *unchanged_url = csv_row_elements[1]; + //open up the certificate file specifed by the line in the input csv FILE *fp = fopen(certificate_file, "r"); if (!(BIO_read_filename(certificate_bio, certificate_file))){ @@ -116,14 +118,10 @@ int main(int argc, char **argv){ fprintf(csv_output,"%s,", csv_row_elements[0]); fprintf(csv_output,"%s,", unchanged_url); + //print validation result fprintf(csv_output,"%d\n", validate_certificate(url, cert)); - // printf ("\tCOMMON NAME VALIDATION: %d\n",); - // printf ("\tMatches Subject Alternative Name Result: %d\n",); - // printf("URL: %s\n",url); - - // - // printf("URL: %s\n",url); + //this is for debugging and printing out line numbers n++; } @@ -131,23 +129,21 @@ int main(int argc, char **argv){ } char* get_basic_constraints(X509 *cert){ - + /* -returns a string that represents the certificate's basic constraint, either CA is false or true + -taken from the sample code and modified + */ X509_EXTENSION *ex = X509_get_ext(cert, X509_get_ext_by_NID(cert, NID_basic_constraints, -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); @@ -161,6 +157,9 @@ char* get_basic_constraints(X509 *cert){ return buf; } char* get_key_usage(X509 *cert){ + /* -returns a string that represents the certificate's key usage + -taken from the sample code and modified + */ X509_EXTENSION *ex = X509_get_ext(cert, X509_get_ext_by_NID(cert, NID_ext_key_usage, -1)); @@ -168,7 +167,7 @@ char* get_key_usage(X509 *cert){ char buff[1024]; OBJ_obj2txt(buff, 1024, obj, 0); - //printf("Extension: %s, ", buff); + BUF_MEM *bptr = NULL; char *buf = NULL; @@ -191,7 +190,7 @@ char* get_key_usage(X509 *cert){ return buf; } int get_public_key_length(X509 *cert){ - + /*Gets the length of the key and returns its size in bits*/ EVP_PKEY *public_key = X509_get_pubkey(cert); RSA *rsa_key = EVP_PKEY_get1_RSA(public_key); @@ -202,6 +201,7 @@ int get_public_key_length(X509 *cert){ } char* get_domain_name(X509 *cert){ + //gets the common name for this certifate and returns it as a string X509_NAME *x509_name = X509_get_subject_name(cert); char *cert_cn = X509_NAME_oneline(x509_name, 0, 0); cert_cn =(cert_cn+1); @@ -213,12 +213,13 @@ char* get_domain_name(X509 *cert){ return domain_clean[1]; } char* compare_not_before(X509 *cert){ + // gets a certificate's not before date and compares it to the current date 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"); + return "invalid"; } if (day > 0 || sec > 0){ @@ -230,9 +231,10 @@ char* compare_not_before(X509 *cert){ else{ return "Same"; } - return "invalid?"; + return "invalid"; } char* compare_not_after(X509 *cert){ + // gets a certificate's not after date and compares it to the current date int day, sec; const ASN1_TIME *not_after = X509_get_notAfter(cert); @@ -262,6 +264,7 @@ char* concat(char *s1, char *s2){ } char** str_split(const char* a_str, const char a_delim){ + //splits up string by a delimiter char** result = 0; size_t count = 0; char* tmp = (char *)a_str; @@ -300,8 +303,7 @@ char** str_split(const char* a_str, const char a_delim){ return result; } int matches_subject_alternative_name(const char *hostname, X509 *server_cert) { - - + //goes through the alternative domain names for a certifate and validates each one int i; int san_names_nb = -1; STACK_OF(GENERAL_NAME) *san_names = NULL; @@ -348,7 +350,7 @@ int matches_subject_alternative_name(const char *hostname, X509 *server_cert) { return 0; } int validate_key_usage(char* key_usage){ - + //gets the key usage as a string from the helper function above, and then validates if it is equal to "TLS Web Server Authentication"" //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)){ @@ -371,7 +373,7 @@ int validate_key_usage(char* key_usage){ } int validate_basic_constraints(char* basic_constraints){ - + //gets the basic constraint from a helper function above and then validates if it is "CA: FALSE" if(strcmp(basic_constraints, "CA:FALSE")==0){ // printf("\tBASIC CONSTRAINT PASS\n"); return 1; @@ -379,38 +381,30 @@ int validate_basic_constraints(char* basic_constraints){ return 0; } int validate_wildcard_string(const char *hostname, char*hostname_with_wildcard){ - + //compares a domain with a wildcard with a given url, the wildcard is stripped of its '*' and '.' + //the string is then compared with the url (also having all things left from the initial '.' removed) char *hostname_with_wildcard_sliced = str_slice_to_end(hostname_with_wildcard, (find_first_instanceof(hostname_with_wildcard, '.'))); char *hostname_sliced = str_slice_to_end(hostname, (find_first_instanceof(hostname, '.'))); - - - - - - - // 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_with_wildcard_sliced, hostname_sliced)==0){ - printf("\t\tWILDCARD FUNCTION\t\t%s == %s\n", hostname_with_wildcard_sliced, hostname_sliced); + + if (DEBUG){ + printf("\t\tWILDCARD FUNCTION\t\t%s == %s\n", hostname_with_wildcard_sliced, hostname_sliced); + } return 1; } - return 0; } int validate_key_length(int length){ + //validates whether or not the certifate's key is 2048 bits if (length==2048){ return 1; } return 0; } int validate_CN(const char* hostname, char*cn){ + //matches the common name with the given url, if a wildcard is present, it gives the strings to the wildcard validator if(cn[0]=='*'){ return (validate_wildcard_string(hostname, cn)); } @@ -425,6 +419,7 @@ int validate_CN(const char* hostname, char*cn){ return 0; } int validate_CN_and_SAN(const char *url, X509 *cert){ + //gets the result from both the CN and SAN validator and returns true if either are valid if(validate_CN(url, get_domain_name(cert)) || matches_subject_alternative_name(url, cert)){ return 1; @@ -432,36 +427,30 @@ int validate_CN_and_SAN(const char *url, X509 *cert){ else{return 0;} } int validate_not_before(X509 *cert){ - + //validates the not before date to be consistent with the current time if(strcmp(compare_not_before(cert), "Sooner")==0){ return 1; } return 0; } int validate_not_after(X509 *cert){ - + //validates the not after date to be consistent with the current time 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)); - + //the final validation decision, takes all of the validation results from each aspect of the certificate + //and makes sure there are no invalid components 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){ + //if any of these is invalid, the certificate is invalid + if(a & b & c & d & e & f){ return 1; } else{ @@ -469,6 +458,7 @@ int validate_certificate(const char *url, X509 *cert){ } } int find_first_instanceof(const char *str, char delim){ + //gets the first instance of a char in a string int i; for (i=0;i<=strlen(str);i++){ if(str[i]==delim){ @@ -479,7 +469,12 @@ int find_first_instanceof(const char *str, char delim){ return -1; } char *str_slice_to_end(const char *str, int begin){ - char *tmp = (char *)str; - tmp = (tmp+=begin+1); - return tmp; + //gets rid of things left of the index(inclusive) in a string + //eg str_slice_to_end("www.example.com",3) becomes example.com + + char *tmp = (char *)str; + tmp = (tmp+=begin+1); + return tmp; + + }