Compare commits
6 Commits
eb4b9c9f7e
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
8e4f6498e8
|
|||
|
1eb4cdc288
|
|||
|
e877a18abf
|
|||
|
80abb9e4dd
|
|||
|
49592ed4c0
|
|||
|
4bde414964
|
1
.gitignore
vendored
1
.gitignore
vendored
@@ -4,3 +4,4 @@ fireproxy
|
|||||||
certs/
|
certs/
|
||||||
|
|
||||||
ca/
|
ca/
|
||||||
|
*.log
|
||||||
|
|||||||
@@ -9,6 +9,12 @@ FireProxy is a lightweight HTTP proxy server written in C that intercepts web re
|
|||||||
- Uses hnsdoh.com as the DoH provider
|
- Uses hnsdoh.com as the DoH provider
|
||||||
- Multithreaded connection handling
|
- Multithreaded connection handling
|
||||||
|
|
||||||
|
## Install Dependencies
|
||||||
|
### Ubuntu/Debian (or similar)
|
||||||
|
```bash
|
||||||
|
apt install libssl-dev libcurl4-openssl-dev build-essential
|
||||||
|
```
|
||||||
|
|
||||||
## Building
|
## Building
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
|
|||||||
436
src/dane.c
436
src/dane.c
@@ -13,89 +13,135 @@
|
|||||||
#include <openssl/sha.h> // For SHA256 and SHA512 functions
|
#include <openssl/sha.h> // For SHA256 and SHA512 functions
|
||||||
#include <sys/stat.h> // For mkdir
|
#include <sys/stat.h> // For mkdir
|
||||||
#include <sys/types.h> // For mkdir
|
#include <sys/types.h> // For mkdir
|
||||||
|
#include <dirent.h> // For directory operations
|
||||||
|
#include <limits.h> // For PATH_MAX
|
||||||
#include <errno.h> // For errno and EEXIST
|
#include <errno.h> // For errno and EEXIST
|
||||||
|
|
||||||
#define CA_CERT_FILE "ca/ca_cert.pem"
|
#define CA_CERT_FILE "ca/ca_cert.pem"
|
||||||
#define CA_KEY_FILE "ca/ca_key.pem"
|
#define CA_KEY_FILE "ca/ca_key.pem"
|
||||||
#define CERT_DIR "certs"
|
#define CERT_DIR "certs"
|
||||||
|
#define DANE_LOG_FILE "dane.log"
|
||||||
|
#define LOG_ERROR 0
|
||||||
|
#define LOG_WARNING 1
|
||||||
|
#define LOG_INFO 2
|
||||||
|
#define LOG_DEBUG 3
|
||||||
|
|
||||||
|
static int log_level = LOG_INFO;
|
||||||
|
static FILE* log_file = NULL;
|
||||||
|
|
||||||
static X509* ca_cert = NULL;
|
static X509* ca_cert = NULL;
|
||||||
static EVP_PKEY* ca_key = NULL;
|
static EVP_PKEY* ca_key = NULL;
|
||||||
|
|
||||||
|
// Initialize logging
|
||||||
|
static void init_logging() {
|
||||||
|
log_file = fopen(DANE_LOG_FILE, "a");
|
||||||
|
if (!log_file) {
|
||||||
|
fprintf(stderr, "Warning: Unable to open log file. Logging to stderr.\n");
|
||||||
|
log_file = stderr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close log file
|
||||||
|
static void close_logging() {
|
||||||
|
if (log_file != NULL && log_file != stderr) {
|
||||||
|
fclose(log_file);
|
||||||
|
log_file = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Log message with specific level
|
||||||
|
static void log_message(int level, const char* format, ...) {
|
||||||
|
if (log_file == NULL) {
|
||||||
|
init_logging();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (level <= log_level) {
|
||||||
|
va_list args;
|
||||||
|
time_t now;
|
||||||
|
struct tm* timeinfo;
|
||||||
|
char timestamp[20];
|
||||||
|
|
||||||
|
time(&now);
|
||||||
|
timeinfo = localtime(&now);
|
||||||
|
strftime(timestamp, sizeof(timestamp), "%Y-%m-%d %H:%M:%S", timeinfo);
|
||||||
|
|
||||||
|
const char* level_str = "UNKNOWN";
|
||||||
|
switch (level) {
|
||||||
|
case LOG_ERROR: level_str = "ERROR"; break;
|
||||||
|
case LOG_WARNING: level_str = "WARNING"; break;
|
||||||
|
case LOG_INFO: level_str = "INFO"; break;
|
||||||
|
case LOG_DEBUG: level_str = "DEBUG"; break;
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf(log_file, "[%s] [%s] ", timestamp, level_str);
|
||||||
|
|
||||||
|
va_start(args, format);
|
||||||
|
vfprintf(log_file, format, args);
|
||||||
|
va_end(args);
|
||||||
|
|
||||||
|
fprintf(log_file, "\n");
|
||||||
|
fflush(log_file);
|
||||||
|
|
||||||
|
// Critical errors should also go to stderr
|
||||||
|
if (level == LOG_ERROR && log_file != stderr) {
|
||||||
|
va_start(args, format);
|
||||||
|
fprintf(stderr, "Error: ");
|
||||||
|
vfprintf(stderr, format, args);
|
||||||
|
fprintf(stderr, "\n");
|
||||||
|
va_end(args);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Helper function to print TLSA record information
|
// Helper function to print TLSA record information
|
||||||
static void print_tlsa_record(const tlsa_record* record, int index) {
|
static void print_tlsa_record(const tlsa_record* record, int index) {
|
||||||
printf("\n=== TLSA Record #%d ===\n", index + 1);
|
log_message(LOG_DEBUG, "=== TLSA Record #%d ===", index + 1);
|
||||||
|
|
||||||
// Print usage field information
|
// Print usage field information
|
||||||
printf("Usage: %d (", record->usage);
|
const char* usage_str = "Unknown";
|
||||||
switch (record->usage) {
|
switch (record->usage) {
|
||||||
case 0:
|
case 0: usage_str = "PKIX-TA - CA certificate"; break;
|
||||||
printf("PKIX-TA - CA certificate");
|
case 1: usage_str = "PKIX-EE - End entity certificate"; break;
|
||||||
break;
|
case 2: usage_str = "DANE-TA - Trust anchor certificate"; break;
|
||||||
case 1:
|
case 3: usage_str = "DANE-EE - Domain issued certificate"; break;
|
||||||
printf("PKIX-EE - End entity certificate");
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
printf("DANE-TA - Trust anchor certificate");
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
printf("DANE-EE - Domain issued certificate");
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
printf("Unknown");
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
printf(")\n");
|
log_message(LOG_DEBUG, "Usage: %d (%s)", record->usage, usage_str);
|
||||||
|
|
||||||
// Print selector field information
|
// Print selector field information
|
||||||
printf("Selector: %d (", record->selector);
|
const char* selector_str = "Unknown";
|
||||||
switch (record->selector) {
|
switch (record->selector) {
|
||||||
case 0:
|
case 0: selector_str = "Full certificate"; break;
|
||||||
printf("Full certificate");
|
case 1: selector_str = "SubjectPublicKeyInfo"; break;
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
printf("SubjectPublicKeyInfo");
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
printf("Unknown");
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
printf(")\n");
|
log_message(LOG_DEBUG, "Selector: %d (%s)", record->selector, selector_str);
|
||||||
|
|
||||||
// Print matching type field information
|
// Print matching type field information
|
||||||
printf("Matching Type: %d (", record->matching_type);
|
const char* matching_type_str = "Unknown";
|
||||||
switch (record->matching_type) {
|
switch (record->matching_type) {
|
||||||
case 0:
|
case 0: matching_type_str = "Exact match"; break;
|
||||||
printf("Exact match");
|
case 1: matching_type_str = "SHA-256 hash"; break;
|
||||||
break;
|
case 2: matching_type_str = "SHA-512 hash"; break;
|
||||||
case 1:
|
|
||||||
printf("SHA-256 hash");
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
printf("SHA-512 hash");
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
printf("Unknown");
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
printf(")\n");
|
log_message(LOG_DEBUG, "Matching Type: %d (%s)", record->matching_type, matching_type_str);
|
||||||
|
|
||||||
// Print certificate association data as hex dump
|
// Print certificate association data as hex dump to log
|
||||||
printf("Certificate Association Data (%zu bytes):\n", record->data_len);
|
log_message(LOG_DEBUG, "Certificate Association Data (%zu bytes):", record->data_len);
|
||||||
|
char hex_line[100];
|
||||||
|
char* p;
|
||||||
for (size_t i = 0; i < record->data_len; i++) {
|
for (size_t i = 0; i < record->data_len; i++) {
|
||||||
if (i % 16 == 0) {
|
if (i % 16 == 0) {
|
||||||
printf(" %04zx: ", i);
|
p = hex_line;
|
||||||
|
p += sprintf(p, " %04zx: ", i);
|
||||||
}
|
}
|
||||||
printf("%02x", record->data[i]);
|
p += sprintf(p, "%02x", record->data[i]);
|
||||||
if ((i + 1) % 16 == 0 || i + 1 == record->data_len) {
|
if ((i + 1) % 16 == 0 || i + 1 == record->data_len) {
|
||||||
printf("\n");
|
log_message(LOG_DEBUG, "%s", hex_line);
|
||||||
} else if ((i + 1) % 8 == 0) {
|
} else if ((i + 1) % 8 == 0) {
|
||||||
printf(" ");
|
p += sprintf(p, " ");
|
||||||
} else {
|
} else {
|
||||||
printf(" ");
|
p += sprintf(p, " ");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
printf("\n");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get TLSA record for a domain
|
// Get TLSA record for a domain
|
||||||
@@ -103,8 +149,6 @@ static int get_tlsa_records(const char* hostname, tlsa_record** records, int* re
|
|||||||
char dns_query[256];
|
char dns_query[256];
|
||||||
sprintf(dns_query, "_443._tcp.%s", hostname);
|
sprintf(dns_query, "_443._tcp.%s", hostname);
|
||||||
|
|
||||||
printf("Looking up TLSA records for %s\n", dns_query);
|
|
||||||
|
|
||||||
// Initialize the record count and records array
|
// Initialize the record count and records array
|
||||||
*record_count = 0;
|
*record_count = 0;
|
||||||
*records = NULL;
|
*records = NULL;
|
||||||
@@ -114,12 +158,12 @@ static int get_tlsa_records(const char* hostname, tlsa_record** records, int* re
|
|||||||
int raw_record_count = 0;
|
int raw_record_count = 0;
|
||||||
|
|
||||||
if (query_tlsa_records_doh(hostname, &raw_records, &raw_record_count) != 0 || raw_record_count == 0) {
|
if (query_tlsa_records_doh(hostname, &raw_records, &raw_record_count) != 0 || raw_record_count == 0) {
|
||||||
// If no records found, return that DANE is not available
|
// If no records found, return silently
|
||||||
printf("No TLSA records found for %s\n", hostname);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("Found %d real TLSA records\n", raw_record_count);
|
// Only log if TLSA records are found
|
||||||
|
log_message(LOG_INFO, "Found %d TLSA records for %s", raw_record_count, hostname);
|
||||||
|
|
||||||
// Allocate memory for TLSA records
|
// Allocate memory for TLSA records
|
||||||
*records = malloc(raw_record_count * sizeof(tlsa_record));
|
*records = malloc(raw_record_count * sizeof(tlsa_record));
|
||||||
@@ -216,14 +260,14 @@ static int extract_and_hash_cert(X509* cert, int selector, int matching_type,
|
|||||||
// Full certificate
|
// Full certificate
|
||||||
data_len = i2d_X509(cert, &data);
|
data_len = i2d_X509(cert, &data);
|
||||||
if (data_len <= 0) {
|
if (data_len <= 0) {
|
||||||
fprintf(stderr, "Failed to convert certificate to DER format\n");
|
log_message(LOG_ERROR, "Failed to convert certificate to DER format");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
} else if (selector == 1) {
|
} else if (selector == 1) {
|
||||||
// Subject Public Key Info
|
// Subject Public Key Info
|
||||||
EVP_PKEY* pubkey = X509_get_pubkey(cert);
|
EVP_PKEY* pubkey = X509_get_pubkey(cert);
|
||||||
if (!pubkey) {
|
if (!pubkey) {
|
||||||
fprintf(stderr, "Failed to extract public key from certificate\n");
|
log_message(LOG_ERROR, "Failed to extract public key from certificate");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -232,11 +276,11 @@ static int extract_and_hash_cert(X509* cert, int selector, int matching_type,
|
|||||||
EVP_PKEY_free(pubkey);
|
EVP_PKEY_free(pubkey);
|
||||||
|
|
||||||
if (data_len <= 0) {
|
if (data_len <= 0) {
|
||||||
fprintf(stderr, "Failed to convert public key to DER format\n");
|
log_message(LOG_ERROR, "Failed to convert public key to DER format");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
fprintf(stderr, "Unsupported selector: %d\n", selector);
|
log_message(LOG_ERROR, "Unsupported selector: %d", selector);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -251,7 +295,7 @@ static int extract_and_hash_cert(X509* cert, int selector, int matching_type,
|
|||||||
hash = malloc(SHA256_DIGEST_LENGTH);
|
hash = malloc(SHA256_DIGEST_LENGTH);
|
||||||
if (!hash) {
|
if (!hash) {
|
||||||
OPENSSL_free(data);
|
OPENSSL_free(data);
|
||||||
fprintf(stderr, "Failed to allocate memory for SHA-256 hash\n");
|
log_message(LOG_ERROR, "Failed to allocate memory for SHA-256 hash");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -266,7 +310,7 @@ static int extract_and_hash_cert(X509* cert, int selector, int matching_type,
|
|||||||
hash = malloc(SHA512_DIGEST_LENGTH);
|
hash = malloc(SHA512_DIGEST_LENGTH);
|
||||||
if (!hash) {
|
if (!hash) {
|
||||||
OPENSSL_free(data);
|
OPENSSL_free(data);
|
||||||
fprintf(stderr, "Failed to allocate memory for SHA-512 hash\n");
|
log_message(LOG_ERROR, "Failed to allocate memory for SHA-512 hash");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -278,7 +322,7 @@ static int extract_and_hash_cert(X509* cert, int selector, int matching_type,
|
|||||||
return 1;
|
return 1;
|
||||||
} else {
|
} else {
|
||||||
OPENSSL_free(data);
|
OPENSSL_free(data);
|
||||||
fprintf(stderr, "Unsupported matching type: %d\n", matching_type);
|
log_message(LOG_ERROR, "Unsupported matching type: %d", matching_type);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -287,68 +331,162 @@ static int extract_and_hash_cert(X509* cert, int selector, int matching_type,
|
|||||||
static int compare_hashes(const unsigned char* expected, size_t expected_len,
|
static int compare_hashes(const unsigned char* expected, size_t expected_len,
|
||||||
const unsigned char* actual, size_t actual_len) {
|
const unsigned char* actual, size_t actual_len) {
|
||||||
if (expected_len != actual_len) {
|
if (expected_len != actual_len) {
|
||||||
printf("Hash length mismatch: expected %zu bytes, got %zu bytes\n", expected_len, actual_len);
|
log_message(LOG_WARNING, "Hash length mismatch: expected %zu bytes, got %zu bytes", expected_len, actual_len);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int result = memcmp(expected, actual, expected_len) == 0;
|
int result = memcmp(expected, actual, expected_len) == 0;
|
||||||
|
|
||||||
printf("Certificate hash comparison: %s\n", result ? "MATCH" : "MISMATCH");
|
log_message(LOG_INFO, "Certificate hash comparison: %s", result ? "MATCH" : "MISMATCH");
|
||||||
|
|
||||||
printf("Expected hash:\n");
|
log_message(LOG_DEBUG, "Expected hash:");
|
||||||
|
char hex_line[100];
|
||||||
|
char* p;
|
||||||
for (size_t i = 0; i < expected_len; i++) {
|
for (size_t i = 0; i < expected_len; i++) {
|
||||||
if (i % 16 == 0) {
|
if (i % 16 == 0) {
|
||||||
printf(" %04zx: ", i);
|
p = hex_line;
|
||||||
|
p += sprintf(p, " %04zx: ", i);
|
||||||
}
|
}
|
||||||
printf("%02x", expected[i]);
|
p += sprintf(p, "%02x", expected[i]);
|
||||||
if ((i + 1) % 16 == 0 || i + 1 == expected_len) {
|
if ((i + 1) % 16 == 0 || i + 1 == expected_len) {
|
||||||
printf("\n");
|
log_message(LOG_DEBUG, "%s", hex_line);
|
||||||
} else if ((i + 1) % 8 == 0) {
|
} else if ((i + 1) % 8 == 0) {
|
||||||
printf(" ");
|
p += sprintf(p, " ");
|
||||||
} else {
|
} else {
|
||||||
printf(" ");
|
p += sprintf(p, " ");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("Actual hash:\n");
|
log_message(LOG_DEBUG, "Actual hash:");
|
||||||
for (size_t i = 0; i < actual_len; i++) {
|
for (size_t i = 0; i < actual_len; i++) {
|
||||||
if (i % 16 == 0) {
|
if (i % 16 == 0) {
|
||||||
printf(" %04zx: ", i);
|
p = hex_line;
|
||||||
|
p += sprintf(p, " %04zx: ", i);
|
||||||
}
|
}
|
||||||
printf("%02x", actual[i]);
|
p += sprintf(p, "%02x", actual[i]);
|
||||||
if ((i + 1) % 16 == 0 || i + 1 == actual_len) {
|
if ((i + 1) % 16 == 0 || i + 1 == actual_len) {
|
||||||
printf("\n");
|
log_message(LOG_DEBUG, "%s", hex_line);
|
||||||
} else if ((i + 1) % 8 == 0) {
|
} else if ((i + 1) % 8 == 0) {
|
||||||
printf(" ");
|
p += sprintf(p, " ");
|
||||||
} else {
|
} else {
|
||||||
printf(" ");
|
p += sprintf(p, " ");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
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 verbose) {
|
||||||
|
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)) {
|
||||||
|
if (verbose) {
|
||||||
|
log_message(LOG_INFO, "Domain matches certificate Common Name: %s", common_name);
|
||||||
|
}
|
||||||
|
valid = 1;
|
||||||
|
} else if (verbose) {
|
||||||
|
log_message(LOG_INFO, "Domain does not match certificate Common Name: %s", 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);
|
||||||
|
if (verbose) {
|
||||||
|
log_message(LOG_INFO, "Certificate has %d Subject Alternative Names", 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)) {
|
||||||
|
if (verbose) {
|
||||||
|
log_message(LOG_INFO, "Domain matches SAN: %s", dns_name);
|
||||||
|
}
|
||||||
|
valid = 1;
|
||||||
|
break;
|
||||||
|
} else if (verbose) {
|
||||||
|
log_message(LOG_INFO, "Domain does not match SAN: %s", dns_name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sk_GENERAL_NAME_pop_free(san_names, GENERAL_NAME_free);
|
||||||
|
} else if (verbose) {
|
||||||
|
log_message(LOG_INFO, "Certificate has no Subject Alternative Names");
|
||||||
|
}
|
||||||
|
|
||||||
|
return valid;
|
||||||
|
}
|
||||||
|
|
||||||
// Verify a certificate against DANE TLSA records
|
// Verify a certificate against DANE TLSA records
|
||||||
int verify_cert_against_dane(const char* hostname, X509* cert) {
|
int verify_cert_against_dane(const char* hostname, X509* cert) {
|
||||||
tlsa_record* records = NULL;
|
tlsa_record* records = NULL;
|
||||||
int record_count = 0;
|
int record_count = 0;
|
||||||
int verified = 0;
|
int dane_verified = 0;
|
||||||
|
int domain_verified = 0;
|
||||||
|
|
||||||
if (!cert) {
|
if (!cert) {
|
||||||
fprintf(stderr, "No certificate provided for DANE verification\n");
|
log_message(LOG_ERROR, "No certificate provided for DANE verification");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!get_tlsa_records(hostname, &records, &record_count)) {
|
// Get TLSA records first to determine if we should do verbose logging
|
||||||
return -1;
|
int has_tlsa = get_tlsa_records(hostname, &records, &record_count);
|
||||||
}
|
|
||||||
|
|
||||||
if (record_count == 0) {
|
if (!has_tlsa || record_count == 0) {
|
||||||
|
// No TLSA records, return silently
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Print records that will be used for verification
|
// Now that we know the domain has TLSA records, do verbose domain validation
|
||||||
printf("\n=== Starting DANE verification for %s ===\n", hostname);
|
domain_verified = validate_cert_domain(cert, hostname, 1);
|
||||||
|
if (!domain_verified) {
|
||||||
|
log_message(LOG_ERROR, "Certificate is not valid for domain: %s", hostname);
|
||||||
|
// Clean up records
|
||||||
|
for (int i = 0; i < record_count; i++) {
|
||||||
|
if (records[i].data) {
|
||||||
|
free(records[i].data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
free(records);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
log_message(LOG_INFO, "Certificate domain validation successful for: %s", hostname);
|
||||||
|
printf("DANE: Verifying certificate for %s...\n", hostname);
|
||||||
|
|
||||||
|
// Log records that will be used for verification
|
||||||
|
log_message(LOG_DEBUG, "=== Starting DANE verification for %s ===", hostname);
|
||||||
for (int i = 0; i < record_count; i++) {
|
for (int i = 0; i < record_count; i++) {
|
||||||
print_tlsa_record(&records[i], i);
|
print_tlsa_record(&records[i], i);
|
||||||
}
|
}
|
||||||
@@ -357,7 +495,7 @@ int verify_cert_against_dane(const char* hostname, X509* cert) {
|
|||||||
for (int i = 0; i < record_count; i++) {
|
for (int i = 0; i < record_count; i++) {
|
||||||
tlsa_record* record = &records[i];
|
tlsa_record* record = &records[i];
|
||||||
|
|
||||||
printf("\nVerifying certificate against TLSA record #%d...\n", i + 1);
|
log_message(LOG_DEBUG, "Verifying certificate against TLSA record #%d...", i + 1);
|
||||||
|
|
||||||
// Generate the certificate hash based on selector and matching type
|
// Generate the certificate hash based on selector and matching type
|
||||||
unsigned char* cert_hash = NULL;
|
unsigned char* cert_hash = NULL;
|
||||||
@@ -365,7 +503,7 @@ int verify_cert_against_dane(const char* hostname, X509* cert) {
|
|||||||
|
|
||||||
if (!extract_and_hash_cert(cert, record->selector, record->matching_type,
|
if (!extract_and_hash_cert(cert, record->selector, record->matching_type,
|
||||||
&cert_hash, &cert_hash_len)) {
|
&cert_hash, &cert_hash_len)) {
|
||||||
fprintf(stderr, "Failed to extract and hash certificate\n");
|
log_message(LOG_ERROR, "Failed to extract and hash certificate");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -373,41 +511,48 @@ int verify_cert_against_dane(const char* hostname, X509* cert) {
|
|||||||
switch (record->usage) {
|
switch (record->usage) {
|
||||||
case 0: // PKIX-TA - CA constraint
|
case 0: // PKIX-TA - CA constraint
|
||||||
// Not implemented in this simplified version
|
// Not implemented in this simplified version
|
||||||
printf("PKIX-TA validation not implemented\n");
|
log_message(LOG_INFO, "PKIX-TA validation not implemented");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 1: // PKIX-EE - Service certificate constraint
|
case 1: // PKIX-EE - Service certificate constraint
|
||||||
// Not implemented in this simplified version
|
// Not implemented in this simplified version
|
||||||
printf("PKIX-EE validation not implemented\n");
|
log_message(LOG_INFO, "PKIX-EE validation not implemented");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 2: // DANE-TA - Trust anchor assertion
|
case 2: // DANE-TA - Trust anchor assertion
|
||||||
// Not implemented in this simplified version
|
// Not implemented in this simplified version
|
||||||
printf("DANE-TA validation not implemented\n");
|
log_message(LOG_INFO, "DANE-TA validation not implemented");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 3: // DANE-EE (3) - Domain-issued certificate
|
case 3: // DANE-EE (3) - Domain-issued certificate
|
||||||
// Verify the certificate directly against the TLSA record
|
// Verify the certificate directly against the TLSA record
|
||||||
printf("Performing DANE-EE validation...\n");
|
log_message(LOG_INFO, "Performing DANE-EE validation...");
|
||||||
verified = compare_hashes(record->data, record->data_len,
|
dane_verified = compare_hashes(record->data, record->data_len,
|
||||||
cert_hash, cert_hash_len);
|
cert_hash, cert_hash_len);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
// Unknown usage type
|
// Unknown usage type
|
||||||
printf("Unknown usage type: %d\n", record->usage);
|
log_message(LOG_WARNING, "Unknown usage type: %d", record->usage);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
free(cert_hash);
|
free(cert_hash);
|
||||||
|
|
||||||
if (verified) {
|
if (dane_verified) {
|
||||||
printf("DANE verification succeeded for record #%d\n", i + 1);
|
log_message(LOG_INFO, "DANE verification succeeded for record #%d", i + 1);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("\nDANE verification result: %s\n", verified ? "SUCCESS" : "FAILED");
|
int verified = domain_verified && dane_verified;
|
||||||
|
log_message(LOG_INFO, "Domain verification: %s", domain_verified ? "SUCCESS" : "FAILED");
|
||||||
|
log_message(LOG_INFO, "DANE verification: %s", dane_verified ? "SUCCESS" : "FAILED");
|
||||||
|
log_message(LOG_INFO, "Overall verification result: %s", verified ? "SUCCESS" : "FAILED");
|
||||||
|
|
||||||
|
// Show minimal output to console
|
||||||
|
printf("DANE: Verification %s for %s\n",
|
||||||
|
verified ? "SUCCEEDED" : "FAILED", hostname);
|
||||||
|
|
||||||
// Clean up
|
// Clean up
|
||||||
for (int i = 0; i < record_count; i++) {
|
for (int i = 0; i < record_count; i++) {
|
||||||
@@ -448,11 +593,12 @@ static int create_cert_directories() {
|
|||||||
static int generate_ca_cert() {
|
static int generate_ca_cert() {
|
||||||
// Check if CA certificate already exists
|
// Check if CA certificate already exists
|
||||||
if (access(CA_CERT_FILE, F_OK) == 0 && access(CA_KEY_FILE, F_OK) == 0) {
|
if (access(CA_CERT_FILE, F_OK) == 0 && access(CA_KEY_FILE, F_OK) == 0) {
|
||||||
printf("CA certificate already exists\n");
|
log_message(LOG_INFO, "CA certificate already exists");
|
||||||
|
|
||||||
// Load the existing CA certificate and key
|
// Load the existing CA certificate and key
|
||||||
FILE* ca_cert_file = fopen(CA_CERT_FILE, "r");
|
FILE* ca_cert_file = fopen(CA_CERT_FILE, "r");
|
||||||
if (!ca_cert_file) {
|
if (!ca_cert_file) {
|
||||||
perror("Failed to open CA certificate file");
|
log_message(LOG_ERROR, "Failed to open CA certificate file");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -460,13 +606,13 @@ static int generate_ca_cert() {
|
|||||||
fclose(ca_cert_file);
|
fclose(ca_cert_file);
|
||||||
|
|
||||||
if (!ca_cert) {
|
if (!ca_cert) {
|
||||||
fprintf(stderr, "Failed to read CA certificate\n");
|
log_message(LOG_ERROR, "Failed to read CA certificate");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
FILE* ca_key_file = fopen(CA_KEY_FILE, "r");
|
FILE* ca_key_file = fopen(CA_KEY_FILE, "r");
|
||||||
if (!ca_key_file) {
|
if (!ca_key_file) {
|
||||||
perror("Failed to open CA key file");
|
log_message(LOG_ERROR, "Failed to open CA key file");
|
||||||
X509_free(ca_cert);
|
X509_free(ca_cert);
|
||||||
ca_cert = NULL;
|
ca_cert = NULL;
|
||||||
return 0;
|
return 0;
|
||||||
@@ -476,7 +622,7 @@ static int generate_ca_cert() {
|
|||||||
fclose(ca_key_file);
|
fclose(ca_key_file);
|
||||||
|
|
||||||
if (!ca_key) {
|
if (!ca_key) {
|
||||||
fprintf(stderr, "Failed to read CA key\n");
|
log_message(LOG_ERROR, "Failed to read CA key");
|
||||||
X509_free(ca_cert);
|
X509_free(ca_cert);
|
||||||
ca_cert = NULL;
|
ca_cert = NULL;
|
||||||
return 0;
|
return 0;
|
||||||
@@ -491,7 +637,7 @@ static int generate_ca_cert() {
|
|||||||
BIGNUM* bn = BN_new();
|
BIGNUM* bn = BN_new();
|
||||||
|
|
||||||
if (!bn) {
|
if (!bn) {
|
||||||
fprintf(stderr, "Failed to create BIGNUM\n");
|
log_message(LOG_ERROR, "Failed to create BIGNUM");
|
||||||
EVP_PKEY_free(ca_key);
|
EVP_PKEY_free(ca_key);
|
||||||
ca_key = NULL;
|
ca_key = NULL;
|
||||||
return 0;
|
return 0;
|
||||||
@@ -501,7 +647,7 @@ static int generate_ca_cert() {
|
|||||||
rsa = RSA_new();
|
rsa = RSA_new();
|
||||||
|
|
||||||
if (!rsa) {
|
if (!rsa) {
|
||||||
fprintf(stderr, "Failed to create RSA\n");
|
log_message(LOG_ERROR, "Failed to create RSA");
|
||||||
BN_free(bn);
|
BN_free(bn);
|
||||||
EVP_PKEY_free(ca_key);
|
EVP_PKEY_free(ca_key);
|
||||||
ca_key = NULL;
|
ca_key = NULL;
|
||||||
@@ -509,7 +655,7 @@ static int generate_ca_cert() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (RSA_generate_key_ex(rsa, 2048, bn, NULL) != 1) {
|
if (RSA_generate_key_ex(rsa, 2048, bn, NULL) != 1) {
|
||||||
fprintf(stderr, "Failed to generate RSA key\n");
|
log_message(LOG_ERROR, "Failed to generate RSA key");
|
||||||
RSA_free(rsa);
|
RSA_free(rsa);
|
||||||
BN_free(bn);
|
BN_free(bn);
|
||||||
EVP_PKEY_free(ca_key);
|
EVP_PKEY_free(ca_key);
|
||||||
@@ -520,7 +666,7 @@ static int generate_ca_cert() {
|
|||||||
BN_free(bn);
|
BN_free(bn);
|
||||||
|
|
||||||
if (!EVP_PKEY_assign_RSA(ca_key, rsa)) {
|
if (!EVP_PKEY_assign_RSA(ca_key, rsa)) {
|
||||||
fprintf(stderr, "Failed to assign RSA key\n");
|
log_message(LOG_ERROR, "Failed to assign RSA key");
|
||||||
RSA_free(rsa);
|
RSA_free(rsa);
|
||||||
EVP_PKEY_free(ca_key);
|
EVP_PKEY_free(ca_key);
|
||||||
ca_key = NULL;
|
ca_key = NULL;
|
||||||
@@ -543,7 +689,7 @@ static int generate_ca_cert() {
|
|||||||
X509_NAME* name = X509_get_subject_name(ca_cert);
|
X509_NAME* name = X509_get_subject_name(ca_cert);
|
||||||
X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_ASC, (unsigned char*)"FireProxy CA", -1, -1, 0);
|
X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_ASC, (unsigned char*)"FireProxy CA", -1, -1, 0);
|
||||||
X509_NAME_add_entry_by_txt(name, "O", MBSTRING_ASC, (unsigned char*)"FireProxy", -1, -1, 0);
|
X509_NAME_add_entry_by_txt(name, "O", MBSTRING_ASC, (unsigned char*)"FireProxy", -1, -1, 0);
|
||||||
X509_NAME_add_entry_by_txt(name, "C", MBSTRING_ASC, (unsigned char*)"US", -1, -1, 0);
|
X509_NAME_add_entry_by_txt(name, "C", MBSTRING_ASC, (unsigned char*)"AU", -1, -1, 0);
|
||||||
|
|
||||||
// Self-sign the certificate
|
// Self-sign the certificate
|
||||||
X509_set_issuer_name(ca_cert, name);
|
X509_set_issuer_name(ca_cert, name);
|
||||||
@@ -555,7 +701,7 @@ static int generate_ca_cert() {
|
|||||||
X509_EXTENSION* ext = X509V3_EXT_conf_nid(NULL, &ctx, NID_basic_constraints, "critical,CA:TRUE");
|
X509_EXTENSION* ext = X509V3_EXT_conf_nid(NULL, &ctx, NID_basic_constraints, "critical,CA:TRUE");
|
||||||
|
|
||||||
if (!ext) {
|
if (!ext) {
|
||||||
fprintf(stderr, "Failed to create CA extension\n");
|
log_message(LOG_ERROR, "Failed to create CA extension");
|
||||||
EVP_PKEY_free(ca_key);
|
EVP_PKEY_free(ca_key);
|
||||||
X509_free(ca_cert);
|
X509_free(ca_cert);
|
||||||
ca_key = NULL;
|
ca_key = NULL;
|
||||||
@@ -568,7 +714,7 @@ static int generate_ca_cert() {
|
|||||||
|
|
||||||
// Sign the certificate
|
// Sign the certificate
|
||||||
if (!X509_sign(ca_cert, ca_key, EVP_sha256())) {
|
if (!X509_sign(ca_cert, ca_key, EVP_sha256())) {
|
||||||
fprintf(stderr, "Failed to sign CA certificate\n");
|
log_message(LOG_ERROR, "Failed to sign CA certificate");
|
||||||
EVP_PKEY_free(ca_key);
|
EVP_PKEY_free(ca_key);
|
||||||
X509_free(ca_cert);
|
X509_free(ca_cert);
|
||||||
ca_key = NULL;
|
ca_key = NULL;
|
||||||
@@ -579,7 +725,7 @@ static int generate_ca_cert() {
|
|||||||
// Save the CA certificate and key
|
// Save the CA certificate and key
|
||||||
FILE* ca_cert_file = fopen(CA_CERT_FILE, "w");
|
FILE* ca_cert_file = fopen(CA_CERT_FILE, "w");
|
||||||
if (!ca_cert_file) {
|
if (!ca_cert_file) {
|
||||||
perror("Failed to create CA certificate file");
|
log_message(LOG_ERROR, "Failed to create CA certificate file");
|
||||||
EVP_PKEY_free(ca_key);
|
EVP_PKEY_free(ca_key);
|
||||||
X509_free(ca_cert);
|
X509_free(ca_cert);
|
||||||
ca_key = NULL;
|
ca_key = NULL;
|
||||||
@@ -592,7 +738,7 @@ static int generate_ca_cert() {
|
|||||||
|
|
||||||
FILE* ca_key_file = fopen(CA_KEY_FILE, "w");
|
FILE* ca_key_file = fopen(CA_KEY_FILE, "w");
|
||||||
if (!ca_key_file) {
|
if (!ca_key_file) {
|
||||||
perror("Failed to create CA key file");
|
log_message(LOG_ERROR, "Failed to create CA key file");
|
||||||
EVP_PKEY_free(ca_key);
|
EVP_PKEY_free(ca_key);
|
||||||
X509_free(ca_cert);
|
X509_free(ca_cert);
|
||||||
ca_key = NULL;
|
ca_key = NULL;
|
||||||
@@ -603,7 +749,7 @@ static int generate_ca_cert() {
|
|||||||
PEM_write_PrivateKey(ca_key_file, ca_key, NULL, NULL, 0, NULL, NULL);
|
PEM_write_PrivateKey(ca_key_file, ca_key, NULL, NULL, 0, NULL, NULL);
|
||||||
fclose(ca_key_file);
|
fclose(ca_key_file);
|
||||||
|
|
||||||
printf("Generated new CA certificate\n");
|
log_message(LOG_INFO, "Generated new CA certificate");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -616,13 +762,13 @@ int setup_local_ca() {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("CA setup complete\n");
|
log_message(LOG_INFO, "CA setup complete");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int generate_trusted_cert(const char* hostname, const char* cert_path, const char* key_path) {
|
int generate_trusted_cert(const char* hostname, const char* cert_path, const char* key_path) {
|
||||||
if (!ca_cert || !ca_key) {
|
if (!ca_cert || !ca_key) {
|
||||||
fprintf(stderr, "CA not initialized\n");
|
log_message(LOG_ERROR, "CA not initialized");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -632,7 +778,7 @@ int generate_trusted_cert(const char* hostname, const char* cert_path, const cha
|
|||||||
BIGNUM* bn = BN_new();
|
BIGNUM* bn = BN_new();
|
||||||
|
|
||||||
if (!bn) {
|
if (!bn) {
|
||||||
fprintf(stderr, "Failed to create BIGNUM\n");
|
log_message(LOG_ERROR, "Failed to create BIGNUM");
|
||||||
EVP_PKEY_free(pkey);
|
EVP_PKEY_free(pkey);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -641,14 +787,14 @@ int generate_trusted_cert(const char* hostname, const char* cert_path, const cha
|
|||||||
rsa = RSA_new();
|
rsa = RSA_new();
|
||||||
|
|
||||||
if (!rsa) {
|
if (!rsa) {
|
||||||
fprintf(stderr, "Failed to create RSA\n");
|
log_message(LOG_ERROR, "Failed to create RSA");
|
||||||
BN_free(bn);
|
BN_free(bn);
|
||||||
EVP_PKEY_free(pkey);
|
EVP_PKEY_free(pkey);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (RSA_generate_key_ex(rsa, 2048, bn, NULL) != 1) {
|
if (RSA_generate_key_ex(rsa, 2048, bn, NULL) != 1) {
|
||||||
fprintf(stderr, "Failed to generate RSA key\n");
|
log_message(LOG_ERROR, "Failed to generate RSA key");
|
||||||
RSA_free(rsa);
|
RSA_free(rsa);
|
||||||
BN_free(bn);
|
BN_free(bn);
|
||||||
EVP_PKEY_free(pkey);
|
EVP_PKEY_free(pkey);
|
||||||
@@ -658,7 +804,7 @@ int generate_trusted_cert(const char* hostname, const char* cert_path, const cha
|
|||||||
BN_free(bn);
|
BN_free(bn);
|
||||||
|
|
||||||
if (!EVP_PKEY_assign_RSA(pkey, rsa)) {
|
if (!EVP_PKEY_assign_RSA(pkey, rsa)) {
|
||||||
fprintf(stderr, "Failed to assign RSA key\n");
|
log_message(LOG_ERROR, "Failed to assign RSA key");
|
||||||
RSA_free(rsa);
|
RSA_free(rsa);
|
||||||
EVP_PKEY_free(pkey);
|
EVP_PKEY_free(pkey);
|
||||||
return 0;
|
return 0;
|
||||||
@@ -681,7 +827,7 @@ int generate_trusted_cert(const char* hostname, const char* cert_path, const cha
|
|||||||
// Set certificate subject
|
// Set certificate subject
|
||||||
X509_NAME* name = X509_get_subject_name(cert);
|
X509_NAME* name = X509_get_subject_name(cert);
|
||||||
X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_ASC, (unsigned char*)hostname, -1, -1, 0);
|
X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_ASC, (unsigned char*)hostname, -1, -1, 0);
|
||||||
X509_NAME_add_entry_by_txt(name, "O", MBSTRING_ASC, (unsigned char*)"FireProxy Secured", -1, -1, 0);
|
X509_NAME_add_entry_by_txt(name, "O", MBSTRING_ASC, (unsigned char*)"FireProxy", -1, -1, 0);
|
||||||
|
|
||||||
// Set certificate issuer (our CA)
|
// Set certificate issuer (our CA)
|
||||||
X509_set_issuer_name(cert, X509_get_subject_name(ca_cert));
|
X509_set_issuer_name(cert, X509_get_subject_name(ca_cert));
|
||||||
@@ -697,7 +843,7 @@ int generate_trusted_cert(const char* hostname, const char* cert_path, const cha
|
|||||||
X509_EXTENSION* ext = X509V3_EXT_conf_nid(NULL, &ctx, NID_subject_alt_name, san);
|
X509_EXTENSION* ext = X509V3_EXT_conf_nid(NULL, &ctx, NID_subject_alt_name, san);
|
||||||
|
|
||||||
if (!ext) {
|
if (!ext) {
|
||||||
fprintf(stderr, "Failed to create SAN extension\n");
|
log_message(LOG_ERROR, "Failed to create SAN extension");
|
||||||
EVP_PKEY_free(pkey);
|
EVP_PKEY_free(pkey);
|
||||||
X509_free(cert);
|
X509_free(cert);
|
||||||
return 0;
|
return 0;
|
||||||
@@ -708,7 +854,7 @@ int generate_trusted_cert(const char* hostname, const char* cert_path, const cha
|
|||||||
|
|
||||||
// Sign the certificate with our CA key
|
// Sign the certificate with our CA key
|
||||||
if (!X509_sign(cert, ca_key, EVP_sha256())) {
|
if (!X509_sign(cert, ca_key, EVP_sha256())) {
|
||||||
fprintf(stderr, "Failed to sign certificate\n");
|
log_message(LOG_ERROR, "Failed to sign certificate");
|
||||||
EVP_PKEY_free(pkey);
|
EVP_PKEY_free(pkey);
|
||||||
X509_free(cert);
|
X509_free(cert);
|
||||||
return 0;
|
return 0;
|
||||||
@@ -717,7 +863,7 @@ int generate_trusted_cert(const char* hostname, const char* cert_path, const cha
|
|||||||
// Save the certificate
|
// Save the certificate
|
||||||
FILE* cert_file = fopen(cert_path, "w");
|
FILE* cert_file = fopen(cert_path, "w");
|
||||||
if (!cert_file) {
|
if (!cert_file) {
|
||||||
perror("Failed to create certificate file");
|
log_message(LOG_ERROR, "Failed to create certificate file");
|
||||||
EVP_PKEY_free(pkey);
|
EVP_PKEY_free(pkey);
|
||||||
X509_free(cert);
|
X509_free(cert);
|
||||||
return 0;
|
return 0;
|
||||||
@@ -729,7 +875,7 @@ int generate_trusted_cert(const char* hostname, const char* cert_path, const cha
|
|||||||
// Save the private key
|
// Save the private key
|
||||||
FILE* key_file = fopen(key_path, "w");
|
FILE* key_file = fopen(key_path, "w");
|
||||||
if (!key_file) {
|
if (!key_file) {
|
||||||
perror("Failed to create key file");
|
log_message(LOG_ERROR, "Failed to create key file");
|
||||||
EVP_PKEY_free(pkey);
|
EVP_PKEY_free(pkey);
|
||||||
X509_free(cert);
|
X509_free(cert);
|
||||||
return 0;
|
return 0;
|
||||||
@@ -742,16 +888,56 @@ int generate_trusted_cert(const char* hostname, const char* cert_path, const cha
|
|||||||
EVP_PKEY_free(pkey);
|
EVP_PKEY_free(pkey);
|
||||||
X509_free(cert);
|
X509_free(cert);
|
||||||
|
|
||||||
printf("Generated trusted certificate for %s\n", hostname);
|
log_message(LOG_INFO, "Generated trusted certificate for %s", hostname);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Function to delete all generated certificates (but not the CA certs)
|
||||||
|
static void delete_all_generated_certs() {
|
||||||
|
DIR* dir;
|
||||||
|
struct dirent* entry;
|
||||||
|
char path[PATH_MAX];
|
||||||
|
|
||||||
|
// Open the certificates directory
|
||||||
|
dir = opendir(CERT_DIR);
|
||||||
|
if (!dir) {
|
||||||
|
log_message(LOG_ERROR, "Failed to open certificates directory for cleanup");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read directory entries
|
||||||
|
while ((entry = readdir(dir)) != NULL) {
|
||||||
|
// Skip "." and ".." directories
|
||||||
|
if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// Create full path
|
||||||
|
snprintf(path, PATH_MAX, "%s/%s", CERT_DIR, entry->d_name);
|
||||||
|
|
||||||
|
// Delete the file and log the action
|
||||||
|
if (unlink(path) == 0) {
|
||||||
|
log_message(LOG_INFO, "Deleted temporary certificate: %s", path);
|
||||||
|
} else {
|
||||||
|
log_message(LOG_ERROR, "Failed to delete certificate: %s", path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
closedir(dir);
|
||||||
|
log_message(LOG_INFO, "Cleaned up all generated certificates");
|
||||||
|
}
|
||||||
|
|
||||||
int dane_init() {
|
int dane_init() {
|
||||||
init_openssl();
|
init_openssl();
|
||||||
|
init_logging();
|
||||||
|
log_message(LOG_INFO, "DANE subsystem initialized");
|
||||||
return setup_local_ca();
|
return setup_local_ca();
|
||||||
}
|
}
|
||||||
|
|
||||||
void dane_cleanup() {
|
void dane_cleanup() {
|
||||||
|
// Delete all generated certificates first
|
||||||
|
delete_all_generated_certs();
|
||||||
|
|
||||||
|
// Then clean up CA resources
|
||||||
if (ca_cert) {
|
if (ca_cert) {
|
||||||
X509_free(ca_cert);
|
X509_free(ca_cert);
|
||||||
ca_cert = NULL;
|
ca_cert = NULL;
|
||||||
@@ -762,5 +948,7 @@ void dane_cleanup() {
|
|||||||
ca_key = NULL;
|
ca_key = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
log_message(LOG_INFO, "DANE subsystem shutdown");
|
||||||
|
close_logging();
|
||||||
EVP_cleanup();
|
EVP_cleanup();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -61,4 +61,9 @@ int dane_init();
|
|||||||
*/
|
*/
|
||||||
void dane_cleanup();
|
void dane_cleanup();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set DANE log level (0=errors only, 1=warnings, 2=info, 3=debug)
|
||||||
|
*/
|
||||||
|
void dane_set_log_level(int level);
|
||||||
|
|
||||||
#endif // DANE_H
|
#endif // DANE_H
|
||||||
|
|||||||
2126
src/proxy.c
2126
src/proxy.c
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user