Exemplo n.º 1
0
int     tls_verify_certificate_callback(int ok, X509_STORE_CTX *ctx)
{
    char    buf[CCERT_BUFSIZ];
    X509   *cert;
    int     err;
    int     depth;
    int     max_depth;
    SSL    *con;
    TLS_SESS_STATE *TLScontext;

    /* May be NULL as of OpenSSL 1.0, thanks for the API change! */
    cert = X509_STORE_CTX_get_current_cert(ctx);
    err = X509_STORE_CTX_get_error(ctx);
    con = X509_STORE_CTX_get_ex_data(ctx, SSL_get_ex_data_X509_STORE_CTX_idx());
    TLScontext = SSL_get_ex_data(con, TLScontext_index);
    depth = X509_STORE_CTX_get_error_depth(ctx);

    /* Don't log the internal root CA unless there's an unexpected error. */
    if (ok && TLScontext->tadepth > 0 && depth > TLScontext->tadepth)
	return (1);

    /*
     * Certificate chain depth limit violations are mis-reported by the
     * OpenSSL library, from SSL_CTX_set_verify(3):
     * 
     * The certificate verification depth set with SSL[_CTX]_verify_depth()
     * stops the verification at a certain depth. The error message produced
     * will be that of an incomplete certificate chain and not
     * X509_V_ERR_CERT_CHAIN_TOO_LONG as may be expected.
     * 
     * We set a limit that is one higher than the user requested limit. If this
     * higher limit is reached, we raise an error even a trusted root CA is
     * present at this depth. This disambiguates trust chain truncation from
     * an incomplete trust chain.
     */
    max_depth = SSL_get_verify_depth(con) - 1;

    /*
     * We never terminate the SSL handshake in the verification callback,
     * rather we allow the TLS handshake to continue, but mark the session as
     * unverified. The application is responsible for closing any sessions
     * with unverified credentials.
     */
    if (max_depth >= 0 && depth > max_depth) {
	X509_STORE_CTX_set_error(ctx, err = X509_V_ERR_CERT_CHAIN_TOO_LONG);
	ok = 0;
    }
    if (ok == 0)
	update_error_state(TLScontext, depth, cert, err);

    if (TLScontext->log_mask & TLS_LOG_VERBOSE) {
	if (cert)
	    X509_NAME_oneline(X509_get_subject_name(cert), buf, sizeof(buf));
	else
	    strcpy(buf, "<unknown>");
	msg_info("%s: depth=%d verify=%d subject=%s",
		 TLScontext->namaddr, depth, ok, printable(buf, '?'));
    }
    return (1);
}
Exemplo n.º 2
0
static int openssl_ssl_get(lua_State*L)
{
  SSL* s = CHECK_OBJECT(1, SSL, "openssl.ssl");
  int i;
  int top = lua_gettop(L);
  for (i = 2; i <= top; i++)
  {
    const char* what = luaL_checklstring(L, i, NULL);
    if (strcmp(what, "fd") == 0)
    {
      lua_pushinteger(L, SSL_get_fd(s));
    }
    else if (strcmp(what, "rfd") == 0)
    {
      lua_pushinteger(L, SSL_get_rfd(s));
    }
    else if (strcmp(what, "wfd") == 0)
    {
      lua_pushinteger(L, SSL_get_wfd(s));
    }
    else if (strcmp(what, "client_CA_list") == 0)
    {
      STACK_OF(X509_NAME)* sn = SSL_get_client_CA_list(s);
      PUSH_OBJECT(sn, "openssl.sk_x509_name");
    }
    else if (strcmp(what, "read_ahead") == 0)
    {
      lua_pushboolean(L, SSL_get_read_ahead(s));
    }
    else if (strcmp(what, "shared_ciphers") == 0)
    {
      char buf[LUAL_BUFFERSIZE] = {0};
      lua_pushstring(L, SSL_get_shared_ciphers(s, buf, sizeof(buf)));
    }
    else if (strcmp(what, "cipher_list") == 0)
    {
      //TODO FIX
      lua_pushstring(L, SSL_get_cipher_list(s, 0));
    }
    else if (strcmp(what, "verify_mode") == 0)
    {
      //FIX
      lua_pushinteger(L, SSL_get_verify_mode(s));
    }
    else if (strcmp(what, "verify_depth") == 0)
    {
      lua_pushinteger(L, SSL_get_verify_depth(s));
    }
    else if (strcmp(what, "state_string") == 0)
    {
      lua_pushstring(L, SSL_state_string(s));
    }
    else if (strcmp(what, "state_string_long") == 0)
    {
      lua_pushstring(L, SSL_state_string_long(s));
    }
    else if (strcmp(what, "rstate_string") == 0)
    {
      lua_pushstring(L, SSL_rstate_string(s));
    }
    else if (strcmp(what, "rstate_string_long") == 0)
    {
      lua_pushstring(L, SSL_rstate_string_long(s));
    }
    else if (strcmp(what, "version") == 0)
    {
      lua_pushstring(L, SSL_get_version(s));
    }
    else if (strcmp(what, "iversion") == 0)
    {
      lua_pushinteger(L, SSL_version(s));
    }
    else if (strcmp(what, "default_timeout") == 0)
    {
      lua_pushinteger(L, SSL_get_default_timeout(s));
    }
    else if (strcmp(what, "certificate") == 0)
    {
      X509* cert = SSL_get_certificate(s);
      PUSH_OBJECT(cert, "openssl.x509");
    }
    else if (strcmp(what, "verify_result") == 0)
    {
      long l = SSL_get_verify_result(s);
      lua_pushinteger(L, l);
    }
    else if (strcmp(what, "version") == 0)
    {
      lua_pushstring(L, SSL_get_version(s));
    }
    else if (strcmp(what, "state") == 0)
    {
      lua_pushinteger(L, SSL_state(s));
    }
    else if (strcmp(what, "hostname") == 0)
    {
      lua_pushstring(L, SSL_get_servername(s, TLSEXT_NAMETYPE_host_name));
    }
    else
      luaL_argerror(L, i, "can't understant");
  }
  return top - 1;
}
Exemplo n.º 3
0
int     tls_verify_certificate_callback(int ok, X509_STORE_CTX *ctx)
{
    char    buf[CCERT_BUFSIZ];
    X509   *cert;
    int     err;
    int     depth;
    SSL    *con;
    TLS_SESS_STATE *TLScontext;

    depth = X509_STORE_CTX_get_error_depth(ctx);
    cert = X509_STORE_CTX_get_current_cert(ctx);
    con = X509_STORE_CTX_get_ex_data(ctx, SSL_get_ex_data_X509_STORE_CTX_idx());
    TLScontext = SSL_get_ex_data(con, TLScontext_index);

    /*
     * The callback function is called repeatedly, first with the root
     * certificate, and then with each intermediate certificate ending with
     * the peer certificate.
     * 
     * With each call, the validity of the current certificate (usage bits,
     * attributes, expiration, ... checked by the OpenSSL library) is
     * available in the "ok" argument. Error details are available via
     * X509_STORE_CTX API.
     * 
     * We never terminate the SSL handshake in the verification callback, rather
     * we allow the TLS handshake to continue, but mark the session as
     * unverified. The application is responsible for closing any sessions
     * with unverified credentials.
     * 
     * Certificate chain depth limit violations are mis-reported by the OpenSSL
     * library, from SSL_CTX_set_verify(3):
     * 
     * The certificate verification depth set with SSL[_CTX]_verify_depth()
     * stops the verification at a certain depth. The error message produced
     * will be that of an incomplete certificate chain and not
     * X509_V_ERR_CERT_CHAIN_TOO_LONG as may be expected.
     * 
     * We set a limit that is one higher than the user requested limit. If this
     * higher limit is reached, we raise an error even a trusted root CA is
     * present at this depth. This disambiguates trust chain truncation from
     * an incomplete trust chain.
     */
    if (depth >= SSL_get_verify_depth(con)) {
	ok = 0;
	X509_STORE_CTX_set_error(ctx, X509_V_ERR_CERT_CHAIN_TOO_LONG);
    }
    if (TLScontext->log_level >= 2) {
	X509_NAME_oneline(X509_get_subject_name(cert), buf, sizeof(buf));
	acl_msg_info("%s: certificate verification depth=%d verify=%d subject=%s",
		 TLScontext->namaddr, depth, ok, printable(buf, '?'));
    }

    /*
     * If no errors, or we are not logging verification errors, we are done.
     */
    if (ok || (TLScontext->peer_status & TLS_CERT_FLAG_LOGGED) != 0)
	return (1);

    /*
     * One counter-example is enough.
     */
    TLScontext->peer_status |= TLS_CERT_FLAG_LOGGED;

#define PURPOSE ((depth>0) ? "CA": TLScontext->am_server ? "client": "server")

    /*
     * Specific causes for verification failure.
     */
    switch (err = X509_STORE_CTX_get_error(ctx)) {
    case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT:
	acl_msg_info("certificate verification failed for %s: "
		 "self-signed certificate", TLScontext->namaddr);
	break;
    case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY:
    case X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN:

	/*
	 * There is no difference between issuing cert not provided and
	 * provided, but not found in CAfile/CApath. Either way, we don't
	 * trust it.
	 */
	X509_NAME_oneline(X509_get_issuer_name(ctx->current_cert),
			  buf, sizeof(buf));
	acl_msg_info("certificate verification failed for %s: untrusted issuer %s",
		 TLScontext->namaddr, printable(buf, '?'));
	break;
    case X509_V_ERR_CERT_NOT_YET_VALID:
    case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD:
	acl_msg_info("%s certificate verification failed for %s: certificate not"
		 " yet valid", PURPOSE, TLScontext->namaddr);
	break;
    case X509_V_ERR_CERT_HAS_EXPIRED:
    case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD:
	acl_msg_info("%s certificate verification failed for %s: certificate has"
		 " expired", PURPOSE, TLScontext->namaddr);
	break;
    case X509_V_ERR_INVALID_PURPOSE:
	acl_msg_info("certificate verification failed for %s: not designated for "
		 "use as a %s certificate", TLScontext->namaddr, PURPOSE);
	break;
    case X509_V_ERR_CERT_CHAIN_TOO_LONG:
	acl_msg_info("certificate verification failed for %s: "
		 "certificate chain longer than limit(%d)",
		 TLScontext->namaddr, SSL_get_verify_depth(con) - 1);
	break;
    default:
	acl_msg_info("%s certificate verification failed for %s: num=%d:%s",
		 PURPOSE, TLScontext->namaddr, err,
		 X509_verify_cert_error_string(err));
	break;
    }

    return (1);
}