Skip to content

AuthRoundCube GET requests have no cURL timeout #72

Description

@poehlert

Summary

AuthRoundCube::sendRequest() only configures CURLOPT_TIMEOUT for POST requests which contain request data.

GET requests have no explicit total timeout, and no request method has an explicit connection timeout.

Opening mail_roundcube performs server-side HTTP requests to Roundcube, so an unreachable or partially responsive Roundcube/reverse-proxy endpoint can hold a Nextcloud web request for an unnecessarily long time.

Steps to reproduce

  1. Configure a valid Roundcube externalLocation.
  2. Make that endpoint accept a connection but stop responding before the HTTP request completes.
  3. Open the Roundcube app in Nextcloud.
  4. Observe the server-side Roundcube request.

This can also be verified directly by inspecting AuthRoundCube::sendRequest().

Expected behavior

Every HTTP request to the external Roundcube instance should have:

  • a finite connection timeout; and
  • a finite overall request timeout.

If Roundcube is unavailable, mail_roundcube should fail within a bounded amount of time and return its normal error state.

Actual behavior

The common cURL options have no timeout:

$curlOpts = [
    CURLOPT_URL            => $rcQuery,
    CURLOPT_HEADER         => true,
    CURLOPT_FOLLOWLOCATION => false,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_FRESH_CONNECT  => true
];

CURLOPT_TIMEOUT is added only inside the POST-with-data branch:

if ($method === 'POST') {
    $curlOpts[CURLOPT_POST] = true;
    if ($data) {
        ...
        $curlOpts[CURLOPT_TIMEOUT] = 60;
    }
} else {
    $curlOpts[CURLOPT_HTTPGET] = true;
}

Therefore GET requests have no application-defined timeout.

Cause

Timeout configuration is nested inside the POST-with-data path rather than being part of the common cURL configuration.

Several operations used during normal login/session handling are GET requests.

Proposed fix

Apply finite timeout values to all requests, for example:

$curlOpts = [
    CURLOPT_URL            => $rcQuery,
    CURLOPT_HEADER         => true,
    CURLOPT_FOLLOWLOCATION => false,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_FRESH_CONNECT  => true,
    CURLOPT_CONNECTTIMEOUT => 10,
    CURLOPT_TIMEOUT        => 60,
];

The exact timeout values are a policy choice; the important point is that both GET and POST requests have bounded connection and total durations.

Environment

  • Nextcloud: 33.0.6
  • PHP: 8.3.32
  • mail_roundcube: 1.3.0 / current NC33 source
  • Roundcube: 1.7.3

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions