Skip to content
Advertisement

PHP: CURL fails to save cookie

I am using PHP from one host to connect to the API of another on the same subnet, which requires cookies to remember the login. It gives me a WARNING: failed to save cookies in /var/includes/cookie. I set up a short test script for myself as follows:

$handle = curl_init();
$logfile = fopen('php://temp', 'w+');

curl_setopt_array($handle, array(
    CURLOPT_URL             => 'https://10.0.0.10:8443/api/login',
    CURLOPT_RETURNTRANSFER  => true,
    CURLOPT_COOKIEJAR       => '/var/includes/cookie',
    CURLOPT_COOKIEFILE      => '/var/includes/cookie',
    CURLOPT_SSL_VERIFYPEER  => false,
    CURLOPT_SSL_VERIFYHOST  => false,
    CURLOPT_VERBOSE         => true,
    CURLOPT_STDERR          => $logfile,
    CURLOPT_POST            => true,
    CURLOPT_POSTFIELDS      => json_encode(array('username' => 'user', 'password' => 'pass'))
));

$output = curl_exec($handle);
curl_close($handle); // Cookies should technically be saved here, right?

// Get contents from curl verbose log file
rewind($logfile);
$log = stream_get_contents($logfile);
fclose($logfile);
error_log($log);

error_log(print_r($output, true));

The verbose log file gives me this output:

* Hostname in DNS cache was stale, zapped
*   Trying 10.0.0.10...
* TCP_NODELAY set
* Connected to 10.0.0.10 (10.0.0.10) port 8443 (#0)
* ALPN, offering http/1.1
* successfully set certificate verify locations:
*   CAfile: /etc/pki/tls/certs/ca-bundle.crt
  CApath: none
* SSL connection using TLSv1.2 / ECDHE-RSA-AES128-GCM-SHA256
* ALPN, server did not agree to a protocol
* Server certificate:
*  subject: CN=api.example.com
*  start date: Oct  5 07:07:04 2020 GMT
*  expire date: Jan  3 07:07:04 2021 GMT
*  issuer: C=US; O=Let's Encrypt; CN=Let's Encrypt Authority X3
*  SSL certificate verify ok.
> POST /api/login HTTP/1.1
Host: 10.0.0.10:8443
Accept: */*
Content-Length: 42
Content-Type: application/x-www-form-urlencoded

* upload completely sent off: 42 out of 42 bytes
< HTTP/1.1 200
< vary: Origin
< Access-Control-Allow-Credentials: true
< Access-Control-Expose-Headers: Access-Control-Allow-Origin,Access-Control-Allow-Credentials
* Added cookie xxx="some_session_id" for domain 10.0.0.10, path /, expire 0
< Set-Cookie: xxx=some_session_id; Path=/; Secure; HttpOnly
* Added cookie yyy="some_other_id" for domain 10.0.0.10, path /, expire 0
< Set-Cookie: yyy=some_other_id; Path=/; Secure
< X-Frame-Options: DENY
< Content-Type: application/json;charset=UTF-8
< Content-Length: 30
< Date: Mon, 16 Nov 2020 12:28:42 GMT
<
* Connection #0 to host 10.0.0.10 left intact
* WARNING: failed to save cookies in /var/includes/cookie

The contents of $output itself is correct; it gives me the OK signal from the API that the login was successful. However subsequent requests give me signals that I am not logged in, certainly due to the cookie not being saved and thus not read.

I have tried:

  • Using a path inside the served web directory for the cookie.
  • touch /var/includes/cookie and set owner and group to apache with read/write permissions.
  • Set 777 permissions on the file.
  • sudo -u apache bash to get a terminal and attempt to modify the file – this works, so surely file permissions are okay?

Any pointers where I should look? Could SELinux affect this? My issue looks similar to this one.

CentOS 8, PHP 7.2.11, libcurl 7.61.1

Advertisement

Answer

So turns out it was SELinux having a go. Feels a bit silly to mention the solution in the problem, but I know I’m not the first one to trip over SELinux.

First off, to test if this is really the issue, you can temporarily toggle it off (if it is safe for you to do so).

setenforce 0

If that works, I would of course suggest to put it back on and instead set a rule for the file(s) that need to be modified.

setenforce 1

Since I have the file at /var/includes/cookie I would run the following command to add a persistent rule:

semanage fcontext -a -t httpd_sys_rw_content_t /var/includes/cookie
  • -a adds a record
  • -t specifies a new type, in this case as one that is writable by httpd

Once that context rule is written, it still has to be applied:

restorecon -v /var/includes/cookie
  • -v to get some output as to what changed

See this guide for more in-depth descriptions.

Also worth noting: I had to install the policycoreutils-python-utils package to get the semanage command on my minimal CentOS system.

User contributions licensed under: CC BY-SA
1 People found this is helpful
Advertisement