-diff -urNpa dovecot-ce-2.3.0.orig/doc/example-config/conf.d/10-ssl.conf dovecot-ce-2.3.0/doc/example-config/conf.d/10-ssl.conf
---- dovecot-ce-2.3.0.orig/doc/example-config/conf.d/10-ssl.conf 2017-12-22 13:53:36.000000000 +0000
-+++ dovecot-ce-2.3.0/doc/example-config/conf.d/10-ssl.conf 2018-01-19 10:16:36.961648643 +0000
+diff -urN dovecot-2.0.3.org/doc/example-config/conf.d/10-ssl.conf dovecot-2.0.3/doc/example-config/conf.d/10-ssl.conf
+--- dovecot-2.0.3.org/doc/example-config/conf.d/10-ssl.conf 2010-05-24 16:35:40.000000000 +0200
++++ dovecot-2.0.3/doc/example-config/conf.d/10-ssl.conf 2010-09-18 22:05:37.079775811 +0200
@@ -3,14 +3,14 @@
##
--- /dev/null
+; export fields from lua back to dovecot also on userdb/passdb failures
+; Patch by Przemysław Plewa
+diff -urNp dovecot-2.3.21.1.org/src/auth/db-lua.c dovecot-2.3.21.1/src/auth/db-lua.c
+--- dovecot-2.3.21.1.org/src/auth/db-lua.c 2024-08-13 12:37:50.000000000 +0200
++++ dovecot-2.3.21.1/src/auth/db-lua.c 2025-02-19 10:28:54.277679024 +0100
+@@ -537,14 +537,13 @@ auth_lua_export_userdb_table(lua_State *
+ {
+ enum userdb_result ret = lua_tointeger(L, -2);
+
++ auth_lua_export_table(L, req, NULL, NULL);
++
+ if (ret != USERDB_RESULT_OK) {
+- lua_pop(L, 2);
+- lua_gc(L, LUA_GCCOLLECT, 0);
+ *error_r = "userdb failed";
+ return ret;
+ }
+
+- auth_lua_export_table(L, req, NULL, NULL);
+ return USERDB_RESULT_OK;
+ }
+
+@@ -555,14 +554,13 @@ auth_lua_export_passdb_table(lua_State *
+ {
+ enum passdb_result ret = lua_tointeger(L, -2);
+
++ auth_lua_export_table(L, req, scheme_r, password_r);
++
+ if (ret != PASSDB_RESULT_OK) {
+- lua_pop(L, 2);
+- lua_gc(L, LUA_GCCOLLECT, 0);
+ *error_r = "passb failed";
+ return ret;
+ }
+
+- auth_lua_export_table(L, req, scheme_r, password_r);
+ return PASSDB_RESULT_OK;
+ }
+
+@@ -585,7 +583,8 @@ auth_lua_call_lookup_finish(lua_State *L
+
+ if (ret != PASSDB_RESULT_OK && ret != PASSDB_RESULT_NEXT) {
+ *error_r = str;
+- } else {
++ }
++ if (str != NULL) {
+ auth_lua_export_fields(req, str, scheme_r, password_r);
+ }
+
-diff -urNpa dovecot-ce-2.3.0.orig/Makefile.am dovecot-ce-2.3.0/Makefile.am
---- dovecot-ce-2.3.0.orig/Makefile.am 2017-12-22 13:53:36.000000000 +0000
-+++ dovecot-ce-2.3.0/Makefile.am 2018-01-19 10:17:38.305644987 +0000
-@@ -73,7 +73,7 @@ install-exec-hook:
+--- dovecot-2.2.18/Makefile.am~ 2015-02-19 12:44:40.000000000 +0100
++++ dovecot-2.2.18/Makefile.am 2015-05-17 08:43:25.681245560 +0200
+@@ -64,7 +64,7 @@ install-exec-hook:
grep -v '^LIBDOVECOT_.*_INCLUDE' dovecot-config | \
grep -v '^LIBDOVECOT.*_DEPS' | sed \
-e "s|^\(DOVECOT_INSTALLED\)=.*$$|\1=yes|" \
exit 0
fi
+if [ -n "${DOVECOT_CONF}" ]; then
+ if [ -f "${DOVECOT_CONF}" ]; then
+ DOVECOT_CFG="-c ${DOVECOT_CONF}"
+ else
+ echo "error: DOVECOT_CONF='$DOVECOT_CONF': not a file"
+ exit 1
+ fi
+fi
+
start() {
# Check if the service is already running?
if [ ! -f /var/lock/subsys/dovecot ]; then
msg_starting "Dovecot"
- daemon /usr/sbin/dovecot
+ daemon /usr/sbin/dovecot $DOVECOT_CFG
RETVAL=$?
[ $RETVAL -eq 0 ] && touch /var/lock/subsys/dovecot
else
# Conditional build:
%bcond_without gssapi # without GSSAPI support
%bcond_without ldap # without LDAP auth
+%bcond_without lua # without Lua auth
%bcond_without mysql # without MySQL auth
%bcond_without pgsql # without PostgreSQL auth
%bcond_without sqlite # without SQLite3 auth
Summary(pl.UTF-8): Serwer IMAP i POP3 pisany głównie z myślą o bezpieczeństwie
Name: dovecot
Version: 2.3.21.1
-Release: 1
+Release: 2
Epoch: 1
License: MIT (libraries), LGPL v2.1 (the rest)
Group: Networking/Daemons
Patch0: %{name}-config.patch
Patch1: %{name}-rpath.patch
Patch2: %{name}-shebang.patch
+Patch3: proc-status.patch
+Patch4: openssl3.patch
+Patch5: icu76.patch
+Patch6: dovecot-lua-export-on-auth-fail.patch
URL: http://dovecot.org/
BuildRequires: autoconf
BuildRequires: automake
BuildRequires: libstemmer-devel
BuildRequires: libexttextcat-devel
BuildRequires: libtool
+%{?with_lua:BuildRequires: lua53-devel}
BuildRequires: lz4-devel
%{?with_mysql:BuildRequires: mysql-devel}
%{?with_ldap:BuildRequires: openldap-devel >= 2.3.3}
BuildRequires: openssl-devel >= 0.9.7d
BuildRequires: pam-devel
BuildRequires: pkgconfig
+BuildRequires: pkgconfig(lua) >= 5.1
%{?with_pgsql:BuildRequires: postgresql-devel}
BuildRequires: rpmbuild(macros) >= 1.647
BuildRequires: sed >= 4.0
%{?with_sqlite:BuildRequires: sqlite3-devel}
BuildRequires: xz-devel
BuildRequires: zlib-devel
+BuildRequires: zstd-devel
Requires(post,preun): /sbin/chkconfig
Requires(postun): /usr/sbin/groupdel
Requires(postun): /usr/sbin/userdel
Requires: %{name}-libs = %{epoch}:%{version}-%{release}
Requires: pam >= 0.79.0
Provides: group(dovecot)
+Provides: group(dovenull)
Provides: imapdaemon
Provides: pop3daemon
Provides: user(dovecot)
%prep
%setup -q
-%patch0 -p1
-%patch1 -p1
-%patch2 -p1
+%patch -P0 -p1
+%patch -P1 -p1
+%patch -P2 -p1
+%patch -P3 -p1
+%patch -P4 -p1
+%patch -P5 -p1
+%patch -P6 -p1
%{__sed} -i 's,/usr/lib/dovecot,%{_libdir}/dovecot,g' doc/example-config/*.conf doc/example-config/conf.d/*.conf
+%{__sed} -i 's,#!/usr/bin/env bash,#!/bin/bash,' src/util/health-check.sh
+
%build
touch config.rpath
%{__libtoolize}
%{__autoheader}
%{__automake}
%configure \
- ac_cv_prog_VALGRIND=no \
+ ac_cv_path_VALGRIND=reject \
CPPFLAGS="%{rpmcppflags} -I/usr/include/libstemmer -D_LINUX_QUOTA_VERSION=2" \
--disable-static \
+ --enable-hardening \
%{?debug:--enable-debug} \
%{?with_ldap:--with-ldap=yes} \
%{?with_mysql:--with-mysql} \
%{?with_pgsql:--with-pgsql} \
%{?with_sqlite:--with-sqlite} \
%{?with_gssapi:--with-gssapi=plugin} \
+ %{?with_lua:--with-lua=plugin} \
--with-lucene \
--with-stemmer \
--with-solr \
--with-bzlib \
--with-libcap \
--with-ssl=openssl \
+ --with-zstd \
+%ifarch x32
+ --without-libunwind \
+%endif
--with-moduledir=%{_libdir}/%{name}/plugins \
--with-ssldir=/var/lib/openssl \
--sysconfdir=%{_sysconfdir}
%attr(755,root,root) %{_libdir}/%{name}/libdovecot-lda.so.0.0.0
%{?with_ldap:%attr(755,root,root) %{_libdir}/%{name}/libdovecot-ldap.so.0.0.0}
%attr(755,root,root) %{_libdir}/%{name}/libdovecot-login.so.0.0.0
+%attr(755,root,root) %{_libdir}/%{name}/libdovecot-lua.so.0.0.0
%attr(755,root,root) %{_libdir}/%{name}/libdovecot-sql.so.0.0.0
%attr(755,root,root) %{_libdir}/%{name}/libdovecot-storage.so.0.0.0
+%attr(755,root,root) %{_libdir}/%{name}/libdovecot-storage-lua.so.0.0.0
# Note: we are in %{_libdir}/dovecot, ldconfig does not look into this
# directory. This is why the following files are not %ghost
%attr(755,root,root) %{_libdir}/%{name}/libdovecot.so.0
%attr(755,root,root) %{_libdir}/%{name}/libdovecot-lda.so.0
%{?with_ldap:%attr(755,root,root) %{_libdir}/%{name}/libdovecot-ldap.so.0}
%attr(755,root,root) %{_libdir}/%{name}/libdovecot-login.so.0
+%attr(755,root,root) %{_libdir}/%{name}/libdovecot-lua.so.0
%attr(755,root,root) %{_libdir}/%{name}/libdovecot-sql.so.0
%attr(755,root,root) %{_libdir}/%{name}/libdovecot-storage.so.0
+%attr(755,root,root) %{_libdir}/%{name}/libdovecot-storage-lua.so.0
%files devel
%defattr(644,root,root,755)
%attr(755,root,root) %{_libdir}/%{name}/libdovecot-lda.so
%{?with_ldap:%attr(755,root,root) %{_libdir}/%{name}/libdovecot-ldap.so}
%attr(755,root,root) %{_libdir}/%{name}/libdovecot-login.so
+%attr(755,root,root) %{_libdir}/%{name}/libdovecot-lua.so
%attr(755,root,root) %{_libdir}/%{name}/libdovecot-sql.so
%attr(755,root,root) %{_libdir}/%{name}/libdovecot-storage.so
+%attr(755,root,root) %{_libdir}/%{name}/libdovecot-storage-lua.so
%{_libdir}/%{name}/%{name}-config
%{_includedir}/%{name}
%{_aclocaldir}/dovecot.m4
--- /dev/null
+--- dovecot-2.3.21.1/m4/want_icu.m4.orig 2024-08-13 12:37:50.000000000 +0200
++++ dovecot-2.3.21.1/m4/want_icu.m4 2025-01-21 17:49:01.402262183 +0100
+@@ -1,7 +1,7 @@
+ AC_DEFUN([DOVECOT_WANT_ICU], [
+ if test "$want_icu" != "no"; then
+ if test "$PKG_CONFIG" != "" && $PKG_CONFIG --exists icu-i18n 2>/dev/null; then
+- PKG_CHECK_MODULES(LIBICU, icu-i18n)
++ PKG_CHECK_MODULES(LIBICU, [icu-i18n icu-uc])
+ have_icu=yes
+ AC_DEFINE(HAVE_LIBICU,, [Define if you want ICU normalization support for FTS])
+ elif test "$want_icu" = "yes"; then
--- /dev/null
+diff -up dovecot-2.3.14/src/lib-dcrypt/dcrypt-openssl.c.opensslv3 dovecot-2.3.14/src/lib-dcrypt/dcrypt-openssl.c
+--- dovecot-2.3.14/src/lib-dcrypt/dcrypt-openssl.c.opensslv3 2021-06-03 18:56:52.573174433 +0200
++++ dovecot-2.3.14/src/lib-dcrypt/dcrypt-openssl.c 2021-06-03 18:56:52.585174274 +0200
+@@ -73,10 +73,30 @@
+ 2<tab>key algo oid<tab>1<tab>symmetric algo name<tab>salt<tab>hash algo<tab>rounds<tab>E(RSA = i2d_PrivateKey, EC=Private Point)<tab>key id
+ **/
+
++#if OPENSSL_VERSION_MAJOR == 3
++static EC_KEY *EVP_PKEY_get0_EC_KEYv3(EVP_PKEY *key)
++{
++ EC_KEY *eck = EVP_PKEY_get1_EC_KEY(key);
++ EVP_PKEY_set1_EC_KEY(key, eck);
++ EC_KEY_free(eck);
++ return eck;
++}
++
++static EC_KEY *EVP_PKEY_get1_EC_KEYv3(EVP_PKEY *key)
++{
++ EC_KEY *eck = EVP_PKEY_get1_EC_KEY(key);
++ EVP_PKEY_set1_EC_KEY(key, eck);
++ return eck;
++}
++
++#define EVP_PKEY_get0_EC_KEY EVP_PKEY_get0_EC_KEYv3
++#define EVP_PKEY_get1_EC_KEY EVP_PKEY_get1_EC_KEYv3
++#else
+ #ifndef HAVE_EVP_PKEY_get0
+ #define EVP_PKEY_get0_EC_KEY(x) x->pkey.ec
+ #define EVP_PKEY_get0_RSA(x) x->pkey.rsa
+ #endif
++#endif
+
+ #ifndef HAVE_OBJ_LENGTH
+ #define OBJ_length(o) ((o)->length)
--- /dev/null
+From f359c6ee179aad5e077711c188fc8422106cbead Mon Sep 17 00:00:00 2001
+From: Aki Tuomi <aki.tuomi@open-xchange.com>
+Date: Tue, 21 Mar 2023 08:55:55 +0200
+Subject: [PATCH 1/3] lib: process-stat - Use buffer_append_full_istream() to
+ read files
+
+---
+ src/lib/process-stat.c | 84 ++++++++++++++++++++++--------------------
+ 1 file changed, 44 insertions(+), 40 deletions(-)
+
+diff --git a/src/lib/process-stat.c b/src/lib/process-stat.c
+index 782503e60b..60eddbc3ec 100644
+--- a/src/lib/process-stat.c
++++ b/src/lib/process-stat.c
+@@ -1,6 +1,9 @@
+ /* Copyright (c) 2008-2021 Dovecot authors, see the included COPYING file */
+
+ #include "lib.h"
++#include "buffer.h"
++#include "str.h"
++#include "istream.h"
+ #include "process-stat.h"
+ #include "time-util.h"
+ #include <limits.h>
+@@ -12,8 +15,12 @@
+ #include <stdio.h>
+
+ #define PROC_STAT_PATH "/proc/self/stat"
++#define PROC_STAT_MAX_SIZE 1024
+ #define PROC_STATUS_PATH "/proc/self/status"
++#define PROC_STATUS_MAX_SIZE 2048
+ #define PROC_IO_PATH "/proc/self/io"
++#define PROC_IO_MAX_SIZE 1024
++#define PROC_BUFFER_INITIAL_SIZE 512
+
+ static const uint64_t stat_undefined = 0xFFFFFFFFFFFFFFFF;
+
+@@ -71,39 +78,38 @@ static int open_fd(const char *path, struct event *event)
+ }
+
+ static int
+-read_file(int fd, const char *path, char *buf_r, size_t buf_size, struct event *event)
++read_file_buffer(const char *path, string_t *buf, size_t max_size, struct event *event)
+ {
+- ssize_t ret;
+- ret = read(fd, buf_r, buf_size);
+- if (ret <= 0) {
+- if (ret == -1)
+- e_error(event, "read(%s) failed: %m", path);
+- else
+- e_error(event, "read(%s) returned EOF", path);
+- } else if (ret == (ssize_t)buf_size) {
+- e_error(event, "%s is larger than expected", path);
+- buf_r[buf_size - 1] = '\0';
+- } else {
+- buf_r[ret] = '\0';
++ const char *error;
++ int fd = open_fd(path, event);
++ if (fd < 0)
++ return -1;
++ struct istream *is = i_stream_create_fd_autoclose(&fd, max_size);
++ i_stream_set_name(is, path);
++ enum buffer_append_result res =
++ buffer_append_full_istream(buf, is, max_size, &error);
++ i_stream_unref(&is);
++ if (res == BUFFER_APPEND_READ_MAX_SIZE)
++ e_error(event, "%s is larger than expected (%zu)", path, max_size);
++ else if (res != BUFFER_APPEND_OK) {
++ e_error(event, "read(%s) failed: %s", path, error);
++ return -1;
+ }
+- i_close_fd(&fd);
+- return ret <= 0 ? -1 : 0;
++ return 0;
+ }
+
+ static int parse_key_val_file(const char *path,
++ size_t max_size,
+ struct key_val *fields,
+ struct event *event)
+ {
+- char buf[2048];
+- int fd;
+-
+- fd = open_fd(path, event);
+- if (fd == -1 || read_file(fd, path, buf, sizeof(buf), event) < 0) {
++ string_t *buf = t_str_new(PROC_BUFFER_INITIAL_SIZE);
++ if (read_file_buffer(path, buf, max_size, event) < 0) {
+ for (; fields->key != NULL; fields++)
+ *fields->value = stat_undefined;
+ return -1;
+ }
+- buffer_parse(buf, fields);
++ buffer_parse(str_c(buf), fields);
+ return 0;
+ }
+
+@@ -117,7 +123,8 @@ static int parse_proc_io(struct process_stat *stat_r, struct event *event)
+ { NULL, NULL, 0 },
+ };
+ if (stat_r->proc_io_failed ||
+- parse_key_val_file(PROC_IO_PATH, fields, event) < 0) {
++ parse_key_val_file(PROC_IO_PATH, PROC_IO_MAX_SIZE, fields,
++ event) < 0) {
+ stat_r->proc_io_failed = TRUE;
+ return -1;
+ }
+@@ -132,7 +139,8 @@ static int parse_proc_status(struct process_stat *stat_r, struct event *event)
+ { NULL, NULL, 0 },
+ };
+ if (stat_r->proc_status_failed ||
+- parse_key_val_file(PROC_STATUS_PATH, fields, event) < 0) {
++ parse_key_val_file(PROC_STATUS_PATH, PROC_STATUS_MAX_SIZE,
++ fields, event) < 0) {
+ stat_r->proc_status_failed = TRUE;
+ return -1;
+ }
+@@ -156,8 +164,7 @@ static int stat_get_rusage(struct process_stat *stat_r)
+
+ static int parse_stat_file(struct process_stat *stat_r, struct event *event)
+ {
+- int fd = -1;
+- char buf[1024];
++ string_t *buf = t_str_new(PROC_BUFFER_INITIAL_SIZE);
+ unsigned int i;
+ const char *const *tmp;
+ struct {
+@@ -171,9 +178,8 @@ static int parse_stat_file(struct process_stat *stat_r, struct event *event)
+ { &stat_r->vsz, 22 },
+ { &stat_r->rss, 23 },
+ };
+- if (!stat_r->proc_stat_failed)
+- fd = open_fd(PROC_STAT_PATH, event);
+- if (fd == -1) {
++ if (stat_r->proc_stat_failed ||
++ read_file_buffer(PROC_STAT_PATH, buf, PROC_STAT_MAX_SIZE, event) < 0) {
+ stat_r->proc_stat_failed = TRUE;
+ /* vsz and rss are not provided by getrusage(), setting to undefined */
+ stat_r->vsz = stat_undefined;
+@@ -187,11 +193,7 @@ static int parse_stat_file(struct process_stat *stat_r, struct event *event)
+ }
+ return 0;
+ }
+- if (read_file(fd, PROC_STAT_PATH, buf, sizeof(buf), event) < 0) {
+- stat_r->proc_stat_failed = TRUE;
+- return -1;
+- }
+- tmp = t_strsplit(buf, " ");
++ tmp = t_strsplit(str_c(buf), " ");
+ unsigned int tmp_count = str_array_length(tmp);
+
+ for (i = 0; i < N_ELEMENTS(fields); i++) {
+@@ -208,13 +210,15 @@ static int parse_all_stats(struct process_stat *stat_r, struct event *event)
+ {
+ bool has_fields = FALSE;
+
+- if (parse_stat_file(stat_r, event) == 0)
+- has_fields = TRUE;
+- if (parse_proc_io(stat_r, event) == 0)
+- has_fields = TRUE;
+- if ((!stat_r->proc_stat_failed || stat_r->rusage_failed) &&
+- parse_proc_status(stat_r, event) == 0)
+- has_fields = TRUE;
++ T_BEGIN {
++ if (parse_stat_file(stat_r, event) == 0)
++ has_fields = TRUE;
++ if (parse_proc_io(stat_r, event) == 0)
++ has_fields = TRUE;
++ if ((!stat_r->proc_stat_failed || stat_r->rusage_failed) &&
++ parse_proc_status(stat_r, event) == 0)
++ has_fields = TRUE;
++ } T_END;
+
+ if (has_fields)
+ return 0;
+
+From 218a79a48bb0e5d2be44bb46c51836fd406b0c50 Mon Sep 17 00:00:00 2001
+From: Aki Tuomi <aki.tuomi@open-xchange.com>
+Date: Tue, 21 Mar 2023 09:05:12 +0200
+Subject: [PATCH 2/3] lib: process-stat - Increase maximum /proc/self/status
+ size
+
+Kernel 6.x has larger status file.
+---
+ src/lib/process-stat.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/src/lib/process-stat.c b/src/lib/process-stat.c
+index 60eddbc3ec..1d23c89964 100644
+--- a/src/lib/process-stat.c
++++ b/src/lib/process-stat.c
+@@ -17,7 +17,7 @@
+ #define PROC_STAT_PATH "/proc/self/stat"
+ #define PROC_STAT_MAX_SIZE 1024
+ #define PROC_STATUS_PATH "/proc/self/status"
+-#define PROC_STATUS_MAX_SIZE 2048
++#define PROC_STATUS_MAX_SIZE 4096
+ #define PROC_IO_PATH "/proc/self/io"
+ #define PROC_IO_MAX_SIZE 1024
+ #define PROC_BUFFER_INITIAL_SIZE 512
+
+From d93c31d51b05d43eaa6eeef9cdc0f7a4157f7d0e Mon Sep 17 00:00:00 2001
+From: Aki Tuomi <aki.tuomi@open-xchange.com>
+Date: Tue, 21 Mar 2023 09:13:35 +0200
+Subject: [PATCH 3/3] lib: process-stat - Use eacces_error_get() for EACCES
+ errno
+
+This tells better why the open failed.
+---
+ src/lib/process-stat.c | 5 ++++-
+ 1 file changed, 4 insertions(+), 1 deletion(-)
+
+diff --git a/src/lib/process-stat.c b/src/lib/process-stat.c
+index 1d23c89964..454d9335d2 100644
+--- a/src/lib/process-stat.c
++++ b/src/lib/process-stat.c
+@@ -4,6 +4,7 @@
+ #include "buffer.h"
+ #include "str.h"
+ #include "istream.h"
++#include "eacces-error.h"
+ #include "process-stat.h"
+ #include "time-util.h"
+ #include <limits.h>
+@@ -69,8 +70,10 @@ static int open_fd(const char *path, struct event *event)
+ errno = EACCES;
+ }
+ if (fd == -1) {
+- if (errno == ENOENT || errno == EACCES)
++ if (errno == ENOENT)
+ e_debug(event, "open(%s) failed: %m", path);
++ else if (errno == EACCES)
++ e_debug(event, "%s", eacces_error_get("open", path));
+ else
+ e_error(event, "open(%s) failed: %m", path);
+ }