示例#1
0
文件: x509_ocsp.c 项目: regit/nufw
G_MODULE_EXPORT int certificate_check(nussl_session* session,
                                      gpointer params_p)
{
    int ret;

    ret = 0;
    if (session)
        ret = check_ocsp(session, params_p);

    return (ret == 0 ) ? SASL_OK : SASL_FAIL;
}
示例#2
0
static void* fetch_thread(void *arg)
{
    struct timespec wait_interval;

    /* the fetching thread is only cancellable while waiting for new events */
    thread_cancelability(FALSE);

    DBG(DBG_CONTROL,
        DBG_log("fetch thread started")
       )

    pthread_mutex_lock(&fetch_wake_mutex);

    while(1)
    {
        int status;

        wait_interval.tv_nsec = 0;
        wait_interval.tv_sec = time(NULL) + crl_check_interval;

        DBG(DBG_CONTROL,
            DBG_log("next regular crl check in %ld seconds", crl_check_interval)
           )

        thread_cancelability(TRUE);
        status = pthread_cond_timedwait(&fetch_wake_cond, &fetch_wake_mutex
                                        , &wait_interval);
        thread_cancelability(FALSE);

        if (status == ETIMEDOUT)
        {
            DBG(DBG_CONTROL,
                DBG_log(" ");
                DBG_log("*time to check crls and the ocsp cache")
               )
            check_ocsp();
            check_crls();
        }
        else
        {
示例#3
0
static int tls_connection_verify_peer(gnutls_session_t session)
{
	struct tls_connection *conn;
	unsigned int status, num_certs, i;
	struct os_time now;
	const gnutls_datum_t *certs;
	gnutls_x509_crt_t cert;
	gnutls_alert_description_t err;
	int res;

	conn = gnutls_session_get_ptr(session);
	if (!conn->verify_peer) {
		wpa_printf(MSG_DEBUG,
			   "GnuTLS: No peer certificate verification enabled");
		return 0;
	}

	wpa_printf(MSG_DEBUG, "GnuTSL: Verifying peer certificate");

#if GNUTLS_VERSION_NUMBER >= 0x030300
	{
		gnutls_typed_vdata_st data[1];
		unsigned int elements = 0;

		os_memset(data, 0, sizeof(data));
		if (!conn->global->server) {
			data[elements].type = GNUTLS_DT_KEY_PURPOSE_OID;
			data[elements].data = (void *) GNUTLS_KP_TLS_WWW_SERVER;
			elements++;
		}
		res = gnutls_certificate_verify_peers(session, data, 1,
						      &status);
	}
#else /* < 3.3.0 */
	res = gnutls_certificate_verify_peers2(session, &status);
#endif
	if (res < 0) {
		wpa_printf(MSG_INFO, "TLS: Failed to verify peer "
			   "certificate chain");
		err = GNUTLS_A_INTERNAL_ERROR;
		goto out;
	}

#if GNUTLS_VERSION_NUMBER >= 0x030104
	{
		gnutls_datum_t info;
		int ret, type;

		type = gnutls_certificate_type_get(session);
		ret = gnutls_certificate_verification_status_print(status, type,
								   &info, 0);
		if (ret < 0) {
			wpa_printf(MSG_DEBUG,
				   "GnuTLS: Failed to print verification status");
			err = GNUTLS_A_INTERNAL_ERROR;
			goto out;
		}
		wpa_printf(MSG_DEBUG, "GnuTLS: %s", info.data);
		gnutls_free(info.data);
	}
#endif /* GnuTLS 3.1.4 or newer */

	certs = gnutls_certificate_get_peers(session, &num_certs);
	if (certs == NULL || num_certs == 0) {
		wpa_printf(MSG_INFO, "TLS: No peer certificate chain received");
		err = GNUTLS_A_UNKNOWN_CA;
		goto out;
	}

	if (conn->verify_peer && (status & GNUTLS_CERT_INVALID)) {
		wpa_printf(MSG_INFO, "TLS: Peer certificate not trusted");
		if (status & GNUTLS_CERT_INSECURE_ALGORITHM) {
			wpa_printf(MSG_INFO, "TLS: Certificate uses insecure "
				   "algorithm");
			gnutls_tls_fail_event(conn, NULL, 0, NULL,
					      "certificate uses insecure algorithm",
					      TLS_FAIL_BAD_CERTIFICATE);
			err = GNUTLS_A_INSUFFICIENT_SECURITY;
			goto out;
		}
		if (status & GNUTLS_CERT_NOT_ACTIVATED) {
			wpa_printf(MSG_INFO, "TLS: Certificate not yet "
				   "activated");
			gnutls_tls_fail_event(conn, NULL, 0, NULL,
					      "certificate not yet valid",
					      TLS_FAIL_NOT_YET_VALID);
			err = GNUTLS_A_CERTIFICATE_EXPIRED;
			goto out;
		}
		if (status & GNUTLS_CERT_EXPIRED) {
			wpa_printf(MSG_INFO, "TLS: Certificate expired");
			gnutls_tls_fail_event(conn, NULL, 0, NULL,
					      "certificate has expired",
					      TLS_FAIL_EXPIRED);
			err = GNUTLS_A_CERTIFICATE_EXPIRED;
			goto out;
		}
		gnutls_tls_fail_event(conn, NULL, 0, NULL,
				      "untrusted certificate",
				      TLS_FAIL_UNTRUSTED);
		err = GNUTLS_A_INTERNAL_ERROR;
		goto out;
	}

	if (status & GNUTLS_CERT_SIGNER_NOT_FOUND) {
		wpa_printf(MSG_INFO, "TLS: Peer certificate does not have a "
			   "known issuer");
		gnutls_tls_fail_event(conn, NULL, 0, NULL, "signed not found",
				      TLS_FAIL_UNTRUSTED);
		err = GNUTLS_A_UNKNOWN_CA;
		goto out;
	}

	if (status & GNUTLS_CERT_REVOKED) {
		wpa_printf(MSG_INFO, "TLS: Peer certificate has been revoked");
		gnutls_tls_fail_event(conn, NULL, 0, NULL,
				      "certificate revoked",
				      TLS_FAIL_REVOKED);
		err = GNUTLS_A_CERTIFICATE_REVOKED;
		goto out;
	}

	if (status != 0) {
		wpa_printf(MSG_INFO, "TLS: Unknown verification status: %d",
			   status);
		err = GNUTLS_A_INTERNAL_ERROR;
		goto out;
	}

	if (check_ocsp(conn, session, &err))
		goto out;

	os_get_time(&now);

	for (i = 0; i < num_certs; i++) {
		char *buf;
		size_t len;
		if (gnutls_x509_crt_init(&cert) < 0) {
			wpa_printf(MSG_INFO, "TLS: Certificate initialization "
				   "failed");
			err = GNUTLS_A_BAD_CERTIFICATE;
			goto out;
		}

		if (gnutls_x509_crt_import(cert, &certs[i],
					   GNUTLS_X509_FMT_DER) < 0) {
			wpa_printf(MSG_INFO, "TLS: Could not parse peer "
				   "certificate %d/%d", i + 1, num_certs);
			gnutls_x509_crt_deinit(cert);
			err = GNUTLS_A_BAD_CERTIFICATE;
			goto out;
		}

		gnutls_x509_crt_get_dn(cert, NULL, &len);
		len++;
		buf = os_malloc(len + 1);
		if (buf) {
			buf[0] = buf[len] = '\0';
			gnutls_x509_crt_get_dn(cert, buf, &len);
		}
		wpa_printf(MSG_DEBUG, "TLS: Peer cert chain %d/%d: %s",
			   i + 1, num_certs, buf);

		if (conn->global->event_cb) {
			struct wpabuf *cert_buf = NULL;
			union tls_event_data ev;
#ifdef CONFIG_SHA256
			u8 hash[32];
			const u8 *_addr[1];
			size_t _len[1];
#endif /* CONFIG_SHA256 */

			os_memset(&ev, 0, sizeof(ev));
			if (conn->global->cert_in_cb) {
				cert_buf = wpabuf_alloc_copy(certs[i].data,
							     certs[i].size);
				ev.peer_cert.cert = cert_buf;
			}
#ifdef CONFIG_SHA256
			_addr[0] = certs[i].data;
			_len[0] = certs[i].size;
			if (sha256_vector(1, _addr, _len, hash) == 0) {
				ev.peer_cert.hash = hash;
				ev.peer_cert.hash_len = sizeof(hash);
			}
#endif /* CONFIG_SHA256 */
			ev.peer_cert.depth = i;
			ev.peer_cert.subject = buf;
			conn->global->event_cb(conn->global->cb_ctx,
					       TLS_PEER_CERTIFICATE, &ev);
			wpabuf_free(cert_buf);
		}

		if (i == 0) {
			if (conn->suffix_match &&
			    !gnutls_x509_crt_check_hostname(
				    cert, conn->suffix_match)) {
				wpa_printf(MSG_WARNING,
					   "TLS: Domain suffix match '%s' not found",
					   conn->suffix_match);
				gnutls_tls_fail_event(
					conn, &certs[i], i, buf,
					"Domain suffix mismatch",
					TLS_FAIL_DOMAIN_SUFFIX_MISMATCH);
				err = GNUTLS_A_BAD_CERTIFICATE;
				gnutls_x509_crt_deinit(cert);
				os_free(buf);
				goto out;
			}

#if GNUTLS_VERSION_NUMBER >= 0x030300
			if (conn->domain_match &&
			    !gnutls_x509_crt_check_hostname2(
				    cert, conn->domain_match,
				    GNUTLS_VERIFY_DO_NOT_ALLOW_WILDCARDS)) {
				wpa_printf(MSG_WARNING,
					   "TLS: Domain match '%s' not found",
					   conn->domain_match);
				gnutls_tls_fail_event(
					conn, &certs[i], i, buf,
					"Domain mismatch",
					TLS_FAIL_DOMAIN_MISMATCH);
				err = GNUTLS_A_BAD_CERTIFICATE;
				gnutls_x509_crt_deinit(cert);
				os_free(buf);
				goto out;
			}
#endif /* >= 3.3.0 */

			/* TODO: validate altsubject_match.
			 * For now, any such configuration is rejected in
			 * tls_connection_set_params() */

#if GNUTLS_VERSION_NUMBER < 0x030300
			/*
			 * gnutls_certificate_verify_peers() not available, so
			 * need to check EKU separately.
			 */
			if (!conn->global->server &&
			    !server_eku_purpose(cert)) {
				wpa_printf(MSG_WARNING,
					   "GnuTLS: No server EKU");
				gnutls_tls_fail_event(
					conn, &certs[i], i, buf,
					"No server EKU",
					TLS_FAIL_BAD_CERTIFICATE);
				err = GNUTLS_A_BAD_CERTIFICATE;
				gnutls_x509_crt_deinit(cert);
				os_free(buf);
				goto out;
			}
#endif /* < 3.3.0 */
		}

		if (!conn->disable_time_checks &&
		    (gnutls_x509_crt_get_expiration_time(cert) < now.sec ||
		     gnutls_x509_crt_get_activation_time(cert) > now.sec)) {
			wpa_printf(MSG_INFO, "TLS: Peer certificate %d/%d is "
				   "not valid at this time",
				   i + 1, num_certs);
			gnutls_tls_fail_event(
				conn, &certs[i], i, buf,
				"Certificate is not valid at this time",
				TLS_FAIL_EXPIRED);
			gnutls_x509_crt_deinit(cert);
			os_free(buf);
			err = GNUTLS_A_CERTIFICATE_EXPIRED;
			goto out;
		}

		os_free(buf);

		gnutls_x509_crt_deinit(cert);
	}

	if (conn->global->event_cb != NULL)
		conn->global->event_cb(conn->global->cb_ctx,
				       TLS_CERT_CHAIN_SUCCESS, NULL);

	return 0;

out:
	conn->failed++;
	gnutls_alert_send(session, GNUTLS_AL_FATAL, err);
	return GNUTLS_E_CERTIFICATE_ERROR;
}