Start with getting files from user area

This commit is contained in:
Willem Toorop 2017-06-20 15:38:32 +02:00
parent b0af051809
commit e496d13777
4 changed files with 119 additions and 123 deletions

View File

@ -37,14 +37,13 @@
#include <openssl/x509.h>
#include <openssl/x509v3.h>
#include <openssl/err.h>
#include "types-internal.h"
#include "context.h"
#define P7SIGNER "dnssec@iana.org"
static const char*
get_builtin_cert(void)
{
return
/* The ICANN CA fetched at 24 Sep 2010. Valid to 2028 */
static const char* _getdns_builtin_cert =
"-----BEGIN CERTIFICATE-----\n"
"MIIDdzCCAl+gAwIBAgIBATANBgkqhkiG9w0BAQsFADBdMQ4wDAYDVQQKEwVJQ0FO\n"
"TjEmMCQGA1UECxMdSUNBTk4gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxFjAUBgNV\n"
@ -66,14 +65,14 @@ get_builtin_cert(void)
"0/wsHNeP22qNyVO+XVBzrM8fk8BSUFuiT/6tZTYXRtEt5aKQZgXbKU5dUF3jT9qg\n"
"j/Br5BZw3X/zd325TvnswzMC1+ljLzHnQGGk\n"
"-----END CERTIFICATE-----\n";
}
/* get key usage out of its extension, returns 0 if no key_usage extension */
static unsigned long
get_usage_of_ex(X509* cert)
_getdns_get_usage_of_ex(X509* cert)
{
unsigned long val = 0;
ASN1_BIT_STRING* s;
if((s=X509_get_ext_d2i(cert, NID_key_usage, NULL, NULL))) {
if(s->length > 0) {
val = s->data[0];
@ -89,75 +88,57 @@ get_usage_of_ex(X509* cert)
static STACK_OF(X509)*
get_valid_signers(PKCS7* p7, const char* p7signer)
{
const int verb = 5;
int i;
STACK_OF(X509)* validsigners = sk_X509_new_null();
STACK_OF(X509)* signers = PKCS7_get0_signers(p7, NULL, 0);
unsigned long usage = 0;
if(!validsigners) {
if(verb) printf("out of memory\n");
DEBUG_ANCHOR("ERROR %s(): Failed to allocated validsigners\n"
, __FUNC__);
sk_X509_free(signers);
return NULL;
}
if(!signers) {
if(verb) printf("no signers in pkcs7 signature\n");
DEBUG_ANCHOR("ERROR %s(): Failed to allocated signers\n"
, __FUNC__);
sk_X509_free(validsigners);
return NULL;
}
for(i=0; i<sk_X509_num(signers); i++) {
char buf[1024];
X509_NAME* nm = X509_get_subject_name(
sk_X509_value(signers, i));
char buf[1024];
if(!nm) {
if(verb) printf("signer %d: cert has no subject name\n", i);
DEBUG_ANCHOR("%s(): cert %d has no subject name\n"
, __FUNC__, i);
continue;
}
if(verb && nm) {
char* nmline = X509_NAME_oneline(nm, buf,
(int)sizeof(buf));
printf("signer %d: Subject: %s\n", i,
nmline?nmline:"no subject");
if(verb >= 3 && X509_NAME_get_text_by_NID(nm,
NID_commonName, buf, (int)sizeof(buf)))
printf("commonName: %s\n", buf);
if(verb >= 3 && X509_NAME_get_text_by_NID(nm,
NID_pkcs9_emailAddress, buf, (int)sizeof(buf)))
printf("emailAddress: %s\n", buf);
}
if(verb) {
int ku_loc = X509_get_ext_by_NID(
sk_X509_value(signers, i), NID_key_usage, -1);
if(verb >= 3 && ku_loc >= 0) {
X509_EXTENSION *ex = X509_get_ext(
sk_X509_value(signers, i), ku_loc);
if(ex) {
printf("keyUsage: ");
X509V3_EXT_print_fp(stdout, ex, 0, 0);
printf("\n");
}
}
}
if(!p7signer || strcmp(p7signer, "")==0) {
/* there is no name to check, return all records */
if(verb) printf("did not check commonName of signer\n");
DEBUG_ANCHOR("%s(): did not check commonName of signer\n"
, __FUNC__);
} else {
if(!X509_NAME_get_text_by_NID(nm,
NID_pkcs9_emailAddress,
buf, (int)sizeof(buf))) {
if(verb) printf("removed cert with no name\n");
DEBUG_ANCHOR("%s(): removed cert with no name\n"
, __FUNC__);
continue; /* no name, no use */
}
if(strcmp(buf, p7signer) != 0) {
if(verb) printf("removed cert with wrong name\n");
DEBUG_ANCHOR("%s(): removed cert with wrong name\n"
, __FUNC__);
continue; /* wrong name, skip it */
}
}
/* check that the key usage allows digital signatures
* (the p7s) */
usage = get_usage_of_ex(sk_X509_value(signers, i));
usage = _getdns_get_usage_of_ex(sk_X509_value(signers, i));
if(!(usage & KU_DIGITAL_SIGNATURE)) {
if(verb) printf("removed cert with no key usage Digital Signature allowed\n");
DEBUG_ANCHOR("%s(): removed cert with no key usage "
"Digital Signature allowed\n"
, __FUNC__);
continue;
}
@ -170,47 +151,34 @@ get_valid_signers(PKCS7* p7, const char* p7signer)
}
static int
verify_p7sig(BIO* data, BIO* p7s, X509_STORE *store, const char* p7signer)
_getdns_verify_p7sig(BIO* data, BIO* p7s, X509_STORE *store, const char* p7signer)
{
const int verb = 5;
PKCS7* p7;
STACK_OF(X509)* validsigners;
int secure = 0;
#ifdef X509_V_FLAG_CHECK_SS_SIGNATURE
X509_VERIFY_PARAM* param = X509_VERIFY_PARAM_new();
if(!param) {
if(verb) printf("out of memory\n");
X509_STORE_free(store);
DEBUG_ANCHOR("ERROR %s(): Failed to allocated param\n"
, __FUNC__);
return 0;
}
/* do the selfcheck on the root certificate; it checks that the
* input is valid */
X509_VERIFY_PARAM_set_flags(param, X509_V_FLAG_CHECK_SS_SIGNATURE);
if(store) X509_STORE_set1_param(store, param);
#endif
if(!store) {
if(verb) printf("out of memory\n");
#ifdef X509_V_FLAG_CHECK_SS_SIGNATURE
X509_VERIFY_PARAM_free(param);
#endif
return 0;
}
#ifdef X509_V_FLAG_CHECK_SS_SIGNATURE
X509_STORE_set1_param(store, param);
X509_VERIFY_PARAM_free(param);
#endif
(void)BIO_reset(p7s);
(void)BIO_reset(data);
/* convert p7s to p7 (the signature) */
p7 = d2i_PKCS7_bio(p7s, NULL);
if(!p7) {
if(verb) printf("could not parse p7s signature file\n");
X509_STORE_free(store);
DEBUG_ANCHOR("ERROR %s(): could not parse p7s signature file\n"
, __FUNC__);
return 0;
}
if(verb >= 2) printf("parsed the PKCS7 signature\n");
/* check what is in the Subject name of the certificates,
* and build a stack that contains only the right certificates */
validsigners = get_valid_signers(p7, p7signer);
@ -218,19 +186,16 @@ verify_p7sig(BIO* data, BIO* p7s, X509_STORE *store, const char* p7signer)
PKCS7_free(p7);
return 0;
}
BIO *out = BIO_new_fd(fileno(stdout), BIO_NOCLOSE);
BIO_printf(out, "Hello World\n");
if(PKCS7_verify(p7, validsigners, store, data, out, PKCS7_NOINTERN) == 1) {
if(PKCS7_verify(p7, validsigners, store, data, NULL, PKCS7_NOINTERN) == 1) {
secure = 1;
if(verb) printf("the PKCS7 signature verified\n");
} else {
if(verb) printf("the PKCS7 signature did not verify\n");
if(verb) {
ERR_print_errors_fp(stdout);
}
}
BIO_free(out);
#if defined(ANCHOR_DEBUG) && ANCHOR_DEBUG
else {
DEBUG_ANCHOR("ERROR %s(): the PKCS7 signature did not verify\n"
, __FUNC__);
ERR_print_errors_cb(_getdns_ERR_print_errors_cb_f, NULL);
}
#endif
sk_X509_free(validsigners);
PKCS7_free(p7);
return secure;
@ -238,68 +203,60 @@ verify_p7sig(BIO* data, BIO* p7s, X509_STORE *store, const char* p7signer)
void _getdns_context_equip_with_anchor(getdns_context *context)
{
char fn[1024];
int xml_fd, p7s_fd;
int n;
BIO *xml, *p7s, *crt;
X509 *x;
X509_STORE *store;
char *crt_str;
uint8_t xml_spc[16384], *xml_data = xml_spc;
uint8_t p7s_spc[16384], *p7s_data = p7s_spc;
size_t xml_len, p7s_len;
DEBUG_ANCHOR("entering %s\n", __FUNC__);
BIO *xml = NULL, *p7s = NULL, *crt = NULL;
X509 *x = NULL;
X509_STORE *store = NULL;
if (!(xml_data = _getdns_context_get_priv_file(context,
"root-anchors.xml", xml_spc, sizeof(xml_spc), &xml_len)))
; /* pass */
else if (!(p7s_data = _getdns_context_get_priv_file(context,
"root-anchors.p7s", p7s_spc, sizeof(p7s_spc), &p7s_len)))
; /* pass */
else if (!(xml = BIO_new_mem_buf(xml_data, xml_len)))
DEBUG_ANCHOR("ERROR %s(): Failed allocating xml BIO\n"
, __FUNC__);
else if (!(p7s = BIO_new_mem_buf(p7s_data, p7s_len)))
DEBUG_ANCHOR("ERROR %s(): Failed allocating p7s BIO\n"
, __FUNC__);
n = snprintf( fn, sizeof(fn)
, "%s/.getdns/root-anchors.xml", getenv("HOME"));
else if (!(crt = BIO_new_mem_buf(_getdns_builtin_cert, -1)))
DEBUG_ANCHOR("ERROR %s(): Failed allocating crt BIO\n"
, __FUNC__);
if (n < 0 || n >= (int)sizeof(fn))
return;
else if (!(x = PEM_read_bio_X509(crt, NULL, 0, NULL)))
DEBUG_ANCHOR("ERROR %s(): Parsing builtin certificate\n"
, __FUNC__);
if ((xml_fd = open(fn, O_RDONLY)) < 0)
return;
else if (!(store = X509_STORE_new()))
DEBUG_ANCHOR("ERROR %s(): Failed allocating store\n"
, __FUNC__);
(void) snprintf( fn, sizeof(fn)
, "%s/.getdns/root-anchors.p7s", getenv("HOME"));
else if (!X509_STORE_add_cert(store, x))
DEBUG_ANCHOR("ERROR %s(): Adding certificate to store\n"
, __FUNC__);
if ((p7s_fd = open(fn, O_RDONLY)) < 0) {
close(xml_fd);
return;
}
if (!(xml = BIO_new_fd(xml_fd, 1))) {
close(xml_fd);
close(p7s_fd);
return;
}
if (!(p7s = BIO_new_fd(p7s_fd, 1))) {
BIO_free(xml);
close(p7s_fd);
return;
}
if (!(crt_str = strdup(get_builtin_cert())))
goto error_free_xml;
if (!(crt = BIO_new_mem_buf(crt_str, (int)strlen(crt_str))))
goto error_free_str;
if (!(store = X509_STORE_new()))
goto error_free_crt;
if (!(x = PEM_read_bio_X509(crt, NULL, 0, NULL)))
goto error_free_store;
if (!X509_STORE_add_cert(store, x))
goto error_free_store;
if (verify_p7sig(xml, p7s, store, "dnssec@iana.org")) {
else if (_getdns_verify_p7sig(xml, p7s, store, "dnssec@iana.org")) {
DEBUG_ANCHOR("Verifying trust-anchors SUCCEEDED, Yay!\n");
;
} else {
DEBUG_ANCHOR("Verifying trust-anchors failed!\n");
;
}
error_free_store:
X509_STORE_free(store);
error_free_crt:
BIO_free(crt);
error_free_str:
free(crt_str);
error_free_xml:
BIO_free(xml);
BIO_free(p7s);
if (store) X509_STORE_free(store);
if (x) X509_free(x);
if (crt) BIO_free(crt);
if (xml) BIO_free(xml);
if (p7s) BIO_free(p7s);
if (xml_data && xml_data != xml_spc)
GETDNS_FREE(context->mf, xml_data);
if (p7s_data && p7s_data != p7s_spc)
GETDNS_FREE(context->mf, p7s_data);
}
/* anchor.c */

View File

@ -4456,4 +4456,37 @@ getdns_context_config(getdns_context *context, const getdns_dict *config_dict)
return r;
}
uint8_t *_getdns_context_get_priv_file(getdns_context *context,
const char *fn, uint8_t *buf, size_t buf_len, size_t *file_sz)
{
char path[FILENAME_MAX];
int n;
FILE *f;
n = snprintf(path, sizeof(path), "%s/.getdns/%s", getenv("HOME"), fn);
if (n < 0 || n > FILENAME_MAX)
return NULL;
if (!(f = fopen(path, "r")))
return NULL;
if ((*file_sz = fread(buf, 1, buf_len, f)) < buf_len && feof(f))
; /* pass */
else if (fseek(f, 0, SEEK_END) < 0)
buf = NULL;
else if ((buf = GETDNS_XMALLOC(
context->mf, uint8_t, (buf_len = ftell(f) + 1)))) {
rewind(f);
if ((*file_sz = fread(buf, 1, buf_len, f)) >= buf_len || !feof(f)) {
GETDNS_FREE(context->mf, buf);
buf = NULL;
}
}
(void) fclose(f);
return buf;
}
/* context.c */

View File

@ -455,4 +455,7 @@ void _getdns_upstreams_dereference(getdns_upstreams *upstreams);
void _getdns_upstream_shutdown(getdns_upstream *upstream);
uint8_t *_getdns_context_get_priv_file(getdns_context *context,
const char *fn, uint8_t *buf, size_t buf_len, size_t *file_sz);
#endif /* _GETDNS_CONTEXT_H_ */

View File

@ -179,6 +179,9 @@ static inline void debug_req(const char *msg, getdns_network_req *netreq)
(defined(MDNS_DEBUG) && MDNS_DEBUG) || \
(defined(ANCHOR_DEBUG) && ANCHOR_DEBUG)
#define DEBUGGING 1
static inline int
_getdns_ERR_print_errors_cb_f(const char *str, size_t len, void *u)
{ DEBUG_ON("%.*s (u: %p)\n", (int)len, str, u); return 1; }
#endif
#endif