feat: Fix a few other issues with certs
This commit is contained in:
87
src/dane.c
87
src/dane.c
@@ -328,17 +328,93 @@ static int compare_hashes(const unsigned char* expected, size_t expected_len,
|
||||
return result;
|
||||
}
|
||||
|
||||
// Check if a domain matches a pattern (supporting wildcards)
|
||||
static int domain_matches_pattern(const char* domain, const char* pattern) {
|
||||
// Exact match
|
||||
if (strcmp(domain, pattern) == 0) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Wildcard match
|
||||
if (pattern[0] == '*' && pattern[1] == '.') {
|
||||
const char* domain_dot = strchr(domain, '.');
|
||||
if (domain_dot && strcmp(domain_dot, pattern + 1) == 0) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Validate that a certificate is valid for a given domain
|
||||
static int validate_cert_domain(X509* cert, const char* hostname) {
|
||||
int valid = 0;
|
||||
|
||||
// First check the Common Name
|
||||
X509_NAME* subject_name = X509_get_subject_name(cert);
|
||||
if (subject_name) {
|
||||
char common_name[256];
|
||||
X509_NAME_get_text_by_NID(subject_name, NID_commonName, common_name, sizeof(common_name));
|
||||
|
||||
if (domain_matches_pattern(hostname, common_name)) {
|
||||
printf("Domain matches certificate Common Name: %s\n", common_name);
|
||||
valid = 1;
|
||||
} else {
|
||||
printf("Domain does not match certificate Common Name: %s\n", common_name);
|
||||
}
|
||||
}
|
||||
|
||||
// Then check Subject Alternative Names
|
||||
STACK_OF(GENERAL_NAME)* san_names = X509_get_ext_d2i(cert, NID_subject_alt_name, NULL, NULL);
|
||||
if (san_names) {
|
||||
int san_count = sk_GENERAL_NAME_num(san_names);
|
||||
printf("Certificate has %d Subject Alternative Names\n", san_count);
|
||||
|
||||
for (int i = 0; i < san_count; i++) {
|
||||
const GENERAL_NAME* current_name = sk_GENERAL_NAME_value(san_names, i);
|
||||
|
||||
if (current_name->type == GEN_DNS) {
|
||||
const char* dns_name = (const char*)ASN1_STRING_get0_data(current_name->d.dNSName);
|
||||
|
||||
if (domain_matches_pattern(hostname, dns_name)) {
|
||||
printf("Domain matches SAN: %s\n", dns_name);
|
||||
valid = 1;
|
||||
break;
|
||||
} else {
|
||||
printf("Domain does not match SAN: %s\n", dns_name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sk_GENERAL_NAME_pop_free(san_names, GENERAL_NAME_free);
|
||||
} else {
|
||||
printf("Certificate has no Subject Alternative Names\n");
|
||||
}
|
||||
|
||||
return valid;
|
||||
}
|
||||
|
||||
// Verify a certificate against DANE TLSA records
|
||||
int verify_cert_against_dane(const char* hostname, X509* cert) {
|
||||
tlsa_record* records = NULL;
|
||||
int record_count = 0;
|
||||
int verified = 0;
|
||||
int dane_verified = 0;
|
||||
int domain_verified = 0;
|
||||
|
||||
if (!cert) {
|
||||
fprintf(stderr, "No certificate provided for DANE verification\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Verify the certificate domain
|
||||
domain_verified = validate_cert_domain(cert, hostname);
|
||||
if (!domain_verified) {
|
||||
fprintf(stderr, "Certificate is not valid for domain: %s\n", hostname);
|
||||
return 0;
|
||||
}
|
||||
|
||||
printf("Certificate domain validation successful for: %s\n", hostname);
|
||||
|
||||
if (!get_tlsa_records(hostname, &records, &record_count)) {
|
||||
return -1;
|
||||
}
|
||||
@@ -389,7 +465,7 @@ int verify_cert_against_dane(const char* hostname, X509* cert) {
|
||||
case 3: // DANE-EE (3) - Domain-issued certificate
|
||||
// Verify the certificate directly against the TLSA record
|
||||
printf("Performing DANE-EE validation...\n");
|
||||
verified = compare_hashes(record->data, record->data_len,
|
||||
dane_verified = compare_hashes(record->data, record->data_len,
|
||||
cert_hash, cert_hash_len);
|
||||
break;
|
||||
|
||||
@@ -401,13 +477,16 @@ int verify_cert_against_dane(const char* hostname, X509* cert) {
|
||||
|
||||
free(cert_hash);
|
||||
|
||||
if (verified) {
|
||||
if (dane_verified) {
|
||||
printf("DANE verification succeeded for record #%d\n", i + 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
printf("\nDANE verification result: %s\n", verified ? "SUCCESS" : "FAILED");
|
||||
int verified = domain_verified && dane_verified;
|
||||
printf("\nDomain verification: %s\n", domain_verified ? "SUCCESS" : "FAILED");
|
||||
printf("DANE verification: %s\n", dane_verified ? "SUCCESS" : "FAILED");
|
||||
printf("Overall verification result: %s\n", verified ? "SUCCESS" : "FAILED");
|
||||
|
||||
// Clean up
|
||||
for (int i = 0; i < record_count; i++) {
|
||||
|
||||
Reference in New Issue
Block a user