Repository: nginx/nginx
File: src/event/ngx_event_openssl.c (C)

Code before:
    for (;;) {
        nrv=ngx_read_dir(&thedir);
        if (nrv != NGX_OK) {
            break;
        }
        den = (char *)ngx_de_name(&thedir);
        nlen = strlen(den);
        if (nlen > 4) {
            last4 = den + nlen - 4;
            if (strncmp(last4, ".ech", 4)) {
                continue;
            }
            if ((elen + 1 + nlen + 1) >= PATH_MAX) {
                ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
                    "load_echkeys, error, name too long: %s with %s",
                    dirname->data, den);
                continue;
            }
            snprintf(privname, PATH_MAX,"%s/%s", dirname->data, den);
            if (!--maxkeyfiles) {
                /* so we don't loop forever, ever */
                ngx_ssl_error(NGX_LOG_ALERT, ssl->log, 0,
                    "load_echkeys, too many private key files to check!");
                ngx_ssl_error(NGX_LOG_ALERT, ssl->log, 0,
                    "load_echkeys, maxkeyfiles is hardcoded to 1024");
                 return NGX_ERROR;
            }
            if (stat(privname, &thestat) == 0) {
                BIO *in = BIO_new_file(privname, "r");
                const int is_retry_config = OSSL_ECH_FOR_RETRY;

                if (in != NULL
                    && 1 == OSSL_ECHSTORE_read_pem(es, in, is_retry_config)) {
                    ngx_ssl_error(NGX_LOG_NOTICE, ssl->log, 0,
                        "load_echkeys, worked for: %s", privname);
                    somekeyworked = 1;
                }
                else {
                    ngx_ssl_error(NGX_LOG_ALERT, ssl->log, 0,
                        "load_echkeys, failed for: %s",privname);
                }
                BIO_free_all(in);
            }
        }
    }
    ngx_close_dir(&thedir);

    if (somekeyworked == 0) {
        ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, 
            "load_echkeys failed for all keys but ECH configured");
        return NGX_ERROR;

Review comment (bug):
Maybe it's worth:
- counting only files that are successfully processed against `maxkeyfiles`. Ignore noise
- if `maxkeyfiles` cap is reached proceed with that and log a warning instead of crashing out

Code after:
    ngx_fd_t             fd;
    ngx_str_t           *pwd;
    ngx_array_t         *passwords;
    ngx_pool_cleanup_t  *cln;
    u_char               buf[NGX_SSL_PASSWORD_BUFFER_SIZE];

    if (ngx_conf_full_name(cf->cycle, file, 1) != NGX_OK) {
        return NULL;
    }

    passwords = ngx_array_create(cf->temp_pool, 4, sizeof(ngx_str_t));
    if (passwords == NULL) {
        return NULL;
    }

    cln = ngx_pool_cleanup_add(cf->temp_pool, 0);
    if (cln == NULL) {
        return NULL;
    }

    cln->handler = ngx_ssl_passwords_cleanup;
    cln->data = passwords;

    fd = ngx_open_file(file->data, NGX_FILE_RDONLY, NGX_FILE_OPEN, 0);

    if (fd == NGX_INVALID_FILE) {
        ngx_conf_log_error(NGX_LOG_EMERG, cf, ngx_errno,
                           ngx_open_file_n " \"%s\" failed", file->data);
        return NULL;
    }

    len = 0;
    last = buf;

    do {
        n = ngx_read_fd(fd, last, NGX_SSL_PASSWORD_BUFFER_SIZE - len);

        if (n == -1) {
            ngx_conf_log_error(NGX_LOG_EMERG, cf, ngx_errno,
                               ngx_read_fd_n " \"%s\" failed", file->data);
            passwords = NULL;
            goto cleanup;
        }

        end = last + n;

        if (len && n == 0) {
            *end++ = LF;
        }

        p = buf;