diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000000000000000000000000000000000000..e126f79bebca0fe5f0098639caf5007e428197c4
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,2 @@
+all:
+		gcc -o certcheck assignment_2.c -lssl -lcrypto
\ No newline at end of file
diff --git a/assignment_2.c b/assignment_2.c
new file mode 100644
index 0000000000000000000000000000000000000000..041055a47e45b481276320a6ad6503d76678fed0
--- /dev/null
+++ b/assignment_2.c
@@ -0,0 +1,272 @@
+/*
+Name: Jihai Fan
+Student ID: 832919
+Login name: j.fan11@student.unimelb.edu.au
+Description: validate of x509 cert against DNS name
+*/
+
+#include <openssl/x509.h>
+#include <openssl/x509v3.h>
+#include <openssl/bio.h>
+#include <openssl/pem.h>
+#include <openssl/err.h>
+#include <stdio.h>
+#include <string.h>
+#include <time.h>
+
+// get column from csv
+char* getfield(char* line, int num){
+    char* tok;
+    char *newline = strtok(line, "\n");
+    for (tok = strtok(newline, ","); tok && *tok; tok = strtok(NULL, ",")){   
+        if (!--num)
+            return tok;
+    }
+    return NULL;
+}
+
+// change the format from asn1_time to time_t
+static time_t ASN1_GetTimeT(const ASN1_TIME* time){
+    struct tm t;
+    const char* str = (const char*) time->data;
+    size_t i = 0;
+
+    memset(&t, 0, sizeof(t));
+
+    if (time->type == V_ASN1_UTCTIME) {/* two digit year YYMMDDHHMMSS*/
+        t.tm_year = (str[i++] - '0') * 10;
+        t.tm_year += (str[i++] - '0');
+        if (t.tm_year < 70)
+            t.tm_year += 100;
+    } else if (time->type == V_ASN1_GENERALIZEDTIME) {/* four digit year YYYYMMDDHHMMSS*/
+        t.tm_year = (str[i++] - '0') * 1000;
+        t.tm_year+= (str[i++] - '0') * 100;
+        t.tm_year+= (str[i++] - '0') * 10;
+        t.tm_year+= (str[i++] - '0');
+        t.tm_year -= 1900;
+    }
+    t.tm_mon  = (str[i++] - '0') * 10;
+    t.tm_mon += (str[i++] - '0') - 1; // -1 since January is 0 not 1.
+    t.tm_mday = (str[i++] - '0') * 10;
+    t.tm_mday+= (str[i++] - '0');
+    t.tm_hour = (str[i++] - '0') * 10;
+    t.tm_hour+= (str[i++] - '0');
+    t.tm_min  = (str[i++] - '0') * 10;
+    t.tm_min += (str[i++] - '0');
+    t.tm_sec  = (str[i++] - '0') * 10;
+    t.tm_sec += (str[i++] - '0');
+
+    return mktime(&t);
+}
+
+// compare ASN1_time with current time
+int cmp_current_time(const ASN1_TIME *ctm){   
+    time_t current = time(NULL);
+    time_t ct = ASN1_GetTimeT(ctm); 
+    double result = difftime(current, ct);
+    if (result < 0){
+        return 1;
+    }else{
+        return -1;
+    }
+}
+
+// validate the time of certificate
+int cmp_time(X509 *cert){
+    int i;
+    i = cmp_current_time(X509_get_notBefore(cert));
+    int j;
+    j = cmp_current_time(X509_get_notAfter(cert));
+    if (i != -1 || j != 1){ // one should before current time, and another should be after
+        return 1;
+    }
+    return 0;
+}
+
+// validate the rsa key length
+int cmp_rsa_length(X509 *cert){
+    EVP_PKEY *public_key = X509_get_pubkey(cert);
+    RSA *rsa_key = EVP_PKEY_get1_RSA(public_key);
+    int key_length = BN_num_bits(rsa_key->n);
+    if (key_length < 2048){
+        RSA_free(rsa_key);
+        return 1;
+    }
+    RSA_free(rsa_key);
+    return 0;
+}
+
+// validate common name
+int cmp_cn(X509 *cert, char *url){
+    X509_NAME *cert_issuer = X509_get_subject_name(cert);
+    char common_name[256] = "Issuer CN NOT FOUND";
+    X509_NAME_get_text_by_NID(cert_issuer, NID_commonName, common_name, 256);
+
+    /**
+     * compare from the back of dns_name
+     *        *.test.com
+     *      www.test.com 
+     *        |---------|
+     */
+    int url_len = strlen(url);
+    int cn_len = strlen(common_name);
+    if (cn_len > url_len){
+        return 1;
+    }
+    int wildcard = 1;
+    int result = strcmp(&common_name[wildcard], &url[url_len - cn_len + wildcard]);
+    if (result != 0){
+        return 1;
+    } 
+    free(cert_issuer);
+    return result;
+}
+
+// validate CA
+int cmp_ca(X509 *cert){
+    BASIC_CONSTRAINTS *bc = X509_get_ext_d2i(cert, NID_basic_constraints, NULL, NULL);
+    if (bc->ca != 0){
+        free(bc);
+        return 1;
+    }
+    free(bc);
+    return 0;
+}
+
+// validate Enhenced Key Usage
+int cmp_key_usage(X509 *cert){
+    EXTENDED_KEY_USAGE *usage = X509_get_ext_d2i(cert, NID_ext_key_usage, NULL, NULL);
+    if(usage){
+        for(int i = 0; i < sk_BIO_num(usage); i++){
+            int result = OBJ_obj2nid(sk_ASN1_OBJECT_value(usage,i)); // get the nid of the EKU in the stack
+            if (result == NID_server_auth){ // NID_server_auth is the ID for TLS web server
+                free(usage);
+                return 0;
+            }
+        }  
+    }
+    free(usage);
+    return 1;
+}
+
+// validate subject alternative name 
+int cmp_san(X509 *cert, char *url){
+    int san_names_nb = -1;
+    int result = 0;
+	STACK_OF(GENERAL_NAME) *san_names = NULL;
+
+	// try to get SAN
+	san_names = X509_get_ext_d2i(cert, NID_subject_alt_name, NULL, NULL);
+	if (san_names == NULL) {
+		return 1;
+	}
+
+    // length of the stack
+	san_names_nb = sk_GENERAL_NAME_num(san_names);
+
+	// check each name within the extension
+	for (int i=0; i<san_names_nb; i++) {
+		const GENERAL_NAME *current_name = sk_GENERAL_NAME_value(san_names, i);
+
+        // make sure it is a dns name
+		if (current_name->type == GEN_DNS) {
+			char *dns_name = (char *) ASN1_STRING_data(current_name->d.dNSName);
+            // printf("san is: %s", dns_name);
+            int url_len = strlen(url);
+            int dns_len = strlen(dns_name);
+            if (dns_len > url_len){
+                return 1;
+            }
+            int wildcard = 1;
+            if(strcmp(&dns_name[wildcard], &url[url_len - dns_len + wildcard]) == 0){
+                return 0;
+            }
+		}
+	}
+	sk_GENERAL_NAME_pop_free(san_names, GENERAL_NAME_free);
+
+    return 1;
+}
+
+int validate_url(X509 *cert, char *url){
+    int time_result = cmp_time(cert);
+    int cn_result = cmp_cn(cert, &url);
+    int rsa_result = cmp_rsa_length(cert);
+    int ca_result = cmp_ca(cert);
+    int eku_result = cmp_key_usage(cert);
+    int san_result = cmp_san(cert, &url);
+    // printf("%i\n",time_result);
+    // printf("%i\n",cn_result);
+    // printf("%i\n",rsa_result);
+    // printf("%i\n",ca_result);
+    // printf("%i\n",eku_result);
+    // printf("%i\n",san_result);
+    int result;
+    // only one fo SAN and CN should be 
+    if (cn_result == 0){
+        result = time_result + rsa_result + ca_result + eku_result;
+    } else {
+        result = time_result + rsa_result + ca_result + eku_result + san_result;
+    }
+    if (result != 0){
+        return 0;
+    }
+    return 1;
+}
+
+int read_and_validate(const char *test_cert_example, const char *url){
+    // const char test_cert_example[] = "cert-file2.pem";
+    BIO *certificate_bio = NULL;
+    X509 *cert = NULL;
+    X509_NAME *cert_issuer = NULL;
+    X509_CINF *cert_inf = NULL;
+    STACK_OF(X509_EXTENSION) * ext_list;
+
+    // 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());
+
+    // read certificate into BIO
+    if (!(BIO_read_filename(certificate_bio, test_cert_example)))
+    {
+        fprintf(stderr, "Error in reading cert BIO filename");
+        exit(EXIT_FAILURE);
+    }
+    if (!(cert = PEM_read_bio_X509(certificate_bio, NULL, 0, NULL)))
+    {
+        fprintf(stderr, "Error in loading certificate");
+        exit(EXIT_FAILURE);
+    }
+
+    // get the result
+    int result = validate_url(cert, url);
+    
+    X509_free(cert);
+    BIO_free_all(certificate_bio);
+    return result;
+}
+
+int main(int argv, char** argc)
+{   
+    
+    FILE* stream = fopen(argc[1], "r");
+    FILE* output = fopen("output.csv", "w+");
+    char line[1024];
+    while (fgets(line, 1024, stream))
+    {   
+        char* tmp = strdup(line);
+        char* url = getfield(tmp, 2);
+        char* cert = getfield(tmp, 1);
+        int result = read_and_validate(cert, url);
+        printf("%s\n",url);
+        fprintf(output, "%s,%s,%i\n", cert, url, result);
+        // NOTE strtok clobbers tmp
+        free(tmp);
+    }
+
+    exit(0);
+}
\ No newline at end of file