mstilkerich / rcmcarddav

CardDAV plugin for RoundCube Webmailer
GNU General Public License v2.0
257 stars 81 forks source link

carddav4 + own CA/ self-signed cert: how to pass curl.cainfo to guzzle for plugin use only? #303

Closed pgnd closed 3 years ago

pgnd commented 3 years ago

i've carddav plugin + roundcube installed.

composer show roundcube/carddav
    Do not run Composer as root/super user! See https://getcomposer.org/root for details
    name     : roundcube/carddav
    descrip. : CardDAV adapter for connecting to CardDAV-enabled addressbooks
    keywords : CardDAV, addressbook, contacts, davical, owncloud
    versions : * dev-master
    type     : roundcube-plugin
    license  : GNU General Public License v2.0 only (GPL-2.0) (OSI approved) https://spdx.org/licenses/GPL-2.0.html#licenseText
    homepage : https://www.benjamin-schieder.de/carddav.html
    source   : [git] https://github.com/blind-coder/rcmcarddav.git dd5b6c8707ed3133aca148802bd7823d32b21b94
    dist     : [zip] https://api.github.com/repos/blind-coder/rcmcarddav/zipball/dd5b6c8707ed3133aca148802bd7823d32b21b94 dd5b6c8707ed3133aca148802bd7823d32b21b94
    path     : /usr/local/src/roundcubemail/plugins/carddav
    names    : roundcube/carddav
    ...

i'm connecting to a radicale3 server.

i've configued the radicale portal to require own-CA/self-signed ssl cert with verification.

as long as I can provide it -- e.g. adding a valid local cert in Thunderbird CardDAV client, or Dav5X on Android -- all's good. I can connect to & interact with CardDAV server backennd without error.

in this config, carddav plugin fails to connect,

==> /var/log/roundcubemail/carddav_http.log <==
[22-Sep-2020 17:54:22]: <5ba9e294> "PROPFIND /.well-known/carddav HTTP/1.1" NULL
>>>>>>>>
PROPFIND /.well-known/carddav HTTP/1.1
Content-Length: 215
User-Agent: GuzzleHttp/7
Host: portal.example.com:11111
Depth: 0
Content-Type: application/xml; charset=UTF-8
Prefer: return=minimal

<?xml version="1.0"?>
<DAV:propfind xmlns:DAV="DAV:" xmlns:CARDDAV="urn:ietf:params:xml:ns:carddav" xmlns:CS="http://calendarserver.org/ns/">
 <DAV:prop>
  <DAV:current-user-principal/>
 </DAV:prop>
</DAV:propfind>

<<<<<<<<

iiuc, there's no php ssl stream context init'd here, which would allow easy config of own CA/crt/key.

instead, it appears that carddav is using guzzle, which needs ca cert in system paths @

/usr/local/src/roundcubemail/vendor/guzzlehttp/guzzle/src/Utils.php

    ...
124 /**
        * Returns the default cacert bundle for the current system.
        *
        * First, the openssl.cafile and curl.cainfo php.ini settings are checked.
        * If those settings are not configured, then the common locations for
        * bundles found on Red Hat, CentOS, Fedora, Ubuntu, Debian, FreeBSD, OS X
        * and Windows are checked. If any of these file locations are found on
        * disk, they will be utilized.
        *
        * Note: the result of this function is cached for subsequent calls.
        *
        * @throws \RuntimeException if no bundle can be found.
        *
        * @deprecated Utils::defaultCaBundle will be removed in guzzlehttp/guzzle:8.0. This method is not needed in PHP 5.6+.
        */
        public static function defaultCaBundle(): string
        {
            static $cached = null;
            static $cafiles = [
                // Red Hat, CentOS, Fedora (provided by the ca-certificates package)
                '/etc/pki/tls/certs/ca-bundle.crt',
                // Ubuntu, Debian (provided by the ca-certificates package)
                '/etc/ssl/certs/ca-certificates.crt',
    ...

i'd prefer not to add/maintain own certs in system-wide paths

which appears to leave specifying one of

    curl.cainfo
    openssl.cafile

i tried 1st to set the param locally resident to carddav plugin's config.inc.php

    <?php

+++     ini_set( 'curl.cainfo', '/srv/ssl/my_ca_chain.crt.' );

        $prefs['_GLOBAL']['fixed'] = true;
        $prefs['_GLOBAL']['hide_preferences'] = false;

but that appears to have no effect; the error returned in the same, as above.

either my usage is wrong, or passing my self-signed cert + ca file paths to carddav needs another approach.

how do I get carddav<guzzle<libcurl using my certs?

mstilkerich commented 3 years ago

Hello,

the options curl.cainfo and openssl.cafile cannot be set using ini_set. You can set these options from your HTTP server configuration.

For example, with apache, I tried the following successfully with a self-signed cert:

<Directory "/var/www/roundcube">
        # ... other settings ...
        php_value openssl.cafile /etc/radicale/cert.pem
</Directory>
pgnd commented 3 years ago

the options curl.cainfo and openssl.cafile cannot be set using ini_set

pebkac. i assumed -- i should've checked the list :-/

with nginx, adding to RC config

    ...
    location ~ \.php$ {
        try_files $uri =404;
        fastcgi_pass phpfpm;
        fastcgi_index index.php;
        include fastcgi.conf;
+       fastcgi_param PHP_VALUE openssl.cafile="/srv/ssl/my_ca_chain.crt.pem";
    }

works as intended -- local to RC config/instance. able to successfully add/use CardDAV stores.

perfect, thx @mstilkerich !

alternative, if willing to add cert to systemwide stores (e.g., on Fedora),

/bin/cp -af \
 /srv/ssl/my_ca_chain.crt.pem \
 /etc/pki/ca-trust/source/anchors/
update-ca-trust extract

works as well.

in the 'local' case, i do need to still check whether that openssl.cafile spec'n causes any limitations elsewhere in RC. iiuc, only the carddav plugin (so far) is using guzzle<libcurl ...