X-Git-Url: https://arthur.barton.de/cgi-bin/gitweb.cgi?p=ngircd-alex.git;a=blobdiff_plain;f=src%2Fngircd%2Fconn-ssl.c;h=4dd335ea9209f6a01fa11f459fb3e0d976e44a21;hp=22b5d07ec3683aca4170901851382375922ffe10;hb=HEAD;hpb=3db3b47fc7172a69b7d99d66eddb07a323dc6e74 diff --git a/src/ngircd/conn-ssl.c b/src/ngircd/conn-ssl.c index 22b5d07e..abcf53c2 100644 --- a/src/ngircd/conn-ssl.c +++ b/src/ngircd/conn-ssl.c @@ -45,6 +45,8 @@ extern struct SSLOptions Conf_SSLOptions; #include #include +#define MAX_CERT_CHAIN_LENGTH 10 /* XXX: do not hardcode */ + static SSL_CTX * ssl_ctx; static DH *dh_params; @@ -52,8 +54,6 @@ static bool ConnSSL_LoadServerKey_openssl PARAMS(( SSL_CTX *c )); static bool ConnSSL_SetVerifyProperties_openssl PARAMS((SSL_CTX * c)); #endif -#define MAX_CERT_CHAIN_LENGTH 10 /* XXX: do not hardcode */ - #ifdef HAVE_LIBGNUTLS #include #include @@ -155,13 +155,13 @@ LogOpenSSL_CertInfo(int level, X509 * cert, const char *msg) mem = BIO_new(BIO_s_mem()); if (!mem) return; - X509_NAME_print_ex(mem, X509_get_subject_name(cert), 4, + X509_NAME_print_ex(mem, X509_get_subject_name(cert), 0, XN_FLAG_ONELINE); - X509_NAME_print_ex(mem, X509_get_issuer_name(cert), 4, XN_FLAG_ONELINE); + X509_NAME_print_ex(mem, X509_get_issuer_name(cert), 2, XN_FLAG_ONELINE); if (BIO_write(mem, "", 1) == 1) { len = BIO_get_mem_data(mem, &memptr); if (memptr && len > 0) - Log(level, "%s: \"%s\"", msg, memptr); + Log(level, "%s: \"%s\".", msg, memptr); } (void)BIO_set_close(mem, BIO_CLOSE); BIO_free(mem); @@ -468,6 +468,9 @@ ConnSSL_SetVerifyProperties_gnutls(void) if (!Conf_SSLOptions.CAFile) return true; + x509_cred_slot *slot = array_get(&x509_creds, sizeof(x509_cred_slot), x509_cred_idx); + gnutls_certificate_credentials_t x509_cred = slot->x509_cred; + err = gnutls_certificate_set_x509_trust_file(x509_cred, Conf_SSLOptions.CAFile, GNUTLS_X509_FMT_PEM); @@ -515,6 +518,7 @@ ConnSSL_LoadServerKey_gnutls(void) return false; gnutls_certificate_set_dh_params(x509_cred, dh_params); + gnutls_certificate_set_flags(x509_cred, GNUTLS_CERTIFICATE_VERIFY_CRLS); cert_file = Conf_SSLOptions.CertFile ? Conf_SSLOptions.CertFile : Conf_SSLOptions.KeyFile; @@ -565,7 +569,7 @@ ConnSSL_LoadServerKey_gnutls(void) return false; } } - Log(LOG_INFO, "Storing new X509 certificate credentials in slot %zd.", x509_cred_idx); + LogDebug("Storing new X509 certificate credentials in slot %zd.", x509_cred_idx); slot->x509_cred = x509_cred; slot->refcnt = 0; @@ -744,6 +748,7 @@ ConnSSL_PrepareConnect(CONNECTION * c, CONF_SERVER * s) #ifdef HAVE_LIBGNUTLS int err; + (void)s; err = gnutls_init(&c->ssl_state.gnutls_session, GNUTLS_CLIENT); if (err) { Log(LOG_ERR, "Failed to initialize new SSL session: %s", @@ -832,9 +837,12 @@ ConnSSL_HandleError(CONNECTION * c, const int code, const char *fname) "SSL error, client disconnected [in %s()]!", fname); break; - case -1: /* low level socket I/O error, check errno */ - Log(LOG_ERR, "SSL error: %s [in %s()]!", - strerror(real_errno), fname); + case -1: + /* Low level socket I/O error, check errno. But + * we don't need to log this here, the generic + * connection layer will take care of it. */ + LogDebug("SSL error: %s [in %s()]!", + strerror(real_errno), fname); } } break; @@ -862,8 +870,10 @@ ConnSSL_HandleError(CONNECTION * c, const int code, const char *fname) default: assert(code < 0); if (gnutls_error_is_fatal(code)) { - Log(LOG_ERR, "SSL error: %s [%s].", - gnutls_strerror(code), fname); + /* We don't need to log this here, the generic + * connection layer will take care of it. */ + LogDebug("SSL error: %s [%s].", + gnutls_strerror(code), fname); ConnSSL_Free(c); return -1; } @@ -907,12 +917,12 @@ LogGnuTLS_CertInfo(int level, gnutls_x509_crt_t cert, const char *msg) assert(size); issuer_dn = LogMalloc(size); if (!issuer_dn) { - Log(level, "%s: Distinguished Name: %s", msg, dn); + Log(level, "%s: Distinguished Name \"%s\".", msg, dn); free(dn); return; } gnutls_x509_crt_get_issuer_dn(cert, issuer_dn, &size); - Log(level, "%s: Distinguished Name: \"%s\", Issuer \"%s\"", msg, dn, + Log(level, "%s: Distinguished Name \"%s\", Issuer \"%s\".", msg, dn, issuer_dn); free(dn); free(issuer_dn); @@ -972,7 +982,7 @@ ConnSSL_LogCertInfo( CONNECTION * c, bool connect) * hand we want client certificates, for example for * "CertFP" authentication with services ... */ LogOpenSSL_CertInfo(LOG_INFO, peer_cert, - "Got unchecked client certificate"); + "Got unchecked peer certificate"); } X509_free(peer_cert); @@ -990,38 +1000,16 @@ ConnSSL_LogCertInfo( CONNECTION * c, bool connect) gnutls_cipher_get_name(cipher), gnutls_mac_get_name(gnutls_mac_get(sess))); cred = gnutls_auth_get_type(c->ssl_state.gnutls_session); - if (cred == GNUTLS_CRD_CERTIFICATE && connect) { - cert_seen = true; - int verify = - gnutls_certificate_verify_peers2(c-> - ssl_state.gnutls_session, - &status); - if (verify < 0) { - Log(LOG_ERR, - "gnutls_certificate_verify_peers2 failed: %s", - gnutls_strerror(verify)); - goto done_cn_validation; - } else if (status) { - gnutls_datum_t out; - - if (gnutls_certificate_verification_status_print - (status, gnutls_certificate_type_get(sess), &out, - 0) == GNUTLS_E_SUCCESS) { - Log(LOG_ERR, - "Certificate validation failed: %s", - out.data); - gnutls_free(out.data); - } - } - + if (cred == GNUTLS_CRD_CERTIFICATE) { gnutls_x509_crt_t cert; unsigned cert_list_size; const gnutls_datum_t *cert_list = gnutls_certificate_get_peers(sess, &cert_list_size); - if (!cert_list || cert_list_size == 0) { - Log(LOG_ERR, "No certificates found"); + + if (!cert_list || cert_list_size == 0) goto done_cn_validation; - } + + cert_seen = true; int err = gnutls_x509_crt_init(&cert); if (err < 0) { Log(LOG_ERR, @@ -1036,17 +1024,46 @@ ConnSSL_LogCertInfo( CONNECTION * c, bool connect) gnutls_strerror(err)); goto done_cn_validation; } - err = gnutls_x509_crt_check_hostname(cert, c->host); - if (err == 0) - Log(LOG_ERR, - "Failed to verify the hostname, expected \"%s\"", - c->host); - else - cert_ok = verify == 0 && status == 0; - - snprintf(msg, sizeof(msg), "%svalid peer certificate", - cert_ok ? "" : "in"); - LogGnuTLS_CertInfo(cert_ok ? LOG_DEBUG : LOG_ERR, cert, msg); + + if (connect) { + int verify = + gnutls_certificate_verify_peers2(c-> + ssl_state.gnutls_session, + &status); + if (verify < 0) { + Log(LOG_ERR, + "gnutls_certificate_verify_peers2 failed: %s", + gnutls_strerror(verify)); + goto done_cn_validation; + } else if (status) { + gnutls_datum_t out; + + if (gnutls_certificate_verification_status_print + (status, gnutls_certificate_type_get(sess), &out, + 0) == GNUTLS_E_SUCCESS) { + Log(LOG_ERR, + "Certificate validation failed: %s", + out.data); + gnutls_free(out.data); + } + } + + err = gnutls_x509_crt_check_hostname(cert, c->host); + if (err == 0) + Log(LOG_ERR, + "Failed to verify the hostname, expected \"%s\"", + c->host); + else + cert_ok = verify == 0 && status == 0; + + snprintf(msg, sizeof(msg), "Got %svalid server certificate", + cert_ok ? "" : "in"); + LogGnuTLS_CertInfo(LOG_INFO, cert, msg); + } else { + /* Incoming connection. Please see comments for OpenSSL! */ + LogGnuTLS_CertInfo(LOG_INFO, cert, + "Got unchecked peer certificate"); + } gnutls_x509_crt_deinit(cert); done_cn_validation: