From 7c4a991c0e59cb1fdc5283bf6d94dd30e7850828 Mon Sep 17 00:00:00 2001 From: DubbleClick Date: Tue, 31 Oct 2023 13:09:01 +0100 Subject: [PATCH] add imap support --- config/ext.json | 8 ++- config/lib.json | 9 +++ config/source.json | 9 +++ src/SPC/builder/extension/imap.php | 28 ++++++++ src/SPC/builder/linux/library/imap.php | 68 +++++++++++++++++++ src/SPC/builder/unix/library/postgresql.php | 3 +- .../patch/1006_openssl1.1_autoverify.patch | 58 ++++++++++++++++ src/globals/patch/2014_openssl1.1.1_sni.patch | 42 ++++++++++++ 8 files changed, 220 insertions(+), 5 deletions(-) create mode 100644 src/SPC/builder/extension/imap.php create mode 100644 src/SPC/builder/linux/library/imap.php create mode 100644 src/globals/patch/1006_openssl1.1_autoverify.patch create mode 100644 src/globals/patch/2014_openssl1.1.1_sni.patch diff --git a/config/ext.json b/config/ext.json index 778afe0e..e3081154 100644 --- a/config/ext.json +++ b/config/ext.json @@ -132,12 +132,13 @@ }, "imap": { "type": "builtin", - "arg-type": "with", + "arg-type": "custom", "lib-depends": [ "imap" ], "lib-suggests": [ - "kerberos" + "kerberos", + "openssl" ] }, "inotify": { @@ -234,7 +235,8 @@ "type": "builtin", "arg-type": "custom", "lib-depends": [ - "openssl" + "openssl", + "zlib" ], "ext-depends": [ "zlib" diff --git a/config/lib.json b/config/lib.json index 6a602d16..5e6189e6 100644 --- a/config/lib.json +++ b/config/lib.json @@ -141,6 +141,15 @@ "libxml2" ] }, + "imap": { + "source": "imap", + "static-libs-unix": [ + "libc-client.a" + ], + "lib-suggests": [ + "openssl" + ] + }, "ldap": { "source": "ldap", "static-libs-unix": [ diff --git a/config/source.json b/config/source.json index cd849f86..7e1de028 100644 --- a/config/source.json +++ b/config/source.json @@ -144,6 +144,15 @@ "path": "LICENSE" } }, + "imap": { + "type": "git", + "url": "https://github.com/uw-imap/imap.git", + "rev": "master", + "license": { + "type": "file", + "path": "LICENSE" + } + }, "inotify": { "type": "url", "url": "https://pecl.php.net/get/inotify", diff --git a/src/SPC/builder/extension/imap.php b/src/SPC/builder/extension/imap.php new file mode 100644 index 00000000..389223ec --- /dev/null +++ b/src/SPC/builder/extension/imap.php @@ -0,0 +1,28 @@ +builder->getOption('enable-zts')) { + throw new WrongUsageException('ext-imap is not thread safe, do not build it with ZTS builds'); + } + $arg = '--with-imap=' . BUILD_ROOT_PATH; + if ($this->builder->getLib('openssl') !== null) { + $arg .= ' --with-imap-ssl=' . BUILD_ROOT_PATH; + } + return $arg; + } +} diff --git a/src/SPC/builder/linux/library/imap.php b/src/SPC/builder/linux/library/imap.php new file mode 100644 index 00000000..594a75bd --- /dev/null +++ b/src/SPC/builder/linux/library/imap.php @@ -0,0 +1,68 @@ +source_dir . '/Makefile', '-DMAC_OSX_KLUDGE=1', ''); + FileSystem::replaceFileStr($this->source_dir . '/src/osdep/unix/Makefile', 'CC=cc', "CC={$cc}"); + FileSystem::replaceFileStr($this->source_dir . '/src/osdep/unix/Makefile', '-lcrypto -lz', '-lcrypto'); + FileSystem::replaceFileStr($this->source_dir . '/src/osdep/unix/Makefile', '-lcrypto', '-lcrypto -lz'); + FileSystem::replaceFileStr( + $this->source_dir . '/src/osdep/unix/ssl_unix.c', + "#include \n#include ", + "#include \n#include " + ); + SourcePatcher::patchFile('1007_openssl1.1_autoverify.patch', $this->source_dir); + SourcePatcher::patchFile('2014_openssl1.1.1_sni.patch', $this->source_dir); + FileSystem::replaceFileStr($this->source_dir . '/Makefile', 'SSLINCLUDE=/usr/include/openssl', 'SSLINCLUDE=' . BUILD_INCLUDE_PATH); + FileSystem::replaceFileStr($this->source_dir . '/Makefile', 'SSLLIB=/usr/lib', 'SSLLIB=' . BUILD_LIB_PATH); + return true; + } + + /** + * @throws FileSystemException + * @throws RuntimeException + * @throws WrongUsageException + */ + protected function build(): void + { + if ($this->builder->getLib('openssl')) { + $ssl_options = 'SPECIALAUTHENTICATORS=ssl SSLTYPE=unix.nopwd SSLINCLUDE=' . BUILD_INCLUDE_PATH . ' SSLLIB=' . BUILD_LIB_PATH; + } else { + $ssl_options = 'SSLTYPE=none'; + } + shell()->cd($this->source_dir) + ->exec('make clean') + ->exec('touch ip6') + ->exec( + "yes | make slx {$ssl_options}" + ); + try { + shell() + ->exec("cp -rf {$this->source_dir}/c-client/c-client.a " . BUILD_LIB_PATH . '/libc-client.a') + ->exec("cp -rf {$this->source_dir}/c-client/*.c " . BUILD_LIB_PATH . '/') + ->exec("cp -rf {$this->source_dir}/c-client/*.h " . BUILD_INCLUDE_PATH . '/') + ->exec("cp -rf {$this->source_dir}/src/osdep/unix/*.h " . BUILD_INCLUDE_PATH . '/'); + } catch (\Throwable) { + // last command throws an exception, no idea why since it works + } + } +} diff --git a/src/SPC/builder/unix/library/postgresql.php b/src/SPC/builder/unix/library/postgresql.php index 38be1bf2..5769c106 100644 --- a/src/SPC/builder/unix/library/postgresql.php +++ b/src/SPC/builder/unix/library/postgresql.php @@ -24,7 +24,6 @@ trait postgresql $optional_packages = [ 'zstd' => 'libzstd', 'ldap' => 'ldap', - 'libpam' => 'libpam', 'libxslt' => 'libxslt', 'icu' => 'icu-i18n', ]; @@ -74,12 +73,12 @@ trait postgresql '--with-libxml ' . ($this->builder->getLib('icu') ? '--with-icu ' : '--without-icu ') . ($this->builder->getLib('ldap') ? '--with-ldap ' : '--without-ldap ') . - ($this->builder->getLib('libpam') ? '--with-pam ' : '--without-pam ') . ($this->builder->getLib('libxslt') ? '--with-libxslt ' : '--without-libxslt ') . ($this->builder->getLib('zstd') ? '--with-zstd ' : '--without-zstd ') . '--without-lz4 ' . '--without-perl ' . '--without-python ' . + '--without-pam ' . '--without-bonjour ' . '--without-tcl ' ); diff --git a/src/globals/patch/1006_openssl1.1_autoverify.patch b/src/globals/patch/1006_openssl1.1_autoverify.patch new file mode 100644 index 00000000..f8629f2f --- /dev/null +++ b/src/globals/patch/1006_openssl1.1_autoverify.patch @@ -0,0 +1,58 @@ +Description: Support OpenSSL 1.1 + When building with OpenSSL 1.1 and newer, use the new built-in + hostname verification instead of code that doesn't compile due to + structs having been made opaque. +Bug-Debian: https://bugs.debian.org/828589 + +--- a/src/osdep/unix/ssl_unix.c ++++ b/src/osdep/unix/ssl_unix.c +@@ -227,8 +227,16 @@ static char *ssl_start_work (SSLSTREAM * + /* disable certificate validation? */ + if (flags & NET_NOVALIDATECERT) + SSL_CTX_set_verify (stream->context,SSL_VERIFY_NONE,NIL); +- else SSL_CTX_set_verify (stream->context,SSL_VERIFY_PEER,ssl_open_verify); ++ else { ++#if OPENSSL_VERSION_NUMBER >= 0x10100000 ++ X509_VERIFY_PARAM *param = SSL_CTX_get0_param(stream->context); ++ X509_VERIFY_PARAM_set_hostflags(param, X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS); ++ X509_VERIFY_PARAM_set1_host(param, host, 0); ++#endif ++ ++ SSL_CTX_set_verify (stream->context,SSL_VERIFY_PEER,ssl_open_verify); + /* set default paths to CAs... */ ++ } + SSL_CTX_set_default_verify_paths (stream->context); + /* ...unless a non-standard path desired */ + if (s = (char *) mail_parameters (NIL,GET_SSLCAPATH,NIL)) +@@ -266,6 +274,7 @@ static char *ssl_start_work (SSLSTREAM * + if (SSL_write (stream->con,"",0) < 0) + return ssl_last_error ? ssl_last_error : "SSL negotiation failed"; + /* need to validate host names? */ ++#if OPENSSL_VERSION_NUMBER < 0x10100000 + if (!(flags & NET_NOVALIDATECERT) && + (err = ssl_validate_cert (cert = SSL_get_peer_certificate (stream->con), + host))) { +@@ -275,6 +284,7 @@ static char *ssl_start_work (SSLSTREAM * + sprintf (tmp,"*%.128s: %.255s",err,cert ? cert->name : "???"); + return ssl_last_error = cpystr (tmp); + } ++#endif + return NIL; + } + +@@ -313,6 +323,7 @@ static int ssl_open_verify (int ok,X509_ + * Returns: NIL if validated, else string of error message + */ + ++#if OPENSSL_VERSION_NUMBER < 0x10100000 + static char *ssl_validate_cert (X509 *cert,char *host) + { + int i,n; +@@ -342,6 +353,7 @@ static char *ssl_validate_cert (X509 *ce + else ret = "Unable to locate common name in certificate"; + return ret; + } ++#endif + + /* Case-independent wildcard pattern match + * Accepts: base string diff --git a/src/globals/patch/2014_openssl1.1.1_sni.patch b/src/globals/patch/2014_openssl1.1.1_sni.patch new file mode 100644 index 00000000..256d7d6d --- /dev/null +++ b/src/globals/patch/2014_openssl1.1.1_sni.patch @@ -0,0 +1,42 @@ +Bug-Debian: https://bugs.debian.org/916041 +Bug-Ubuntu: https://bugs.launchpad.net/bugs/1834340 +Description: + Google IMAP servers require SNI if TLSv1.3 is used, + otherwise it sends a self-signed certificate which + fails validation. + + OpenSSL support/versions: + - TLSv1.3 on 1.1.1, + - a2i_IPADDRESS() on 0.9.8'ish, + - SSL_set_tlsext_host_name() on 0.9.8'ish/1.0.0; + per 'git blame/describe' and the CHANGES file. + + So check for TLSv1.3 support / OpenSSL 1.1.1 + not to incur behavior changes on pre-TLSv1.3, + and set host_name to 'host' (ssl_open_verify() + validates this, via 'ssl_last_host' variable) + + This patch just combines these two patches: + - BTS#916041 (message #5) by Ed Spiridonov, + - LP#1834340 (comment #6) by David Zuelke. +Author: Mauricio Faria de Oliveira + +Index: uw-imap-2007f~dfsg/src/osdep/unix/ssl_unix.c +=================================================================== +--- uw-imap-2007f~dfsg.orig/src/osdep/unix/ssl_unix.c ++++ uw-imap-2007f~dfsg/src/osdep/unix/ssl_unix.c +@@ -266,6 +266,14 @@ static char *ssl_start_work (SSLSTREAM * + /* create connection */ + if (!(stream->con = (SSL *) SSL_new (stream->context))) + return "SSL connection failed"; ++#if OPENSSL_VERSION_NUMBER >= 0x10101000 ++ /* Use SNI in case server requires it with TLSv1.3. ++ * Literal IP addresses not permitted per RFC 6066. */ ++ if (!a2i_IPADDRESS(host)) { ++ ERR_clear_error(); ++ SSL_set_tlsext_host_name(stream->con,host); ++ } ++#endif + bio = BIO_new_socket (stream->tcpstream->tcpsi,BIO_NOCLOSE); + SSL_set_bio (stream->con,bio,bio); + SSL_set_connect_state (stream->con);