From 72b95c0aa8be424d1af088f9696ebf3ef1e20c50 Mon Sep 17 00:00:00 2001 From: KarthikaRajendran11 Date: Sat, 12 Mar 2022 14:21:02 -0500 Subject: [PATCH 01/18] Add modified certificate DNS check --- tlscommon.c | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/tlscommon.c b/tlscommon.c index b033c6ad..a10514b2 100644 --- a/tlscommon.c +++ b/tlscommon.c @@ -626,6 +626,30 @@ static int certattr_matchip(GENERAL_NAME *gn, struct certattrmatch *match){ && !memcmp(ASN1_STRING_get0_data(gn->d.iPAddress), &match->ipaddr, l)) ? 1 : 0 ; } +static int compareWithModifiedHostname(char* certDNS, char* scriptHostName) { + int len = 0; + int len1 = 0, len2 = 0; + char* pos; + char* modifiedScriptHostName; + char *result; + char generic[] = "*"; + pos = strchr(scriptHostName, '.'); + len = strlen(pos); + modifiedScriptHostName = malloc(len + 1); + memcpy(modifiedScriptHostName, pos, len); + modifiedScriptHostName[len] = '\0'; + debug(DBG_DBG, "generic : %s", generic); + debug(DBG_DBG, "modifiedScriptHostName : %s", modifiedScriptHostName); + len1 = strlen(generic); + len2 = strlen(modifiedScriptHostName); + result = malloc(len1 + len2 + 1); + memcpy(result, generic, len1); + memcpy(result + len1, modifiedScriptHostName, len2 + 1); + if (strlen(certDNS) == strlen(result) && memcmp(result, certDNS, strlen(certDNS)) == 0) + return 1; + return 0; +} + static int _general_name_regex_match(char *v, int l, struct certattrmatch *match) { char *s; if (l <= 0 ) @@ -633,6 +657,8 @@ static int _general_name_regex_match(char *v, int l, struct certattrmatch *match if (match->exact) { if (l == strlen(match->exact) && memcmp(v, match->exact, l) == 0) return 1; + if(compareWithModifiedHostname(v, match->exact)) + return 1; return 0; } From 06d5c57833316aa3d7ca708ecc27ccc785f43c16 Mon Sep 17 00:00:00 2001 From: KarthikaRajendran11 Date: Mon, 14 Mar 2022 09:11:14 -0400 Subject: [PATCH 02/18] Remove log --- tlscommon.c | 1 - 1 file changed, 1 deletion(-) diff --git a/tlscommon.c b/tlscommon.c index a10514b2..b1bb1a62 100644 --- a/tlscommon.c +++ b/tlscommon.c @@ -638,7 +638,6 @@ static int compareWithModifiedHostname(char* certDNS, char* scriptHostName) { modifiedScriptHostName = malloc(len + 1); memcpy(modifiedScriptHostName, pos, len); modifiedScriptHostName[len] = '\0'; - debug(DBG_DBG, "generic : %s", generic); debug(DBG_DBG, "modifiedScriptHostName : %s", modifiedScriptHostName); len1 = strlen(generic); len2 = strlen(modifiedScriptHostName); From 1b6cc4f42cb1d819e3ce2acb266bbb302d67cce6 Mon Sep 17 00:00:00 2001 From: KarthikaRajendran11 Date: Mon, 14 Mar 2022 10:51:54 -0400 Subject: [PATCH 03/18] Address PR comments --- tlscommon.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/tlscommon.c b/tlscommon.c index b1bb1a62..e0936bb8 100644 --- a/tlscommon.c +++ b/tlscommon.c @@ -626,9 +626,10 @@ static int certattr_matchip(GENERAL_NAME *gn, struct certattrmatch *match){ && !memcmp(ASN1_STRING_get0_data(gn->d.iPAddress), &match->ipaddr, l)) ? 1 : 0 ; } +// Generates a generic DNS. eg: converts idp.openroaming.net to *.openroaming.net static int compareWithModifiedHostname(char* certDNS, char* scriptHostName) { int len = 0; - int len1 = 0, len2 = 0; + int lenOfGeneric = 0, lenOfModifiedScriptHostName = 0; char* pos; char* modifiedScriptHostName; char *result; @@ -639,11 +640,11 @@ static int compareWithModifiedHostname(char* certDNS, char* scriptHostName) { memcpy(modifiedScriptHostName, pos, len); modifiedScriptHostName[len] = '\0'; debug(DBG_DBG, "modifiedScriptHostName : %s", modifiedScriptHostName); - len1 = strlen(generic); - len2 = strlen(modifiedScriptHostName); - result = malloc(len1 + len2 + 1); - memcpy(result, generic, len1); - memcpy(result + len1, modifiedScriptHostName, len2 + 1); + lenOfGeneric = strlen(generic); + lenOfModifiedScriptHostName = strlen(modifiedScriptHostName); + result = malloc(lenOfGeneric + lenOfModifiedScriptHostName + 1); + memcpy(result, generic, lenOfGeneric); + memcpy(result + lenOfGeneric, modifiedScriptHostName, lenOfModifiedScriptHostName + 1); if (strlen(certDNS) == strlen(result) && memcmp(result, certDNS, strlen(certDNS)) == 0) return 1; return 0; From 0bb9d0168f6e2869ab6cd4f1a8af282a348163cb Mon Sep 17 00:00:00 2001 From: KarthikaRajendran11 Date: Mon, 14 Mar 2022 10:54:01 -0400 Subject: [PATCH 04/18] Add comment --- tlscommon.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tlscommon.c b/tlscommon.c index e0936bb8..8f774b25 100644 --- a/tlscommon.c +++ b/tlscommon.c @@ -627,6 +627,8 @@ static int certattr_matchip(GENERAL_NAME *gn, struct certattrmatch *match){ } // Generates a generic DNS. eg: converts idp.openroaming.net to *.openroaming.net +// Compares generated generic DNS with DNS from certificate +// returns 1 if both match else returns 0 static int compareWithModifiedHostname(char* certDNS, char* scriptHostName) { int len = 0; int lenOfGeneric = 0, lenOfModifiedScriptHostName = 0; From e37c4f77e07d0a4387a5a6ae1b4feceb3415abfe Mon Sep 17 00:00:00 2001 From: KarthikaRajendran11 Date: Tue, 15 Mar 2022 14:47:28 -0400 Subject: [PATCH 05/18] Address PR comments --- tlscommon.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/tlscommon.c b/tlscommon.c index 8f774b25..8a3656b2 100644 --- a/tlscommon.c +++ b/tlscommon.c @@ -637,6 +637,9 @@ static int compareWithModifiedHostname(char* certDNS, char* scriptHostName) { char *result; char generic[] = "*"; pos = strchr(scriptHostName, '.'); + if(pos == -1) { + return 0; + } len = strlen(pos); modifiedScriptHostName = malloc(len + 1); memcpy(modifiedScriptHostName, pos, len); @@ -647,8 +650,13 @@ static int compareWithModifiedHostname(char* certDNS, char* scriptHostName) { result = malloc(lenOfGeneric + lenOfModifiedScriptHostName + 1); memcpy(result, generic, lenOfGeneric); memcpy(result + lenOfGeneric, modifiedScriptHostName, lenOfModifiedScriptHostName + 1); - if (strlen(certDNS) == strlen(result) && memcmp(result, certDNS, strlen(certDNS)) == 0) - return 1; + if (strlen(certDNS) == strlen(result) && memcmp(result, certDNS, strlen(certDNS)) == 0) { + free(result); + free(modifiedScriptHostName); + return 1; + } + free(result); + free(modifiedScriptHostName); return 0; } From e84afdfbd1b1c9601254f8ed4c954235086c58f1 Mon Sep 17 00:00:00 2001 From: KarthikaRajendran11 Date: Tue, 15 Mar 2022 15:04:37 -0400 Subject: [PATCH 06/18] Check for IP v4 or v6 inputs --- tlscommon.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tlscommon.c b/tlscommon.c index 8a3656b2..09fc917a 100644 --- a/tlscommon.c +++ b/tlscommon.c @@ -637,7 +637,7 @@ static int compareWithModifiedHostname(char* certDNS, char* scriptHostName) { char *result; char generic[] = "*"; pos = strchr(scriptHostName, '.'); - if(pos == -1) { + if(pos == NULL) { return 0; } len = strlen(pos); From 34cea3643e567c12a443a0bf9cd53520db32ee4c Mon Sep 17 00:00:00 2001 From: KarthikaRajendran11 Date: Wed, 16 Mar 2022 16:24:40 -0400 Subject: [PATCH 07/18] Address PR comments --- tlscommon.c | 38 +++++++++++++++++++++++++------------- 1 file changed, 25 insertions(+), 13 deletions(-) diff --git a/tlscommon.c b/tlscommon.c index 09fc917a..00c3f579 100644 --- a/tlscommon.c +++ b/tlscommon.c @@ -630,34 +630,46 @@ static int certattr_matchip(GENERAL_NAME *gn, struct certattrmatch *match){ // Compares generated generic DNS with DNS from certificate // returns 1 if both match else returns 0 static int compareWithModifiedHostname(char* certDNS, char* scriptHostName) { + if(certDNS == NULL || scriptHostName == NULL) { + return 0; + } + int retCode = 0; int len = 0; int lenOfGeneric = 0, lenOfModifiedScriptHostName = 0; - char* pos; - char* modifiedScriptHostName; - char *result; + char* pos = NULL; + char* modifiedScriptHostName = NULL; + char *result = NULL; char generic[] = "*"; pos = strchr(scriptHostName, '.'); if(pos == NULL) { - return 0; + return retCode; } len = strlen(pos); - modifiedScriptHostName = malloc(len + 1); + modifiedScriptHostName = (char*) calloc(len + 1, sizeof(char)); + if(modifiedScriptHostName == NULL) { + return retCode; + } memcpy(modifiedScriptHostName, pos, len); - modifiedScriptHostName[len] = '\0'; - debug(DBG_DBG, "modifiedScriptHostName : %s", modifiedScriptHostName); lenOfGeneric = strlen(generic); lenOfModifiedScriptHostName = strlen(modifiedScriptHostName); - result = malloc(lenOfGeneric + lenOfModifiedScriptHostName + 1); + result = (char*) calloc(lenOfGeneric + lenOfModifiedScriptHostName + 1, sizeof(char)); + if(result == NULL) { + return retCode; + } memcpy(result, generic, lenOfGeneric); - memcpy(result + lenOfGeneric, modifiedScriptHostName, lenOfModifiedScriptHostName + 1); + memcpy(result + lenOfGeneric, modifiedScriptHostName, lenOfModifiedScriptHostName); if (strlen(certDNS) == strlen(result) && memcmp(result, certDNS, strlen(certDNS)) == 0) { + retCode = 1; + } + if(result) { free(result); + result = NULL; + } + if (modifiedScriptHostName) { free(modifiedScriptHostName); - return 1; + modifiedScriptHostName = NULL; } - free(result); - free(modifiedScriptHostName); - return 0; + return retCode; } static int _general_name_regex_match(char *v, int l, struct certattrmatch *match) { From ddd2f577e574cc10937c1173e8c76678f77e5a9f Mon Sep 17 00:00:00 2001 From: KarthikaRajendran11 Date: Thu, 17 Mar 2022 16:14:08 -0400 Subject: [PATCH 08/18] Adding regex matching --- tlscommon.c | 167 ++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 129 insertions(+), 38 deletions(-) diff --git a/tlscommon.c b/tlscommon.c index 00c3f579..c07e0f14 100644 --- a/tlscommon.c +++ b/tlscommon.c @@ -626,50 +626,140 @@ static int certattr_matchip(GENERAL_NAME *gn, struct certattrmatch *match){ && !memcmp(ASN1_STRING_get0_data(gn->d.iPAddress), &match->ipaddr, l)) ? 1 : 0 ; } -// Generates a generic DNS. eg: converts idp.openroaming.net to *.openroaming.net -// Compares generated generic DNS with DNS from certificate -// returns 1 if both match else returns 0 -static int compareWithModifiedHostname(char* certDNS, char* scriptHostName) { - if(certDNS == NULL || scriptHostName == NULL) { - return 0; +static char* extractFirstPortion(char* dns) { + char* result = NULL; + char *firstPos = strchr(dns, '.'); + if(firstPos == NULL) { + return result; + } + int lenOfFirstPortion = strlen(dns) - strlen(firstPos); + result = (char*) calloc(lenOfFirstPortion, sizeof(char)); + memcpy(result, dns, lenOfFirstPortion); +} + +static char* copy(char* s1, char* s2) { + if(s1 == NULL) { + return s2; + } + if(s2 == NULL) { + return s1; } - int retCode = 0; - int len = 0; - int lenOfGeneric = 0, lenOfModifiedScriptHostName = 0; - char* pos = NULL; - char* modifiedScriptHostName = NULL; - char *result = NULL; - char generic[] = "*"; - pos = strchr(scriptHostName, '.'); - if(pos == NULL) { - return retCode; - } - len = strlen(pos); - modifiedScriptHostName = (char*) calloc(len + 1, sizeof(char)); - if(modifiedScriptHostName == NULL) { - return retCode; - } - memcpy(modifiedScriptHostName, pos, len); - lenOfGeneric = strlen(generic); - lenOfModifiedScriptHostName = strlen(modifiedScriptHostName); - result = (char*) calloc(lenOfGeneric + lenOfModifiedScriptHostName + 1, sizeof(char)); + if(s1 == NULL && s2 == NULL) { + return NULL; + } + char* result = (char*) calloc(strlen(s1) + strlen(s2), sizeof(char)); if(result == NULL) { - return retCode; + return NULL; } - memcpy(result, generic, lenOfGeneric); - memcpy(result + lenOfGeneric, modifiedScriptHostName, lenOfModifiedScriptHostName); - if (strlen(certDNS) == strlen(result) && memcmp(result, certDNS, strlen(certDNS)) == 0) { - retCode = 1; + memcpy(result, s1, strlen(s1)); + memcpy(result + strlen(s1), s2, strlen(s2)); + return result; +} + +static char* append(int n, ...) { + char* val = NULL; + va_list ap; + int i; + + va_start(ap, n); + char* v = NULL; + int size = 0; + for(i = 0; i < n; i++) { + val = va_arg(ap, char*); + v = copy(v, val); + } + va_end(ap); + return v; +} + +static char* extractFirstPortion(char* dns, char c) { + char* result = NULL; + char *firstPos = strchr(dns, c); + if(firstPos == NULL) { + return result; } - if(result) { - free(result); - result = NULL; + int lenOfFirstPortion = strlen(dns) - strlen(firstPos); + result = (char*) calloc(lenOfFirstPortion, sizeof(char)); + memcpy(result, dns, lenOfFirstPortion); + return result; +} + +static int regexMatcher(char* pattern, char* str) { + regex_t regex; + char buffer[100]; + + int reti = regcomp(®ex, pattern, REG_EXTENDED); + if (reti) { + regerror(reti, ®ex, buffer, 100); + printf("regcomp() failed with '%s'\n", buffer); + return 0; + } + reti = regexec(®ex, str, 0, NULL, 0); + if(reti) { + return 0; + } + return 1; +} + +static int compareWithModifiedHostname(char* certDNS, char* hostname) { + // extract first portion from certDNS + char* firstPorCertDNS = extractFirstPortion(certDNS, '.'); + char* firstPorHostName = extractFirstPortion(hostname, '.'); + // printf("firstPorHostName : %s\n", firstPorHostName); + debug(DBG_DBG, "firstPorHostName : %s\n", firstPorHostName); + // printf("firstPorCertDNS : %s\n", firstPorCertDNS); + debug(DBG_DBG, "firstPorCertDNS : %s\n", firstPorCertDNS); + // printf("firstPorCertDNS + 1 : %s\n", firstPorCertDNS+1); + debug(DBG_DBG, "firstPorCertDNS + 1 : %s\n", firstPorCertDNS + 1); + + char* pattern = NULL; + char* regex1 = "[a-zA-Z0-9]"; + char* regex2 = "[a-zA-Z0-9_-]"; + char* startRegex = "^"; + char* endRregex = "$"; + char* wildcard = "*"; + + if(strlen(firstPorCertDNS) == 1) { + // look for exact match + // char* lastPorCertDNS = strchr(certDNS, '.'); + char* lastPorHostName = strchr(hostname, '.'); + char* _s = append(2, wildcard, lastPorHostName); + // printf("lastPorHostName : %s\n", lastPorHostName); + debug(DBG_DBG, "lastPorHostName : %s\n", lastPorHostName); + // printf("_s : %s\n", _s); + debug(DBG_DBG, "_s : %s\n", _s); + if(strlen(_s) == strlen(certDNS) && memcmp(_s, certDNS, strlen(certDNS)) == 0) { + // printf("Matched : _s : %s, certDNS : %s\n", _s, certDNS); + debug(DBG_DBG, "Matched : _s : %s, certDNS : %s\n", _s, certDNS); + } + } + + // find where and if * is present + char* asteriskPos = strchr(firstPorCertDNS, '*'); + if(asteriskPos == NULL) { + // printf("No asterisk found!"); + debug(DBG_DBG, "No asterisk found!"); + } + + if(firstPorCertDNS[0] == '*') { + // *buzz + pattern = append(5, startRegex, regex1, regex2, firstPorCertDNS, endRregex); + } else if(firstPorCertDNS[strlen(firstPorCertDNS)-1] == '*') { + // buzz* + // ^buzz[a-zA-Z0-9_-]*$ + pattern = append(5, startRegex, extractFirstPortion(firstPorCertDNS, '*'), regex2, wildcard, endRregex); + } else { + // bu*z => ^bu[a-zA-Z0-9-_]*z$ + pattern = append(5, startRegex, extractFirstPortion(firstPorCertDNS, '*'), regex2, strchr(firstPorCertDNS, '*'), endRregex); } - if (modifiedScriptHostName) { - free(modifiedScriptHostName); - modifiedScriptHostName = NULL; + if(regexMatcher(pattern, firstPorHostName)) { + // printf("Matched : pattern : %s, certdns : %s, hostname: %s\n", pattern, firstPorCertDNS, firstPorHostName); + debug(DBG_DBG, "Matched : pattern : %s, certdns : %s, hostname: %s\n", pattern, firstPorCertDNS, firstPorHostName); + } else { + // printf("Unmatched : pattern : %s, certdns : %s, hostname: %s\n", pattern, firstPorCertDNS, firstPorHostName); + debug(DBG_DBG, "Unmatched : pattern : %s, certdns : %s, hostname: %s\n", pattern, firstPorCertDNS, firstPorHostName); } - return retCode; + return 0; } static int _general_name_regex_match(char *v, int l, struct certattrmatch *match) { @@ -699,6 +789,7 @@ static int _general_name_regex_match(char *v, int l, struct certattrmatch *match } static int certattr_matchregex(GENERAL_NAME *gn, struct certattrmatch *match) { + debug(DBG_DBG, "cert DNS name (%s)", (char *)ASN1_STRING_get0_data(gn->d.ia5)); return _general_name_regex_match((char *)ASN1_STRING_get0_data(gn->d.ia5), ASN1_STRING_length(gn->d.ia5), match); } From 2706fd0f4634e6ddaf620414fe87c6200e27eb56 Mon Sep 17 00:00:00 2001 From: KarthikaRajendran11 Date: Thu, 17 Mar 2022 16:16:18 -0400 Subject: [PATCH 09/18] Add libraries --- tlscommon.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tlscommon.c b/tlscommon.c index c07e0f14..de5b30a8 100644 --- a/tlscommon.c +++ b/tlscommon.c @@ -10,6 +10,8 @@ #include #include #include +#include +#include #include #include #include From 6f6b68c7c184654246482d3b99aa5b1dc432ffea Mon Sep 17 00:00:00 2001 From: KarthikaRajendran11 Date: Sat, 19 Mar 2022 16:01:34 -0400 Subject: [PATCH 10/18] Fix tests --- tests/t_verify_cert.c | 95 +++++++++++------------------ tlscommon.c | 135 +++++++++++++++++++++++++----------------- 2 files changed, 115 insertions(+), 115 deletions(-) diff --git a/tests/t_verify_cert.c b/tests/t_verify_cert.c index b52a9901..7cb544a9 100644 --- a/tests/t_verify_cert.c +++ b/tests/t_verify_cert.c @@ -36,6 +36,8 @@ int main (int argc, char *argv[]) { struct clsrvconf conf; + // X509 + X509 /* /CN=test */ *certsimple = getcert("-----BEGIN CERTIFICATE-----\n\ @@ -64,16 +66,6 @@ tCGaM1KbqRZA/3VgQt+6iEFuoxkwFzAVBgNVHREEDjAMggp0ZXN0LmxvY2FsMAkG\n\ ByqGSM49BAEDJAAwIQIPAId8FJW00y8XSFmd2lBvAg5K6WAMIFgjhtwcRFcfQg==\n\ -----END CERTIFICATE-----"), -/* /CN=other, SAN DNS:other.local */ -*certsandnsother = getcert("-----BEGIN CERTIFICATE-----\n\ -MIHuMIG6oAMCAQICFAiFPNqpXcSIwxS0bfJZs8KDDafVMAkGByqGSM49BAEwEDEO\n\ -MAwGA1UEAwwFb3RoZXIwHhcNMjAwOTI5MTYxMTM2WhcNMjAxMDA5MTYxMTM2WjAQ\n\ -MQ4wDAYDVQQDDAVvdGhlcjAyMBAGByqGSM49AgEGBSuBBAAGAx4ABJxnszX24oQM\n\ -NcK0IZozUpupFkD/dWBC37qIQW6jGjAYMBYGA1UdEQQPMA2CC290aGVyLmxvY2Fs\n\ -MAkGByqGSM49BAEDJAAwIQIOTrQCgOkGcknZEchJFDgCDwCY84F0R2BnNEba95o9\n\ -NA==\n\ ------END CERTIFICATE-----"), - /* /CN=test, SAN IP Address:192.0.2.1 */ *certsanip = getcert("-----BEGIN CERTIFICATE-----\n\ MIHlMIGxoAMCAQICFEukd75rE75+qB95Bo7fcb9wXlA9MAkGByqGSM49BAEwDzEN\n\ @@ -92,6 +84,25 @@ NcK0IZozUpupFkD/dWBC37qIQW6jEzARMA8GA1UdEQQIMAaHBMAAAgIwCQYHKoZI\n\ zj0EAQMjADAgAg5trehJeRpM04SJJZ6XnAIOFfzRRnQtm5rnsP+QBe8=\n\ -----END CERTIFICATE-----"), +/* /CN=test, SAN DNS:192.0.2.1 */ +*certsanipindns = getcert("-----BEGIN CERTIFICATE-----\n\ +MIHqMIG2oAMCAQICFFUjZGG96kpFI2fu90+jAhWsTr8YMAkGByqGSM49BAEwDzEN\n\ +MAsGA1UEAwwEdGVzdDAeFw0yMDA5MjkxNTU4NDBaFw0yMDEwMDkxNTU4NDBaMA8x\n\ +DTALBgNVBAMMBHRlc3QwMjAQBgcqhkjOPQIBBgUrgQQABgMeAAScZ7M19uKEDDXC\n\ +tCGaM1KbqRZA/3VgQt+6iEFuoxgwFjAUBgNVHREEDTALggkxOTIuMC4yLjEwCQYH\n\ +KoZIzj0EAQMkADAhAg5BngyplTbRlQ8o/oWWwQIPAL9SfgIaXi/gD6YlQCOU\n\ +-----END CERTIFICATE-----"), + +/* /CN=test, DNS:somethinglese, DNS:test.local, IP Address:192.0.2.1, IP Address:2001:DB8:0:0:0:0:0:1 */ +*certcomplex = getcert("-----BEGIN CERTIFICATE-----\n\ +MIIBEjCB3qADAgECAhRgxyW7klgZvTf9isALCvwlVwvRtDAJBgcqhkjOPQQBMA8x\n\ +DTALBgNVBAMMBHRlc3QwHhcNMjAwOTMwMDU1MjIyWhcNMjAxMDEwMDU1MjIyWjAP\n\ +MQ0wCwYDVQQDDAR0ZXN0MDIwEAYHKoZIzj0CAQYFK4EEAAYDHgAEnGezNfbihAw1\n\ +wrQhmjNSm6kWQP91YELfuohBbqNAMD4wPAYDVR0RBDUwM4INc29tZXRoaW5nbGVz\n\ +ZYIKdGVzdC5sb2NhbIcEwAACAYcQIAENuAAAAAAAAAAAAAAAATAJBgcqhkjOPQQB\n\ +AyQAMCECDlTfJfMJElZZgvUdkatdAg8ApiXkPXLXXrV6OMRG9us=\n\ +-----END CERTIFICATE-----"), + /* /CN=test, SAN IP Address:2001:DB8:0:0:0:0:0:1 */ *certsanipv6 = getcert("-----BEGIN CERTIFICATE-----\n\ MIHxMIG9oAMCAQICFGhkABYXfolor1EF6Li3hDQeEVU+MAkGByqGSM49BAEwDzEN\n\ @@ -102,15 +113,6 @@ AAABMAkGByqGSM49BAEDJAAwIQIPAKsn++FWaDIcpnNBOFTuAg5C7gs7DxaNWgEu\n\ OrBTXA==\n\ -----END CERTIFICATE-----"), -/* /CN=test, SAN DNS:192.0.2.1 */ -*certsanipindns = getcert("-----BEGIN CERTIFICATE-----\n\ -MIHqMIG2oAMCAQICFFUjZGG96kpFI2fu90+jAhWsTr8YMAkGByqGSM49BAEwDzEN\n\ -MAsGA1UEAwwEdGVzdDAeFw0yMDA5MjkxNTU4NDBaFw0yMDEwMDkxNTU4NDBaMA8x\n\ -DTALBgNVBAMMBHRlc3QwMjAQBgcqhkjOPQIBBgUrgQQABgMeAAScZ7M19uKEDDXC\n\ -tCGaM1KbqRZA/3VgQt+6iEFuoxgwFjAUBgNVHREEDTALggkxOTIuMC4yLjEwCQYH\n\ -KoZIzj0EAQMkADAhAg5BngyplTbRlQ8o/oWWwQIPAL9SfgIaXi/gD6YlQCOU\n\ ------END CERTIFICATE-----"), - /* /CN=test, SAN DNS:2001:DB8::1 */ *certsanipv6indns = getcert("-----BEGIN CERTIFICATE-----\n\ MIHsMIG4oAMCAQICFFgnXltbOEGcWsS0vCv6Lsj4FhO3MAkGByqGSM49BAEwDzEN\n\ @@ -120,28 +122,18 @@ tCGaM1KbqRZA/3VgQt+6iEFuoxowGDAWBgNVHREEDzANggsyMDAxOmRiODo6MTAJ\n\ BgcqhkjOPQQBAyQAMCECDlWFhJxpHRgt93ZzN9k7Ag8Ag0YN+dL3MEIo2sqgRWg=\n\ -----END CERTIFICATE-----"), -/* /CN=test, DNS:somethinglese, DNS:test.local, IP Address:192.0.2.1, IP Address:2001:DB8:0:0:0:0:0:1 */ -*certcomplex = getcert("-----BEGIN CERTIFICATE-----\n\ -MIIBEjCB3qADAgECAhRgxyW7klgZvTf9isALCvwlVwvRtDAJBgcqhkjOPQQBMA8x\n\ -DTALBgNVBAMMBHRlc3QwHhcNMjAwOTMwMDU1MjIyWhcNMjAxMDEwMDU1MjIyWjAP\n\ -MQ0wCwYDVQQDDAR0ZXN0MDIwEAYHKoZIzj0CAQYFK4EEAAYDHgAEnGezNfbihAw1\n\ -wrQhmjNSm6kWQP91YELfuohBbqNAMD4wPAYDVR0RBDUwM4INc29tZXRoaW5nbGVz\n\ -ZYIKdGVzdC5sb2NhbIcEwAACAYcQIAENuAAAAAAAAAAAAAAAATAJBgcqhkjOPQQB\n\ -AyQAMCECDlTfJfMJElZZgvUdkatdAg8ApiXkPXLXXrV6OMRG9us=\n\ +/* /CN=other, SAN DNS:other.local */ +*certsandnsother = getcert("-----BEGIN CERTIFICATE-----\n\ +MIHuMIG6oAMCAQICFAiFPNqpXcSIwxS0bfJZs8KDDafVMAkGByqGSM49BAEwEDEO\n\ +MAwGA1UEAwwFb3RoZXIwHhcNMjAwOTI5MTYxMTM2WhcNMjAxMDA5MTYxMTM2WjAQ\n\ +MQ4wDAYDVQQDDAVvdGhlcjAyMBAGByqGSM49AgEGBSuBBAAGAx4ABJxnszX24oQM\n\ +NcK0IZozUpupFkD/dWBC37qIQW6jGjAYMBYGA1UdEQQPMA2CC290aGVyLmxvY2Fs\n\ +MAkGByqGSM49BAEDJAAwIQIOTrQCgOkGcknZEchJFDgCDwCY84F0R2BnNEba95o9\n\ +NA==\n\ -----END CERTIFICATE-----"), -/* /CN=test, DNS:somethinglese, DNS:other.local, IP Address:192.0.2.2, IP Address:2001:DB8:0:0:0:0:0:2 */ -*certcomplexother = getcert("-----BEGIN CERTIFICATE-----\n\ -MIIBFTCB4aADAgECAhR0GSgeV7pqQnbHRgv5y5plz/6+NjAJBgcqhkjOPQQBMBAx\n\ -DjAMBgNVBAMMBW90aGVyMB4XDTIwMDkzMDA1NTI1NVoXDTIwMTAxMDA1NTI1NVow\n\ -EDEOMAwGA1UEAwwFb3RoZXIwMjAQBgcqhkjOPQIBBgUrgQQABgMeAAScZ7M19uKE\n\ -DDXCtCGaM1KbqRZA/3VgQt+6iEFuo0EwPzA9BgNVHREENjA0gg1zb21ldGhpbmds\n\ -ZXNlggtvdGhlci5sb2NhbIcEwAACAocQIAENuAAAAAAAAAAAAAAAAjAJBgcqhkjO\n\ -PQQBAyQAMCECDwCEaHL6oHT4zwH6jD91YwIOYO3L8cHIzmnGCOJYIQ4=\n\ ------END CERTIFICATE-----"), - - /* /CN=test, URI:https://test.local/profile#me */ - *certsanuri = getcert("-----BEGIN CERTIFICATE-----\n\ +/* /CN=test, URI:https://test.local/profile#me */ +*certsanuri = getcert("-----BEGIN CERTIFICATE-----\n\ MIH9MIHKoAMCAQICFHsSOjcYexRKQpNlH1oHV1cxvdgHMAkGByqGSM49BAEwDzEN\n\ MAsGA1UEAwwEdGVzdDAeFw0yMDEwMDYwODU5MzRaFw0yMDEwMTYwODU5MzRaMA8x\n\ DTALBgNVBAMMBHRlc3QwMjAQBgcqhkjOPQIBBgUrgQQABgMeAAScZ7M19uKEDDXC\n\ @@ -238,8 +230,7 @@ vY/uPjA=\n\ while(list_shift(conf.hostports)); } - - /* test no check if prefixlen != 255 (CIDR) */ + /* test no check if prefixlen != 255 (CIDR) */ { struct hostportres hp; @@ -253,7 +244,6 @@ vY/uPjA=\n\ while(list_shift(conf.hostports)); } - /* test simple match for CN=test */ { struct hostportres hp; @@ -272,7 +262,6 @@ vY/uPjA=\n\ while(list_shift(conf.hostports)); } - /* test literal ip match to SAN IP */ { struct hostportres hp; @@ -288,12 +277,11 @@ vY/uPjA=\n\ ok(0,verifyconfcert(certsanipother, &conf, &hp),"wrong san ip"); ok(0,verifyconfcert(certsimple, &conf, &hp), "negative san ip"); ok(1,verifyconfcert(certsanipindns, &conf, &hp),"san ip in dns"); - ok(1,verifyconfcert(certcomplex,&conf, &hp),"san ip in complex cert"); + ok(1,verifyconfcert(certcomplex, &conf, &hp),"san ip in complex cert"); freeaddrinfo(hp.addrinfo); while(list_shift(conf.hostports)); } - /* test literal ipv6 match to SAN IP */ { struct hostportres hp; @@ -315,7 +303,6 @@ vY/uPjA=\n\ freeaddrinfo(hp.addrinfo); while(list_shift(conf.hostports)); } - /* test simple match for SAN DNS:test.local */ { struct hostportres hp; @@ -333,7 +320,6 @@ vY/uPjA=\n\ while(list_shift(conf.hostports)); } - /* test multiple hostports san dns(match in second) */ { struct hostportres hp1, hp2; @@ -352,7 +338,6 @@ vY/uPjA=\n\ while(list_shift(conf.hostports)); } - /* test multiple hostports san dns(match in second) */ { struct hostportres hp1, hp2; @@ -377,7 +362,6 @@ vY/uPjA=\n\ while(list_shift(conf.hostports)); } - /* test explicit CN regex */ { conf.name = "test"; @@ -391,7 +375,6 @@ vY/uPjA=\n\ freematchcertattr(&conf); } - /* test explicit ip match to SAN IP */ { conf.name = "test"; @@ -406,7 +389,6 @@ vY/uPjA=\n\ freematchcertattr(&conf); } - /* test explicit ipv6 match to SAN IP */ { conf.name = "test"; @@ -421,7 +403,6 @@ vY/uPjA=\n\ freematchcertattr(&conf); } - /* test explicit SAN DNS regex */ { conf.name = "test"; @@ -436,7 +417,6 @@ vY/uPjA=\n\ freematchcertattr(&conf); } - /* test explicit SAN URI regex */ { conf.name = "test"; @@ -450,7 +430,6 @@ vY/uPjA=\n\ freematchcertattr(&conf); } - /* test explicit SAN rID */ { conf.name = "test"; @@ -464,7 +443,6 @@ vY/uPjA=\n\ freematchcertattr(&conf); } - /* test explicit SAN otherNAME */ { conf.name = "test"; @@ -478,7 +456,6 @@ vY/uPjA=\n\ freematchcertattr(&conf); } - /* test valid config syntax */ { conf.name = "test"; @@ -489,7 +466,6 @@ vY/uPjA=\n\ freematchcertattr(&conf); } - /* test invalid config syntax */ { conf.name = "test"; @@ -510,7 +486,6 @@ vY/uPjA=\n\ ok(0,addmatchcertattr(&conf, "SubjectAltName:rID:1:2"),"test invalid syntax rID"); freematchcertattr(&conf); } - /* test explicit & implicit combined */ { struct hostportres hp; @@ -531,7 +506,6 @@ vY/uPjA=\n\ while(list_shift(conf.hostports)); freematchcertattr(&conf); } - /* test multiple explicit checks*/ { struct hostportres hp; @@ -556,6 +530,7 @@ vY/uPjA=\n\ freematchcertattr(&conf); } + printf("1..%d\n", numtests); list_free(conf.hostports); X509_free(certsimple); @@ -568,7 +543,6 @@ vY/uPjA=\n\ X509_free(certsanipv6); X509_free(certsanipv6indns); X509_free(certcomplex); - X509_free(certcomplexother); X509_free(certsanuri); X509_free(certsanuriother); X509_free(certsanrid); @@ -577,6 +551,5 @@ vY/uPjA=\n\ X509_free(certsanothernameother); X509_free(certmulti); X509_free(certmultiother); - return 0; } diff --git a/tlscommon.c b/tlscommon.c index de5b30a8..953bea0c 100644 --- a/tlscommon.c +++ b/tlscommon.c @@ -628,17 +628,6 @@ static int certattr_matchip(GENERAL_NAME *gn, struct certattrmatch *match){ && !memcmp(ASN1_STRING_get0_data(gn->d.iPAddress), &match->ipaddr, l)) ? 1 : 0 ; } -static char* extractFirstPortion(char* dns) { - char* result = NULL; - char *firstPos = strchr(dns, '.'); - if(firstPos == NULL) { - return result; - } - int lenOfFirstPortion = strlen(dns) - strlen(firstPos); - result = (char*) calloc(lenOfFirstPortion, sizeof(char)); - memcpy(result, dns, lenOfFirstPortion); -} - static char* copy(char* s1, char* s2) { if(s1 == NULL) { return s2; @@ -659,19 +648,18 @@ static char* copy(char* s1, char* s2) { } static char* append(int n, ...) { - char* val = NULL; + char* val = NULL; va_list ap; int i; va_start(ap, n); - char* v = NULL; - int size = 0; + char* result = NULL; for(i = 0; i < n; i++) { val = va_arg(ap, char*); - v = copy(v, val); + result = copy(result, val); } va_end(ap); - return v; + return result; } static char* extractFirstPortion(char* dns, char c) { @@ -682,6 +670,9 @@ static char* extractFirstPortion(char* dns, char c) { } int lenOfFirstPortion = strlen(dns) - strlen(firstPos); result = (char*) calloc(lenOfFirstPortion, sizeof(char)); + if(result == NULL) { + return NULL; + } memcpy(result, dns, lenOfFirstPortion); return result; } @@ -693,74 +684,109 @@ static int regexMatcher(char* pattern, char* str) { int reti = regcomp(®ex, pattern, REG_EXTENDED); if (reti) { regerror(reti, ®ex, buffer, 100); - printf("regcomp() failed with '%s'\n", buffer); + debug(DBG_ERR, "regcomp failed with '%s'\n", buffer); return 0; } reti = regexec(®ex, str, 0, NULL, 0); - if(reti) { + if(reti) { return 0; } return 1; } +static char* calculateLenOfLabel(int len) { + char str[3]; + sprintf(str, "%d", len); + debug(DBG_DBG, "str : %s", str); + char* result = append(3, "{0,", str, "}"); + return result; +} + +// compareWithModifiedHostname generates a regular expression based on the first label present +// in certificate DNS. Matches the regular expression with the first label of hostname and +// returns result - 1 - matched, 0 - unmatched +// Refer https://datatracker.ietf.org/doc/html/rfc6125#section-6.4 +// buzz* => ^buzz[a-zA-Z0-9-_]{0,59}$ +// *buzz => ^[a-z0-9A-Z][a-z0-9A-Z-_]{0,59}buzz$ +// b*uzz => ^b[a-zA-Z0-9-_]{0,59}uzz$ static int compareWithModifiedHostname(char* certDNS, char* hostname) { - // extract first portion from certDNS char* firstPorCertDNS = extractFirstPortion(certDNS, '.'); + if(firstPorCertDNS == NULL) { + return 0; + } char* firstPorHostName = extractFirstPortion(hostname, '.'); - // printf("firstPorHostName : %s\n", firstPorHostName); - debug(DBG_DBG, "firstPorHostName : %s\n", firstPorHostName); - // printf("firstPorCertDNS : %s\n", firstPorCertDNS); - debug(DBG_DBG, "firstPorCertDNS : %s\n", firstPorCertDNS); - // printf("firstPorCertDNS + 1 : %s\n", firstPorCertDNS+1); - debug(DBG_DBG, "firstPorCertDNS + 1 : %s\n", firstPorCertDNS + 1); + if(firstPorHostName == NULL) { + free(firstPorCertDNS); + return 0; + } char* pattern = NULL; - char* regex1 = "[a-zA-Z0-9]"; char* regex2 = "[a-zA-Z0-9_-]"; char* startRegex = "^"; char* endRregex = "$"; char* wildcard = "*"; - if(strlen(firstPorCertDNS) == 1) { - // look for exact match - // char* lastPorCertDNS = strchr(certDNS, '.'); + // Handles *.3af521.net (cert DNS) and idp.3af521.net (host name) case + if(strlen(firstPorCertDNS) == 1 && firstPorCertDNS[0] == '*') { + char* lastPorHostName = strchr(hostname, '.'); - char* _s = append(2, wildcard, lastPorHostName); - // printf("lastPorHostName : %s\n", lastPorHostName); - debug(DBG_DBG, "lastPorHostName : %s\n", lastPorHostName); - // printf("_s : %s\n", _s); - debug(DBG_DBG, "_s : %s\n", _s); - if(strlen(_s) == strlen(certDNS) && memcmp(_s, certDNS, strlen(certDNS)) == 0) { - // printf("Matched : _s : %s, certDNS : %s\n", _s, certDNS); - debug(DBG_DBG, "Matched : _s : %s, certDNS : %s\n", _s, certDNS); + if(lastPorHostName == NULL) { + free(firstPorCertDNS); + free(firstPorHostName); + return 0; } + char* modifiedHostName = append(2, wildcard, lastPorHostName); + if(modifiedHostName == NULL) { + free(firstPorCertDNS); + free(firstPorHostName); + return 0; + } + if(strlen(modifiedHostName) == strlen(certDNS) && memcmp(modifiedHostName, certDNS, strlen(certDNS)) == 0) { + free(modifiedHostName); + free(firstPorCertDNS); + free(firstPorHostName); + return 1; + } + free(modifiedHostName); + free(firstPorCertDNS); + free(firstPorHostName); + return 0; } - // find where and if * is present char* asteriskPos = strchr(firstPorCertDNS, '*'); if(asteriskPos == NULL) { - // printf("No asterisk found!"); - debug(DBG_DBG, "No asterisk found!"); + free(firstPorCertDNS); + free(firstPorHostName); + return 0; } - + + char* lenRegex = calculateLenOfLabel(63 - strlen(firstPorCertDNS) - 1); + if(lenRegex == NULL) { + free(firstPorCertDNS); + free(firstPorHostName); + return 0; + } + if(firstPorCertDNS[0] == '*') { - // *buzz - pattern = append(5, startRegex, regex1, regex2, firstPorCertDNS, endRregex); + char* regex1 = "^[a-z0-9A-Z][a-z0-9A-Z_-]"; + pattern = append(4, regex1, lenRegex, asteriskPos + 1, endRregex); } else if(firstPorCertDNS[strlen(firstPorCertDNS)-1] == '*') { - // buzz* - // ^buzz[a-zA-Z0-9_-]*$ - pattern = append(5, startRegex, extractFirstPortion(firstPorCertDNS, '*'), regex2, wildcard, endRregex); + char* regex1 = extractFirstPortion(firstPorCertDNS, '*'); + pattern = append(5, startRegex, regex1, regex2, lenRegex, endRregex); } else { - // bu*z => ^bu[a-zA-Z0-9-_]*z$ - pattern = append(5, startRegex, extractFirstPortion(firstPorCertDNS, '*'), regex2, strchr(firstPorCertDNS, '*'), endRregex); + char* regex1 = extractFirstPortion(firstPorCertDNS, '*'); + pattern = append(6, startRegex, regex1, regex2, lenRegex, asteriskPos + 1, endRregex); } + if(regexMatcher(pattern, firstPorHostName)) { - // printf("Matched : pattern : %s, certdns : %s, hostname: %s\n", pattern, firstPorCertDNS, firstPorHostName); - debug(DBG_DBG, "Matched : pattern : %s, certdns : %s, hostname: %s\n", pattern, firstPorCertDNS, firstPorHostName); - } else { - // printf("Unmatched : pattern : %s, certdns : %s, hostname: %s\n", pattern, firstPorCertDNS, firstPorHostName); - debug(DBG_DBG, "Unmatched : pattern : %s, certdns : %s, hostname: %s\n", pattern, firstPorCertDNS, firstPorHostName); + free(pattern); + free(firstPorCertDNS); + free(firstPorHostName); + return 1; } + free(pattern); + free(firstPorCertDNS); + free(firstPorHostName); return 0; } @@ -771,8 +797,9 @@ static int _general_name_regex_match(char *v, int l, struct certattrmatch *match if (match->exact) { if (l == strlen(match->exact) && memcmp(v, match->exact, l) == 0) return 1; - if(compareWithModifiedHostname(v, match->exact)) + if(compareWithModifiedHostname(v, match->exact)) { return 1; + } return 0; } From ce1ddfb657e0cfe37e9929c4fdd30badfc9d9dd9 Mon Sep 17 00:00:00 2001 From: KarthikaRajendran11 Date: Mon, 21 Mar 2022 08:29:29 -0400 Subject: [PATCH 11/18] Cleanup --- tlscommon.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/tlscommon.c b/tlscommon.c index 953bea0c..75625bf6 100644 --- a/tlscommon.c +++ b/tlscommon.c @@ -706,9 +706,13 @@ static char* calculateLenOfLabel(int len) { // in certificate DNS. Matches the regular expression with the first label of hostname and // returns result - 1 - matched, 0 - unmatched // Refer https://datatracker.ietf.org/doc/html/rfc6125#section-6.4 -// buzz* => ^buzz[a-zA-Z0-9-_]{0,59}$ -// *buzz => ^[a-z0-9A-Z][a-z0-9A-Z-_]{0,59}buzz$ -// b*uzz => ^b[a-zA-Z0-9-_]{0,59}uzz$ +// buzz* => ^buzz[a-zA-Z0-9-]{0,59}$ +// *buzz => ^[a-z0-9A-Z][a-z0-9A-Z-]{0,59}buzz$ +// b*uzz => ^b[a-zA-Z0-9-]{0,59}uzz$ +// 63 - Maximum length of a label +// A domain name consists of one or more labels, each of which is formed from the set of ASCII letters, +// digits, and hyphens (a-z, A-Z, 0–9, -), but not starting or ending with a hyphen. +// The labels are case-insensitive static int compareWithModifiedHostname(char* certDNS, char* hostname) { char* firstPorCertDNS = extractFirstPortion(certDNS, '.'); if(firstPorCertDNS == NULL) { @@ -721,7 +725,7 @@ static int compareWithModifiedHostname(char* certDNS, char* hostname) { } char* pattern = NULL; - char* regex2 = "[a-zA-Z0-9_-]"; + char* regex2 = "[a-zA-Z0-9-]"; char* startRegex = "^"; char* endRregex = "$"; char* wildcard = "*"; @@ -768,7 +772,7 @@ static int compareWithModifiedHostname(char* certDNS, char* hostname) { } if(firstPorCertDNS[0] == '*') { - char* regex1 = "^[a-z0-9A-Z][a-z0-9A-Z_-]"; + char* regex1 = "^[a-z0-9A-Z][a-z0-9A-Z-]"; pattern = append(4, regex1, lenRegex, asteriskPos + 1, endRregex); } else if(firstPorCertDNS[strlen(firstPorCertDNS)-1] == '*') { char* regex1 = extractFirstPortion(firstPorCertDNS, '*'); From 1b0e791feda68450122d28465298c950b4584a9f Mon Sep 17 00:00:00 2001 From: KarthikaRajendran11 Date: Mon, 21 Mar 2022 08:34:04 -0400 Subject: [PATCH 12/18] Cleanup --- tlscommon.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tlscommon.c b/tlscommon.c index 75625bf6..ee74f38b 100644 --- a/tlscommon.c +++ b/tlscommon.c @@ -710,7 +710,7 @@ static char* calculateLenOfLabel(int len) { // *buzz => ^[a-z0-9A-Z][a-z0-9A-Z-]{0,59}buzz$ // b*uzz => ^b[a-zA-Z0-9-]{0,59}uzz$ // 63 - Maximum length of a label -// A domain name consists of one or more labels, each of which is formed from the set of ASCII letters, +// Wiki: A domain name consists of one or more labels, each of which is formed from the set of ASCII letters, // digits, and hyphens (a-z, A-Z, 0–9, -), but not starting or ending with a hyphen. // The labels are case-insensitive static int compareWithModifiedHostname(char* certDNS, char* hostname) { @@ -822,7 +822,6 @@ static int _general_name_regex_match(char *v, int l, struct certattrmatch *match } static int certattr_matchregex(GENERAL_NAME *gn, struct certattrmatch *match) { - debug(DBG_DBG, "cert DNS name (%s)", (char *)ASN1_STRING_get0_data(gn->d.ia5)); return _general_name_regex_match((char *)ASN1_STRING_get0_data(gn->d.ia5), ASN1_STRING_length(gn->d.ia5), match); } From 92b5a3459dc4beb23bd75931bbf815fec98f9980 Mon Sep 17 00:00:00 2001 From: KarthikaRajendran11 Date: Mon, 21 Mar 2022 09:20:31 -0400 Subject: [PATCH 13/18] Add IDN examples in code --- tlscommon.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tlscommon.c b/tlscommon.c index ee74f38b..7e01e500 100644 --- a/tlscommon.c +++ b/tlscommon.c @@ -713,6 +713,9 @@ static char* calculateLenOfLabel(int len) { // Wiki: A domain name consists of one or more labels, each of which is formed from the set of ASCII letters, // digits, and hyphens (a-z, A-Z, 0–9, -), but not starting or ending with a hyphen. // The labels are case-insensitive +// Internationlized Domain Names: www.äöü.com converted to www.xn--4ca0bs.com. xn--4ca0bs is considered +// a valid DN and let through. diseñolatinoamericano.com => xn--diseolatinoamericano-66b.com will also be +// let through. So IDNs are passed in Punycode encoded and xn-- says everything that follows is unicode encoded. static int compareWithModifiedHostname(char* certDNS, char* hostname) { char* firstPorCertDNS = extractFirstPortion(certDNS, '.'); if(firstPorCertDNS == NULL) { From 521d294206b7dab5c83c8d7471bb63b962644df4 Mon Sep 17 00:00:00 2001 From: KarthikaRajendran11 Date: Mon, 21 Mar 2022 11:24:07 -0400 Subject: [PATCH 14/18] Free regex1; Rename fn --- tlscommon.c | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/tlscommon.c b/tlscommon.c index 7e01e500..174a255a 100644 --- a/tlscommon.c +++ b/tlscommon.c @@ -628,7 +628,7 @@ static int certattr_matchip(GENERAL_NAME *gn, struct certattrmatch *match){ && !memcmp(ASN1_STRING_get0_data(gn->d.iPAddress), &match->ipaddr, l)) ? 1 : 0 ; } -static char* copy(char* s1, char* s2) { +static char* concatenate(char* s1, char* s2) { if(s1 == NULL) { return s2; } @@ -656,7 +656,7 @@ static char* append(int n, ...) { char* result = NULL; for(i = 0; i < n; i++) { val = va_arg(ap, char*); - result = copy(result, val); + result = concatenate(result, val); } va_end(ap); return result; @@ -779,10 +779,22 @@ static int compareWithModifiedHostname(char* certDNS, char* hostname) { pattern = append(4, regex1, lenRegex, asteriskPos + 1, endRregex); } else if(firstPorCertDNS[strlen(firstPorCertDNS)-1] == '*') { char* regex1 = extractFirstPortion(firstPorCertDNS, '*'); + if(regex1 == NULL) { + free(firstPorCertDNS); + free(firstPorHostName); + return 0; + } pattern = append(5, startRegex, regex1, regex2, lenRegex, endRregex); + free(regex1); } else { char* regex1 = extractFirstPortion(firstPorCertDNS, '*'); + if(regex1 == NULL) { + free(firstPorCertDNS); + free(firstPorHostName); + return 0; + } pattern = append(6, startRegex, regex1, regex2, lenRegex, asteriskPos + 1, endRregex); + free(regex1); } if(regexMatcher(pattern, firstPorHostName)) { @@ -801,6 +813,8 @@ static int _general_name_regex_match(char *v, int l, struct certattrmatch *match char *s; if (l <= 0 ) return 0; + + // Found DNS if (match->exact) { if (l == strlen(match->exact) && memcmp(v, match->exact, l) == 0) return 1; From 5172582143b463dce590cf408b6485905be5ca45 Mon Sep 17 00:00:00 2001 From: KarthikaRajendran11 Date: Wed, 23 Mar 2022 10:07:55 -0400 Subject: [PATCH 15/18] Use goto blocks --- tlscommon.c | 158 +++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 113 insertions(+), 45 deletions(-) diff --git a/tlscommon.c b/tlscommon.c index 174a255a..fe76af15 100644 --- a/tlscommon.c +++ b/tlscommon.c @@ -629,16 +629,23 @@ static int certattr_matchip(GENERAL_NAME *gn, struct certattrmatch *match){ } static char* concatenate(char* s1, char* s2) { + char* result = NULL; + if(s1 == NULL && s2 == NULL) { + return NULL; + } if(s1 == NULL) { - return s2; + result = (char*) calloc(strlen(s2) + 1, sizeof(char)); + // memcpy(result, s2, strlen(s2)); + strcpy(result, s2); + return result; } if(s2 == NULL) { - return s1; - } - if(s1 == NULL && s2 == NULL) { - return NULL; + result = (char*) calloc(strlen(s2) + 1, sizeof(char)); + // memcpy(result, s2, strlen(s2)); + strcpy(result, s2); + return result; } - char* result = (char*) calloc(strlen(s1) + strlen(s2), sizeof(char)); + result = (char*) calloc(strlen(s1) + strlen(s2) + 1, sizeof(char)); if(result == NULL) { return NULL; } @@ -662,14 +669,14 @@ static char* append(int n, ...) { return result; } -static char* extractFirstPortion(char* dns, char c) { +static char* extractFirstPortion(const char* dns, const char c) { char* result = NULL; char *firstPos = strchr(dns, c); if(firstPos == NULL) { return result; } int lenOfFirstPortion = strlen(dns) - strlen(firstPos); - result = (char*) calloc(lenOfFirstPortion, sizeof(char)); + result = (char*) calloc(lenOfFirstPortion + 1, sizeof(char)); if(result == NULL) { return NULL; } @@ -683,7 +690,7 @@ static int regexMatcher(char* pattern, char* str) { int reti = regcomp(®ex, pattern, REG_EXTENDED); if (reti) { - regerror(reti, ®ex, buffer, 100); + regerror(reti, ®ex, buffer, sizeof(buffer)); debug(DBG_ERR, "regcomp failed with '%s'\n", buffer); return 0; } @@ -719,12 +726,13 @@ static char* calculateLenOfLabel(int len) { static int compareWithModifiedHostname(char* certDNS, char* hostname) { char* firstPorCertDNS = extractFirstPortion(certDNS, '.'); if(firstPorCertDNS == NULL) { - return 0; + return retCode; } char* firstPorHostName = extractFirstPortion(hostname, '.'); if(firstPorHostName == NULL) { - free(firstPorCertDNS); - return 0; + // free(firstPorCertDNS); + // return 0; + goto cleanupInit; } char* pattern = NULL; @@ -733,80 +741,140 @@ static int compareWithModifiedHostname(char* certDNS, char* hostname) { char* endRregex = "$"; char* wildcard = "*"; + int retCode = 0; + // Handles *.3af521.net (cert DNS) and idp.3af521.net (host name) case if(strlen(firstPorCertDNS) == 1 && firstPorCertDNS[0] == '*') { char* lastPorHostName = strchr(hostname, '.'); if(lastPorHostName == NULL) { - free(firstPorCertDNS); - free(firstPorHostName); - return 0; + // free(firstPorCertDNS); + // free(firstPorHostName); + // return 0; + goto cleanupFirstPortions; } char* modifiedHostName = append(2, wildcard, lastPorHostName); if(modifiedHostName == NULL) { - free(firstPorCertDNS); - free(firstPorHostName); - return 0; + // free(firstPorCertDNS); + // free(firstPorHostName); + // return 0; + goto cleanupFirstPortions; } if(strlen(modifiedHostName) == strlen(certDNS) && memcmp(modifiedHostName, certDNS, strlen(certDNS)) == 0) { - free(modifiedHostName); + // free(modifiedHostName); + // free(firstPorCertDNS); + // free(firstPorHostName); + // return 1; + retCode = 1; + goto cleanupBlock; + } + // free(modifiedHostName); + // free(firstPorCertDNS); + // free(firstPorHostName); + // return 0; + goto cleanupBlock; + + cleanupBlock: free(firstPorCertDNS); free(firstPorHostName); - return 1; - } - free(modifiedHostName); - free(firstPorCertDNS); - free(firstPorHostName); - return 0; + free(modifiedHostName); + return retCode; } char* asteriskPos = strchr(firstPorCertDNS, '*'); if(asteriskPos == NULL) { - free(firstPorCertDNS); - free(firstPorHostName); - return 0; + // free(firstPorCertDNS); + // free(firstPorHostName); + // return 0; + goto cleanupFirstPortions; } char* lenRegex = calculateLenOfLabel(63 - strlen(firstPorCertDNS) - 1); if(lenRegex == NULL) { - free(firstPorCertDNS); - free(firstPorHostName); - return 0; + // free(firstPorCertDNS); + // free(firstPorHostName); + // return 0; + goto cleanupFirstPortions; } if(firstPorCertDNS[0] == '*') { char* regex1 = "^[a-z0-9A-Z][a-z0-9A-Z-]"; pattern = append(4, regex1, lenRegex, asteriskPos + 1, endRregex); + if(pattern == NULL) { + // free(firstPorCertDNS); + // free(firstPorHostName); + // free(lenRegex); + // return 0; + goto cleanupWOPattern; + } } else if(firstPorCertDNS[strlen(firstPorCertDNS)-1] == '*') { char* regex1 = extractFirstPortion(firstPorCertDNS, '*'); if(regex1 == NULL) { - free(firstPorCertDNS); - free(firstPorHostName); - return 0; + // free(firstPorCertDNS); + // free(firstPorHostName); + // free(lenRegex); + // return 0; + goto cleanupWOPattern; } pattern = append(5, startRegex, regex1, regex2, lenRegex, endRregex); - free(regex1); + if(pattern == NULL) { + // free(firstPorCertDNS); + // free(firstPorHostName); + // free(lenRegex); + // return 0; + free(regex1); + goto cleanup; + } + // free(regex1); } else { char* regex1 = extractFirstPortion(firstPorCertDNS, '*'); if(regex1 == NULL) { - free(firstPorCertDNS); - free(firstPorHostName); - return 0; + // free(firstPorCertDNS); + // free(firstPorHostName); + // return 0; + goto cleanupWOPattern; } pattern = append(6, startRegex, regex1, regex2, lenRegex, asteriskPos + 1, endRregex); - free(regex1); + if(pattern == NULL) { + // free(firstPorCertDNS); + // free(firstPorHostName); + // free(lenRegex); + // return 0; + free(regex1); + goto cleanup; + } + // free(regex1); } if(regexMatcher(pattern, firstPorHostName)) { + // free(lenRegex); + // free(pattern); + // free(firstPorCertDNS); + // free(firstPorHostName); + // return 1; + goto cleanup; + retCode = 1; + } + + cleanupInit: + free(firstPorCertDNS); + + cleanupFirstPortions: + free(firstPorCertDNS); + free(firstPorHostName); + + cleanupWOPattern: + free(firstPorCertDNS); + free(firstPorHostName); + free(lenRegex); + + cleanup: + free(lenRegex); free(pattern); free(firstPorCertDNS); free(firstPorHostName); - return 1; - } - free(pattern); - free(firstPorCertDNS); - free(firstPorHostName); - return 0; + + return retCode; } static int _general_name_regex_match(char *v, int l, struct certattrmatch *match) { From 1511ae1a0a0e4b533190af940c7d8155792f0cca Mon Sep 17 00:00:00 2001 From: KarthikaRajendran11 Date: Wed, 23 Mar 2022 10:18:46 -0400 Subject: [PATCH 16/18] Modify calculateLenOfLabel --- tlscommon.c | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/tlscommon.c b/tlscommon.c index fe76af15..24a50b2f 100644 --- a/tlscommon.c +++ b/tlscommon.c @@ -702,11 +702,28 @@ static int regexMatcher(char* pattern, char* str) { } static char* calculateLenOfLabel(int len) { - char str[3]; - sprintf(str, "%d", len); - debug(DBG_DBG, "str : %s", str); + + // int x = -42; + // int length = snprintf( NULL, 0, "%d", x ); + // char* str = malloc( length + 1 ); + // snprintf( str, length + 1, "%d", x ); + // ... + // free(str); + + int length = snprintf(NULL, 0, "%d", len); + char* str = (char*) calloc(length+1); + if(str == NULL) { + return NULL; + } + snprintf(str, length+1, "%d", len); char* result = append(3, "{0,", str, "}"); + free(str); return result; + + // char str[3]; + // sprintf(str, "%d", len); + // char* result = append(3, "{0,", str, "}"); + // return result; } // compareWithModifiedHostname generates a regular expression based on the first label present From 834d6c9481b1e7895472fedf0aa4c6c4369b45c9 Mon Sep 17 00:00:00 2001 From: KarthikaRajendran11 Date: Wed, 23 Mar 2022 14:03:50 -0400 Subject: [PATCH 17/18] Cleanup --- tlscommon.c | 143 ++++++++++++++++------------------------------------ 1 file changed, 43 insertions(+), 100 deletions(-) diff --git a/tlscommon.c b/tlscommon.c index 24a50b2f..f08a53c4 100644 --- a/tlscommon.c +++ b/tlscommon.c @@ -635,14 +635,12 @@ static char* concatenate(char* s1, char* s2) { } if(s1 == NULL) { result = (char*) calloc(strlen(s2) + 1, sizeof(char)); - // memcpy(result, s2, strlen(s2)); strcpy(result, s2); return result; } if(s2 == NULL) { - result = (char*) calloc(strlen(s2) + 1, sizeof(char)); - // memcpy(result, s2, strlen(s2)); - strcpy(result, s2); + result = (char*) calloc(strlen(s1) + 1, sizeof(char)); + strcpy(result, s1); return result; } result = (char*) calloc(strlen(s1) + strlen(s2) + 1, sizeof(char)); @@ -701,17 +699,9 @@ static int regexMatcher(char* pattern, char* str) { return 1; } -static char* calculateLenOfLabel(int len) { - - // int x = -42; - // int length = snprintf( NULL, 0, "%d", x ); - // char* str = malloc( length + 1 ); - // snprintf( str, length + 1, "%d", x ); - // ... - // free(str); - +static char* convertLenToString(int len) { int length = snprintf(NULL, 0, "%d", len); - char* str = (char*) calloc(length+1); + char* str = (char*) calloc(length+1, sizeof(char)); if(str == NULL) { return NULL; } @@ -719,11 +709,6 @@ static char* calculateLenOfLabel(int len) { char* result = append(3, "{0,", str, "}"); free(str); return result; - - // char str[3]; - // sprintf(str, "%d", len); - // char* result = append(3, "{0,", str, "}"); - // return result; } // compareWithModifiedHostname generates a regular expression based on the first label present @@ -741,157 +726,115 @@ static char* calculateLenOfLabel(int len) { // a valid DN and let through. diseñolatinoamericano.com => xn--diseolatinoamericano-66b.com will also be // let through. So IDNs are passed in Punycode encoded and xn-- says everything that follows is unicode encoded. static int compareWithModifiedHostname(char* certDNS, char* hostname) { + + int retCode = 0; char* firstPorCertDNS = extractFirstPortion(certDNS, '.'); + char* pattern = NULL; + char* lenRegex = NULL; + if(firstPorCertDNS == NULL) { return retCode; } char* firstPorHostName = extractFirstPortion(hostname, '.'); if(firstPorHostName == NULL) { - // free(firstPorCertDNS); - // return 0; - goto cleanupInit; + goto cleanup; } - char* pattern = NULL; char* regex2 = "[a-zA-Z0-9-]"; char* startRegex = "^"; char* endRregex = "$"; char* wildcard = "*"; - - int retCode = 0; // Handles *.3af521.net (cert DNS) and idp.3af521.net (host name) case if(strlen(firstPorCertDNS) == 1 && firstPorCertDNS[0] == '*') { char* lastPorHostName = strchr(hostname, '.'); if(lastPorHostName == NULL) { - // free(firstPorCertDNS); - // free(firstPorHostName); - // return 0; - goto cleanupFirstPortions; + goto cleanup; } char* modifiedHostName = append(2, wildcard, lastPorHostName); if(modifiedHostName == NULL) { - // free(firstPorCertDNS); - // free(firstPorHostName); - // return 0; - goto cleanupFirstPortions; + goto cleanup; } if(strlen(modifiedHostName) == strlen(certDNS) && memcmp(modifiedHostName, certDNS, strlen(certDNS)) == 0) { - // free(modifiedHostName); - // free(firstPorCertDNS); - // free(firstPorHostName); - // return 1; retCode = 1; goto cleanupBlock; } - // free(modifiedHostName); - // free(firstPorCertDNS); - // free(firstPorHostName); - // return 0; goto cleanupBlock; cleanupBlock: - free(firstPorCertDNS); - free(firstPorHostName); - free(modifiedHostName); + if(firstPorCertDNS != NULL) { + free(firstPorCertDNS); + } + if(firstPorHostName != NULL) { + free(firstPorHostName); + } + if(modifiedHostName != NULL) { + free(modifiedHostName); + } return retCode; } char* asteriskPos = strchr(firstPorCertDNS, '*'); if(asteriskPos == NULL) { - // free(firstPorCertDNS); - // free(firstPorHostName); - // return 0; - goto cleanupFirstPortions; + goto cleanup; } - char* lenRegex = calculateLenOfLabel(63 - strlen(firstPorCertDNS) - 1); + lenRegex = convertLenToString(63 - strlen(firstPorCertDNS) - 1); if(lenRegex == NULL) { - // free(firstPorCertDNS); - // free(firstPorHostName); - // return 0; - goto cleanupFirstPortions; + goto cleanup; } if(firstPorCertDNS[0] == '*') { char* regex1 = "^[a-z0-9A-Z][a-z0-9A-Z-]"; pattern = append(4, regex1, lenRegex, asteriskPos + 1, endRregex); if(pattern == NULL) { - // free(firstPorCertDNS); - // free(firstPorHostName); - // free(lenRegex); - // return 0; - goto cleanupWOPattern; + goto cleanup; } } else if(firstPorCertDNS[strlen(firstPorCertDNS)-1] == '*') { char* regex1 = extractFirstPortion(firstPorCertDNS, '*'); if(regex1 == NULL) { - // free(firstPorCertDNS); - // free(firstPorHostName); - // free(lenRegex); - // return 0; - goto cleanupWOPattern; + goto cleanup; } pattern = append(5, startRegex, regex1, regex2, lenRegex, endRregex); if(pattern == NULL) { - // free(firstPorCertDNS); - // free(firstPorHostName); - // free(lenRegex); - // return 0; free(regex1); goto cleanup; } - // free(regex1); + free(regex1); } else { char* regex1 = extractFirstPortion(firstPorCertDNS, '*'); if(regex1 == NULL) { - // free(firstPorCertDNS); - // free(firstPorHostName); - // return 0; - goto cleanupWOPattern; + goto cleanup; } pattern = append(6, startRegex, regex1, regex2, lenRegex, asteriskPos + 1, endRregex); if(pattern == NULL) { - // free(firstPorCertDNS); - // free(firstPorHostName); - // free(lenRegex); - // return 0; free(regex1); goto cleanup; } - // free(regex1); + free(regex1); } if(regexMatcher(pattern, firstPorHostName)) { - // free(lenRegex); - // free(pattern); - // free(firstPorCertDNS); - // free(firstPorHostName); - // return 1; - goto cleanup; retCode = 1; } - cleanupInit: - free(firstPorCertDNS); - - cleanupFirstPortions: - free(firstPorCertDNS); - free(firstPorHostName); - - cleanupWOPattern: - free(firstPorCertDNS); - free(firstPorHostName); - free(lenRegex); + goto cleanup; cleanup: - free(lenRegex); - free(pattern); - free(firstPorCertDNS); - free(firstPorHostName); - - return retCode; + if(firstPorCertDNS != NULL) { + free(firstPorCertDNS); + } + if(firstPorHostName != NULL) { + free(firstPorHostName); + } + if(lenRegex != NULL) { + free(lenRegex); + } + if(pattern != NULL) { + free(pattern); + } + return retCode; } static int _general_name_regex_match(char *v, int l, struct certattrmatch *match) { From 4f8c53ef0d67eecb51f6b9856690ec1febf653fc Mon Sep 17 00:00:00 2001 From: KarthikaRajendran11 Date: Thu, 24 Mar 2022 12:34:16 -0400 Subject: [PATCH 18/18] Replace 1st memcpy with strcpy --- tlscommon.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tlscommon.c b/tlscommon.c index f08a53c4..3b892aff 100644 --- a/tlscommon.c +++ b/tlscommon.c @@ -647,7 +647,7 @@ static char* concatenate(char* s1, char* s2) { if(result == NULL) { return NULL; } - memcpy(result, s1, strlen(s1)); + strcpy(result, s1); memcpy(result + strlen(s1), s2, strlen(s2)); return result; }