Repository: valkey-io/valkey
File: src/tls.c (C)

Code before:
        return;
    }

    serverLog(LL_NOTICE, "TLS: Config Auto Auth %s = %s", field, field_value);
    conn->c.cert_user = sdsnew(field_value);
    X509_free(cert);

    client *c = connGetPrivateData(&conn->c);
    if (!c) return;

    user *u = ACLGetUserByName(conn->c.cert_user, sdslen(conn->c.cert_user));
    serverLog(LL_NOTICE, "TLS: ACL lookup user: %s", u ? u->name : "NOT FOUND");
    if (u) {
        c->user = u;
        c->flag.authenticated = true;
        serverLog(LL_NOTICE, "TLS: Auto-authenticated client as %s", u->name);
    }
}

static void TLSAccept(void *_conn) {
    tls_connection *conn = (tls_connection *)_conn;
    ERR_clear_error();
    int ret = SSL_accept(conn->ssl);
    if (ret > 0) {
        conn->flags |= TLS_CONN_FLAG_ACCEPT_SUCCESS;
        autoAuthenticateClientFromCert(conn);
    } else if (handleSSLReturnCode(conn, ret)) {
        conn->flags |= TLS_CONN_FLAG_ACCEPT_ERROR;
    }
}

static void tlsHandleEvent(tls_connection *conn, int mask) {
    int ret, conn_error;

    switch (conn->c.state) {
    case CONN_STATE_CONNECTING:
        conn_error = anetGetError(conn->c.fd);
        if (conn_error) {
            conn->c.last_errno = conn_error;
            conn->c.state = CONN_STATE_ERROR;
        } else {
            ERR_clear_error();
            if (!(conn->flags & TLS_CONN_FLAG_FD_SET)) {
                SSL_set_fd(conn->ssl, conn->c.fd);
                conn->flags |= TLS_CONN_FLAG_FD_SET;
            }
            ret = SSL_connect(conn->ssl);
            if (ret <= 0) {
                if (!handleSSLReturnCode(conn, ret)) {
                    registerSSLEvent(conn);
                    /* Avoid hitting UpdateSSLEvent, which knows nothing

Review comment (suggestion):
We can't do this here, it's executed from the IO threads and the ACL code is not thread safe, we probably need to grab the user and stuff it on the connection to evaluate later.

Code after:
    X509 *cert = SSL_get_peer_certificate(conn->ssl);
    if (!cert) return NULL;

    char field_value[256];
    sds result = NULL;

    if (getCertFieldByName(cert, field, field_value, sizeof(field_value))) {
        result = sdsnew(field_value);
    } else {
        serverLog(LL_NOTICE, "TLS: Failed to extract field '%s' from certificate", field);
    }

    X509_free(cert);
    return result;
}

static void TLSAccept(void *_conn) {
    tls_connection *conn = (tls_connection *)_conn;
    ERR_clear_error();
    int ret = SSL_accept(conn->ssl);
    if (ret > 0) {
        conn->flags |= TLS_CONN_FLAG_ACCEPT_SUCCESS;
    } else if (handleSSLReturnCode(conn, ret)) {
        conn->flags |= TLS_CONN_FLAG_ACCEPT_ERROR;
    }
}

static void tlsHandleEvent(tls_connection *conn, int mask) {
    int ret, conn_error;

    switch (conn->c.state) {
    case CONN_STATE_CONNECTING:
        conn_error = anetGetError(conn->c.fd);
        if (conn_error) {
            conn->c.last_errno = conn_error;
            conn->c.state = CONN_STATE_ERROR;
        } else {
            ERR_clear_error();
            if (!(conn->flags & TLS_CONN_FLAG_FD_SET)) {
                SSL_set_fd(conn->ssl, conn->c.fd);
                conn->flags |= TLS_CONN_FLAG_FD_SET;
            }
            ret = SSL_connect(conn->ssl);
            if (ret <= 0) {
                if (!handleSSLReturnCode(conn, ret)) {
                    registerSSLEvent(conn);
                    /* Avoid hitting UpdateSSLEvent, which knows nothing
                     * of what SSL_connect() wants and instead looks at our
                     * R/W handlers.
                     */
                    return;