X-Git-Url: https://git.netwichtig.de/gitweb/?a=blobdiff_plain;f=src%2Fsrc%2Fdane-openssl.c;h=6345b39ca459cd1461985fa5c8d6edb7d2212cb3;hb=a1bccd48f3956b50a13a34f5aed4b72c658c61af;hp=7815570758f32c84a7322c3c7c2aff64f06354a0;hpb=880a1e7750a0d8935d48788e35ff03e47f7f6ada;p=user%2Fhenk%2Fcode%2Fexim.git diff --git a/src/src/dane-openssl.c b/src/src/dane-openssl.c index 781557075..6345b39ca 100644 --- a/src/src/dane-openssl.c +++ b/src/src/dane-openssl.c @@ -202,9 +202,9 @@ for(matched = 0; !matched && slist; slist = slist->next) { dane_mtype_list m; unsigned char mdbuf[EVP_MAX_MD_SIZE]; - unsigned char *buf; + unsigned char *buf = NULL; unsigned char *buf2; - unsigned int len; + unsigned int len = 0; /* * Extract ASN.1 DER form of certificate or public key. @@ -679,6 +679,7 @@ int matched; matched = match(dane->selectors[SSL_DANE_USAGE_FIXED_LEAF], cert, 0); if(matched > 0) if(!ctx->chain) + { if( (ctx->chain = sk_X509_new_null()) && sk_X509_push(ctx->chain, cert)) CRYPTO_add(&cert->references, 1, CRYPTO_LOCK_X509); @@ -687,6 +688,7 @@ if(matched > 0) DANEerr(DANE_F_CHECK_END_ENTITY, ERR_R_MALLOC_FAILURE); return -1; } + } return matched; } @@ -714,12 +716,14 @@ for(hosts = dane->hosts; hosts; hosts = hosts->next) * Sub-domain match: certid is any sub-domain of hostname. */ if(match_subdomain) + { if( (idlen = strlen(certid)) > (domlen = strlen(domain)) + 1 && certid[idlen - domlen - 1] == '.' && !strcasecmp(certid + (idlen - domlen), domain)) return 1; else continue; + } /* * Exact match and initial "*" match. The initial "*" in a certid @@ -859,6 +863,8 @@ X509 *cert = ctx->cert; /* XXX: accessor? */ int matched = 0; int chain_length = sk_X509_num(ctx->chain); +DEBUG(D_tls) debug_printf("Dane verify-chain\n"); + issuer_rrs = dane->selectors[SSL_DANE_USAGE_LIMIT_ISSUER]; leaf_rrs = dane->selectors[SSL_DANE_USAGE_LIMIT_LEAF]; ctx->verify = dane->verify; @@ -950,6 +956,8 @@ int (*cb)(int, X509_STORE_CTX *) = ctx->verify_cb; int matched; X509 *cert = ctx->cert; /* XXX: accessor? */ +DEBUG(D_tls) debug_printf("Dane verify-cert\n"); + if(ssl_idx < 0) ssl_idx = SSL_get_ex_data_X509_STORE_CTX_idx(); if(dane_idx < 0) @@ -1058,12 +1066,30 @@ list_free(((dane_selector) p)->mtype, dane_mtype_free); OPENSSL_free(p); } + + +/* + +Tidy up once the connection is finished with. + +Arguments + ssl The ssl connection handle + +=> Before calling SSL_free() +tls_close() and tls_getc() [the error path] are the obvious places. +Could we do it earlier - right after verification? In tls_client_start() +right after SSL_connect() returns, in that case. + +*/ + void DANESSL_cleanup(SSL *ssl) { ssl_dane *dane; int u; +DEBUG(D_tls) debug_printf("Dane lib-cleanup\n"); + if(dane_idx < 0 || !(dane = SSL_get_ex_data(ssl, dane_idx))) return; (void) SSL_set_ex_data(ssl, dane_idx, 0); @@ -1105,6 +1131,28 @@ while(*src) return head; } + + + +/* + +Call this for each TLSA record found for the target, after the +DANE setup has been done on the ssl connection handle. + +Arguments: + ssl Connection handle + usage TLSA record field + selector TLSA record field + mdname ??? message digest name? + data ??? TLSA record megalump? + dlen length of data + +Return + -1 on error + 0 action not taken + 1 record accepted +*/ + int DANESSL_add_tlsa(SSL *ssl, uint8_t usage, uint8_t selector, const char *mdname, unsigned const char *data, size_t dlen) @@ -1117,6 +1165,9 @@ dane_cert_list xlist = 0; dane_pkey_list klist = 0; const EVP_MD *md = 0; +DEBUG(D_tls) debug_printf("Dane add-tlsa: usage %u sel %u mdname \"%s\"\n", + usage, selector, mdname); + if(dane_idx < 0 || !(dane = SSL_get_ex_data(ssl, dane_idx))) { DANEerr(DANE_F_SSL_DANE_ADD_TLSA, DANE_R_DANE_INIT); @@ -1254,6 +1305,30 @@ else if(klist) return 1; } + + + +/* +Call this once we have an ssl connection handle but before +making the TLS connection. + +=> In tls_client_start() after the call to SSL_new() +and before the call to SSL_connect(). Exactly where +probably does not matter. +We probably want to keep our existing SNI handling; +call this with NULL. + +Arguments: + ssl Connection handle + sni_domain Optional peer server name + hostnames list of names to chack against peer cert + +Return + -1 on fatal error + 0 nonfatal error + 1 success +*/ + int DANESSL_init(SSL *ssl, const char *sni_domain, const char **hostnames) { @@ -1262,12 +1337,14 @@ int i; #ifdef OPENSSL_INTERNAL SSL_CTX *sctx = SSL_get_SSL_CTX(ssl); + if(sctx->app_verify_callback != verify_cert) { DANEerr(DANE_F_SSL_DANE_INIT, DANE_R_SCTX_INIT); return -1; } #else +DEBUG(D_tls) debug_printf("Dane ssl-init\n"); if(dane_idx < 0) { DANEerr(DANE_F_SSL_DANE_INIT, DANE_R_LIBRARY_INIT); @@ -1290,6 +1367,9 @@ if(!SSL_set_ex_data(ssl, dane_idx, dane)) return 0; } +dane->verify = 0; +dane->hosts = 0; +dane->thost = 0; dane->pkeys = 0; dane->certs = 0; dane->chain = 0; @@ -1312,9 +1392,29 @@ if(hostnames && !(dane->hosts = host_list_init(hostnames))) return 1; } + +/* + +Call this once we have a context to work with, but +before DANESSL_init() + +=> in tls_client_start(), after tls_init() call gives us the ctx, +if we decide we want to (policy) and can (TLSA records available) +replacing (? what about fallback) everything from testing tls_verify_hosts +down to just before calling SSL_new() for the conn handle. + +Arguments + ctx SSL context + +Return + -1 Error + 1 Success +*/ + int DANESSL_CTX_init(SSL_CTX *ctx) { +DEBUG(D_tls) debug_printf("Dane ctx-init\n"); if(dane_idx >= 0) { SSL_CTX_set_cert_verify_callback(ctx, verify_cert, 0); @@ -1383,9 +1483,24 @@ if(!EVP_get_digestbyname(LN_sha512)) EVP_add_digest(EVP_sha512()); dane_idx = SSL_get_ex_new_index(0, 0, 0, 0, 0); } + + +/* + +Call this once. Probably early in startup will do; may need +to be after SSL library init. + +=> put after call to tls_init() for now + +Return + 1 Success + 0 Fail +*/ + int DANESSL_library_init(void) { +DEBUG(D_tls) debug_printf("Dane lib-init\n"); if(err_lib_dane < 0) init_once(&err_lib_dane, ERR_get_next_error_library, dane_init); @@ -1399,6 +1514,7 @@ DANEerr(DANE_F_SSL_DANE_LIBRARY_INIT, DANE_R_DANE_SUPPORT); return 0; } + #endif /* OPENSSL_VERSION_NUMBER */ /* vi: aw ai sw=2 */