commit
f9bd795ae0
@ -0,0 +1,2 @@
|
|||||||
|
e0707a46cb9e1342a74cb03803430f9198608e5e SOURCES/dovecot-2.3-pigeonhole-0.5.21.tar.gz
|
||||||
|
20300087e8575a42dc16245d05b0905b588396f9 SOURCES/dovecot-2.3.21.tar.gz
|
@ -0,0 +1,2 @@
|
|||||||
|
SOURCES/dovecot-2.3-pigeonhole-0.5.21.tar.gz
|
||||||
|
SOURCES/dovecot-2.3.21.tar.gz
|
@ -0,0 +1,11 @@
|
|||||||
|
--- dovecot-1.0.beta2/doc/mkcert.sh.configfile 2006-01-16 21:14:54.000000000 +0100
|
||||||
|
+++ dovecot-1.0.beta2/doc/mkcert.sh 2006-01-26 14:28:38.000000000 +0100
|
||||||
|
@@ -29,6 +29,7 @@
|
||||||
|
fi
|
||||||
|
|
||||||
|
$OPENSSL req -new -x509 -nodes -config $OPENSSLCONFIG -out $CERTFILE -keyout $KEYFILE -days 365 || exit 2
|
||||||
|
-chmod 0600 $KEYFILE
|
||||||
|
+chown root:root $CERTFILE $KEYFILE
|
||||||
|
+chmod 0600 $CERTFILE $KEYFILE
|
||||||
|
echo
|
||||||
|
$OPENSSL x509 -subject -fingerprint -noout -in $CERTFILE || exit 2
|
@ -0,0 +1,14 @@
|
|||||||
|
diff -up dovecot-2.2.27/doc/mkcert.sh.mkcert-paths dovecot-2.2.27/doc/mkcert.sh
|
||||||
|
--- dovecot-2.2.27/doc/mkcert.sh.mkcert-paths 2016-12-05 10:26:07.913515286 +0100
|
||||||
|
+++ dovecot-2.2.27/doc/mkcert.sh 2016-12-05 10:28:25.439634417 +0100
|
||||||
|
@@ -5,8 +5,8 @@
|
||||||
|
|
||||||
|
umask 077
|
||||||
|
OPENSSL=${OPENSSL-openssl}
|
||||||
|
-SSLDIR=${SSLDIR-/etc/ssl}
|
||||||
|
-OPENSSLCONFIG=${OPENSSLCONFIG-dovecot-openssl.cnf}
|
||||||
|
+SSLDIR=${SSLDIR-/etc/pki/dovecot}
|
||||||
|
+OPENSSLCONFIG=${OPENSSLCONFIG-/etc/pki/dovecot/dovecot-openssl.cnf}
|
||||||
|
|
||||||
|
CERTDIR=$SSLDIR/certs
|
||||||
|
KEYDIR=$SSLDIR/private
|
@ -0,0 +1,42 @@
|
|||||||
|
diff -up dovecot-2.3.16/doc/example-config/conf.d/10-mail.conf.default-settings dovecot-2.3.16/doc/example-config/conf.d/10-mail.conf
|
||||||
|
--- dovecot-2.3.16/doc/example-config/conf.d/10-mail.conf.default-settings 2021-08-06 11:25:51.000000000 +0200
|
||||||
|
+++ dovecot-2.3.16/doc/example-config/conf.d/10-mail.conf 2021-10-27 11:13:45.666956339 +0200
|
||||||
|
@@ -175,7 +175,7 @@ namespace inbox {
|
||||||
|
# to make sure that users can't log in as daemons or other system users.
|
||||||
|
# Note that denying root logins is hardcoded to dovecot binary and can't
|
||||||
|
# be done even if first_valid_uid is set to 0.
|
||||||
|
-#first_valid_uid = 500
|
||||||
|
+first_valid_uid = 1000
|
||||||
|
#last_valid_uid = 0
|
||||||
|
|
||||||
|
# Valid GID range for users, defaults to non-root/wheel. Users having
|
||||||
|
@@ -322,6 +322,7 @@ protocol !indexer-worker {
|
||||||
|
# them simultaneously.
|
||||||
|
#mbox_read_locks = fcntl
|
||||||
|
#mbox_write_locks = dotlock fcntl
|
||||||
|
+mbox_write_locks = fcntl
|
||||||
|
|
||||||
|
# Maximum time to wait for lock (all of them) before aborting.
|
||||||
|
#mbox_lock_timeout = 5 mins
|
||||||
|
diff -up dovecot-2.3.16/doc/example-config/conf.d/10-ssl.conf.default-settings dovecot-2.3.16/doc/example-config/conf.d/10-ssl.conf
|
||||||
|
--- dovecot-2.3.16/doc/example-config/conf.d/10-ssl.conf.default-settings 2021-08-06 11:25:51.000000000 +0200
|
||||||
|
+++ dovecot-2.3.16/doc/example-config/conf.d/10-ssl.conf 2021-10-27 11:13:02.834533975 +0200
|
||||||
|
@@ -3,7 +3,9 @@
|
||||||
|
##
|
||||||
|
|
||||||
|
# SSL/TLS support: yes, no, required. <doc/wiki/SSL.txt>
|
||||||
|
-#ssl = yes
|
||||||
|
+# disable plain pop3 and imap, allowed are only pop3+TLS, pop3s, imap+TLS and imaps
|
||||||
|
+# plain imap and pop3 are still allowed for local connections
|
||||||
|
+ssl = required
|
||||||
|
|
||||||
|
# PEM encoded X.509 SSL/TLS certificate and private key. They're opened before
|
||||||
|
# dropping root privileges, so keep the key file unreadable by anyone but
|
||||||
|
@@ -64,6 +66,7 @@ ssl_key = </etc/ssl/private/dovecot.pem
|
||||||
|
#ssl_cipher_list = ALL:!kRSA:!SRP:!kDHd:!DSS:!aNULL:!eNULL:!EXPORT:!DES:!3DES:!MD5:!PSK:!RC4:!ADH:!LOW@STRENGTH
|
||||||
|
# To disable non-EC DH, use:
|
||||||
|
#ssl_cipher_list = ALL:!DH:!kRSA:!SRP:!kDHd:!DSS:!aNULL:!eNULL:!EXPORT:!DES:!3DES:!MD5:!PSK:!RC4:!ADH:!LOW@STRENGTH
|
||||||
|
+ssl_cipher_list = PROFILE=SYSTEM
|
||||||
|
|
||||||
|
# Colon separated list of elliptic curves to use. Empty value (the default)
|
||||||
|
# means use the defaults from the SSL library. P-521:P-384:P-256 would be an
|
@ -0,0 +1,11 @@
|
|||||||
|
diff -up dovecot-2.3.19.1/dovecot.service.in.waitonline dovecot-2.3.19.1/dovecot.service.in
|
||||||
|
--- dovecot-2.3.19.1/dovecot.service.in.waitonline 2022-06-14 08:55:03.000000000 +0200
|
||||||
|
+++ dovecot-2.3.19.1/dovecot.service.in 2022-11-08 20:28:37.550081709 +0100
|
||||||
|
@@ -12,6 +12,7 @@ Description=Dovecot IMAP/POP3 email serv
|
||||||
|
Documentation=man:dovecot(1)
|
||||||
|
Documentation=https://doc.dovecot.org/
|
||||||
|
After=local-fs.target network-online.target
|
||||||
|
+Wants=network-online.target
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Type=@systemdservicetype@
|
@ -0,0 +1,51 @@
|
|||||||
|
diff -up dovecot-2.3.15/dovecot-init.service.initbysystemd dovecot-2.3.15/dovecot-init.service
|
||||||
|
--- dovecot-2.3.15/dovecot-init.service.initbysystemd 2021-06-21 20:21:49.250680889 +0200
|
||||||
|
+++ dovecot-2.3.15/dovecot-init.service 2021-06-21 20:21:49.250680889 +0200
|
||||||
|
@@ -0,0 +1,13 @@
|
||||||
|
+[Unit]
|
||||||
|
+Description=One-time Dovecot init service
|
||||||
|
+ConditionPathExists=|!/etc/pki/dovecot/certs/dovecot.pem
|
||||||
|
+
|
||||||
|
+[Service]
|
||||||
|
+Type=oneshot
|
||||||
|
+RemainAfterExit=no
|
||||||
|
+ExecStart=/bin/sh -c '\
|
||||||
|
+if [ ! -f /etc/pki/dovecot/certs/dovecot.pem ]; \
|
||||||
|
+then\
|
||||||
|
+ SSLDIR=/etc/pki/dovecot/ OPENSSLCONFIG=/etc/pki/dovecot/dovecot-openssl.cnf /usr/libexec/dovecot/mkcert.sh /dev/null 2>&1;\
|
||||||
|
+fi'
|
||||||
|
+
|
||||||
|
diff -up dovecot-2.3.15/dovecot.service.in.initbysystemd dovecot-2.3.15/dovecot.service.in
|
||||||
|
--- dovecot-2.3.15/dovecot.service.in.initbysystemd 2021-06-21 20:21:49.250680889 +0200
|
||||||
|
+++ dovecot-2.3.15/dovecot.service.in 2021-06-21 20:22:46.935981920 +0200
|
||||||
|
@@ -11,7 +11,8 @@
|
||||||
|
Description=Dovecot IMAP/POP3 email server
|
||||||
|
Documentation=man:dovecot(1)
|
||||||
|
Documentation=https://doc.dovecot.org/
|
||||||
|
-After=local-fs.target network-online.target
|
||||||
|
+After=local-fs.target network-online.target dovecot-init.service
|
||||||
|
+Requires=dovecot-init.service
|
||||||
|
Wants=network-online.target
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
diff -up dovecot-2.3.15/Makefile.am.initbysystemd dovecot-2.3.15/Makefile.am
|
||||||
|
--- dovecot-2.3.15/Makefile.am.initbysystemd 2021-06-21 20:21:49.250680889 +0200
|
||||||
|
+++ dovecot-2.3.15/Makefile.am 2021-06-21 20:24:26.676765849 +0200
|
||||||
|
@@ -21,6 +21,7 @@ EXTRA_DIST = \
|
||||||
|
run-test-valgrind.supp \
|
||||||
|
dovecot.service.in \
|
||||||
|
dovecot.socket \
|
||||||
|
+ dovecot-init.service \
|
||||||
|
$(conf_DATA)
|
||||||
|
|
||||||
|
noinst_DATA = dovecot-config
|
||||||
|
@@ -69,7 +70,8 @@ dovecot-config: dovecot-config.in Makefi
|
||||||
|
if WANT_SYSTEMD
|
||||||
|
systemdsystemunit_DATA = \
|
||||||
|
dovecot.socket \
|
||||||
|
- dovecot.service
|
||||||
|
+ dovecot.service \
|
||||||
|
+ dovecot-init.service
|
||||||
|
endif
|
||||||
|
|
||||||
|
install-exec-hook:
|
@ -0,0 +1,11 @@
|
|||||||
|
diff -up dovecot-2.3.2/dovecot.service.in.systemd_w_protectsystem dovecot-2.3.2/dovecot.service.in
|
||||||
|
--- dovecot-2.3.2/dovecot.service.in.systemd_w_protectsystem 2018-07-09 12:00:13.359193526 +0200
|
||||||
|
+++ dovecot-2.3.2/dovecot.service.in 2018-07-09 12:00:46.387716884 +0200
|
||||||
|
@@ -23,6 +23,7 @@ ExecReload=@bindir@/doveadm reload
|
||||||
|
ExecStop=@bindir@/doveadm stop
|
||||||
|
PrivateTmp=true
|
||||||
|
NonBlocking=yes
|
||||||
|
+# this will make /usr /boot /etc read only for dovecot
|
||||||
|
ProtectSystem=full
|
||||||
|
ProtectHome=no
|
||||||
|
PrivateDevices=true
|
@ -0,0 +1,48 @@
|
|||||||
|
diff -up dovecot-2.3.21/dovecot-pigeonhole/src/lib-sieve/plugins/include/cmd-include.c.ph_optglob dovecot-2.3.21/dovecot-pigeonhole/src/lib-sieve/plugins/include/cmd-include.c
|
||||||
|
--- dovecot-2.3.21/dovecot-pigeonhole/src/lib-sieve/plugins/include/cmd-include.c.ph_optglob 2024-06-04 09:11:28.514189662 +0200
|
||||||
|
+++ dovecot-2.3.21/dovecot-pigeonhole/src/lib-sieve/plugins/include/cmd-include.c 2024-06-04 09:18:23.219809778 +0200
|
||||||
|
@@ -368,11 +368,13 @@ static bool opc_include_dump
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
sieve_code_descend(denv);
|
||||||
|
- sieve_code_dumpf(denv, "script: `%s' from %s %s%s[ID: %d, BLOCK: %d]",
|
||||||
|
+ sieve_code_dumpf(denv, "script: `%s' from %s %s%s%s[ID: %d, BLOCK: %d]",
|
||||||
|
sieve_script_name(included->script), sieve_script_location(included->script),
|
||||||
|
((flags & EXT_INCLUDE_FLAG_ONCE) != 0 ? "(once) " : ""),
|
||||||
|
((flags & EXT_INCLUDE_FLAG_OPTIONAL) != 0 ? "(optional) " : ""),
|
||||||
|
- include_id, sieve_binary_block_get_id(included->block));
|
||||||
|
+ (included->block == NULL ? "(missing) " : ""),
|
||||||
|
+ include_id,
|
||||||
|
+ (included->block == NULL ? -1 : sieve_binary_block_get_id(included->block)));
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
diff -up dovecot-2.3.21/dovecot-pigeonhole/src/lib-sieve/plugins/include/ext-include-common.c.ph_optglob dovecot-2.3.21/dovecot-pigeonhole/src/lib-sieve/plugins/include/ext-include-common.c
|
||||||
|
--- dovecot-2.3.21/dovecot-pigeonhole/src/lib-sieve/plugins/include/ext-include-common.c.ph_optglob 2023-09-14 15:18:26.000000000 +0200
|
||||||
|
+++ dovecot-2.3.21/dovecot-pigeonhole/src/lib-sieve/plugins/include/ext-include-common.c 2024-06-04 09:10:45.187823805 +0200
|
||||||
|
@@ -693,6 +693,25 @@ int ext_include_execute_include(const st
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx = ext_include_get_interpreter_context(this_ext, renv->interp);
|
||||||
|
+ if (included->block == NULL) {
|
||||||
|
+ if ((flags & EXT_INCLUDE_FLAG_OPTIONAL) != 0) {
|
||||||
|
+ sieve_runtime_trace(
|
||||||
|
+ renv, SIEVE_TRLVL_NONE,
|
||||||
|
+ "include: skipped include for script '%s' "
|
||||||
|
+ "[inc id: %d, block: NULL]; optional and unavailable",
|
||||||
|
+ sieve_script_name(included->script),
|
||||||
|
+ include_id);
|
||||||
|
+ return result;
|
||||||
|
+ } else {
|
||||||
|
+ sieve_runtime_trace(
|
||||||
|
+ renv, SIEVE_TRLVL_NONE,
|
||||||
|
+ "include: unavailable script '%s' "
|
||||||
|
+ "[inc id: %d, block: NULL]",
|
||||||
|
+ sieve_script_name(included->script),
|
||||||
|
+ include_id);
|
||||||
|
+ return SIEVE_EXEC_BIN_CORRUPT;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
block_id = sieve_binary_block_get_id(included->block);
|
||||||
|
|
||||||
|
/* If :once modifier is specified, check for duplicate include */
|
@ -0,0 +1,12 @@
|
|||||||
|
diff -up dovecot-2.3.21/dovecot-pigeonhole/src/lib-sieve/storage/file/sieve-file-script.c.testfix4 dovecot-2.3.21/dovecot-pigeonhole/src/lib-sieve/storage/file/sieve-file-script.c
|
||||||
|
--- dovecot-2.3.21/dovecot-pigeonhole/src/lib-sieve/storage/file/sieve-file-script.c.testfix4 2024-06-03 13:35:24.408858593 +0200
|
||||||
|
+++ dovecot-2.3.21/dovecot-pigeonhole/src/lib-sieve/storage/file/sieve-file-script.c 2024-06-03 13:35:24.434858849 +0200
|
||||||
|
@@ -800,7 +800,7 @@ static bool sieve_file_script_equals
|
||||||
|
(struct sieve_file_script *)other;
|
||||||
|
|
||||||
|
return ( CMP_DEV_T(fscript->st.st_dev, fother->st.st_dev) &&
|
||||||
|
- fscript->st.st_ino == fother->st.st_ino );
|
||||||
|
+ fscript->st.st_ino == fother->st.st_ino && (fscript->st.st_ino != 0 || script->location != NULL && other->location != NULL && strcmp(script->location, other->location) == 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
@ -0,0 +1,11 @@
|
|||||||
|
diff -up dovecot-2.3.0.1/src/auth/mycrypt.c.libxcrypt dovecot-2.3.0.1/src/auth/mycrypt.c
|
||||||
|
--- dovecot-2.3.0.1/src/auth/mycrypt.c.libxcrypt 2018-02-28 15:28:58.000000000 +0100
|
||||||
|
+++ dovecot-2.3.0.1/src/auth/mycrypt.c 2018-03-27 10:57:38.447769201 +0200
|
||||||
|
@@ -14,6 +14,7 @@
|
||||||
|
# define _XPG6 /* Some Solaris versions require this, some break with this */
|
||||||
|
#endif
|
||||||
|
#include <unistd.h>
|
||||||
|
+#include <crypt.h>
|
||||||
|
|
||||||
|
#include "mycrypt.h"
|
||||||
|
|
@ -0,0 +1,10 @@
|
|||||||
|
diff -up dovecot-2.3.15/doc/dovecot-openssl.cnf.bigkey dovecot-2.3.15/doc/dovecot-openssl.cnf
|
||||||
|
--- dovecot-2.3.15/doc/dovecot-openssl.cnf.bigkey 2021-06-21 20:24:51.913456628 +0200
|
||||||
|
+++ dovecot-2.3.15/doc/dovecot-openssl.cnf 2021-06-21 20:25:36.352912123 +0200
|
||||||
|
@@ -1,5 +1,5 @@
|
||||||
|
[ req ]
|
||||||
|
-default_bits = 2048
|
||||||
|
+default_bits = 3072
|
||||||
|
encrypt_key = yes
|
||||||
|
distinguished_name = req_dn
|
||||||
|
x509_extensions = cert_type
|
@ -0,0 +1,34 @@
|
|||||||
|
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)
|
@ -0,0 +1,24 @@
|
|||||||
|
diff -up dovecot-2.3.17/dovecot-pigeonhole/src/lib-sieve/storage/dict/sieve-dict-script.c.fixvalcond dovecot-2.3.17/dovecot-pigeonhole/src/lib-sieve/storage/dict/sieve-dict-script.c
|
||||||
|
--- dovecot-2.3.17/dovecot-pigeonhole/src/lib-sieve/storage/dict/sieve-dict-script.c.fixvalcond 2021-11-02 21:51:36.109032050 +0100
|
||||||
|
+++ dovecot-2.3.17/dovecot-pigeonhole/src/lib-sieve/storage/dict/sieve-dict-script.c 2021-11-02 21:52:28.409344118 +0100
|
||||||
|
@@ -114,7 +114,7 @@ static int sieve_dict_script_get_stream
|
||||||
|
(struct sieve_dict_script *)script;
|
||||||
|
struct sieve_dict_storage *dstorage =
|
||||||
|
(struct sieve_dict_storage *)script->storage;
|
||||||
|
- const char *path, *name = script->name, *data, *error;
|
||||||
|
+ const char *path, *name = script->name, *data, *error = NULL;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
dscript->data_pool =
|
||||||
|
diff -up dovecot-2.3.17/src/lib-storage/index/index-attribute.c.fixvalcond dovecot-2.3.17/src/lib-storage/index/index-attribute.c
|
||||||
|
--- dovecot-2.3.17/src/lib-storage/index/index-attribute.c.fixvalcond 2021-10-27 13:09:04.000000000 +0200
|
||||||
|
+++ dovecot-2.3.17/src/lib-storage/index/index-attribute.c 2021-11-02 21:51:36.109032050 +0100
|
||||||
|
@@ -248,7 +248,7 @@ int index_storage_attribute_get(struct m
|
||||||
|
struct mail_attribute_value *value_r)
|
||||||
|
{
|
||||||
|
struct dict *dict;
|
||||||
|
- const char *mailbox_prefix, *error;
|
||||||
|
+ const char *mailbox_prefix, *error = NULL;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
i_zero(value_r);
|
@ -0,0 +1,20 @@
|
|||||||
|
diff -up dovecot-2.3.15/run-test-valgrind.supp.valbasherr dovecot-2.3.15/run-test-valgrind.supp
|
||||||
|
--- dovecot-2.3.15/run-test-valgrind.supp.valbasherr 2021-06-21 22:52:53.272707239 +0200
|
||||||
|
+++ dovecot-2.3.15/run-test-valgrind.supp 2021-06-21 22:54:19.786668430 +0200
|
||||||
|
@@ -1,4 +1,16 @@
|
||||||
|
{
|
||||||
|
+ <bashagin>
|
||||||
|
+ Memcheck:Leak
|
||||||
|
+ match-leak-kinds: definite
|
||||||
|
+ fun:malloc
|
||||||
|
+ fun:make_if_command
|
||||||
|
+ fun:yyparse
|
||||||
|
+ fun:parse_command
|
||||||
|
+ fun:read_command
|
||||||
|
+ fun:reader_loop
|
||||||
|
+ fun:main
|
||||||
|
+}
|
||||||
|
+{
|
||||||
|
<bash>
|
||||||
|
Memcheck:Leak
|
||||||
|
fun:malloc
|
@ -0,0 +1,131 @@
|
|||||||
|
From 7bad6a24160e34bce8f10e73dbbf9e5fbbcd1904 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Timo Sirainen <timo.sirainen@open-xchange.com>
|
||||||
|
Date: Mon, 9 May 2022 15:23:33 +0300
|
||||||
|
Subject: [PATCH] auth: Fix handling passdbs with identical driver/args but
|
||||||
|
different mechanisms/username_filter
|
||||||
|
|
||||||
|
The passdb was wrongly deduplicated in this situation, causing wrong
|
||||||
|
mechanisms or username_filter setting to be used. This would be a rather
|
||||||
|
unlikely configuration though.
|
||||||
|
|
||||||
|
Fixed by moving mechanisms and username_filter from struct passdb_module
|
||||||
|
to struct auth_passdb, which is where they should have been in the first
|
||||||
|
place.
|
||||||
|
---
|
||||||
|
src/auth/auth-request.c | 6 +++---
|
||||||
|
src/auth/auth.c | 18 ++++++++++++++++++
|
||||||
|
src/auth/auth.h | 5 +++++
|
||||||
|
src/auth/passdb.c | 15 ++-------------
|
||||||
|
src/auth/passdb.h | 4 ----
|
||||||
|
5 files changed, 28 insertions(+), 20 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/src/auth/auth-request.c b/src/auth/auth-request.c
|
||||||
|
index cd08b1fa02..0ca29f3674 100644
|
||||||
|
--- a/src/auth/auth-request.c
|
||||||
|
+++ b/src/auth/auth-request.c
|
||||||
|
@@ -534,8 +534,8 @@ auth_request_want_skip_passdb(struct auth_request *request,
|
||||||
|
struct auth_passdb *passdb)
|
||||||
|
{
|
||||||
|
/* if mechanism is not supported, skip */
|
||||||
|
- const char *const *mechs = passdb->passdb->mechanisms;
|
||||||
|
- const char *const *username_filter = passdb->passdb->username_filter;
|
||||||
|
+ const char *const *mechs = passdb->mechanisms;
|
||||||
|
+ const char *const *username_filter = passdb->username_filter;
|
||||||
|
const char *username;
|
||||||
|
|
||||||
|
username = request->fields.user;
|
||||||
|
@@ -548,7 +548,7 @@ auth_request_want_skip_passdb(struct auth_request *request,
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
- if (passdb->passdb->username_filter != NULL &&
|
||||||
|
+ if (passdb->username_filter != NULL &&
|
||||||
|
!auth_request_username_accepted(username_filter, username)) {
|
||||||
|
auth_request_log_debug(request,
|
||||||
|
request->mech != NULL ? AUTH_SUBSYS_MECH
|
||||||
|
diff --git a/src/auth/auth.c b/src/auth/auth.c
|
||||||
|
index f2f3fda20c..9f6c4ba60c 100644
|
||||||
|
--- a/src/auth/auth.c
|
||||||
|
+++ b/src/auth/auth.c
|
||||||
|
@@ -99,6 +99,24 @@ auth_passdb_preinit(struct auth *auth, const struct auth_passdb_settings *set,
|
||||||
|
auth_passdb->override_fields_tmpl =
|
||||||
|
passdb_template_build(auth->pool, set->override_fields);
|
||||||
|
|
||||||
|
+ if (*set->mechanisms == '\0') {
|
||||||
|
+ auth_passdb->mechanisms = NULL;
|
||||||
|
+ } else if (strcasecmp(set->mechanisms, "none") == 0) {
|
||||||
|
+ auth_passdb->mechanisms = (const char *const[]){ NULL };
|
||||||
|
+ } else {
|
||||||
|
+ auth_passdb->mechanisms =
|
||||||
|
+ (const char *const *)p_strsplit_spaces(auth->pool,
|
||||||
|
+ set->mechanisms, " ,");
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (*set->username_filter == '\0') {
|
||||||
|
+ auth_passdb->username_filter = NULL;
|
||||||
|
+ } else {
|
||||||
|
+ auth_passdb->username_filter =
|
||||||
|
+ (const char *const *)p_strsplit_spaces(auth->pool,
|
||||||
|
+ set->username_filter, " ,");
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
/* for backwards compatibility: */
|
||||||
|
if (set->pass)
|
||||||
|
auth_passdb->result_success = AUTH_DB_RULE_CONTINUE;
|
||||||
|
diff --git a/src/auth/auth.h b/src/auth/auth.h
|
||||||
|
index f700e29d5c..460a179765 100644
|
||||||
|
--- a/src/auth/auth.h
|
||||||
|
+++ b/src/auth/auth.h
|
||||||
|
@@ -41,6 +41,11 @@ struct auth_passdb {
|
||||||
|
struct passdb_template *default_fields_tmpl;
|
||||||
|
struct passdb_template *override_fields_tmpl;
|
||||||
|
|
||||||
|
+ /* Supported authentication mechanisms, NULL is all, {NULL} is none */
|
||||||
|
+ const char *const *mechanisms;
|
||||||
|
+ /* Username filter, NULL is no filter */
|
||||||
|
+ const char *const *username_filter;
|
||||||
|
+
|
||||||
|
enum auth_passdb_skip skip;
|
||||||
|
enum auth_db_rule result_success;
|
||||||
|
enum auth_db_rule result_failure;
|
||||||
|
diff --git a/src/auth/passdb.c b/src/auth/passdb.c
|
||||||
|
index eb4ac8ae82..f5eed1af4f 100644
|
||||||
|
--- a/src/auth/passdb.c
|
||||||
|
+++ b/src/auth/passdb.c
|
||||||
|
@@ -224,19 +224,8 @@ passdb_preinit(pool_t pool, const struct auth_passdb_settings *set)
|
||||||
|
passdb->id = ++auth_passdb_id;
|
||||||
|
passdb->iface = *iface;
|
||||||
|
passdb->args = p_strdup(pool, set->args);
|
||||||
|
- if (*set->mechanisms == '\0') {
|
||||||
|
- passdb->mechanisms = NULL;
|
||||||
|
- } else if (strcasecmp(set->mechanisms, "none") == 0) {
|
||||||
|
- passdb->mechanisms = (const char *const[]){NULL};
|
||||||
|
- } else {
|
||||||
|
- passdb->mechanisms = (const char* const*)p_strsplit_spaces(pool, set->mechanisms, " ,");
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- if (*set->username_filter == '\0') {
|
||||||
|
- passdb->username_filter = NULL;
|
||||||
|
- } else {
|
||||||
|
- passdb->username_filter = (const char* const*)p_strsplit_spaces(pool, set->username_filter, " ,");
|
||||||
|
- }
|
||||||
|
+ /* NOTE: if anything else than driver & args are added here,
|
||||||
|
+ passdb_find() also needs to be updated. */
|
||||||
|
array_push_back(&passdb_modules, &passdb);
|
||||||
|
return passdb;
|
||||||
|
}
|
||||||
|
diff --git a/src/auth/passdb.h b/src/auth/passdb.h
|
||||||
|
index 2e95328e5c..e466a9fdb6 100644
|
||||||
|
--- a/src/auth/passdb.h
|
||||||
|
+++ b/src/auth/passdb.h
|
||||||
|
@@ -63,10 +63,6 @@ struct passdb_module {
|
||||||
|
/* Default password scheme for this module.
|
||||||
|
If default_cache_key is set, must not be NULL. */
|
||||||
|
const char *default_pass_scheme;
|
||||||
|
- /* Supported authentication mechanisms, NULL is all, [NULL] is none*/
|
||||||
|
- const char *const *mechanisms;
|
||||||
|
- /* Username filter, NULL is no filter */
|
||||||
|
- const char *const *username_filter;
|
||||||
|
|
||||||
|
/* If blocking is set to TRUE, use child processes to access
|
||||||
|
this passdb. */
|
@ -0,0 +1,295 @@
|
|||||||
|
diff -up dovecot-2.3.20/configure.ac.nolibotp dovecot-2.3.20/configure.ac
|
||||||
|
--- dovecot-2.3.20/configure.ac.nolibotp 2022-12-21 09:49:12.000000000 +0100
|
||||||
|
+++ dovecot-2.3.20/configure.ac 2023-02-14 16:54:02.118531016 +0100
|
||||||
|
@@ -854,7 +854,6 @@ src/lib-lua/Makefile
|
||||||
|
src/lib-mail/Makefile
|
||||||
|
src/lib-master/Makefile
|
||||||
|
src/lib-program-client/Makefile
|
||||||
|
-src/lib-otp/Makefile
|
||||||
|
src/lib-dovecot/Makefile
|
||||||
|
src/lib-sasl/Makefile
|
||||||
|
src/lib-settings/Makefile
|
||||||
|
diff -up dovecot-2.3.20/src/auth/main.c.nolibotp dovecot-2.3.20/src/auth/main.c
|
||||||
|
--- dovecot-2.3.20/src/auth/main.c.nolibotp 2022-12-21 09:49:12.000000000 +0100
|
||||||
|
+++ dovecot-2.3.20/src/auth/main.c 2023-02-14 16:54:02.118531016 +0100
|
||||||
|
@@ -19,8 +19,6 @@
|
||||||
|
#include "password-scheme.h"
|
||||||
|
#include "passdb-cache.h"
|
||||||
|
#include "mech.h"
|
||||||
|
-#include "otp.h"
|
||||||
|
-#include "mech-otp-common.h"
|
||||||
|
#include "auth.h"
|
||||||
|
#include "auth-penalty.h"
|
||||||
|
#include "auth-token.h"
|
||||||
|
@@ -283,7 +281,6 @@ static void main_deinit(void)
|
||||||
|
|
||||||
|
auth_policy_deinit();
|
||||||
|
mech_register_deinit(&mech_reg);
|
||||||
|
- mech_otp_deinit();
|
||||||
|
mech_deinit(global_auth_settings);
|
||||||
|
|
||||||
|
/* allow modules to unregister their dbs/drivers/etc. before freeing
|
||||||
|
diff -up dovecot-2.3.20/src/auth/Makefile.am.nolibotp dovecot-2.3.20/src/auth/Makefile.am
|
||||||
|
--- dovecot-2.3.20/src/auth/Makefile.am.nolibotp 2022-12-21 09:49:12.000000000 +0100
|
||||||
|
+++ dovecot-2.3.20/src/auth/Makefile.am 2023-02-14 16:54:02.118531016 +0100
|
||||||
|
@@ -45,7 +45,6 @@ AM_CPPFLAGS = \
|
||||||
|
-I$(top_srcdir)/src/lib-sql \
|
||||||
|
-I$(top_srcdir)/src/lib-settings \
|
||||||
|
-I$(top_srcdir)/src/lib-old-stats \
|
||||||
|
- -I$(top_srcdir)/src/lib-otp \
|
||||||
|
-I$(top_srcdir)/src/lib-master \
|
||||||
|
-I$(top_srcdir)/src/lib-oauth2 \
|
||||||
|
-I$(top_srcdir)/src/lib-ssl-iostream \
|
||||||
|
@@ -67,7 +66,6 @@ libpassword_la_SOURCES = \
|
||||||
|
password-scheme-crypt.c \
|
||||||
|
password-scheme-md5crypt.c \
|
||||||
|
password-scheme-scram.c \
|
||||||
|
- password-scheme-otp.c \
|
||||||
|
password-scheme-pbkdf2.c \
|
||||||
|
password-scheme-sodium.c
|
||||||
|
libpassword_la_CFLAGS = $(AM_CPPFLAGS) $(LIBSODIUM_CFLAGS)
|
||||||
|
@@ -76,7 +74,6 @@ auth_libs = \
|
||||||
|
libauth.la \
|
||||||
|
libstats_auth.la \
|
||||||
|
libpassword.la \
|
||||||
|
- ../lib-otp/libotp.la \
|
||||||
|
$(AUTH_LUA_LIBS) \
|
||||||
|
$(LIBDOVECOT_SQL)
|
||||||
|
|
||||||
|
@@ -95,7 +92,6 @@ libauth_la_SOURCES = \
|
||||||
|
auth-client-connection.c \
|
||||||
|
auth-master-connection.c \
|
||||||
|
auth-policy.c \
|
||||||
|
- mech-otp-common.c \
|
||||||
|
mech-plain-common.c \
|
||||||
|
auth-penalty.c \
|
||||||
|
auth-request.c \
|
||||||
|
@@ -122,7 +118,6 @@ libauth_la_SOURCES = \
|
||||||
|
mech-digest-md5.c \
|
||||||
|
mech-external.c \
|
||||||
|
mech-gssapi.c \
|
||||||
|
- mech-otp.c \
|
||||||
|
mech-scram.c \
|
||||||
|
mech-apop.c \
|
||||||
|
mech-winbind.c \
|
||||||
|
@@ -161,7 +156,6 @@ headers = \
|
||||||
|
auth-client-connection.h \
|
||||||
|
auth-common.h \
|
||||||
|
auth-master-connection.h \
|
||||||
|
- mech-otp-common.h \
|
||||||
|
mech-plain-common.h \
|
||||||
|
mech-digest-md5-private.h \
|
||||||
|
mech-scram.h \
|
||||||
|
@@ -260,7 +254,6 @@ test_libs = \
|
||||||
|
test_libpassword_SOURCES = test-libpassword.c
|
||||||
|
test_libpassword_LDADD = \
|
||||||
|
libpassword.la \
|
||||||
|
- ../lib-otp/libotp.la \
|
||||||
|
$(CRYPT_LIBS) \
|
||||||
|
$(LIBDOVECOT_SQL) \
|
||||||
|
$(LIBSODIUM_LIBS) \
|
||||||
|
diff -up dovecot-2.3.20/src/auth/mech.c.nolibotp dovecot-2.3.20/src/auth/mech.c
|
||||||
|
--- dovecot-2.3.20/src/auth/mech.c.nolibotp 2023-02-14 16:55:38.421231797 +0100
|
||||||
|
+++ dovecot-2.3.20/src/auth/mech.c 2023-02-14 16:55:38.434231892 +0100
|
||||||
|
@@ -71,7 +71,6 @@ extern const struct mech_module mech_apo
|
||||||
|
extern const struct mech_module mech_cram_md5;
|
||||||
|
extern const struct mech_module mech_digest_md5;
|
||||||
|
extern const struct mech_module mech_external;
|
||||||
|
-extern const struct mech_module mech_otp;
|
||||||
|
extern const struct mech_module mech_scram_sha1;
|
||||||
|
extern const struct mech_module mech_scram_sha256;
|
||||||
|
extern const struct mech_module mech_anonymous;
|
||||||
|
@@ -206,7 +205,6 @@ void mech_init(const struct auth_setting
|
||||||
|
mech_register_module(&mech_gssapi_spnego);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
- mech_register_module(&mech_otp);
|
||||||
|
mech_register_module(&mech_scram_sha1);
|
||||||
|
mech_register_module(&mech_scram_sha256);
|
||||||
|
mech_register_module(&mech_anonymous);
|
||||||
|
@@ -233,7 +231,6 @@ void mech_deinit(const struct auth_setti
|
||||||
|
mech_unregister_module(&mech_gssapi_spnego);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
- mech_unregister_module(&mech_otp);
|
||||||
|
mech_unregister_module(&mech_scram_sha1);
|
||||||
|
mech_unregister_module(&mech_scram_sha256);
|
||||||
|
mech_unregister_module(&mech_anonymous);
|
||||||
|
diff -up dovecot-2.3.20/src/auth/password-scheme.c.nolibotp dovecot-2.3.20/src/auth/password-scheme.c
|
||||||
|
--- dovecot-2.3.20/src/auth/password-scheme.c.nolibotp 2023-02-14 16:54:02.109530950 +0100
|
||||||
|
+++ dovecot-2.3.20/src/auth/password-scheme.c 2023-02-14 16:54:02.119531023 +0100
|
||||||
|
@@ -13,7 +13,6 @@
|
||||||
|
#include "randgen.h"
|
||||||
|
#include "sha1.h"
|
||||||
|
#include "sha2.h"
|
||||||
|
-#include "otp.h"
|
||||||
|
#include "str.h"
|
||||||
|
#include "password-scheme.h"
|
||||||
|
|
||||||
|
@@ -709,32 +708,6 @@ plain_md5_generate(const char *plaintext
|
||||||
|
*size_r = MD5_RESULTLEN;
|
||||||
|
}
|
||||||
|
|
||||||
|
-static int otp_verify(const char *plaintext, const struct password_generate_params *params ATTR_UNUSED,
|
||||||
|
- const unsigned char *raw_password, size_t size,
|
||||||
|
- const char **error_r)
|
||||||
|
-{
|
||||||
|
- const char *password, *generated;
|
||||||
|
-
|
||||||
|
- password = t_strndup(raw_password, size);
|
||||||
|
- if (password_generate_otp(plaintext, password, UINT_MAX, &generated) < 0) {
|
||||||
|
- *error_r = "Invalid OTP data in passdb";
|
||||||
|
- return -1;
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- return strcasecmp(password, generated) == 0 ? 1 : 0;
|
||||||
|
-}
|
||||||
|
-
|
||||||
|
-static void
|
||||||
|
-otp_generate(const char *plaintext, const struct password_generate_params *params ATTR_UNUSED,
|
||||||
|
- const unsigned char **raw_password_r, size_t *size_r)
|
||||||
|
-{
|
||||||
|
- const char *password;
|
||||||
|
-
|
||||||
|
- if (password_generate_otp(plaintext, NULL, OTP_HASH_SHA1, &password) < 0)
|
||||||
|
- i_unreached();
|
||||||
|
- *raw_password_r = (const unsigned char *)password;
|
||||||
|
- *size_r = strlen(password);
|
||||||
|
-}
|
||||||
|
|
||||||
|
static const struct password_scheme builtin_schemes[] = {
|
||||||
|
{ "MD5", PW_ENCODING_NONE, 0, md5_verify, md5_crypt_generate },
|
||||||
|
@@ -770,7 +743,6 @@ static const struct password_scheme buil
|
||||||
|
NULL, plain_md5_generate },
|
||||||
|
{ "LDAP-MD5", PW_ENCODING_BASE64, MD5_RESULTLEN,
|
||||||
|
NULL, plain_md5_generate },
|
||||||
|
- { "OTP", PW_ENCODING_NONE, 0, otp_verify, otp_generate },
|
||||||
|
{ "PBKDF2", PW_ENCODING_NONE, 0, pbkdf2_verify, pbkdf2_generate },
|
||||||
|
};
|
||||||
|
|
||||||
|
diff -up dovecot-2.3.20/src/auth/password-scheme.h.nolibotp dovecot-2.3.20/src/auth/password-scheme.h
|
||||||
|
--- dovecot-2.3.20/src/auth/password-scheme.h.nolibotp 2023-02-14 16:56:50.929759540 +0100
|
||||||
|
+++ dovecot-2.3.20/src/auth/password-scheme.h 2023-02-14 16:56:50.947759671 +0100
|
||||||
|
@@ -92,9 +92,6 @@ void password_set_encryption_rounds(unsi
|
||||||
|
/* INTERNAL: */
|
||||||
|
const char *password_generate_salt(size_t len);
|
||||||
|
const char *password_generate_md5_crypt(const char *pw, const char *salt);
|
||||||
|
-int password_generate_otp(const char *pw, const char *state_data,
|
||||||
|
- unsigned int algo, const char **result_r)
|
||||||
|
- ATTR_NULL(2);
|
||||||
|
|
||||||
|
int crypt_verify(const char *plaintext,
|
||||||
|
const struct password_generate_params *params,
|
||||||
|
diff -up dovecot-2.3.20/src/auth/test-libpassword.c.nolibotp dovecot-2.3.20/src/auth/test-libpassword.c
|
||||||
|
--- dovecot-2.3.20/src/auth/test-libpassword.c.nolibotp 2023-02-14 16:54:55.880922175 +0100
|
||||||
|
+++ dovecot-2.3.20/src/auth/test-libpassword.c 2023-02-14 16:54:55.896922291 +0100
|
||||||
|
@@ -106,7 +106,6 @@ static void test_password_schemes(void)
|
||||||
|
test_password_scheme("SHA512", "{SHA512}7iaw3Ur350mqGo7jwQrpkj9hiYB3Lkc/iBml1JQODbJ6wYX4oOHV+E+IvIh/1nsUNzLDBMxfqa2Ob1f1ACio/w==", "test");
|
||||||
|
test_password_scheme("SSHA", "{SSHA}H/zrDv8FXUu1JmwvVYijfrYEF34jVZcO", "test");
|
||||||
|
test_password_scheme("MD5-CRYPT", "{MD5-CRYPT}$1$GgvxyNz8$OjZhLh4P.gF1lxYEbLZ3e/", "test");
|
||||||
|
- test_password_scheme("OTP", "{OTP}sha1 1024 ae6b49aa481f7233 f69fc7f98b8fbf54", "test");
|
||||||
|
test_password_scheme("PBKDF2", "{PBKDF2}$1$bUnT4Pl7yFtYX0KU$5000$50a83cafdc517b9f46519415e53c6a858908680a", "test");
|
||||||
|
test_password_scheme("CRAM-MD5", "{CRAM-MD5}e02d374fde0dc75a17a557039a3a5338c7743304777dccd376f332bee68d2cf6", "test");
|
||||||
|
test_password_scheme("DIGEST-MD5", "{DIGEST-MD5}77c1a8c437c9b08ba2f460fe5d58db5d", "test");
|
||||||
|
diff -up dovecot-2.3.20/src/auth/test-mech.c.nolibotp dovecot-2.3.20/src/auth/test-mech.c
|
||||||
|
--- dovecot-2.3.20/src/auth/test-mech.c.nolibotp 2022-12-21 09:49:12.000000000 +0100
|
||||||
|
+++ dovecot-2.3.20/src/auth/test-mech.c 2023-02-14 16:54:02.119531023 +0100
|
||||||
|
@@ -8,8 +8,6 @@
|
||||||
|
#include "auth-request-handler-private.h"
|
||||||
|
#include "auth-settings.h"
|
||||||
|
#include "mech-digest-md5-private.h"
|
||||||
|
-#include "otp.h"
|
||||||
|
-#include "mech-otp-common.h"
|
||||||
|
#include "settings-parser.h"
|
||||||
|
#include "password-scheme.h"
|
||||||
|
#include "auth-token.h"
|
||||||
|
@@ -27,7 +25,6 @@ extern const struct mech_module mech_dov
|
||||||
|
extern const struct mech_module mech_external;
|
||||||
|
extern const struct mech_module mech_login;
|
||||||
|
extern const struct mech_module mech_oauthbearer;
|
||||||
|
-extern const struct mech_module mech_otp;
|
||||||
|
extern const struct mech_module mech_plain;
|
||||||
|
extern const struct mech_module mech_scram_sha1;
|
||||||
|
extern const struct mech_module mech_scram_sha256;
|
||||||
|
@@ -65,10 +62,7 @@ request_handler_reply_mock_callback(stru
|
||||||
|
|
||||||
|
if (request->passdb_result == PASSDB_RESULT_OK)
|
||||||
|
request->failed = FALSE;
|
||||||
|
- else if (request->mech == &mech_otp) {
|
||||||
|
- if (null_strcmp(request->fields.user, "otp_phase_2") == 0)
|
||||||
|
- request->failed = FALSE;
|
||||||
|
- } else if (request->mech == &mech_oauthbearer) {
|
||||||
|
+ else if (request->mech == &mech_oauthbearer) {
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
@@ -224,10 +218,6 @@ static void test_mechs(void)
|
||||||
|
{&mech_plain, UCHAR_LEN("\0testuser\0testpass"), "testuser", NULL, TRUE, FALSE, FALSE},
|
||||||
|
{&mech_plain, UCHAR_LEN("normaluser\0masteruser\0masterpass"), "masteruser", NULL, TRUE, FALSE, FALSE},
|
||||||
|
{&mech_plain, UCHAR_LEN("normaluser\0normaluser\0masterpass"), "normaluser", NULL, TRUE, FALSE, FALSE},
|
||||||
|
- {&mech_otp, UCHAR_LEN("hex:5Bf0 75d9 959d 036f"), "otp_phase_2", NULL, TRUE, TRUE, FALSE},
|
||||||
|
- {&mech_otp, UCHAR_LEN("word:BOND FOGY DRAB NE RISE MART"), "otp_phase_2", NULL, TRUE, TRUE, FALSE},
|
||||||
|
- {&mech_otp, UCHAR_LEN("init-hex:f6bd 6b33 89b8 7203:md5 499 ke6118:23d1 b253 5ae0 2b7e"), "otp_phase_2", NULL, TRUE, TRUE, FALSE},
|
||||||
|
- {&mech_otp, UCHAR_LEN("init-word:END KERN BALM NICK EROS WAVY:md5 499 ke1235:BABY FAIN OILY NIL TIDY DADE"), "otp_phase_2", NULL , TRUE, TRUE, FALSE},
|
||||||
|
{&mech_oauthbearer, UCHAR_LEN("n,a=testuser,p=cHJvb2Y=,f=nonstandart\x01host=server\x01port=143\x01""auth=Bearer vF9dft4qmTc2Nvb3RlckBhbHRhdmlzdGEuY29tCg==\x01\x01"), "testuser", NULL, FALSE, TRUE, FALSE},
|
||||||
|
{&mech_scram_sha1, UCHAR_LEN("n,,n=testuser,r=rOprNGfwEbeRWgbNEkqO"), "testuser", NULL, TRUE, FALSE, FALSE},
|
||||||
|
{&mech_scram_sha256, UCHAR_LEN("n,,n=testuser,r=rOprNGfwEbeRWgbNEkqO"), "testuser", NULL, TRUE, FALSE, FALSE},
|
||||||
|
@@ -242,8 +232,6 @@ static void test_mechs(void)
|
||||||
|
{&mech_external, UCHAR_LEN(""), "testuser", NULL, FALSE, TRUE, FALSE},
|
||||||
|
{&mech_external, UCHAR_LEN(""), NULL, NULL, FALSE, FALSE, FALSE},
|
||||||
|
{&mech_login, UCHAR_LEN(""), NULL, NULL, FALSE, FALSE, FALSE},
|
||||||
|
- {&mech_otp, UCHAR_LEN(""), NULL, "invalid input", FALSE, FALSE, FALSE},
|
||||||
|
- {&mech_otp, UCHAR_LEN(""), "testuser", "invalid input", FALSE, FALSE, FALSE},
|
||||||
|
{&mech_plain, UCHAR_LEN(""), NULL, NULL, FALSE, FALSE, FALSE},
|
||||||
|
{&mech_oauthbearer, UCHAR_LEN(""), NULL, NULL, FALSE, FALSE, FALSE},
|
||||||
|
{&mech_xoauth2, UCHAR_LEN(""), NULL, NULL, FALSE, FALSE, FALSE},
|
||||||
|
@@ -255,7 +243,6 @@ static void test_mechs(void)
|
||||||
|
{&mech_apop, UCHAR_LEN("1.1.1\0testuser\0tooshort"), NULL, NULL, FALSE, FALSE, FALSE},
|
||||||
|
{&mech_apop, UCHAR_LEN("1.1.1\0testuser\0responseoflen16-"), NULL, NULL, FALSE, FALSE, FALSE},
|
||||||
|
{&mech_apop, UCHAR_LEN("1.1.1"), NULL, NULL, FALSE, FALSE, FALSE},
|
||||||
|
- {&mech_otp, UCHAR_LEN("somebody\0testuser"), "testuser", "otp(testuser): unsupported response type", FALSE, TRUE, FALSE},
|
||||||
|
{&mech_cram_md5, UCHAR_LEN("testuser\0response"), "testuser", NULL, FALSE, FALSE, FALSE},
|
||||||
|
{&mech_plain, UCHAR_LEN("testuser\0"), "testuser", NULL, FALSE, FALSE, FALSE},
|
||||||
|
|
||||||
|
@@ -297,9 +284,7 @@ static void test_mechs(void)
|
||||||
|
{&mech_plain, UCHAR_LEN("\0fa\0il\0ing\0withthis"), NULL, NULL, FALSE, FALSE, FALSE},
|
||||||
|
{&mech_plain, UCHAR_LEN("failingwiththis"), NULL, NULL, FALSE, FALSE, FALSE},
|
||||||
|
{&mech_plain, UCHAR_LEN("failing\0withthis"), NULL, NULL, FALSE, FALSE, FALSE},
|
||||||
|
- {&mech_otp, UCHAR_LEN("someb\0ody\0testuser"), NULL, "invalid input", FALSE, FALSE, FALSE},
|
||||||
|
/* phase 2 */
|
||||||
|
- {&mech_otp, UCHAR_LEN("someb\0ody\0testuser"), "testuser", "otp(testuser): unsupported response type", FALSE, TRUE, FALSE},
|
||||||
|
{&mech_scram_sha1, UCHAR_LEN("c=biws,r=fyko+d2lbbFgONRv9qkxdawL3rfcNHYJY1ZVvWVs7j,p=v0X8v3Bz2T0CJGbJQyF0X+HI4Ts="), NULL, NULL, FALSE, FALSE, FALSE},
|
||||||
|
{&mech_scram_sha1, UCHAR_LEN("iws0X8v3Bz2T0CJGbJQyF0X+HI4Ts=,,,,"), NULL, NULL, FALSE, FALSE, FALSE},
|
||||||
|
{&mech_scram_sha1, UCHAR_LEN("n,a=masteruser,,"), NULL, NULL, FALSE, FALSE, FALSE},
|
||||||
|
@@ -387,7 +372,6 @@ static void test_mechs(void)
|
||||||
|
|
||||||
|
test_end();
|
||||||
|
} T_END;
|
||||||
|
- mech_otp_deinit();
|
||||||
|
auths_deinit();
|
||||||
|
auth_token_deinit();
|
||||||
|
password_schemes_deinit();
|
||||||
|
diff -up dovecot-2.3.20/src/doveadm/Makefile.am.nolibotp dovecot-2.3.20/src/doveadm/Makefile.am
|
||||||
|
--- dovecot-2.3.20/src/doveadm/Makefile.am.nolibotp 2022-12-21 09:49:12.000000000 +0100
|
||||||
|
+++ dovecot-2.3.20/src/doveadm/Makefile.am 2023-02-14 16:54:02.119531023 +0100
|
||||||
|
@@ -36,8 +36,7 @@ AM_CPPFLAGS = \
|
||||||
|
$(BINARY_CFLAGS)
|
||||||
|
|
||||||
|
cmd_pw_libs = \
|
||||||
|
- ../auth/libpassword.la \
|
||||||
|
- ../lib-otp/libotp.la
|
||||||
|
+ ../auth/libpassword.la
|
||||||
|
|
||||||
|
libs = \
|
||||||
|
dsync/libdsync.la \
|
||||||
|
diff -up dovecot-2.3.20/src/Makefile.am.nolibotp dovecot-2.3.20/src/Makefile.am
|
||||||
|
--- dovecot-2.3.20/src/Makefile.am.nolibotp 2022-12-21 09:49:12.000000000 +0100
|
||||||
|
+++ dovecot-2.3.20/src/Makefile.am 2023-02-14 16:54:02.119531023 +0100
|
||||||
|
@@ -40,7 +40,6 @@ SUBDIRS = \
|
||||||
|
lib-index \
|
||||||
|
lib-storage \
|
||||||
|
lib-sql \
|
||||||
|
- lib-otp \
|
||||||
|
lib-lda \
|
||||||
|
lib-dict-backend \
|
||||||
|
anvil \
|
@ -0,0 +1,200 @@
|
|||||||
|
diff -up dovecot-2.3.21/src/lib-dcrypt/dcrypt-openssl.c.noengine dovecot-2.3.21/src/lib-dcrypt/dcrypt-openssl.c
|
||||||
|
--- dovecot-2.3.21/src/lib-dcrypt/dcrypt-openssl.c.noengine 2024-07-23 13:18:35.040720598 -0400
|
||||||
|
+++ dovecot-2.3.21/src/lib-dcrypt/dcrypt-openssl.c 2024-07-23 13:20:16.250720598 -0400
|
||||||
|
@@ -20,7 +20,6 @@
|
||||||
|
#include <openssl/bio.h>
|
||||||
|
#include <openssl/pem.h>
|
||||||
|
#include <openssl/x509.h>
|
||||||
|
-#include <openssl/engine.h>
|
||||||
|
#include <openssl/hmac.h>
|
||||||
|
#include <openssl/objects.h>
|
||||||
|
#include <openssl/bn.h>
|
||||||
|
diff -up dovecot-2.3.21/m4/ssl.m4.noengine dovecot-2.3.21/m4/ssl.m4
|
||||||
|
--- dovecot-2.3.21/m4/ssl.m4.noengine 2024-05-06 17:39:59.362886891 +0200
|
||||||
|
+++ dovecot-2.3.21/m4/ssl.m4 2024-05-06 17:42:17.945312656 +0200
|
||||||
|
@@ -233,6 +233,27 @@ AC_DEFUN([DOVECOT_SSL], [
|
||||||
|
AC_CHECK_LIB(ssl, ECDSA_SIG_set0, [
|
||||||
|
AC_DEFINE(HAVE_ECDSA_SIG_SET0,, [Build with ECDSA_SIG_set0 support])
|
||||||
|
],, $SSL_LIBS)
|
||||||
|
+ AC_CHECK_LIB(ssl, OSSL_PROVIDER_try_load, [
|
||||||
|
+ AC_DEFINE(HAVE_OSSL_PROVIDER_try_load,, [Build with OSSL_PROVIDER_try_load support])
|
||||||
|
+ ],, $SSL_LIBS)
|
||||||
|
+ AC_CHECK_LIB(ssl, OPENSSL_init_ssl, [
|
||||||
|
+ AC_DEFINE(HAVE_OPENSSL_init_ssl,, [Build with OPENSSL_init_ssl support])
|
||||||
|
+ ],, $SSL_LIBS)
|
||||||
|
+ AC_CHECK_LIB(ssl, OPENSSL_cleanup, [
|
||||||
|
+ AC_DEFINE(HAVE_OPENSSL_cleanup,, [OpenSSL supports OPENSSL_cleanup()])
|
||||||
|
+ ],, $SSL_LIBS)
|
||||||
|
+ AC_CHECK_LIB(ssl, OPENSSL_thread_stop, [
|
||||||
|
+ AC_DEFINE(HAVE_OPENSSL_thread_stop,, [OpenSSL supports OPENSSL_thread_stop()])
|
||||||
|
+ ],, $SSL_LIBS)
|
||||||
|
+ AC_CHECK_LIB(ssl, ERR_remove_thread_state, [
|
||||||
|
+ AC_DEFINE(HAVE_ERR_remove_thread_state,, [OpenSSL supports ERR_remove_thread_state()])
|
||||||
|
+ ],, $SSL_LIBS)
|
||||||
|
+ AC_CHECK_LIB(ssl, ERR_remove_state, [
|
||||||
|
+ AC_DEFINE(HAVE_ERR_remove_state,, [OpenSSL supports ERR_remove_state()])
|
||||||
|
+ ],, $SSL_LIBS)
|
||||||
|
+ AC_CHECK_LIB(ssl, ENGINE_by_id_DISABLED, [
|
||||||
|
+ AC_DEFINE(HAVE_ENGINE_by_id,, [OpenSSL supports ENGINE_by_id() - !!!EXPLICITELY DISABLED!!! ])
|
||||||
|
+ ],, $SSL_LIBS)
|
||||||
|
AC_CHECK_LIB(ssl, EC_GROUP_order_bits, [
|
||||||
|
AC_DEFINE(HAVE_EC_GROUP_order_bits,, [Build with EC_GROUP_order_bits support])
|
||||||
|
],, $SSL_LIBS)
|
||||||
|
diff -up dovecot-2.3.21/src/lib-ssl-iostream/dovecot-openssl-common.c.noengine dovecot-2.3.21/src/lib-ssl-iostream/dovecot-openssl-common.c
|
||||||
|
--- dovecot-2.3.21/src/lib-ssl-iostream/dovecot-openssl-common.c.noengine 2023-09-14 15:17:46.000000000 +0200
|
||||||
|
+++ dovecot-2.3.21/src/lib-ssl-iostream/dovecot-openssl-common.c 2024-05-06 17:39:59.363886901 +0200
|
||||||
|
@@ -3,13 +3,23 @@
|
||||||
|
#include "lib.h"
|
||||||
|
#include "randgen.h"
|
||||||
|
#include "dovecot-openssl-common.h"
|
||||||
|
+#include "iostream-openssl.h"
|
||||||
|
|
||||||
|
#include <openssl/ssl.h>
|
||||||
|
-#include <openssl/engine.h>
|
||||||
|
+#include <openssl/err.h>
|
||||||
|
+#ifdef HAVE_OSSL_PROVIDER_try_load
|
||||||
|
+# include <openssl/provider.h>
|
||||||
|
+#else
|
||||||
|
+# include <openssl/engine.h>
|
||||||
|
+#endif
|
||||||
|
#include <openssl/rand.h>
|
||||||
|
|
||||||
|
static int openssl_init_refcount = 0;
|
||||||
|
-static ENGINE *dovecot_openssl_engine;
|
||||||
|
+#ifdef HAVE_OSSL_PROVIDER_try_load
|
||||||
|
+static OSSL_PROVIDER *dovecot_openssl_engine = NULL;
|
||||||
|
+#else
|
||||||
|
+static ENGINE *dovecot_openssl_engine = NULL;
|
||||||
|
+#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_SSL_NEW_MEM_FUNCS
|
||||||
|
static void *dovecot_openssl_malloc(size_t size, const char *u0 ATTR_UNUSED, int u1 ATTR_UNUSED)
|
||||||
|
@@ -17,12 +27,14 @@ static void *dovecot_openssl_malloc(size
|
||||||
|
static void *dovecot_openssl_malloc(size_t size)
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
+ if (size == 0)
|
||||||
|
+ return NULL;
|
||||||
|
/* this may be performance critical, so don't use
|
||||||
|
i_malloc() or calloc() */
|
||||||
|
void *mem = malloc(size);
|
||||||
|
- if (mem == NULL) {
|
||||||
|
+ if (unlikely(mem == NULL)) {
|
||||||
|
i_fatal_status(FATAL_OUTOFMEM,
|
||||||
|
- "OpenSSL: malloc(%zu): Out of memory", size);
|
||||||
|
+ "OpenSSL: malloc(%zu): Out of memory", size);
|
||||||
|
}
|
||||||
|
return mem;
|
||||||
|
}
|
||||||
|
@@ -33,10 +45,14 @@ static void *dovecot_openssl_realloc(voi
|
||||||
|
static void *dovecot_openssl_realloc(void *ptr, size_t size)
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
+ if (size == 0) {
|
||||||
|
+ free(ptr);
|
||||||
|
+ return NULL;
|
||||||
|
+ }
|
||||||
|
void *mem = realloc(ptr, size);
|
||||||
|
- if (mem == NULL) {
|
||||||
|
+ if (unlikely(mem == NULL)) {
|
||||||
|
i_fatal_status(FATAL_OUTOFMEM,
|
||||||
|
- "OpenSSL: realloc(%zu): Out of memory", size);
|
||||||
|
+ "OpenSSL: realloc(%zu): Out of memory", size);
|
||||||
|
}
|
||||||
|
return mem;
|
||||||
|
}
|
||||||
|
@@ -63,9 +79,13 @@ void dovecot_openssl_common_global_ref(v
|
||||||
|
/*i_warning("CRYPTO_set_mem_functions() was called too late");*/
|
||||||
|
}
|
||||||
|
|
||||||
|
+#ifdef HAVE_OPENSSL_init_ssl
|
||||||
|
+ OPENSSL_init_ssl(0, NULL);
|
||||||
|
+#else
|
||||||
|
SSL_library_init();
|
||||||
|
SSL_load_error_strings();
|
||||||
|
OpenSSL_add_all_algorithms();
|
||||||
|
+#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
bool dovecot_openssl_common_global_unref(void)
|
||||||
|
@@ -76,30 +96,35 @@ bool dovecot_openssl_common_global_unref
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
if (dovecot_openssl_engine != NULL) {
|
||||||
|
+#ifdef HAVE_OSSL_PROVIDER_try_load
|
||||||
|
+ OSSL_PROVIDER_unload(dovecot_openssl_engine);
|
||||||
|
+#else
|
||||||
|
ENGINE_finish(dovecot_openssl_engine);
|
||||||
|
+#endif
|
||||||
|
dovecot_openssl_engine = NULL;
|
||||||
|
}
|
||||||
|
+#ifdef HAVE_OPENSSL_cleanup
|
||||||
|
+ OPENSSL_cleanup();
|
||||||
|
+#else
|
||||||
|
/* OBJ_cleanup() is called automatically by EVP_cleanup() in
|
||||||
|
newer versions. Doesn't hurt to call it anyway. */
|
||||||
|
OBJ_cleanup();
|
||||||
|
-#ifdef HAVE_SSL_COMP_FREE_COMPRESSION_METHODS
|
||||||
|
+# if !defined(OPENSSL_NO_COMP)
|
||||||
|
SSL_COMP_free_compression_methods();
|
||||||
|
-#endif
|
||||||
|
+# endif
|
||||||
|
ENGINE_cleanup();
|
||||||
|
EVP_cleanup();
|
||||||
|
CRYPTO_cleanup_all_ex_data();
|
||||||
|
-#ifdef HAVE_OPENSSL_AUTO_THREAD_DEINIT
|
||||||
|
+# ifdef HAVE_OPENSSL_thread_stop
|
||||||
|
/* no cleanup needed */
|
||||||
|
-#elif defined(HAVE_OPENSSL_ERR_REMOVE_THREAD_STATE)
|
||||||
|
+# elif defined(HAVE_ERR_remove_thread_state)
|
||||||
|
/* This was marked as deprecated in v1.1. */
|
||||||
|
ERR_remove_thread_state(NULL);
|
||||||
|
-#else
|
||||||
|
+# elif defined(HAVE_ERR_remove_state)
|
||||||
|
/* This was deprecated by ERR_remove_thread_state(NULL) in v1.0.0. */
|
||||||
|
ERR_remove_state(0);
|
||||||
|
-#endif
|
||||||
|
+# endif
|
||||||
|
ERR_free_strings();
|
||||||
|
-#ifdef HAVE_OPENSSL_CLEANUP
|
||||||
|
- OPENSSL_cleanup();
|
||||||
|
#endif
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
@@ -110,6 +135,7 @@ int dovecot_openssl_common_global_set_en
|
||||||
|
if (dovecot_openssl_engine != NULL)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
+#ifdef HAVE_ENGINE_by_id
|
||||||
|
ENGINE_load_builtin_engines();
|
||||||
|
dovecot_openssl_engine = ENGINE_by_id(engine);
|
||||||
|
if (dovecot_openssl_engine == NULL) {
|
||||||
|
@@ -128,5 +154,15 @@ int dovecot_openssl_common_global_set_en
|
||||||
|
dovecot_openssl_engine = NULL;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
+#elif defined(HAVE_OSSL_PROVIDER_try_load)
|
||||||
|
+ if ((dovecot_openssl_engine = OSSL_PROVIDER_try_load(NULL, engine, 1)) == NULL) {
|
||||||
|
+ *error_r = t_strdup_printf("Cannot load '%s': %s", engine,
|
||||||
|
+ openssl_iostream_error());
|
||||||
|
+ return 0;
|
||||||
|
+ }
|
||||||
|
+ return 1;
|
||||||
|
+#else
|
||||||
|
+ *error_r = t_strdup_printf("Cannot load '%s': No engine/provider support available", engine);
|
||||||
|
+#endif
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
diff -up dovecot-2.3.21/src/lib-ssl-iostream/Makefile.am.noengine dovecot-2.3.21/src/lib-ssl-iostream/Makefile.am
|
||||||
|
--- dovecot-2.3.21/src/lib-ssl-iostream/Makefile.am.noengine 2023-09-14 15:17:46.000000000 +0200
|
||||||
|
+++ dovecot-2.3.21/src/lib-ssl-iostream/Makefile.am 2024-05-06 17:39:59.363886901 +0200
|
||||||
|
@@ -5,7 +5,8 @@ NOPLUGIN_LDFLAGS =
|
||||||
|
AM_CPPFLAGS = \
|
||||||
|
-I$(top_srcdir)/src/lib \
|
||||||
|
-I$(top_srcdir)/src/lib-test \
|
||||||
|
- -DMODULE_DIR=\""$(moduledir)"\"
|
||||||
|
+ -DMODULE_DIR=\""$(moduledir)"\" \
|
||||||
|
+ $(SSL_CFLAGS)
|
||||||
|
|
||||||
|
if BUILD_OPENSSL
|
||||||
|
module_LTLIBRARIES = libssl_iostream_openssl.la
|
@ -0,0 +1,22 @@
|
|||||||
|
From 9a3e0d099044d3a7478c3a24ccb8990181767f7c Mon Sep 17 00:00:00 2001
|
||||||
|
From: Duncan Bellamy <dunk@denkimushi.com>
|
||||||
|
Date: Sat, 6 Mar 2021 14:25:29 +0000
|
||||||
|
Subject: [PATCH] imap: Shorten test-imap-client-hibernate socket path length
|
||||||
|
|
||||||
|
---
|
||||||
|
src/imap/test-imap-client-hibernate.c | 2 +-
|
||||||
|
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/src/imap/test-imap-client-hibernate.c b/src/imap/test-imap-client-hibernate.c
|
||||||
|
index 9b90e1bd9a..c5392fa3fc 100644
|
||||||
|
--- a/src/imap/test-imap-client-hibernate.c
|
||||||
|
+++ b/src/imap/test-imap-client-hibernate.c
|
||||||
|
@@ -19,7 +19,7 @@
|
||||||
|
|
||||||
|
#include <sys/stat.h>
|
||||||
|
|
||||||
|
-#define TEMP_DIRNAME ".test-imap-client-hibernate"
|
||||||
|
+#define TEMP_DIRNAME ".test-ich"
|
||||||
|
|
||||||
|
#define EVILSTR "\t\r\n\001"
|
||||||
|
|
@ -0,0 +1,976 @@
|
|||||||
|
From 8e4c42dbb3c770fcdbc396f2abcf1bc228ec548d Mon Sep 17 00:00:00 2001
|
||||||
|
From: Timo Sirainen <timo.sirainen@open-xchange.com>
|
||||||
|
Date: Fri, 9 Feb 2024 00:32:39 +0200
|
||||||
|
Subject: [PATCH 1/6] lib: test-llist - Fix dllist2 test name
|
||||||
|
|
||||||
|
---
|
||||||
|
src/lib/test-llist.c | 2 +-
|
||||||
|
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/src/lib/test-llist.c b/src/lib/test-llist.c
|
||||||
|
index d57006ce2aa..ed584318fa3 100644
|
||||||
|
--- a/src/lib/test-llist.c
|
||||||
|
+++ b/src/lib/test-llist.c
|
||||||
|
@@ -71,7 +71,7 @@ static void test_dllist2(void)
|
||||||
|
l2 = t_new(struct dllist, 1);
|
||||||
|
l1 = t_new(struct dllist, 1);
|
||||||
|
|
||||||
|
- test_begin("dllist");
|
||||||
|
+ test_begin("dllist2");
|
||||||
|
/* prepend to empty */
|
||||||
|
DLLIST2_PREPEND(&head, &tail, l3);
|
||||||
|
test_assert(head == l3 && tail == l3);
|
||||||
|
|
||||||
|
From cee08202c759a3bdf185d998dcf888ebd1bc6e36 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Timo Sirainen <timo.sirainen@open-xchange.com>
|
||||||
|
Date: Fri, 9 Feb 2024 00:33:00 +0200
|
||||||
|
Subject: [PATCH 2/6] lib: Add DLLIST2_JOIN()
|
||||||
|
|
||||||
|
---
|
||||||
|
src/lib/llist.h | 14 ++++++++++++++
|
||||||
|
src/lib/test-llist.c | 39 +++++++++++++++++++++++++++++++++++++++
|
||||||
|
2 files changed, 53 insertions(+)
|
||||||
|
|
||||||
|
diff --git a/src/lib/llist.h b/src/lib/llist.h
|
||||||
|
index 8a52e873352..5ad5d75c0df 100644
|
||||||
|
--- a/src/lib/llist.h
|
||||||
|
+++ b/src/lib/llist.h
|
||||||
|
@@ -78,4 +78,18 @@
|
||||||
|
#define DLLIST2_REMOVE(head, tail, item) \
|
||||||
|
DLLIST2_REMOVE_FULL(head, tail, item, prev, next)
|
||||||
|
|
||||||
|
+#define DLLIST2_JOIN_FULL(head1, tail1, head2, tail2, prev, next) STMT_START { \
|
||||||
|
+ if (*(head1) == NULL) { \
|
||||||
|
+ *(head1) = *(head2); \
|
||||||
|
+ *(tail1) = *(tail2); \
|
||||||
|
+ } else if (*(head2) != NULL) { \
|
||||||
|
+ (*(tail1))->next = *(head2); \
|
||||||
|
+ (*(head2))->prev = *(tail1); \
|
||||||
|
+ (*tail1) = (*tail2); \
|
||||||
|
+ } \
|
||||||
|
+ } STMT_END
|
||||||
|
+
|
||||||
|
+#define DLLIST2_JOIN(head1, tail1, head2, tail2) \
|
||||||
|
+ DLLIST2_JOIN_FULL(head1, tail1, head2, tail2, prev, next)
|
||||||
|
+
|
||||||
|
#endif
|
||||||
|
diff --git a/src/lib/test-llist.c b/src/lib/test-llist.c
|
||||||
|
index ed584318fa3..e293eb6a603 100644
|
||||||
|
--- a/src/lib/test-llist.c
|
||||||
|
+++ b/src/lib/test-llist.c
|
||||||
|
@@ -131,8 +131,47 @@ static void test_dllist2(void)
|
||||||
|
test_end();
|
||||||
|
}
|
||||||
|
|
||||||
|
+static void test_dllist2_join(void)
|
||||||
|
+{
|
||||||
|
+ struct dllist *head, *tail, *elem[4];
|
||||||
|
+ struct dllist *head2, *tail2, *elem2[N_ELEMENTS(elem)];
|
||||||
|
+
|
||||||
|
+ test_begin("dllist2 join");
|
||||||
|
+ for (unsigned int i = 0; i < N_ELEMENTS(elem); i++) {
|
||||||
|
+ elem[i] = t_new(struct dllist, 1);
|
||||||
|
+ elem2[i] = t_new(struct dllist, 1);
|
||||||
|
+ }
|
||||||
|
+ for (unsigned int i = 0; i < N_ELEMENTS(elem); i++) {
|
||||||
|
+ for (unsigned int j = 0; j < N_ELEMENTS(elem2); j++) {
|
||||||
|
+ head = tail = head2 = tail2 = NULL;
|
||||||
|
+ for (unsigned int n = 0; n < i; n++)
|
||||||
|
+ DLLIST2_APPEND(&head, &tail, elem[n]);
|
||||||
|
+ for (unsigned int n = 0; n < j; n++)
|
||||||
|
+ DLLIST2_APPEND(&head2, &tail2, elem2[n]);
|
||||||
|
+ DLLIST2_JOIN(&head, &tail, &head2, &tail2);
|
||||||
|
+
|
||||||
|
+ /* verify */
|
||||||
|
+ struct dllist *tmp = head, *last = NULL;
|
||||||
|
+ for (unsigned int n = 0; n < i; n++) {
|
||||||
|
+ test_assert(tmp == elem[n]);
|
||||||
|
+ last = tmp;
|
||||||
|
+ tmp = tmp->next;
|
||||||
|
+ }
|
||||||
|
+ for (unsigned int n = 0; n < j; n++) {
|
||||||
|
+ test_assert(tmp == elem2[n]);
|
||||||
|
+ last = tmp;
|
||||||
|
+ tmp = tmp->next;
|
||||||
|
+ }
|
||||||
|
+ test_assert(tmp == NULL);
|
||||||
|
+ test_assert(tail == last);
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ test_end();
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
void test_llist(void)
|
||||||
|
{
|
||||||
|
test_dllist();
|
||||||
|
test_dllist2();
|
||||||
|
+ test_dllist2_join();
|
||||||
|
}
|
||||||
|
|
||||||
|
From 0bae091859c905dc335f21eed01347e6b8338672 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Timo Sirainen <timo.sirainen@open-xchange.com>
|
||||||
|
Date: Tue, 30 Jan 2024 22:42:50 +0200
|
||||||
|
Subject: [PATCH 3/6] lib-mail: test-imap-envelope - Use test_assert_idx()
|
||||||
|
where possible
|
||||||
|
|
||||||
|
---
|
||||||
|
src/lib-imap/test-imap-envelope.c | 6 +++---
|
||||||
|
1 file changed, 3 insertions(+), 3 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/src/lib-imap/test-imap-envelope.c b/src/lib-imap/test-imap-envelope.c
|
||||||
|
index 1f295e58bab..c9b92b4be2b 100644
|
||||||
|
--- a/src/lib-imap/test-imap-envelope.c
|
||||||
|
+++ b/src/lib-imap/test-imap-envelope.c
|
||||||
|
@@ -157,7 +157,7 @@ static void test_imap_envelope_write(void)
|
||||||
|
envlp = msg_parse(pool, test->message);
|
||||||
|
|
||||||
|
imap_envelope_write(envlp, str);
|
||||||
|
- test_assert(strcmp(str_c(str), test->envelope) == 0);
|
||||||
|
+ test_assert_idx(strcmp(str_c(str), test->envelope) == 0, i);
|
||||||
|
|
||||||
|
pool_unref(&pool);
|
||||||
|
test_end();
|
||||||
|
@@ -179,12 +179,12 @@ static void test_imap_envelope_parse(void)
|
||||||
|
test_begin(t_strdup_printf("imap envelope parser [%u]", i));
|
||||||
|
|
||||||
|
ret = imap_envelope_parse(test->envelope, pool, &envlp, &error);
|
||||||
|
- test_assert(ret);
|
||||||
|
+ test_assert_idx(ret, i);
|
||||||
|
|
||||||
|
if (ret) {
|
||||||
|
str_truncate(str, 0);
|
||||||
|
imap_envelope_write(envlp, str);
|
||||||
|
- test_assert(strcmp(str_c(str), test->envelope) == 0);
|
||||||
|
+ test_assert_idx(strcmp(str_c(str), test->envelope) == 0, i);
|
||||||
|
} else {
|
||||||
|
i_error("Invalid envelope: %s", error);
|
||||||
|
}
|
||||||
|
|
||||||
|
From a1c9b0409454e45937bf7e9c3685f5e91d6a5a43 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Timo Sirainen <timo.sirainen@open-xchange.com>
|
||||||
|
Date: Sun, 4 Feb 2024 00:26:57 +0200
|
||||||
|
Subject: [PATCH 4/6] lib-mail: Change message_address to be doubly linked list
|
||||||
|
|
||||||
|
---
|
||||||
|
src/lib-imap/imap-envelope.c | 11 +-
|
||||||
|
src/lib-mail/message-address.c | 8 +-
|
||||||
|
src/lib-mail/message-address.h | 2 +-
|
||||||
|
src/lib-mail/test-message-address.c | 226 ++++++++++++++--------------
|
||||||
|
4 files changed, 121 insertions(+), 126 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/src/lib-imap/imap-envelope.c b/src/lib-imap/imap-envelope.c
|
||||||
|
index 87297f4f691..1312eae2ff3 100644
|
||||||
|
--- a/src/lib-imap/imap-envelope.c
|
||||||
|
+++ b/src/lib-imap/imap-envelope.c
|
||||||
|
@@ -1,6 +1,7 @@
|
||||||
|
/* Copyright (c) 2002-2018 Dovecot authors, see the included COPYING file */
|
||||||
|
|
||||||
|
#include "lib.h"
|
||||||
|
+#include "llist.h"
|
||||||
|
#include "istream.h"
|
||||||
|
#include "str.h"
|
||||||
|
#include "message-address.h"
|
||||||
|
@@ -127,7 +128,7 @@ static bool
|
||||||
|
imap_envelope_parse_addresses(const struct imap_arg *arg,
|
||||||
|
pool_t pool, struct message_address **addrs_r)
|
||||||
|
{
|
||||||
|
- struct message_address *first, *addr, *prev;
|
||||||
|
+ struct message_address *first, *last, *addr;
|
||||||
|
const struct imap_arg *list_args;
|
||||||
|
|
||||||
|
if (arg->type == IMAP_ARG_NIL) {
|
||||||
|
@@ -138,16 +139,12 @@ imap_envelope_parse_addresses(const struct imap_arg *arg,
|
||||||
|
if (!imap_arg_get_list(arg, &list_args))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
- first = addr = prev = NULL;
|
||||||
|
+ first = last = addr = NULL;
|
||||||
|
for (; !IMAP_ARG_IS_EOL(list_args); list_args++) {
|
||||||
|
if (!imap_envelope_parse_address
|
||||||
|
(list_args, pool, &addr))
|
||||||
|
return FALSE;
|
||||||
|
- if (first == NULL)
|
||||||
|
- first = addr;
|
||||||
|
- if (prev != NULL)
|
||||||
|
- prev->next = addr;
|
||||||
|
- prev = addr;
|
||||||
|
+ DLLIST2_APPEND(&first, &last, addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
*addrs_r = first;
|
||||||
|
diff --git a/src/lib-mail/message-address.c b/src/lib-mail/message-address.c
|
||||||
|
index fb06afae7b7..9d192799468 100644
|
||||||
|
--- a/src/lib-mail/message-address.c
|
||||||
|
+++ b/src/lib-mail/message-address.c
|
||||||
|
@@ -1,6 +1,7 @@
|
||||||
|
/* Copyright (c) 2002-2018 Dovecot authors, see the included COPYING file */
|
||||||
|
|
||||||
|
#include "lib.h"
|
||||||
|
+#include "llist.h"
|
||||||
|
#include "str.h"
|
||||||
|
#include "strescape.h"
|
||||||
|
#include "smtp-address.h"
|
||||||
|
@@ -27,11 +28,7 @@ static void add_address(struct message_address_parser_context *ctx)
|
||||||
|
memcpy(addr, &ctx->addr, sizeof(ctx->addr));
|
||||||
|
i_zero(&ctx->addr);
|
||||||
|
|
||||||
|
- if (ctx->first_addr == NULL)
|
||||||
|
- ctx->first_addr = addr;
|
||||||
|
- else
|
||||||
|
- ctx->last_addr->next = addr;
|
||||||
|
- ctx->last_addr = addr;
|
||||||
|
+ DLLIST2_APPEND(&ctx->first_addr, &ctx->last_addr, addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* quote with "" and escape all '\', '"' and "'" characters if need */
|
||||||
|
@@ -631,6 +628,7 @@ const char *message_address_first_to_string(const struct message_address *addr)
|
||||||
|
struct message_address first_addr;
|
||||||
|
|
||||||
|
first_addr = *addr;
|
||||||
|
+ first_addr.prev = NULL;
|
||||||
|
first_addr.next = NULL;
|
||||||
|
first_addr.route = NULL;
|
||||||
|
return message_address_to_string(&first_addr);
|
||||||
|
diff --git a/src/lib-mail/message-address.h b/src/lib-mail/message-address.h
|
||||||
|
index 8370397741c..85cff3dcc6f 100644
|
||||||
|
--- a/src/lib-mail/message-address.h
|
||||||
|
+++ b/src/lib-mail/message-address.h
|
||||||
|
@@ -18,7 +18,7 @@ enum message_address_parse_flags {
|
||||||
|
{name = NULL, NULL, "group", NULL}, ..., {NULL, NULL, NULL, NULL}
|
||||||
|
*/
|
||||||
|
struct message_address {
|
||||||
|
- struct message_address *next;
|
||||||
|
+ struct message_address *prev, *next;
|
||||||
|
|
||||||
|
/* display-name */
|
||||||
|
const char *name;
|
||||||
|
diff --git a/src/lib-mail/test-message-address.c b/src/lib-mail/test-message-address.c
|
||||||
|
index e6204bb0588..261cbfba70a 100644
|
||||||
|
--- a/src/lib-mail/test-message-address.c
|
||||||
|
+++ b/src/lib-mail/test-message-address.c
|
||||||
|
@@ -47,174 +47,174 @@ static void test_message_address(void)
|
||||||
|
} tests[] = {
|
||||||
|
/* user@domain -> <user@domain> */
|
||||||
|
{ "user@domain", "<user@domain>", NULL,
|
||||||
|
- { NULL, NULL, NULL, "user", "domain", FALSE },
|
||||||
|
- { NULL, NULL, NULL, "user", "domain", FALSE }, 0 },
|
||||||
|
+ { NULL, NULL, NULL, NULL, "user", "domain", FALSE },
|
||||||
|
+ { NULL, NULL, NULL, NULL, "user", "domain", FALSE }, 0 },
|
||||||
|
{ "\"user\"@domain", "<user@domain>", NULL,
|
||||||
|
- { NULL, NULL, NULL, "user", "domain", FALSE },
|
||||||
|
- { NULL, NULL, NULL, "user", "domain", FALSE }, 0 },
|
||||||
|
+ { NULL, NULL, NULL, NULL, "user", "domain", FALSE },
|
||||||
|
+ { NULL, NULL, NULL, NULL, "user", "domain", FALSE }, 0 },
|
||||||
|
{ "\"user name\"@domain", "<\"user name\"@domain>", NULL,
|
||||||
|
- { NULL, NULL, NULL, "user name", "domain", FALSE },
|
||||||
|
- { NULL, NULL, NULL, "user name", "domain", FALSE }, 0 },
|
||||||
|
+ { NULL, NULL, NULL, NULL, "user name", "domain", FALSE },
|
||||||
|
+ { NULL, NULL, NULL, NULL, "user name", "domain", FALSE }, 0 },
|
||||||
|
{ "\"user@na\\\\me\"@domain", "<\"user@na\\\\me\"@domain>", NULL,
|
||||||
|
- { NULL, NULL, NULL, "user@na\\me", "domain", FALSE },
|
||||||
|
- { NULL, NULL, NULL, "user@na\\me", "domain", FALSE }, 0 },
|
||||||
|
+ { NULL, NULL, NULL, NULL, "user@na\\me", "domain", FALSE },
|
||||||
|
+ { NULL, NULL, NULL, NULL, "user@na\\me", "domain", FALSE }, 0 },
|
||||||
|
{ "\"user\\\"name\"@domain", "<\"user\\\"name\"@domain>", NULL,
|
||||||
|
- { NULL, NULL, NULL, "user\"name", "domain", FALSE },
|
||||||
|
- { NULL, NULL, NULL, "user\"name", "domain", FALSE }, 0 },
|
||||||
|
+ { NULL, NULL, NULL, NULL, "user\"name", "domain", FALSE },
|
||||||
|
+ { NULL, NULL, NULL, NULL, "user\"name", "domain", FALSE }, 0 },
|
||||||
|
{ "\"\"@domain", "<\"\"@domain>", NULL,
|
||||||
|
- { NULL, NULL, NULL, "", "domain", FALSE },
|
||||||
|
- { NULL, NULL, NULL, "", "domain", FALSE }, 0 },
|
||||||
|
+ { NULL, NULL, NULL, NULL, "", "domain", FALSE },
|
||||||
|
+ { NULL, NULL, NULL, NULL, "", "domain", FALSE }, 0 },
|
||||||
|
{ "user", "<user>", "<user@MISSING_DOMAIN>",
|
||||||
|
- { NULL, NULL, NULL, "user", "", TRUE },
|
||||||
|
- { NULL, NULL, NULL, "user", "MISSING_DOMAIN", TRUE }, 0 },
|
||||||
|
+ { NULL, NULL, NULL, NULL, "user", "", TRUE },
|
||||||
|
+ { NULL, NULL, NULL, NULL, "user", "MISSING_DOMAIN", TRUE }, 0 },
|
||||||
|
{ "@domain", "<\"\"@domain>", "<MISSING_MAILBOX@domain>",
|
||||||
|
- { NULL, NULL, NULL, "", "domain", TRUE },
|
||||||
|
- { NULL, NULL, NULL, "MISSING_MAILBOX", "domain", TRUE }, 0 },
|
||||||
|
+ { NULL, NULL, NULL, NULL, "", "domain", TRUE },
|
||||||
|
+ { NULL, NULL, NULL, NULL, "MISSING_MAILBOX", "domain", TRUE }, 0 },
|
||||||
|
|
||||||
|
/* Display Name -> Display Name */
|
||||||
|
{ "Display Name", "\"Display Name\"", "\"Display Name\" <MISSING_MAILBOX@MISSING_DOMAIN>",
|
||||||
|
- { NULL, "Display Name", NULL, "", "", TRUE },
|
||||||
|
- { NULL, "Display Name", NULL, "MISSING_MAILBOX", "MISSING_DOMAIN", TRUE }, 0 },
|
||||||
|
+ { NULL, NULL, "Display Name", NULL, "", "", TRUE },
|
||||||
|
+ { NULL, NULL, "Display Name", NULL, "MISSING_MAILBOX", "MISSING_DOMAIN", TRUE }, 0 },
|
||||||
|
{ "\"Display Name\"", "\"Display Name\"", "\"Display Name\" <MISSING_MAILBOX@MISSING_DOMAIN>",
|
||||||
|
- { NULL, "Display Name", NULL, "", "", TRUE },
|
||||||
|
- { NULL, "Display Name", NULL, "MISSING_MAILBOX", "MISSING_DOMAIN", TRUE }, 0 },
|
||||||
|
+ { NULL, NULL, "Display Name", NULL, "", "", TRUE },
|
||||||
|
+ { NULL, NULL, "Display Name", NULL, "MISSING_MAILBOX", "MISSING_DOMAIN", TRUE }, 0 },
|
||||||
|
{ "Display \"Name\"", "\"Display Name\"", "\"Display Name\" <MISSING_MAILBOX@MISSING_DOMAIN>",
|
||||||
|
- { NULL, "Display Name", NULL, "", "", TRUE },
|
||||||
|
- { NULL, "Display Name", NULL, "MISSING_MAILBOX", "MISSING_DOMAIN", TRUE }, 0 },
|
||||||
|
+ { NULL, NULL, "Display Name", NULL, "", "", TRUE },
|
||||||
|
+ { NULL, NULL, "Display Name", NULL, "MISSING_MAILBOX", "MISSING_DOMAIN", TRUE }, 0 },
|
||||||
|
{ "\"Display\" \"Name\"", "\"Display Name\"", "\"Display Name\" <MISSING_MAILBOX@MISSING_DOMAIN>",
|
||||||
|
- { NULL, "Display Name", NULL, "", "", TRUE },
|
||||||
|
- { NULL, "Display Name", NULL, "MISSING_MAILBOX", "MISSING_DOMAIN", TRUE }, 0 },
|
||||||
|
+ { NULL, NULL, "Display Name", NULL, "", "", TRUE },
|
||||||
|
+ { NULL, NULL, "Display Name", NULL, "MISSING_MAILBOX", "MISSING_DOMAIN", TRUE }, 0 },
|
||||||
|
{ "\"\"", "", "<MISSING_MAILBOX@MISSING_DOMAIN>",
|
||||||
|
- { NULL, "", NULL, "", "", TRUE },
|
||||||
|
- { NULL, "", NULL, "MISSING_MAILBOX", "MISSING_DOMAIN", TRUE }, 0 },
|
||||||
|
+ { NULL, NULL, "", NULL, "", "", TRUE },
|
||||||
|
+ { NULL, NULL, "", NULL, "MISSING_MAILBOX", "MISSING_DOMAIN", TRUE }, 0 },
|
||||||
|
|
||||||
|
/* <user@domain> -> <user@domain> */
|
||||||
|
{ "<user@domain>", NULL, NULL,
|
||||||
|
- { NULL, NULL, NULL, "user", "domain", FALSE },
|
||||||
|
- { NULL, NULL, NULL, "user", "domain", FALSE }, 0 },
|
||||||
|
+ { NULL, NULL, NULL, NULL, "user", "domain", FALSE },
|
||||||
|
+ { NULL, NULL, NULL, NULL, "user", "domain", FALSE }, 0 },
|
||||||
|
{ "<\"user\"@domain>", "<user@domain>", NULL,
|
||||||
|
- { NULL, NULL, NULL, "user", "domain", FALSE },
|
||||||
|
- { NULL, NULL, NULL, "user", "domain", FALSE }, 0 },
|
||||||
|
+ { NULL, NULL, NULL, NULL, "user", "domain", FALSE },
|
||||||
|
+ { NULL, NULL, NULL, NULL, "user", "domain", FALSE }, 0 },
|
||||||
|
{ "<\"user name\"@domain>", NULL, NULL,
|
||||||
|
- { NULL, NULL, NULL, "user name", "domain", FALSE },
|
||||||
|
- { NULL, NULL, NULL, "user name", "domain", FALSE }, 0 },
|
||||||
|
+ { NULL, NULL, NULL, NULL, "user name", "domain", FALSE },
|
||||||
|
+ { NULL, NULL, NULL, NULL, "user name", "domain", FALSE }, 0 },
|
||||||
|
{ "<\"user@na\\\\me\"@domain>", NULL, NULL,
|
||||||
|
- { NULL, NULL, NULL, "user@na\\me", "domain", FALSE },
|
||||||
|
- { NULL, NULL, NULL, "user@na\\me", "domain", FALSE }, 0 },
|
||||||
|
+ { NULL, NULL, NULL, NULL, "user@na\\me", "domain", FALSE },
|
||||||
|
+ { NULL, NULL, NULL, NULL, "user@na\\me", "domain", FALSE }, 0 },
|
||||||
|
{ "<\"user\\\"name\"@domain>", NULL, NULL,
|
||||||
|
- { NULL, NULL, NULL, "user\"name", "domain", FALSE },
|
||||||
|
- { NULL, NULL, NULL, "user\"name", "domain", FALSE }, 0 },
|
||||||
|
+ { NULL, NULL, NULL, NULL, "user\"name", "domain", FALSE },
|
||||||
|
+ { NULL, NULL, NULL, NULL, "user\"name", "domain", FALSE }, 0 },
|
||||||
|
{ "<\"\"@domain>", NULL, NULL,
|
||||||
|
- { NULL, NULL, NULL, "", "domain", FALSE },
|
||||||
|
- { NULL, NULL, NULL, "", "domain", FALSE }, 0 },
|
||||||
|
+ { NULL, NULL, NULL, NULL, "", "domain", FALSE },
|
||||||
|
+ { NULL, NULL, NULL, NULL, "", "domain", FALSE }, 0 },
|
||||||
|
{ "<user>", NULL, "<user@MISSING_DOMAIN>",
|
||||||
|
- { NULL, NULL, NULL, "user", "", TRUE },
|
||||||
|
- { NULL, NULL, NULL, "user", "MISSING_DOMAIN", TRUE }, 0 },
|
||||||
|
+ { NULL, NULL, NULL, NULL, "user", "", TRUE },
|
||||||
|
+ { NULL, NULL, NULL, NULL, "user", "MISSING_DOMAIN", TRUE }, 0 },
|
||||||
|
{ "<@route>", "<@route:\"\">", "<INVALID_ROUTE:MISSING_MAILBOX@MISSING_DOMAIN>",
|
||||||
|
- { NULL, NULL, "@route", "", "", TRUE },
|
||||||
|
- { NULL, NULL, "INVALID_ROUTE", "MISSING_MAILBOX", "MISSING_DOMAIN", TRUE }, 0 },
|
||||||
|
+ { NULL, NULL, NULL, "@route", "", "", TRUE },
|
||||||
|
+ { NULL, NULL, NULL, "INVALID_ROUTE", "MISSING_MAILBOX", "MISSING_DOMAIN", TRUE }, 0 },
|
||||||
|
|
||||||
|
/* user@domain (Display Name) -> "Display Name" <user@domain> */
|
||||||
|
{ "user@domain (DisplayName)", "DisplayName <user@domain>", NULL,
|
||||||
|
- { NULL, "DisplayName", NULL, "user", "domain", FALSE },
|
||||||
|
- { NULL, "DisplayName", NULL, "user", "domain", FALSE }, 0 },
|
||||||
|
+ { NULL, NULL, "DisplayName", NULL, "user", "domain", FALSE },
|
||||||
|
+ { NULL, NULL, "DisplayName", NULL, "user", "domain", FALSE }, 0 },
|
||||||
|
{ "user@domain (Display Name)", "\"Display Name\" <user@domain>", NULL,
|
||||||
|
- { NULL, "Display Name", NULL, "user", "domain", FALSE },
|
||||||
|
- { NULL, "Display Name", NULL, "user", "domain", FALSE }, 0 },
|
||||||
|
+ { NULL, NULL, "Display Name", NULL, "user", "domain", FALSE },
|
||||||
|
+ { NULL, NULL, "Display Name", NULL, "user", "domain", FALSE }, 0 },
|
||||||
|
{ "user@domain (Display\"Name)", "\"Display\\\"Name\" <user@domain>", NULL,
|
||||||
|
- { NULL, "Display\"Name", NULL, "user", "domain", FALSE },
|
||||||
|
- { NULL, "Display\"Name", NULL, "user", "domain", FALSE }, 0 },
|
||||||
|
+ { NULL, NULL, "Display\"Name", NULL, "user", "domain", FALSE },
|
||||||
|
+ { NULL, NULL, "Display\"Name", NULL, "user", "domain", FALSE }, 0 },
|
||||||
|
{ "user (Display Name)", "\"Display Name\" <user>", "\"Display Name\" <user@MISSING_DOMAIN>",
|
||||||
|
- { NULL, "Display Name", NULL, "user", "", TRUE },
|
||||||
|
- { NULL, "Display Name", NULL, "user", "MISSING_DOMAIN", TRUE }, 0 },
|
||||||
|
+ { NULL, NULL, "Display Name", NULL, "user", "", TRUE },
|
||||||
|
+ { NULL, NULL, "Display Name", NULL, "user", "MISSING_DOMAIN", TRUE }, 0 },
|
||||||
|
{ "@domain (Display Name)", "\"Display Name\" <\"\"@domain>", "\"Display Name\" <MISSING_MAILBOX@domain>",
|
||||||
|
- { NULL, "Display Name", NULL, "", "domain", TRUE },
|
||||||
|
- { NULL, "Display Name", NULL, "MISSING_MAILBOX", "domain", TRUE }, 0 },
|
||||||
|
+ { NULL, NULL, "Display Name", NULL, "", "domain", TRUE },
|
||||||
|
+ { NULL, NULL, "Display Name", NULL, "MISSING_MAILBOX", "domain", TRUE }, 0 },
|
||||||
|
{ "user@domain ()", "<user@domain>", NULL,
|
||||||
|
- { NULL, NULL, NULL, "user", "domain", FALSE },
|
||||||
|
- { NULL, NULL, NULL, "user", "domain", FALSE }, 0 },
|
||||||
|
+ { NULL, NULL, NULL, NULL, "user", "domain", FALSE },
|
||||||
|
+ { NULL, NULL, NULL, NULL, "user", "domain", FALSE }, 0 },
|
||||||
|
|
||||||
|
/* Display Name <user@domain> -> "Display Name" <user@domain> */
|
||||||
|
{ "DisplayName <user@domain>", NULL, NULL,
|
||||||
|
- { NULL, "DisplayName", NULL, "user", "domain", FALSE },
|
||||||
|
- { NULL, "DisplayName", NULL, "user", "domain", FALSE }, 0 },
|
||||||
|
+ { NULL, NULL, "DisplayName", NULL, "user", "domain", FALSE },
|
||||||
|
+ { NULL, NULL, "DisplayName", NULL, "user", "domain", FALSE }, 0 },
|
||||||
|
{ "Display Name <user@domain>", "\"Display Name\" <user@domain>", NULL,
|
||||||
|
- { NULL, "Display Name", NULL, "user", "domain", FALSE },
|
||||||
|
- { NULL, "Display Name", NULL, "user", "domain", FALSE }, 0 },
|
||||||
|
+ { NULL, NULL, "Display Name", NULL, "user", "domain", FALSE },
|
||||||
|
+ { NULL, NULL, "Display Name", NULL, "user", "domain", FALSE }, 0 },
|
||||||
|
{ "\"Display Name\" <user@domain>", NULL, NULL,
|
||||||
|
- { NULL, "Display Name", NULL, "user", "domain", FALSE },
|
||||||
|
- { NULL, "Display Name", NULL, "user", "domain", FALSE }, 0 },
|
||||||
|
+ { NULL, NULL, "Display Name", NULL, "user", "domain", FALSE },
|
||||||
|
+ { NULL, NULL, "Display Name", NULL, "user", "domain", FALSE }, 0 },
|
||||||
|
{ "\"Display\\\"Name\" <user@domain>", NULL, NULL,
|
||||||
|
- { NULL, "Display\"Name", NULL, "user", "domain", FALSE },
|
||||||
|
- { NULL, "Display\"Name", NULL, "user", "domain", FALSE }, 0 },
|
||||||
|
+ { NULL, NULL, "Display\"Name", NULL, "user", "domain", FALSE },
|
||||||
|
+ { NULL, NULL, "Display\"Name", NULL, "user", "domain", FALSE }, 0 },
|
||||||
|
{ "Display Name <user>", "\"Display Name\" <user>", "\"Display Name\" <user@MISSING_DOMAIN>",
|
||||||
|
- { NULL, "Display Name", NULL, "user", "", TRUE },
|
||||||
|
- { NULL, "Display Name", NULL, "user", "MISSING_DOMAIN", TRUE }, 0 },
|
||||||
|
+ { NULL, NULL, "Display Name", NULL, "user", "", TRUE },
|
||||||
|
+ { NULL, NULL, "Display Name", NULL, "user", "MISSING_DOMAIN", TRUE }, 0 },
|
||||||
|
{ "\"\" <user@domain>", "<user@domain>", NULL,
|
||||||
|
- { NULL, NULL, NULL, "user", "domain", FALSE },
|
||||||
|
- { NULL, NULL, NULL, "user", "domain", FALSE }, 0 },
|
||||||
|
+ { NULL, NULL, NULL, NULL, "user", "domain", FALSE },
|
||||||
|
+ { NULL, NULL, NULL, NULL, "user", "domain", FALSE }, 0 },
|
||||||
|
|
||||||
|
/* <@route:user@domain> -> <@route:user@domain> */
|
||||||
|
{ "<@route:user@domain>", NULL, NULL,
|
||||||
|
- { NULL, NULL, "@route", "user", "domain", FALSE },
|
||||||
|
- { NULL, NULL, "@route", "user", "domain", FALSE }, 0 },
|
||||||
|
+ { NULL, NULL, NULL, "@route", "user", "domain", FALSE },
|
||||||
|
+ { NULL, NULL, NULL, "@route", "user", "domain", FALSE }, 0 },
|
||||||
|
{ "<@route,@route2:user@domain>", NULL, NULL,
|
||||||
|
- { NULL, NULL, "@route,@route2", "user", "domain", FALSE },
|
||||||
|
- { NULL, NULL, "@route,@route2", "user", "domain", FALSE }, 0 },
|
||||||
|
+ { NULL, NULL, NULL, "@route,@route2", "user", "domain", FALSE },
|
||||||
|
+ { NULL, NULL, NULL, "@route,@route2", "user", "domain", FALSE }, 0 },
|
||||||
|
{ "<@route@route2:user@domain>", "<@route,@route2:user@domain>", NULL,
|
||||||
|
- { NULL, NULL, "@route,@route2", "user", "domain", FALSE },
|
||||||
|
- { NULL, NULL, "@route,@route2", "user", "domain", FALSE }, 0 },
|
||||||
|
+ { NULL, NULL, NULL, "@route,@route2", "user", "domain", FALSE },
|
||||||
|
+ { NULL, NULL, NULL, "@route,@route2", "user", "domain", FALSE }, 0 },
|
||||||
|
{ "<@route@route2:user>", "<@route,@route2:user>", "<@route,@route2:user@MISSING_DOMAIN>",
|
||||||
|
- { NULL, NULL, "@route,@route2", "user", "", TRUE },
|
||||||
|
- { NULL, NULL, "@route,@route2", "user", "MISSING_DOMAIN", TRUE }, 0 },
|
||||||
|
+ { NULL, NULL, NULL, "@route,@route2", "user", "", TRUE },
|
||||||
|
+ { NULL, NULL, NULL, "@route,@route2", "user", "MISSING_DOMAIN", TRUE }, 0 },
|
||||||
|
{ "<@route@route2:\"\"@domain>", "<@route,@route2:\"\"@domain>", NULL,
|
||||||
|
- { NULL, NULL, "@route,@route2", "", "domain", FALSE },
|
||||||
|
- { NULL, NULL, "@route,@route2", "", "domain", FALSE }, 0 },
|
||||||
|
+ { NULL, NULL, NULL, "@route,@route2", "", "domain", FALSE },
|
||||||
|
+ { NULL, NULL, NULL, "@route,@route2", "", "domain", FALSE }, 0 },
|
||||||
|
|
||||||
|
/* Display Name <@route:user@domain> ->
|
||||||
|
"Display Name" <@route:user@domain> */
|
||||||
|
{ "Display Name <@route:user@domain>", "\"Display Name\" <@route:user@domain>", NULL,
|
||||||
|
- { NULL, "Display Name", "@route", "user", "domain", FALSE },
|
||||||
|
- { NULL, "Display Name", "@route", "user", "domain", FALSE }, 0 },
|
||||||
|
+ { NULL, NULL, "Display Name", "@route", "user", "domain", FALSE },
|
||||||
|
+ { NULL, NULL, "Display Name", "@route", "user", "domain", FALSE }, 0 },
|
||||||
|
{ "Display Name <@route,@route2:user@domain>", "\"Display Name\" <@route,@route2:user@domain>", NULL,
|
||||||
|
- { NULL, "Display Name", "@route,@route2", "user", "domain", FALSE },
|
||||||
|
- { NULL, "Display Name", "@route,@route2", "user", "domain", FALSE }, 0 },
|
||||||
|
+ { NULL, NULL, "Display Name", "@route,@route2", "user", "domain", FALSE },
|
||||||
|
+ { NULL, NULL, "Display Name", "@route,@route2", "user", "domain", FALSE }, 0 },
|
||||||
|
{ "Display Name <@route@route2:user@domain>", "\"Display Name\" <@route,@route2:user@domain>", NULL,
|
||||||
|
- { NULL, "Display Name", "@route,@route2", "user", "domain", FALSE },
|
||||||
|
- { NULL, "Display Name", "@route,@route2", "user", "domain", FALSE }, 0 },
|
||||||
|
+ { NULL, NULL, "Display Name", "@route,@route2", "user", "domain", FALSE },
|
||||||
|
+ { NULL, NULL, "Display Name", "@route,@route2", "user", "domain", FALSE }, 0 },
|
||||||
|
{ "Display Name <@route@route2:user>", "\"Display Name\" <@route,@route2:user>", "\"Display Name\" <@route,@route2:user@MISSING_DOMAIN>",
|
||||||
|
- { NULL, "Display Name", "@route,@route2", "user", "", TRUE },
|
||||||
|
- { NULL, "Display Name", "@route,@route2", "user", "MISSING_DOMAIN", TRUE }, 0 },
|
||||||
|
+ { NULL, NULL, "Display Name", "@route,@route2", "user", "", TRUE },
|
||||||
|
+ { NULL, NULL, "Display Name", "@route,@route2", "user", "MISSING_DOMAIN", TRUE }, 0 },
|
||||||
|
{ "Display Name <@route@route2:\"\"@domain>", "\"Display Name\" <@route,@route2:\"\"@domain>", NULL,
|
||||||
|
- { NULL, "Display Name", "@route,@route2", "", "domain", FALSE },
|
||||||
|
- { NULL, "Display Name", "@route,@route2", "", "domain", FALSE }, 0 },
|
||||||
|
+ { NULL, NULL, "Display Name", "@route,@route2", "", "domain", FALSE },
|
||||||
|
+ { NULL, NULL, "Display Name", "@route,@route2", "", "domain", FALSE }, 0 },
|
||||||
|
|
||||||
|
/* other tests: */
|
||||||
|
{ "\"foo: <a@b>;,\" <user@domain>", NULL, NULL,
|
||||||
|
- { NULL, "foo: <a@b>;,", NULL, "user", "domain", FALSE },
|
||||||
|
- { NULL, "foo: <a@b>;,", NULL, "user", "domain", FALSE }, 0 },
|
||||||
|
+ { NULL, NULL, "foo: <a@b>;,", NULL, "user", "domain", FALSE },
|
||||||
|
+ { NULL, NULL, "foo: <a@b>;,", NULL, "user", "domain", FALSE }, 0 },
|
||||||
|
{ "<>", "", "<MISSING_MAILBOX@MISSING_DOMAIN>",
|
||||||
|
- { NULL, NULL, NULL, "", "", TRUE },
|
||||||
|
- { NULL, NULL, NULL, "MISSING_MAILBOX", "MISSING_DOMAIN", TRUE }, 0 },
|
||||||
|
+ { NULL, NULL, NULL, NULL, "", "", TRUE },
|
||||||
|
+ { NULL, NULL, NULL, NULL, "MISSING_MAILBOX", "MISSING_DOMAIN", TRUE }, 0 },
|
||||||
|
{ "<@>", "", "<INVALID_ROUTE:MISSING_MAILBOX@MISSING_DOMAIN>",
|
||||||
|
- { NULL, NULL, NULL, "", "", TRUE },
|
||||||
|
- { NULL, NULL, "INVALID_ROUTE", "MISSING_MAILBOX", "MISSING_DOMAIN", TRUE }, 0 },
|
||||||
|
+ { NULL, NULL, NULL, NULL, "", "", TRUE },
|
||||||
|
+ { NULL, NULL, NULL, "INVALID_ROUTE", "MISSING_MAILBOX", "MISSING_DOMAIN", TRUE }, 0 },
|
||||||
|
|
||||||
|
/* Test against a out-of-bounds read bug - keep these two tests
|
||||||
|
together in this same order: */
|
||||||
|
{ "aaaa@", "<aaaa>", "<aaaa@MISSING_DOMAIN>",
|
||||||
|
- { NULL, NULL, NULL, "aaaa", "", TRUE },
|
||||||
|
- { NULL, NULL, NULL, "aaaa", "MISSING_DOMAIN", TRUE }, 0 },
|
||||||
|
+ { NULL, NULL, NULL, NULL, "aaaa", "", TRUE },
|
||||||
|
+ { NULL, NULL, NULL, NULL, "aaaa", "MISSING_DOMAIN", TRUE }, 0 },
|
||||||
|
{ "a(aa", "", "<MISSING_MAILBOX@MISSING_DOMAIN>",
|
||||||
|
- { NULL, NULL, NULL, "", "", TRUE },
|
||||||
|
- { NULL, NULL, NULL, "MISSING_MAILBOX", "MISSING_DOMAIN", TRUE },
|
||||||
|
+ { NULL, NULL, NULL, NULL, "", "", TRUE },
|
||||||
|
+ { NULL, NULL, NULL, NULL, "MISSING_MAILBOX", "MISSING_DOMAIN", TRUE },
|
||||||
|
TEST_MESSAGE_ADDRESS_FLAG_SKIP_LIST },
|
||||||
|
};
|
||||||
|
static struct message_address group_prefix = {
|
||||||
|
- NULL, NULL, NULL, "group", NULL, FALSE
|
||||||
|
+ NULL, NULL, NULL, NULL, "group", NULL, FALSE
|
||||||
|
};
|
||||||
|
static struct message_address group_suffix = {
|
||||||
|
- NULL, NULL, NULL, NULL, NULL, FALSE
|
||||||
|
+ NULL, NULL, NULL, NULL, NULL, NULL, FALSE
|
||||||
|
};
|
||||||
|
const struct message_address *addr;
|
||||||
|
string_t *str, *group;
|
||||||
|
@@ -327,7 +327,7 @@ static void test_message_address_nuls(void)
|
||||||
|
const unsigned char input[] =
|
||||||
|
"\"user\0nuls\\\0-esc\"@[domain\0nuls\\\0-esc] (comment\0nuls\\\0-esc)";
|
||||||
|
const struct message_address output = {
|
||||||
|
- NULL, "comment\xEF\xBF\xBDnuls\\\xEF\xBF\xBD-esc", NULL,
|
||||||
|
+ NULL, NULL, "comment\xEF\xBF\xBDnuls\\\xEF\xBF\xBD-esc", NULL,
|
||||||
|
"user\xEF\xBF\xBDnuls\\\xEF\xBF\xBD-esc",
|
||||||
|
"[domain\xEF\xBF\xBDnuls\\\xEF\xBF\xBD-esc]", FALSE
|
||||||
|
};
|
||||||
|
@@ -345,7 +345,7 @@ static void test_message_address_nuls_display_name(void)
|
||||||
|
const unsigned char input[] =
|
||||||
|
"\"displayname\0nuls\\\0-esc\" <\"user\0nuls\\\0-esc\"@[domain\0nuls\\\0-esc]>";
|
||||||
|
const struct message_address output = {
|
||||||
|
- NULL, "displayname\xEF\xBF\xBDnuls\\\xEF\xBF\xBD-esc", NULL,
|
||||||
|
+ NULL, NULL, "displayname\xEF\xBF\xBDnuls\\\xEF\xBF\xBD-esc", NULL,
|
||||||
|
"user\xEF\xBF\xBDnuls\\\xEF\xBF\xBD-esc",
|
||||||
|
"[domain\xEF\xBF\xBDnuls\\\xEF\xBF\xBD-esc]", FALSE
|
||||||
|
};
|
||||||
|
@@ -369,7 +369,7 @@ static void test_message_address_non_strict_dots(void)
|
||||||
|
};
|
||||||
|
const struct message_address *addr;
|
||||||
|
struct message_address output = {
|
||||||
|
- NULL, NULL, NULL, "local-part",
|
||||||
|
+ NULL, NULL, NULL, NULL, "local-part",
|
||||||
|
"example.com", FALSE
|
||||||
|
};
|
||||||
|
|
||||||
|
@@ -421,29 +421,29 @@ static void test_message_address_path(void)
|
||||||
|
struct message_address addr;
|
||||||
|
} tests[] = {
|
||||||
|
{ "<>", NULL,
|
||||||
|
- { NULL, NULL, NULL, NULL, NULL, FALSE } },
|
||||||
|
+ { NULL, NULL, NULL, NULL, NULL, NULL, FALSE } },
|
||||||
|
{ " < > ", "<>",
|
||||||
|
- { NULL, NULL, NULL, NULL, NULL, FALSE } },
|
||||||
|
+ { NULL, NULL, NULL, NULL, NULL, NULL, FALSE } },
|
||||||
|
{ "<user@domain>", NULL,
|
||||||
|
- { NULL, NULL, NULL, "user", "domain", FALSE } },
|
||||||
|
+ { NULL, NULL, NULL, NULL, "user", "domain", FALSE } },
|
||||||
|
{ " <user@domain> ", "<user@domain>",
|
||||||
|
- { NULL, NULL, NULL, "user", "domain", FALSE } },
|
||||||
|
+ { NULL, NULL, NULL, NULL, "user", "domain", FALSE } },
|
||||||
|
{ "user@domain", "<user@domain>",
|
||||||
|
- { NULL, NULL, NULL, "user", "domain", FALSE } },
|
||||||
|
+ { NULL, NULL, NULL, NULL, "user", "domain", FALSE } },
|
||||||
|
{ " user@domain ", "<user@domain>",
|
||||||
|
- { NULL, NULL, NULL, "user", "domain", FALSE } },
|
||||||
|
+ { NULL, NULL, NULL, NULL, "user", "domain", FALSE } },
|
||||||
|
{ "<\"user\"@domain>", "<user@domain>",
|
||||||
|
- { NULL, NULL, NULL, "user", "domain", FALSE } },
|
||||||
|
+ { NULL, NULL, NULL, NULL, "user", "domain", FALSE } },
|
||||||
|
{ "<\"user name\"@domain>", NULL,
|
||||||
|
- { NULL, NULL, NULL, "user name", "domain", FALSE } },
|
||||||
|
+ { NULL, NULL, NULL, NULL, "user name", "domain", FALSE } },
|
||||||
|
{ "<\"user@na\\\\me\"@domain>", NULL,
|
||||||
|
- { NULL, NULL, NULL, "user@na\\me", "domain", FALSE } },
|
||||||
|
+ { NULL, NULL, NULL, NULL, "user@na\\me", "domain", FALSE } },
|
||||||
|
{ "<\"user\\\"name\"@domain>", NULL,
|
||||||
|
- { NULL, NULL, NULL, "user\"name", "domain", FALSE } },
|
||||||
|
+ { NULL, NULL, NULL, NULL, "user\"name", "domain", FALSE } },
|
||||||
|
{ "<\"\"@domain>", NULL,
|
||||||
|
- { NULL, NULL, NULL, "", "domain", FALSE } },
|
||||||
|
+ { NULL, NULL, NULL, NULL, "", "domain", FALSE } },
|
||||||
|
{ "<@source", "<>",
|
||||||
|
- { NULL, NULL, NULL, NULL, NULL, TRUE } },
|
||||||
|
+ { NULL, NULL, NULL, NULL, NULL, NULL, TRUE } },
|
||||||
|
};
|
||||||
|
const struct message_address *addr;
|
||||||
|
string_t *str;
|
||||||
|
|
||||||
|
From da61d20311da34f22944c6111a0b97ea2a1f8a47 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Timo Sirainen <timo.sirainen@open-xchange.com>
|
||||||
|
Date: Tue, 30 Jan 2024 22:17:38 +0200
|
||||||
|
Subject: [PATCH 5/6] lib-mail: Add message_address_parse_full() and struct
|
||||||
|
message_address_list
|
||||||
|
|
||||||
|
---
|
||||||
|
src/lib-mail/message-address.c | 37 +++++++++++++---------
|
||||||
|
src/lib-mail/message-address.h | 10 ++++++
|
||||||
|
src/lib-mail/test-message-address.c | 48 +++++++++++++++++++++++++----
|
||||||
|
3 files changed, 75 insertions(+), 20 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/src/lib-mail/message-address.c b/src/lib-mail/message-address.c
|
||||||
|
index 9d192799468..ae37014079a 100644
|
||||||
|
--- a/src/lib-mail/message-address.c
|
||||||
|
+++ b/src/lib-mail/message-address.c
|
||||||
|
@@ -13,7 +13,8 @@ struct message_address_parser_context {
|
||||||
|
pool_t pool;
|
||||||
|
struct rfc822_parser_context parser;
|
||||||
|
|
||||||
|
- struct message_address *first_addr, *last_addr, addr;
|
||||||
|
+ struct message_address addr;
|
||||||
|
+ struct message_address_list addr_list;
|
||||||
|
string_t *str;
|
||||||
|
|
||||||
|
bool fill_missing, non_strict_dots;
|
||||||
|
@@ -28,7 +29,7 @@ static void add_address(struct message_address_parser_context *ctx)
|
||||||
|
memcpy(addr, &ctx->addr, sizeof(ctx->addr));
|
||||||
|
i_zero(&ctx->addr);
|
||||||
|
|
||||||
|
- DLLIST2_APPEND(&ctx->first_addr, &ctx->last_addr, addr);
|
||||||
|
+ DLLIST2_APPEND(&ctx->addr_list.head, &ctx->addr_list.tail, addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* quote with "" and escape all '\', '"' and "'" characters if need */
|
||||||
|
@@ -439,10 +440,11 @@ static int parse_path(struct message_address_parser_context *ctx)
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
-static struct message_address *
|
||||||
|
+static void
|
||||||
|
message_address_parse_real(pool_t pool, const unsigned char *data, size_t size,
|
||||||
|
unsigned int max_addresses,
|
||||||
|
- enum message_address_parse_flags flags)
|
||||||
|
+ enum message_address_parse_flags flags,
|
||||||
|
+ struct message_address_list *list_r)
|
||||||
|
{
|
||||||
|
struct message_address_parser_context ctx;
|
||||||
|
|
||||||
|
@@ -461,7 +463,7 @@ message_address_parse_real(pool_t pool, const unsigned char *data, size_t size,
|
||||||
|
(void)parse_address_list(&ctx, max_addresses);
|
||||||
|
}
|
||||||
|
rfc822_parser_deinit(&ctx.parser);
|
||||||
|
- return ctx.first_addr;
|
||||||
|
+ *list_r = ctx.addr_list;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
@@ -481,7 +483,7 @@ message_address_parse_path_real(pool_t pool, const unsigned char *data,
|
||||||
|
ret = parse_path(&ctx);
|
||||||
|
|
||||||
|
rfc822_parser_deinit(&ctx.parser);
|
||||||
|
- *addr_r = ctx.first_addr;
|
||||||
|
+ *addr_r = ctx.addr_list.head;
|
||||||
|
return (ret < 0 ? -1 : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -490,17 +492,24 @@ message_address_parse(pool_t pool, const unsigned char *data, size_t size,
|
||||||
|
unsigned int max_addresses,
|
||||||
|
enum message_address_parse_flags flags)
|
||||||
|
{
|
||||||
|
- struct message_address *addr;
|
||||||
|
+ struct message_address_list list;
|
||||||
|
+ message_address_parse_full(pool, data, size, max_addresses, flags,
|
||||||
|
+ &list);
|
||||||
|
+ return list.head;
|
||||||
|
+}
|
||||||
|
|
||||||
|
+void message_address_parse_full(pool_t pool, const unsigned char *data,
|
||||||
|
+ size_t size, unsigned int max_addresses,
|
||||||
|
+ enum message_address_parse_flags flags,
|
||||||
|
+ struct message_address_list *list_r)
|
||||||
|
+{
|
||||||
|
if (pool->datastack_pool) {
|
||||||
|
- return message_address_parse_real(pool, data, size,
|
||||||
|
- max_addresses, flags);
|
||||||
|
- }
|
||||||
|
- T_BEGIN {
|
||||||
|
- addr = message_address_parse_real(pool, data, size,
|
||||||
|
- max_addresses, flags);
|
||||||
|
+ message_address_parse_real(pool, data, size,
|
||||||
|
+ max_addresses, flags, list_r);
|
||||||
|
+ } else T_BEGIN {
|
||||||
|
+ message_address_parse_real(pool, data, size,
|
||||||
|
+ max_addresses, flags, list_r);
|
||||||
|
} T_END;
|
||||||
|
- return addr;
|
||||||
|
}
|
||||||
|
|
||||||
|
int message_address_parse_path(pool_t pool, const unsigned char *data,
|
||||||
|
diff --git a/src/lib-mail/message-address.h b/src/lib-mail/message-address.h
|
||||||
|
index 85cff3dcc6f..224f7a75605 100644
|
||||||
|
--- a/src/lib-mail/message-address.h
|
||||||
|
+++ b/src/lib-mail/message-address.h
|
||||||
|
@@ -31,12 +31,22 @@ struct message_address {
|
||||||
|
bool invalid_syntax;
|
||||||
|
};
|
||||||
|
|
||||||
|
+struct message_address_list {
|
||||||
|
+ struct message_address *head, *tail;
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
/* Parse message addresses from given data. Note that giving an empty string
|
||||||
|
will return NULL since there are no addresses. */
|
||||||
|
struct message_address *
|
||||||
|
message_address_parse(pool_t pool, const unsigned char *data, size_t size,
|
||||||
|
unsigned int max_addresses,
|
||||||
|
enum message_address_parse_flags flags);
|
||||||
|
+/* Same as message_address_parse(), but return message_address_list containing
|
||||||
|
+ both the first and the last address in the linked list. */
|
||||||
|
+void message_address_parse_full(pool_t pool, const unsigned char *data,
|
||||||
|
+ size_t size, unsigned int max_addresses,
|
||||||
|
+ enum message_address_parse_flags flags,
|
||||||
|
+ struct message_address_list *list_r);
|
||||||
|
|
||||||
|
/* Parse RFC 5322 "path" (Return-Path header) from given data. Returns -1 if
|
||||||
|
the path is invalid and 0 otherwise.
|
||||||
|
diff --git a/src/lib-mail/test-message-address.c b/src/lib-mail/test-message-address.c
|
||||||
|
index 261cbfba70a..54aa9a83101 100644
|
||||||
|
--- a/src/lib-mail/test-message-address.c
|
||||||
|
+++ b/src/lib-mail/test-message-address.c
|
||||||
|
@@ -19,8 +19,9 @@ static bool cmp_addr(const struct message_address *a1,
|
||||||
|
a1->invalid_syntax == a2->invalid_syntax;
|
||||||
|
}
|
||||||
|
|
||||||
|
-static const struct message_address *
|
||||||
|
-test_parse_address(const char *input, bool fill_missing)
|
||||||
|
+static void
|
||||||
|
+test_parse_address_full(const char *input, bool fill_missing,
|
||||||
|
+ struct message_address_list *list_r)
|
||||||
|
{
|
||||||
|
const enum message_address_parse_flags flags =
|
||||||
|
fill_missing ? MESSAGE_ADDRESS_PARSE_FLAG_FILL_MISSING : 0;
|
||||||
|
@@ -28,11 +29,18 @@ test_parse_address(const char *input, bool fill_missing)
|
||||||
|
if there's any out-of-bounds access */
|
||||||
|
size_t input_len = strlen(input);
|
||||||
|
unsigned char *input_dup = i_memdup(input, input_len);
|
||||||
|
- const struct message_address *addr =
|
||||||
|
- message_address_parse(pool_datastack_create(),
|
||||||
|
- input_dup, input_len, UINT_MAX, flags);
|
||||||
|
+ message_address_parse_full(pool_datastack_create(),
|
||||||
|
+ input_dup, input_len, UINT_MAX, flags,
|
||||||
|
+ list_r);
|
||||||
|
i_free(input_dup);
|
||||||
|
- return addr;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static const struct message_address *
|
||||||
|
+test_parse_address(const char *input, bool fill_missing)
|
||||||
|
+{
|
||||||
|
+ struct message_address_list list;
|
||||||
|
+ test_parse_address_full(input, fill_missing, &list);
|
||||||
|
+ return list.head;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_message_address(void)
|
||||||
|
@@ -322,6 +330,33 @@ static void test_message_address(void)
|
||||||
|
test_end();
|
||||||
|
}
|
||||||
|
|
||||||
|
+static void test_message_address_list(void)
|
||||||
|
+{
|
||||||
|
+ test_begin("message address list");
|
||||||
|
+
|
||||||
|
+ const char *test_input =
|
||||||
|
+ "user1@example1.com, user2@example2.com, user3@example3.com";
|
||||||
|
+ const struct message_address wanted_addrs[] = {
|
||||||
|
+ { NULL, NULL, NULL, NULL, "user1", "example1.com", FALSE },
|
||||||
|
+ { NULL, NULL, NULL, NULL, "user2", "example2.com", FALSE },
|
||||||
|
+ { NULL, NULL, NULL, NULL, "user3", "example3.com", FALSE },
|
||||||
|
+ };
|
||||||
|
+
|
||||||
|
+ struct message_address_list list;
|
||||||
|
+ struct message_address *addr, *scanned_last_addr;
|
||||||
|
+ test_parse_address_full(test_input, FALSE, &list);
|
||||||
|
+ addr = list.head;
|
||||||
|
+ for (unsigned int i = 0; i < N_ELEMENTS(wanted_addrs); i++) {
|
||||||
|
+ test_assert_idx(cmp_addr(addr, &wanted_addrs[i]), i);
|
||||||
|
+ scanned_last_addr = addr;
|
||||||
|
+ addr = addr->next;
|
||||||
|
+ }
|
||||||
|
+ test_assert(list.tail == scanned_last_addr);
|
||||||
|
+ test_assert(addr == NULL);
|
||||||
|
+
|
||||||
|
+ test_end();
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
static void test_message_address_nuls(void)
|
||||||
|
{
|
||||||
|
const unsigned char input[] =
|
||||||
|
@@ -521,6 +556,7 @@ int main(void)
|
||||||
|
{
|
||||||
|
static void (*const test_functions[])(void) = {
|
||||||
|
test_message_address,
|
||||||
|
+ test_message_address_list,
|
||||||
|
test_message_address_nuls,
|
||||||
|
test_message_address_nuls_display_name,
|
||||||
|
test_message_address_non_strict_dots,
|
||||||
|
|
||||||
|
From 1481c04f02df7647f520df65d63df7626bf0ee32 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Timo Sirainen <timo.sirainen@open-xchange.com>
|
||||||
|
Date: Fri, 9 Feb 2024 00:57:12 +0200
|
||||||
|
Subject: [PATCH 6/6] lib-mail, lib-imap: Optimize parsing large number of
|
||||||
|
address headers
|
||||||
|
|
||||||
|
Every header was appended to a linked list by walking through the whole
|
||||||
|
list, causing excessive CPU usage when the list became large enough.
|
||||||
|
Fixed by changing struct message_part_envelope to use struct
|
||||||
|
message_address_list, which stores also linked list tail pointers. This
|
||||||
|
allows quickly appending to the end of the linked list.
|
||||||
|
---
|
||||||
|
src/lib-imap/imap-envelope.c | 27 ++++++++++-------------
|
||||||
|
src/lib-mail/message-part-data.c | 17 +++++++-------
|
||||||
|
src/lib-mail/message-part-data.h | 6 +++--
|
||||||
|
src/lib-storage/index/index-search-mime.c | 4 ++--
|
||||||
|
4 files changed, 27 insertions(+), 27 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/src/lib-imap/imap-envelope.c b/src/lib-imap/imap-envelope.c
|
||||||
|
index 1312eae2ff3..da3177025a5 100644
|
||||||
|
--- a/src/lib-imap/imap-envelope.c
|
||||||
|
+++ b/src/lib-imap/imap-envelope.c
|
||||||
|
@@ -67,17 +67,17 @@ void imap_envelope_write(struct message_part_envelope *data,
|
||||||
|
}
|
||||||
|
|
||||||
|
str_append_c(str, ' ');
|
||||||
|
- imap_write_address(str, data->from);
|
||||||
|
+ imap_write_address(str, data->from.head);
|
||||||
|
str_append_c(str, ' ');
|
||||||
|
- imap_write_address(str, NVL(data->sender, data->from));
|
||||||
|
+ imap_write_address(str, NVL(data->sender.head, data->from.head));
|
||||||
|
str_append_c(str, ' ');
|
||||||
|
- imap_write_address(str, NVL(data->reply_to, data->from));
|
||||||
|
+ imap_write_address(str, NVL(data->reply_to.head, data->from.head));
|
||||||
|
str_append_c(str, ' ');
|
||||||
|
- imap_write_address(str, data->to);
|
||||||
|
+ imap_write_address(str, data->to.head);
|
||||||
|
str_append_c(str, ' ');
|
||||||
|
- imap_write_address(str, data->cc);
|
||||||
|
+ imap_write_address(str, data->cc.head);
|
||||||
|
str_append_c(str, ' ');
|
||||||
|
- imap_write_address(str, data->bcc);
|
||||||
|
+ imap_write_address(str, data->bcc.head);
|
||||||
|
|
||||||
|
str_append_c(str, ' ');
|
||||||
|
imap_append_nstring_nolf(str, data->in_reply_to);
|
||||||
|
@@ -126,28 +126,25 @@ imap_envelope_parse_address(const struct imap_arg *arg,
|
||||||
|
|
||||||
|
static bool
|
||||||
|
imap_envelope_parse_addresses(const struct imap_arg *arg,
|
||||||
|
- pool_t pool, struct message_address **addrs_r)
|
||||||
|
+ pool_t pool, struct message_address_list *addrs_r)
|
||||||
|
{
|
||||||
|
- struct message_address *first, *last, *addr;
|
||||||
|
+ struct message_address *addr;
|
||||||
|
const struct imap_arg *list_args;
|
||||||
|
|
||||||
|
- if (arg->type == IMAP_ARG_NIL) {
|
||||||
|
- *addrs_r = NULL;
|
||||||
|
+ i_zero(addrs_r);
|
||||||
|
+ if (arg->type == IMAP_ARG_NIL)
|
||||||
|
return TRUE;
|
||||||
|
- }
|
||||||
|
|
||||||
|
if (!imap_arg_get_list(arg, &list_args))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
- first = last = addr = NULL;
|
||||||
|
+ addr = NULL;
|
||||||
|
for (; !IMAP_ARG_IS_EOL(list_args); list_args++) {
|
||||||
|
if (!imap_envelope_parse_address
|
||||||
|
(list_args, pool, &addr))
|
||||||
|
return FALSE;
|
||||||
|
- DLLIST2_APPEND(&first, &last, addr);
|
||||||
|
+ DLLIST2_APPEND(&addrs_r->head, &addrs_r->tail, addr);
|
||||||
|
}
|
||||||
|
-
|
||||||
|
- *addrs_r = first;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
diff --git a/src/lib-mail/message-part-data.c b/src/lib-mail/message-part-data.c
|
||||||
|
index a5771f87e2e..25019ab432d 100644
|
||||||
|
--- a/src/lib-mail/message-part-data.c
|
||||||
|
+++ b/src/lib-mail/message-part-data.c
|
||||||
|
@@ -4,6 +4,7 @@
|
||||||
|
#include "str.h"
|
||||||
|
#include "wildcard-match.h"
|
||||||
|
#include "array.h"
|
||||||
|
+#include "llist.h"
|
||||||
|
#include "rfc822-parser.h"
|
||||||
|
#include "rfc2231-parser.h"
|
||||||
|
#include "message-address.h"
|
||||||
|
@@ -176,7 +177,7 @@ void message_part_envelope_parse_from_header(pool_t pool,
|
||||||
|
{
|
||||||
|
struct message_part_envelope *d;
|
||||||
|
enum envelope_field field;
|
||||||
|
- struct message_address **addr_p, *addr;
|
||||||
|
+ struct message_address_list *addr_p, new_addr;
|
||||||
|
const char **str_p;
|
||||||
|
|
||||||
|
if (*data == NULL) {
|
||||||
|
@@ -234,18 +235,18 @@ void message_part_envelope_parse_from_header(pool_t pool,
|
||||||
|
}
|
||||||
|
|
||||||
|
if (addr_p != NULL) {
|
||||||
|
- addr = message_address_parse(pool, hdr->full_value,
|
||||||
|
- hdr->full_value_len,
|
||||||
|
- UINT_MAX,
|
||||||
|
- MESSAGE_ADDRESS_PARSE_FLAG_FILL_MISSING);
|
||||||
|
+ message_address_parse_full(pool, hdr->full_value,
|
||||||
|
+ hdr->full_value_len,
|
||||||
|
+ UINT_MAX,
|
||||||
|
+ MESSAGE_ADDRESS_PARSE_FLAG_FILL_MISSING,
|
||||||
|
+ &new_addr);
|
||||||
|
/* Merge multiple headers the same as if they were comma
|
||||||
|
separated in a single line. This is better from security
|
||||||
|
point of view, because attacker could intentionally write
|
||||||
|
addresses in a way that e.g. the first From header is
|
||||||
|
validated while MUA only shows the second From header. */
|
||||||
|
- while (*addr_p != NULL)
|
||||||
|
- addr_p = &(*addr_p)->next;
|
||||||
|
- *addr_p = addr;
|
||||||
|
+ DLLIST2_JOIN(&addr_p->head, &addr_p->tail,
|
||||||
|
+ &new_addr.head, &new_addr.tail);
|
||||||
|
} else if (str_p != NULL) {
|
||||||
|
*str_p = message_header_strdup(pool, hdr->full_value,
|
||||||
|
hdr->full_value_len);
|
||||||
|
diff --git a/src/lib-mail/message-part-data.h b/src/lib-mail/message-part-data.h
|
||||||
|
index 5ff9ffe1bc6..7ec878de68e 100644
|
||||||
|
--- a/src/lib-mail/message-part-data.h
|
||||||
|
+++ b/src/lib-mail/message-part-data.h
|
||||||
|
@@ -2,6 +2,7 @@
|
||||||
|
#define MESSAGE_PART_DATA_H
|
||||||
|
|
||||||
|
#include "message-part.h"
|
||||||
|
+#include "message-address.h"
|
||||||
|
|
||||||
|
#define MESSAGE_PART_DEFAULT_CHARSET "us-ascii"
|
||||||
|
|
||||||
|
@@ -14,8 +15,9 @@ struct message_part_param {
|
||||||
|
|
||||||
|
struct message_part_envelope {
|
||||||
|
const char *date, *subject;
|
||||||
|
- struct message_address *from, *sender, *reply_to;
|
||||||
|
- struct message_address *to, *cc, *bcc;
|
||||||
|
+
|
||||||
|
+ struct message_address_list from, sender, reply_to;
|
||||||
|
+ struct message_address_list to, cc, bcc;
|
||||||
|
|
||||||
|
const char *in_reply_to, *message_id;
|
||||||
|
};
|
||||||
|
diff --git a/src/lib-storage/index/index-search-mime.c b/src/lib-storage/index/index-search-mime.c
|
||||||
|
index da7e5e17092..3328ce98af1 100644
|
||||||
|
--- a/src/lib-storage/index/index-search-mime.c
|
||||||
|
+++ b/src/lib-storage/index/index-search-mime.c
|
||||||
|
@@ -205,7 +205,7 @@ seach_arg_mime_envelope_address_match(
|
||||||
|
enum mail_search_mime_arg_type type, const char *key,
|
||||||
|
const struct message_part_envelope *envelope)
|
||||||
|
{
|
||||||
|
- const struct message_address *addrs;
|
||||||
|
+ struct message_address_list addrs;
|
||||||
|
string_t *addrs_enc;
|
||||||
|
|
||||||
|
if (envelope == NULL)
|
||||||
|
@@ -239,7 +239,7 @@ seach_arg_mime_envelope_address_match(
|
||||||
|
probably be normalized directly in the struct message_address. */
|
||||||
|
|
||||||
|
addrs_enc = t_str_new(128);
|
||||||
|
- message_address_write(addrs_enc, addrs);
|
||||||
|
+ message_address_write(addrs_enc, addrs.head);
|
||||||
|
return (strstr(str_c(addrs_enc), key) != NULL ? 1 : 0);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,493 @@
|
|||||||
|
From f020e139c519121d9630a966310ea8e100ee33b7 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Marco Bettini <marco.bettini@open-xchange.com>
|
||||||
|
Date: Fri, 12 Apr 2024 15:06:43 +0000
|
||||||
|
Subject: [PATCH 1/2] lib-mail: message-header-parser - Limit header block to
|
||||||
|
10MB by default
|
||||||
|
|
||||||
|
---
|
||||||
|
src/lib-mail/message-header-parser.c | 48 ++++++++++++----
|
||||||
|
src/lib-mail/message-header-parser.h | 10 ++++
|
||||||
|
src/lib-mail/test-message-header-parser.c | 67 +++++++++++++++++++++++
|
||||||
|
3 files changed, 114 insertions(+), 11 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/src/lib-mail/message-header-parser.c b/src/lib-mail/message-header-parser.c
|
||||||
|
index c5026f1bb7..5e020bbeb3 100644
|
||||||
|
--- a/src/lib-mail/message-header-parser.c
|
||||||
|
+++ b/src/lib-mail/message-header-parser.c
|
||||||
|
@@ -21,6 +21,9 @@ struct message_header_parser_ctx {
|
||||||
|
string_t *name;
|
||||||
|
buffer_t *value_buf;
|
||||||
|
|
||||||
|
+ size_t header_block_max_size;
|
||||||
|
+ size_t header_block_total_size;
|
||||||
|
+
|
||||||
|
enum message_header_parser_flags flags;
|
||||||
|
bool skip_line:1;
|
||||||
|
bool has_nuls:1;
|
||||||
|
@@ -38,6 +41,7 @@ message_parse_header_init(struct istream *input, struct message_size *hdr_size,
|
||||||
|
ctx->name = str_new(default_pool, 128);
|
||||||
|
ctx->flags = flags;
|
||||||
|
ctx->value_buf = buffer_create_dynamic(default_pool, 4096);
|
||||||
|
+ ctx->header_block_max_size = MESSAGE_HEADER_BLOCK_DEFAULT_MAX_SIZE;
|
||||||
|
i_stream_ref(input);
|
||||||
|
|
||||||
|
if (hdr_size != NULL)
|
||||||
|
@@ -45,6 +49,21 @@ message_parse_header_init(struct istream *input, struct message_size *hdr_size,
|
||||||
|
return ctx;
|
||||||
|
}
|
||||||
|
|
||||||
|
+void
|
||||||
|
+message_parse_header_set_limit(struct message_header_parser_ctx *parser,
|
||||||
|
+ size_t header_block_max_size)
|
||||||
|
+{
|
||||||
|
+ parser->header_block_max_size = header_block_max_size;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+void
|
||||||
|
+message_parse_header_lower_limit(struct message_header_parser_ctx *parser,
|
||||||
|
+ size_t header_block_max_size)
|
||||||
|
+{
|
||||||
|
+ if (header_block_max_size < parser->header_block_max_size)
|
||||||
|
+ message_parse_header_set_limit(parser, header_block_max_size);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
void message_parse_header_deinit(struct message_header_parser_ctx **_ctx)
|
||||||
|
{
|
||||||
|
struct message_header_parser_ctx *ctx = *_ctx;
|
||||||
|
@@ -77,6 +96,7 @@ int message_parse_header_next(struct message_header_parser_ctx *ctx,
|
||||||
|
/* new header line */
|
||||||
|
line->name_offset = ctx->input->v_offset;
|
||||||
|
colon_pos = UINT_MAX;
|
||||||
|
+ ctx->header_block_total_size += ctx->value_buf->used;
|
||||||
|
buffer_set_used_size(ctx->value_buf, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -342,33 +362,39 @@ int message_parse_header_next(struct message_header_parser_ctx *ctx,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
+ line->value_len = I_MIN(line->value_len, ctx->header_block_max_size);
|
||||||
|
+ size_t line_value_size = line->value_len;
|
||||||
|
+ size_t header_total_used = ctx->header_block_total_size + ctx->value_buf->used;
|
||||||
|
+ size_t line_available = ctx->header_block_max_size <= header_total_used ? 0 :
|
||||||
|
+ ctx->header_block_max_size - header_total_used;
|
||||||
|
+ line_value_size = I_MIN(line_value_size, line_available);
|
||||||
|
+
|
||||||
|
if (!line->continued) {
|
||||||
|
/* first header line. make a copy of the line since we can't
|
||||||
|
really trust input stream not to lose it. */
|
||||||
|
- buffer_append(ctx->value_buf, line->value, line->value_len);
|
||||||
|
+ buffer_append(ctx->value_buf, line->value, line_value_size);
|
||||||
|
line->value = line->full_value = ctx->value_buf->data;
|
||||||
|
- line->full_value_len = line->value_len;
|
||||||
|
+ line->full_value_len = line->value_len = line_value_size;
|
||||||
|
} else if (line->use_full_value) {
|
||||||
|
/* continue saving the full value. */
|
||||||
|
if (last_no_newline) {
|
||||||
|
/* line is longer than fit into our buffer, so we
|
||||||
|
were forced to break it into multiple
|
||||||
|
message_header_lines */
|
||||||
|
- } else {
|
||||||
|
- if (last_crlf)
|
||||||
|
+ } else if (line_value_size > 1) {
|
||||||
|
+ if (last_crlf && line_value_size > 2)
|
||||||
|
buffer_append_c(ctx->value_buf, '\r');
|
||||||
|
buffer_append_c(ctx->value_buf, '\n');
|
||||||
|
}
|
||||||
|
if ((ctx->flags & MESSAGE_HEADER_PARSER_FLAG_CLEAN_ONELINE) != 0 &&
|
||||||
|
line->value_len > 0 && line->value[0] != ' ' &&
|
||||||
|
- IS_LWSP(line->value[0])) {
|
||||||
|
+ IS_LWSP(line->value[0]) &&
|
||||||
|
+ line_value_size > 0) {
|
||||||
|
buffer_append_c(ctx->value_buf, ' ');
|
||||||
|
- buffer_append(ctx->value_buf,
|
||||||
|
- line->value + 1, line->value_len - 1);
|
||||||
|
- } else {
|
||||||
|
- buffer_append(ctx->value_buf,
|
||||||
|
- line->value, line->value_len);
|
||||||
|
- }
|
||||||
|
+ buffer_append(ctx->value_buf, line->value + 1, line_value_size - 1);
|
||||||
|
+ } else
|
||||||
|
+ buffer_append(ctx->value_buf, line->value, line_value_size);
|
||||||
|
+
|
||||||
|
line->full_value = ctx->value_buf->data;
|
||||||
|
line->full_value_len = ctx->value_buf->used;
|
||||||
|
} else {
|
||||||
|
diff --git a/src/lib-mail/message-header-parser.h b/src/lib-mail/message-header-parser.h
|
||||||
|
index ce0825c8e5..43cf95e56a 100644
|
||||||
|
--- a/src/lib-mail/message-header-parser.h
|
||||||
|
+++ b/src/lib-mail/message-header-parser.h
|
||||||
|
@@ -1,6 +1,9 @@
|
||||||
|
#ifndef MESSAGE_HEADER_PARSER_H
|
||||||
|
#define MESSAGE_HEADER_PARSER_H
|
||||||
|
|
||||||
|
+/* This can be overridden by message_parse_header_set_limit() */
|
||||||
|
+#define MESSAGE_HEADER_BLOCK_DEFAULT_MAX_SIZE ((size_t) 10 * 1024*1024)
|
||||||
|
+
|
||||||
|
#define IS_LWSP(c) \
|
||||||
|
((c) == ' ' || (c) == '\t')
|
||||||
|
|
||||||
|
@@ -48,6 +51,13 @@ message_parse_header_init(struct istream *input, struct message_size *hdr_size,
|
||||||
|
enum message_header_parser_flags flags) ATTR_NULL(2);
|
||||||
|
void message_parse_header_deinit(struct message_header_parser_ctx **ctx);
|
||||||
|
|
||||||
|
+void
|
||||||
|
+message_parse_header_set_limit(struct message_header_parser_ctx *parser,
|
||||||
|
+ size_t header_block_max_size);
|
||||||
|
+void
|
||||||
|
+message_parse_header_lower_limit(struct message_header_parser_ctx *parser,
|
||||||
|
+ size_t header_block_max_size);
|
||||||
|
+
|
||||||
|
/* Read and return next header line. Returns 1 if header is returned, 0 if
|
||||||
|
input stream is non-blocking and more data needs to be read, -1 when all is
|
||||||
|
done or error occurred (see stream's error status). */
|
||||||
|
diff --git a/src/lib-mail/test-message-header-parser.c b/src/lib-mail/test-message-header-parser.c
|
||||||
|
index 700d3413f1..93d8842002 100644
|
||||||
|
--- a/src/lib-mail/test-message-header-parser.c
|
||||||
|
+++ b/src/lib-mail/test-message-header-parser.c
|
||||||
|
@@ -463,6 +463,71 @@ static void test_message_header_parser_extra_crlf_in_name(void)
|
||||||
|
test_end();
|
||||||
|
}
|
||||||
|
|
||||||
|
+#define assert_parsed_field(line, expected, actual, len) STMT_START { \
|
||||||
|
+ test_assert_idx(memcmp(expected, actual, strlen(expected)) == 0, line); \
|
||||||
|
+ test_assert_cmp_idx(strlen(expected), ==, len, line); \
|
||||||
|
+} STMT_END
|
||||||
|
+
|
||||||
|
+/* NOTE: implicit variables: (parser, hdr) */
|
||||||
|
+#define assert_parse_line(line, exp_name, exp_value, exp_full) STMT_START { \
|
||||||
|
+ test_assert_idx(message_parse_header_next(parser, &hdr) > 0, line); \
|
||||||
|
+ assert_parsed_field(line, exp_name, hdr->name, hdr->name_len); \
|
||||||
|
+ assert_parsed_field(line, exp_value, hdr->value, hdr->value_len); \
|
||||||
|
+ assert_parsed_field(line, exp_full, hdr->full_value, hdr->full_value_len); \
|
||||||
|
+ if (hdr->continues) hdr->use_full_value = TRUE; \
|
||||||
|
+} STMT_END
|
||||||
|
+
|
||||||
|
+static const unsigned char test_message_header_truncation_input[] =
|
||||||
|
+ /*01*/ "header1: this is short\n"
|
||||||
|
+ /*02*/ "header2: this is multiline\n"
|
||||||
|
+ /*03*/ " and long 343638404244464850525456586062\n"
|
||||||
|
+ /*04*/ " 64666870727476788082848688909294969800\n"
|
||||||
|
+ /*05*/ " 02040608101214161820222426283032343638\n"
|
||||||
|
+ /*06*/ "header3: I should not appear at all\n"
|
||||||
|
+ /*07*/ "\n";
|
||||||
|
+
|
||||||
|
+static void test_message_header_truncation_clean_oneline(void)
|
||||||
|
+{
|
||||||
|
+ test_begin("message header parser truncate + CLEAN_ONELINE flag");
|
||||||
|
+ struct message_header_line *hdr = NULL;
|
||||||
|
+ struct istream *input = test_istream_create_data(test_message_header_truncation_input, sizeof(test_message_header_truncation_input));
|
||||||
|
+ struct message_header_parser_ctx *parser = message_parse_header_init(input, NULL, MESSAGE_HEADER_PARSER_FLAG_CLEAN_ONELINE);
|
||||||
|
+ message_parse_header_set_limit(parser, 96);
|
||||||
|
+
|
||||||
|
+ assert_parse_line( 1, "header1", "this is short", "this is short");
|
||||||
|
+ assert_parse_line( 2, "header2", "this is multiline", "this is multiline");
|
||||||
|
+ assert_parse_line( 3, "header2", " and long 343638404244464850525456586062", "this is multiline and long 343638404244464850525456586062");
|
||||||
|
+ assert_parse_line( 4, "header2", " 64666870727476788082848688909294969800", "this is multiline and long 343638404244464850525456586062 6466687072747678808284868");
|
||||||
|
+ assert_parse_line( 5, "header2", " 02040608101214161820222426283032343638", "this is multiline and long 343638404244464850525456586062 6466687072747678808284868");
|
||||||
|
+ assert_parse_line( 6, "header3", "", "");
|
||||||
|
+ test_assert(message_parse_header_next(parser, &hdr) > 0 && hdr->eoh);
|
||||||
|
+
|
||||||
|
+ message_parse_header_deinit(&parser);
|
||||||
|
+ i_stream_unref(&input);
|
||||||
|
+ test_end();
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static void test_message_header_truncation_flag0(void)
|
||||||
|
+{
|
||||||
|
+ test_begin("message header parser truncate + NO flags");
|
||||||
|
+ struct message_header_line *hdr = NULL;
|
||||||
|
+ struct istream *input = test_istream_create_data(test_message_header_truncation_input, sizeof(test_message_header_truncation_input));
|
||||||
|
+ struct message_header_parser_ctx *parser = message_parse_header_init(input, NULL, 0);
|
||||||
|
+ message_parse_header_set_limit(parser, 96);
|
||||||
|
+
|
||||||
|
+ assert_parse_line( 1, "header1", "this is short", "this is short");
|
||||||
|
+ assert_parse_line( 2, "header2", "this is multiline", "this is multiline");
|
||||||
|
+ assert_parse_line( 3, "header2", " and long 343638404244464850525456586062", "this is multiline\n and long 343638404244464850525456586062");
|
||||||
|
+ assert_parse_line( 4, "header2", " 64666870727476788082848688909294969800", "this is multiline\n and long 343638404244464850525456586062\n 646668707274767880828486");
|
||||||
|
+ assert_parse_line( 5, "header2", " 02040608101214161820222426283032343638", "this is multiline\n and long 343638404244464850525456586062\n 646668707274767880828486");
|
||||||
|
+ assert_parse_line( 6, "header3", "", "");
|
||||||
|
+ test_assert(message_parse_header_next(parser, &hdr) > 0 && hdr->eoh);
|
||||||
|
+
|
||||||
|
+ message_parse_header_deinit(&parser);
|
||||||
|
+ i_stream_unref(&input);
|
||||||
|
+ test_end();
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
static void (*const test_functions[])(void) = {
|
||||||
|
@@ -473,6 +538,8 @@ int main(void)
|
||||||
|
test_message_header_parser_no_eoh,
|
||||||
|
test_message_header_parser_nul,
|
||||||
|
test_message_header_parser_extra_crlf_in_name,
|
||||||
|
+ test_message_header_truncation_flag0,
|
||||||
|
+ test_message_header_truncation_clean_oneline,
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
return test_run(test_functions);
|
||||||
|
|
||||||
|
From ce88c33abc37e408592eff70aeefa28f803effb9 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Marco Bettini <marco.bettini@open-xchange.com>
|
||||||
|
Date: Wed, 24 Apr 2024 10:45:46 +0000
|
||||||
|
Subject: [PATCH 2/2] lib-mail: message-parser - Limit headers total count to
|
||||||
|
50MB by default
|
||||||
|
|
||||||
|
(including top headers and all mime-sections headers)
|
||||||
|
---
|
||||||
|
src/lib-mail/message-parser-private.h | 2 +
|
||||||
|
src/lib-mail/message-parser.c | 15 +++
|
||||||
|
src/lib-mail/message-parser.h | 6 +
|
||||||
|
src/lib-mail/test-message-parser.c | 154 ++++++++++++++++++++++++++
|
||||||
|
4 files changed, 177 insertions(+)
|
||||||
|
|
||||||
|
diff --git a/src/lib-mail/message-parser-private.h b/src/lib-mail/message-parser-private.h
|
||||||
|
index 41c32daf3a..8b362a9e71 100644
|
||||||
|
--- a/src/lib-mail/message-parser-private.h
|
||||||
|
+++ b/src/lib-mail/message-parser-private.h
|
||||||
|
@@ -30,6 +30,8 @@ struct message_parser_ctx {
|
||||||
|
enum message_parser_flags flags;
|
||||||
|
unsigned int max_nested_mime_parts;
|
||||||
|
unsigned int max_total_mime_parts;
|
||||||
|
+ size_t all_headers_max_size;
|
||||||
|
+ size_t all_headers_total_size;
|
||||||
|
|
||||||
|
char *last_boundary;
|
||||||
|
struct message_boundary *boundaries;
|
||||||
|
diff --git a/src/lib-mail/message-parser.c b/src/lib-mail/message-parser.c
|
||||||
|
index 9a9c9a3515..c7e3b1e96a 100644
|
||||||
|
--- a/src/lib-mail/message-parser.c
|
||||||
|
+++ b/src/lib-mail/message-parser.c
|
||||||
|
@@ -617,7 +617,18 @@ static int parse_next_header(struct message_parser_ctx *ctx,
|
||||||
|
}
|
||||||
|
if (ret < 0) {
|
||||||
|
/* no boundary */
|
||||||
|
+ size_t headers_available =
|
||||||
|
+ ctx->all_headers_max_size > ctx->all_headers_total_size ?
|
||||||
|
+ ctx->all_headers_max_size - ctx->all_headers_total_size : 0;
|
||||||
|
+ message_parse_header_lower_limit(ctx->hdr_parser_ctx, headers_available);
|
||||||
|
ret = message_parse_header_next(ctx->hdr_parser_ctx, &hdr);
|
||||||
|
+ if (ret > 0) {
|
||||||
|
+ if (!hdr->continues) {
|
||||||
|
+ ctx->all_headers_total_size += hdr->name_len;
|
||||||
|
+ ctx->all_headers_total_size += hdr->middle_len;
|
||||||
|
+ }
|
||||||
|
+ ctx->all_headers_total_size += hdr->value_len;
|
||||||
|
+ }
|
||||||
|
if (ret == 0 || (ret < 0 && ctx->input->stream_errno != 0)) {
|
||||||
|
ctx->want_count = i_stream_get_data_size(ctx->input) + 1;
|
||||||
|
return ret;
|
||||||
|
@@ -762,6 +773,9 @@ message_parser_init_int(struct istream *input,
|
||||||
|
ctx->max_total_mime_parts = set->max_total_mime_parts != 0 ?
|
||||||
|
set->max_total_mime_parts :
|
||||||
|
MESSAGE_PARSER_DEFAULT_MAX_TOTAL_MIME_PARTS;
|
||||||
|
+ ctx->all_headers_max_size = set->all_headers_max_size != 0 ?
|
||||||
|
+ set->all_headers_max_size :
|
||||||
|
+ MESSAGE_PARSER_DEFAULT_ALL_HEADERS_MAX_SIZE;
|
||||||
|
ctx->input = input;
|
||||||
|
i_stream_ref(input);
|
||||||
|
return ctx;
|
||||||
|
@@ -779,6 +793,7 @@ message_parser_init(pool_t part_pool, struct istream *input,
|
||||||
|
ctx->next_part = &ctx->part->children;
|
||||||
|
ctx->parse_next_block = parse_next_header_init;
|
||||||
|
ctx->total_parts_count = 1;
|
||||||
|
+ ctx->all_headers_total_size = 0;
|
||||||
|
i_array_init(&ctx->next_part_stack, 4);
|
||||||
|
return ctx;
|
||||||
|
}
|
||||||
|
diff --git a/src/lib-mail/message-parser.h b/src/lib-mail/message-parser.h
|
||||||
|
index f19e526284..8d70d73f05 100644
|
||||||
|
--- a/src/lib-mail/message-parser.h
|
||||||
|
+++ b/src/lib-mail/message-parser.h
|
||||||
|
@@ -19,6 +19,7 @@ enum message_parser_flags {
|
||||||
|
|
||||||
|
#define MESSAGE_PARSER_DEFAULT_MAX_NESTED_MIME_PARTS 100
|
||||||
|
#define MESSAGE_PARSER_DEFAULT_MAX_TOTAL_MIME_PARTS 10000
|
||||||
|
+#define MESSAGE_PARSER_DEFAULT_ALL_HEADERS_MAX_SIZE ((size_t) 50 * 1024*1024)
|
||||||
|
|
||||||
|
struct message_parser_settings {
|
||||||
|
enum message_header_parser_flags hdr_flags;
|
||||||
|
@@ -30,6 +31,11 @@ struct message_parser_settings {
|
||||||
|
/* Maximum MIME parts in total.
|
||||||
|
0 = MESSAGE_PARSER_DEFAULT_MAX_TOTAL_MIME_PARTS. */
|
||||||
|
unsigned int max_total_mime_parts;
|
||||||
|
+
|
||||||
|
+ /* Maximum bytes fore headers in top header plus all
|
||||||
|
+ MIME sections headers
|
||||||
|
+ 0 = MESSAGE_PARSER_DEFAULT_ALL_HEADERS_MAX_SIZE */
|
||||||
|
+ size_t all_headers_max_size;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct message_parser_ctx;
|
||||||
|
diff --git a/src/lib-mail/test-message-parser.c b/src/lib-mail/test-message-parser.c
|
||||||
|
index 663bfe8c5a..b6bada2303 100644
|
||||||
|
--- a/src/lib-mail/test-message-parser.c
|
||||||
|
+++ b/src/lib-mail/test-message-parser.c
|
||||||
|
@@ -1369,6 +1369,158 @@ static const char input_msg[] =
|
||||||
|
test_end();
|
||||||
|
}
|
||||||
|
|
||||||
|
+#define test_assert_virtual_size(part) \
|
||||||
|
+ test_assert((part).virtual_size == (part).lines + (part).physical_size)
|
||||||
|
+
|
||||||
|
+#define test_assert_part(part, flags_, children, h_lines, h_size, b_lines, b_size ) \
|
||||||
|
+STMT_START { \
|
||||||
|
+ test_assert((part)->flags == (flags_)); \
|
||||||
|
+ test_assert((part)->children_count == children); \
|
||||||
|
+ test_assert((part)->header_size.lines == h_lines); \
|
||||||
|
+ test_assert((part)->header_size.physical_size == h_size); \
|
||||||
|
+ test_assert((part)->body_size.lines == b_lines); \
|
||||||
|
+ test_assert((part)->body_size.physical_size == b_size); \
|
||||||
|
+ test_assert_virtual_size((part)->header_size); \
|
||||||
|
+ test_assert_virtual_size((part)->body_size); \
|
||||||
|
+} STMT_END
|
||||||
|
+
|
||||||
|
+static const enum message_part_flags FLAGS_MULTIPART =
|
||||||
|
+ MESSAGE_PART_FLAG_IS_MIME | MESSAGE_PART_FLAG_MULTIPART;
|
||||||
|
+static const enum message_part_flags FLAGS_RFC822 =
|
||||||
|
+ MESSAGE_PART_FLAG_IS_MIME | MESSAGE_PART_FLAG_MESSAGE_RFC822;
|
||||||
|
+static const enum message_part_flags FLAGS_TEXT =
|
||||||
|
+ MESSAGE_PART_FLAG_IS_MIME | MESSAGE_PART_FLAG_TEXT;
|
||||||
|
+
|
||||||
|
+static const char too_many_header_bytes_input_msg[] =
|
||||||
|
+ "Content-Type: multipart/mixed; boundary=\"1\"\n\n"
|
||||||
|
+ "--1\n"
|
||||||
|
+ "Content-Type: multipart/mixed; boundary=\"2\"\n\n"
|
||||||
|
+ "--2\n"
|
||||||
|
+ "Content-Type: message/rfc822\n\n"
|
||||||
|
+ "Content-Type: text/plain\n\n1-rfc822\n"
|
||||||
|
+ "--2\n"
|
||||||
|
+ "Content-Type: message/rfc822\n\n"
|
||||||
|
+ "Content-Type: text/plain\n\n2-rfc822\n"
|
||||||
|
+ "--1\n"
|
||||||
|
+ "Content-Type: message/rfc822\n\n"
|
||||||
|
+ "Content-Type: text/plain\n\n3-rfc822\n";
|
||||||
|
+
|
||||||
|
+static void test_message_parser_too_many_header_bytes_run(
|
||||||
|
+ const struct message_parser_settings *parser_set,
|
||||||
|
+ pool_t *pool_r, struct istream **input_r,
|
||||||
|
+ struct message_part **parts_r)
|
||||||
|
+{
|
||||||
|
+ *pool_r = pool_alloconly_create("message parser", 10240);
|
||||||
|
+ *input_r = test_istream_create(too_many_header_bytes_input_msg);
|
||||||
|
+ struct message_parser_ctx *parser = message_parser_init(*pool_r, *input_r, parser_set);
|
||||||
|
+
|
||||||
|
+ int ret;
|
||||||
|
+ struct message_block block ATTR_UNUSED;
|
||||||
|
+ while ((ret = message_parser_parse_next_block(parser, &block)) > 0);
|
||||||
|
+ test_assert(ret < 0);
|
||||||
|
+
|
||||||
|
+ message_parser_deinit(&parser, parts_r);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static void test_message_parser_too_many_header_bytes_default(void)
|
||||||
|
+{
|
||||||
|
+ test_begin("message parser too many header bytes default");
|
||||||
|
+
|
||||||
|
+ pool_t pool;
|
||||||
|
+ struct istream *input;
|
||||||
|
+ struct message_part *part_root;
|
||||||
|
+ const struct message_parser_settings parser_set = { .all_headers_max_size = 0 };
|
||||||
|
+
|
||||||
|
+ test_message_parser_too_many_header_bytes_run(&parser_set, &pool, &input, &part_root);
|
||||||
|
+
|
||||||
|
+ // test_assert_part(part, flags_, children, h_lines, h_size, b_lines, b_size )
|
||||||
|
+
|
||||||
|
+ test_assert_part(part_root, FLAGS_MULTIPART, 7, 2, 45, 21, 256);
|
||||||
|
+ test_assert(part_root->parent == NULL);
|
||||||
|
+
|
||||||
|
+ struct message_part *part_1 = part_root->children;
|
||||||
|
+ test_assert_part(part_1, FLAGS_MULTIPART, 4, 2, 45, 11, 137);
|
||||||
|
+
|
||||||
|
+ struct message_part *part_1_1 = part_1->children;
|
||||||
|
+ test_assert_part(part_1_1, FLAGS_RFC822, 1, 2, 30, 2, 34);
|
||||||
|
+
|
||||||
|
+ struct message_part *part_1_1_1 = part_1_1->children;
|
||||||
|
+ test_assert_part(part_1_1_1, FLAGS_TEXT, 0, 2, 26, 0, 8);
|
||||||
|
+
|
||||||
|
+ test_assert(part_1_1_1->next == NULL);
|
||||||
|
+
|
||||||
|
+ struct message_part *part_1_2 = part_1_1->next;
|
||||||
|
+ test_assert_part(part_1_2, FLAGS_RFC822, 1, 2, 30, 2, 34);
|
||||||
|
+
|
||||||
|
+ struct message_part *part_1_2_1 = part_1_2->children;
|
||||||
|
+ test_assert_part(part_1_2_1, FLAGS_TEXT, 0, 2, 26, 0, 8);
|
||||||
|
+
|
||||||
|
+ test_assert(part_1_2_1->next == NULL);
|
||||||
|
+
|
||||||
|
+ test_assert(part_1_2->next == NULL);
|
||||||
|
+
|
||||||
|
+ struct message_part *part_2 = part_1->next;
|
||||||
|
+ test_assert_part(part_2, FLAGS_RFC822, 1, 2, 30, 3, 35);
|
||||||
|
+
|
||||||
|
+ struct message_part *part_2_1 = part_2->children;
|
||||||
|
+ test_assert_part(part_2_1, FLAGS_TEXT, 0, 2, 26, 1, 9);
|
||||||
|
+ test_assert(part_2_1->next == NULL);
|
||||||
|
+
|
||||||
|
+ test_assert(part_2->next == NULL);
|
||||||
|
+
|
||||||
|
+ test_assert(part_root->next == NULL);
|
||||||
|
+
|
||||||
|
+ test_parsed_parts(input, part_root);
|
||||||
|
+ i_stream_unref(&input);
|
||||||
|
+ pool_unref(&pool);
|
||||||
|
+ test_end();
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static void test_message_parser_too_many_header_bytes_100(void)
|
||||||
|
+{
|
||||||
|
+ test_begin("message parser too many header bytes 100");
|
||||||
|
+
|
||||||
|
+ pool_t pool;
|
||||||
|
+ struct istream *input;
|
||||||
|
+ struct message_part *part_root;
|
||||||
|
+ const struct message_parser_settings parser_set = { .all_headers_max_size = 100 };
|
||||||
|
+
|
||||||
|
+ test_message_parser_too_many_header_bytes_run(&parser_set, &pool, &input, &part_root);
|
||||||
|
+
|
||||||
|
+ // test_assert_part(part, flags_, children, h_lines, h_size, b_lines, b_size )
|
||||||
|
+
|
||||||
|
+ test_assert_part(part_root, FLAGS_MULTIPART, 5, 2, 45, 21, 256);
|
||||||
|
+ test_assert(part_root->parent == NULL);
|
||||||
|
+
|
||||||
|
+ struct message_part *part_1 = part_root->children;
|
||||||
|
+ test_assert_part(part_1, FLAGS_MULTIPART, 3, 2, 45, 11, 137);
|
||||||
|
+
|
||||||
|
+ struct message_part *part_1_1 = part_1->children;
|
||||||
|
+ test_assert_part(part_1_1, FLAGS_RFC822, 1, 2, 30, 2, 34);
|
||||||
|
+
|
||||||
|
+ struct message_part *part_1_1_1 = part_1_1->children;
|
||||||
|
+ test_assert_part(part_1_1_1, MESSAGE_PART_FLAG_IS_MIME, 0, 2, 26, 0, 8);
|
||||||
|
+
|
||||||
|
+ test_assert(part_1_1_1->next == NULL);
|
||||||
|
+
|
||||||
|
+ struct message_part *part_1_2 = part_1_1->next;
|
||||||
|
+ test_assert_part(part_1_2, MESSAGE_PART_FLAG_IS_MIME, 0, 2, 30, 2, 34);
|
||||||
|
+
|
||||||
|
+ test_assert(part_1_2->next == NULL);
|
||||||
|
+
|
||||||
|
+ struct message_part *part_2 = part_1->next;
|
||||||
|
+ test_assert_part(part_2, MESSAGE_PART_FLAG_IS_MIME, 0, 2, 30, 3, 35);
|
||||||
|
+
|
||||||
|
+ test_assert(part_2->next == NULL);
|
||||||
|
+
|
||||||
|
+ test_assert(part_root->next == NULL);
|
||||||
|
+
|
||||||
|
+ test_parsed_parts(input, part_root);
|
||||||
|
+ i_stream_unref(&input);
|
||||||
|
+ pool_unref(&pool);
|
||||||
|
+ test_end();
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
static void (*const test_functions[])(void) = {
|
||||||
|
@@ -1392,6 +1544,8 @@ int main(void)
|
||||||
|
test_message_parser_mime_part_limit_rfc822,
|
||||||
|
test_message_parser_mime_version,
|
||||||
|
test_message_parser_mime_version_missing,
|
||||||
|
+ test_message_parser_too_many_header_bytes_default,
|
||||||
|
+ test_message_parser_too_many_header_bytes_100,
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
return test_run(test_functions);
|
@ -0,0 +1,813 @@
|
|||||||
|
diff -up dovecot-2.3.18/src/auth/auth-token.c.opensslhmac dovecot-2.3.18/src/auth/auth-token.c
|
||||||
|
--- dovecot-2.3.18/src/auth/auth-token.c.opensslhmac 2022-02-02 12:42:23.000000000 +0100
|
||||||
|
+++ dovecot-2.3.18/src/auth/auth-token.c 2022-02-09 09:27:15.887883359 +0100
|
||||||
|
@@ -161,17 +161,17 @@ void auth_token_deinit(void)
|
||||||
|
const char *auth_token_get(const char *service, const char *session_pid,
|
||||||
|
const char *username, const char *session_id)
|
||||||
|
{
|
||||||
|
- struct hmac_context ctx;
|
||||||
|
+ struct openssl_hmac_context ctx;
|
||||||
|
unsigned char result[SHA1_RESULTLEN];
|
||||||
|
|
||||||
|
- hmac_init(&ctx, (const unsigned char*)username, strlen(username),
|
||||||
|
+ openssl_hmac_init(&ctx, (const unsigned char*)username, strlen(username),
|
||||||
|
&hash_method_sha1);
|
||||||
|
- hmac_update(&ctx, session_pid, strlen(session_pid));
|
||||||
|
+ openssl_hmac_update(&ctx, session_pid, strlen(session_pid));
|
||||||
|
if (session_id != NULL && *session_id != '\0')
|
||||||
|
- hmac_update(&ctx, session_id, strlen(session_id));
|
||||||
|
- hmac_update(&ctx, service, strlen(service));
|
||||||
|
- hmac_update(&ctx, auth_token_secret, sizeof(auth_token_secret));
|
||||||
|
- hmac_final(&ctx, result);
|
||||||
|
+ openssl_hmac_update(&ctx, session_id, strlen(session_id));
|
||||||
|
+ openssl_hmac_update(&ctx, service, strlen(service));
|
||||||
|
+ openssl_hmac_update(&ctx, auth_token_secret, sizeof(auth_token_secret));
|
||||||
|
+ openssl_hmac_final(&ctx, result);
|
||||||
|
|
||||||
|
return binary_to_hex(result, sizeof(result));
|
||||||
|
}
|
||||||
|
diff -up dovecot-2.3.18/src/auth/mech-cram-md5.c.opensslhmac dovecot-2.3.18/src/auth/mech-cram-md5.c
|
||||||
|
--- dovecot-2.3.18/src/auth/mech-cram-md5.c.opensslhmac 2022-02-02 12:42:23.000000000 +0100
|
||||||
|
+++ dovecot-2.3.18/src/auth/mech-cram-md5.c 2022-02-09 09:27:15.887883359 +0100
|
||||||
|
@@ -51,7 +51,7 @@ static bool verify_credentials(struct cr
|
||||||
|
{
|
||||||
|
|
||||||
|
unsigned char digest[MD5_RESULTLEN];
|
||||||
|
- struct hmac_context ctx;
|
||||||
|
+ struct orig_hmac_context ctx;
|
||||||
|
const char *response_hex;
|
||||||
|
|
||||||
|
if (size != CRAM_MD5_CONTEXTLEN) {
|
||||||
|
@@ -60,10 +60,10 @@ static bool verify_credentials(struct cr
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
- hmac_init(&ctx, NULL, 0, &hash_method_md5);
|
||||||
|
+ orig_hmac_init(&ctx, NULL, 0, &hash_method_md5);
|
||||||
|
hmac_md5_set_cram_context(&ctx, credentials);
|
||||||
|
- hmac_update(&ctx, request->challenge, strlen(request->challenge));
|
||||||
|
- hmac_final(&ctx, digest);
|
||||||
|
+ orig_hmac_update(&ctx, request->challenge, strlen(request->challenge));
|
||||||
|
+ orig_hmac_final(&ctx, digest);
|
||||||
|
|
||||||
|
response_hex = binary_to_hex(digest, sizeof(digest));
|
||||||
|
|
||||||
|
diff -up dovecot-2.3.18/src/auth/mech-scram.c.opensslhmac dovecot-2.3.18/src/auth/mech-scram.c
|
||||||
|
--- dovecot-2.3.18/src/auth/mech-scram.c.opensslhmac 2022-02-02 12:42:23.000000000 +0100
|
||||||
|
+++ dovecot-2.3.18/src/auth/mech-scram.c 2022-02-09 09:31:50.927146858 +0100
|
||||||
|
@@ -93,7 +93,7 @@ get_scram_server_first(struct scram_auth
|
||||||
|
static const char *get_scram_server_final(struct scram_auth_request *request)
|
||||||
|
{
|
||||||
|
const struct hash_method *hmethod = request->hash_method;
|
||||||
|
- struct hmac_context ctx;
|
||||||
|
+ struct openssl_hmac_context ctx;
|
||||||
|
const char *auth_message;
|
||||||
|
unsigned char server_signature[hmethod->digest_size];
|
||||||
|
string_t *str;
|
||||||
|
@@ -109,9 +109,9 @@ static const char *get_scram_server_fina
|
||||||
|
request->server_first_message, ",",
|
||||||
|
request->client_final_message_without_proof, NULL);
|
||||||
|
|
||||||
|
- hmac_init(&ctx, request->server_key, hmethod->digest_size, hmethod);
|
||||||
|
- hmac_update(&ctx, auth_message, strlen(auth_message));
|
||||||
|
- hmac_final(&ctx, server_signature);
|
||||||
|
+ openssl_hmac_init(&ctx, request->server_key, hmethod->digest_size, hmethod);
|
||||||
|
+ openssl_hmac_update(&ctx, auth_message, strlen(auth_message));
|
||||||
|
+ openssl_hmac_final(&ctx, server_signature);
|
||||||
|
|
||||||
|
/* RFC 5802, Section 7:
|
||||||
|
|
||||||
|
@@ -292,7 +292,7 @@ parse_scram_client_first(struct scram_au
|
||||||
|
static bool verify_credentials(struct scram_auth_request *request)
|
||||||
|
{
|
||||||
|
const struct hash_method *hmethod = request->hash_method;
|
||||||
|
- struct hmac_context ctx;
|
||||||
|
+ struct openssl_hmac_context ctx;
|
||||||
|
const char *auth_message;
|
||||||
|
unsigned char client_key[hmethod->digest_size];
|
||||||
|
unsigned char client_signature[hmethod->digest_size];
|
||||||
|
@@ -310,9 +310,9 @@ static bool verify_credentials(struct sc
|
||||||
|
request->server_first_message, ",",
|
||||||
|
request->client_final_message_without_proof, NULL);
|
||||||
|
|
||||||
|
- hmac_init(&ctx, request->stored_key, hmethod->digest_size, hmethod);
|
||||||
|
- hmac_update(&ctx, auth_message, strlen(auth_message));
|
||||||
|
- hmac_final(&ctx, client_signature);
|
||||||
|
+ openssl_hmac_init(&ctx, request->stored_key, hmethod->digest_size, hmethod);
|
||||||
|
+ openssl_hmac_update(&ctx, auth_message, strlen(auth_message));
|
||||||
|
+ openssl_hmac_final(&ctx, client_signature);
|
||||||
|
|
||||||
|
/* ClientProof := ClientKey XOR ClientSignature */
|
||||||
|
const unsigned char *proof_data = request->proof->data;
|
||||||
|
diff -up dovecot-2.3.18/src/auth/password-scheme.c.opensslhmac dovecot-2.3.18/src/auth/password-scheme.c
|
||||||
|
--- dovecot-2.3.18/src/auth/password-scheme.c.opensslhmac 2022-02-02 12:42:23.000000000 +0100
|
||||||
|
+++ dovecot-2.3.18/src/auth/password-scheme.c 2022-02-09 09:27:15.888883345 +0100
|
||||||
|
@@ -639,11 +639,11 @@ static void
|
||||||
|
cram_md5_generate(const char *plaintext, const struct password_generate_params *params ATTR_UNUSED,
|
||||||
|
const unsigned char **raw_password_r, size_t *size_r)
|
||||||
|
{
|
||||||
|
- struct hmac_context ctx;
|
||||||
|
+ struct orig_hmac_context ctx;
|
||||||
|
unsigned char *context_digest;
|
||||||
|
|
||||||
|
context_digest = t_malloc_no0(CRAM_MD5_CONTEXTLEN);
|
||||||
|
- hmac_init(&ctx, (const unsigned char *)plaintext,
|
||||||
|
+ orig_hmac_init(&ctx, (const unsigned char *)plaintext,
|
||||||
|
strlen(plaintext), &hash_method_md5);
|
||||||
|
hmac_md5_get_cram_context(&ctx, context_digest);
|
||||||
|
|
||||||
|
diff -up dovecot-2.3.18/src/auth/password-scheme-scram.c.opensslhmac dovecot-2.3.18/src/auth/password-scheme-scram.c
|
||||||
|
--- dovecot-2.3.18/src/auth/password-scheme-scram.c.opensslhmac 2022-02-02 12:42:23.000000000 +0100
|
||||||
|
+++ dovecot-2.3.18/src/auth/password-scheme-scram.c 2022-02-09 09:27:15.888883345 +0100
|
||||||
|
@@ -30,23 +30,23 @@ Hi(const struct hash_method *hmethod, co
|
||||||
|
const unsigned char *salt, size_t salt_size, unsigned int i,
|
||||||
|
unsigned char *result)
|
||||||
|
{
|
||||||
|
- struct hmac_context ctx;
|
||||||
|
+ struct openssl_hmac_context ctx;
|
||||||
|
unsigned char U[hmethod->digest_size];
|
||||||
|
unsigned int j, k;
|
||||||
|
|
||||||
|
/* Calculate U1 */
|
||||||
|
- hmac_init(&ctx, str, str_size, hmethod);
|
||||||
|
- hmac_update(&ctx, salt, salt_size);
|
||||||
|
- hmac_update(&ctx, "\0\0\0\1", 4);
|
||||||
|
- hmac_final(&ctx, U);
|
||||||
|
+ openssl_hmac_init(&ctx, str, str_size, hmethod);
|
||||||
|
+ openssl_hmac_update(&ctx, salt, salt_size);
|
||||||
|
+ openssl_hmac_update(&ctx, "\0\0\0\1", 4);
|
||||||
|
+ openssl_hmac_final(&ctx, U);
|
||||||
|
|
||||||
|
memcpy(result, U, hmethod->digest_size);
|
||||||
|
|
||||||
|
/* Calculate U2 to Ui and Hi */
|
||||||
|
for (j = 2; j <= i; j++) {
|
||||||
|
- hmac_init(&ctx, str, str_size, hmethod);
|
||||||
|
- hmac_update(&ctx, U, sizeof(U));
|
||||||
|
- hmac_final(&ctx, U);
|
||||||
|
+ openssl_hmac_init(&ctx, str, str_size, hmethod);
|
||||||
|
+ openssl_hmac_update(&ctx, U, sizeof(U));
|
||||||
|
+ openssl_hmac_final(&ctx, U);
|
||||||
|
for (k = 0; k < hmethod->digest_size; k++)
|
||||||
|
result[k] ^= U[k];
|
||||||
|
}
|
||||||
|
@@ -102,7 +102,7 @@ int scram_verify(const struct hash_metho
|
||||||
|
const char *plaintext, const unsigned char *raw_password,
|
||||||
|
size_t size, const char **error_r)
|
||||||
|
{
|
||||||
|
- struct hmac_context ctx;
|
||||||
|
+ struct openssl_hmac_context ctx;
|
||||||
|
const char *salt_base64;
|
||||||
|
unsigned int iter_count;
|
||||||
|
const unsigned char *salt;
|
||||||
|
@@ -126,9 +126,9 @@ int scram_verify(const struct hash_metho
|
||||||
|
salt, salt_len, iter_count, salted_password);
|
||||||
|
|
||||||
|
/* Calculate ClientKey */
|
||||||
|
- hmac_init(&ctx, salted_password, sizeof(salted_password), hmethod);
|
||||||
|
- hmac_update(&ctx, "Client Key", 10);
|
||||||
|
- hmac_final(&ctx, client_key);
|
||||||
|
+ openssl_hmac_init(&ctx, salted_password, sizeof(salted_password), hmethod);
|
||||||
|
+ openssl_hmac_update(&ctx, "Client Key", 10);
|
||||||
|
+ openssl_hmac_final(&ctx, client_key);
|
||||||
|
|
||||||
|
/* Calculate StoredKey */
|
||||||
|
hash_method_get_digest(hmethod, client_key, sizeof(client_key),
|
||||||
|
@@ -147,7 +147,7 @@ void scram_generate(const struct hash_me
|
||||||
|
const unsigned char **raw_password_r, size_t *size_r)
|
||||||
|
{
|
||||||
|
string_t *str;
|
||||||
|
- struct hmac_context ctx;
|
||||||
|
+ struct openssl_hmac_context ctx;
|
||||||
|
unsigned char salt[16];
|
||||||
|
unsigned char salted_password[hmethod->digest_size];
|
||||||
|
unsigned char client_key[hmethod->digest_size];
|
||||||
|
@@ -165,9 +165,9 @@ void scram_generate(const struct hash_me
|
||||||
|
sizeof(salt), SCRAM_DEFAULT_ITERATE_COUNT, salted_password);
|
||||||
|
|
||||||
|
/* Calculate ClientKey */
|
||||||
|
- hmac_init(&ctx, salted_password, sizeof(salted_password), hmethod);
|
||||||
|
- hmac_update(&ctx, "Client Key", 10);
|
||||||
|
- hmac_final(&ctx, client_key);
|
||||||
|
+ openssl_hmac_init(&ctx, salted_password, sizeof(salted_password), hmethod);
|
||||||
|
+ openssl_hmac_update(&ctx, "Client Key", 10);
|
||||||
|
+ openssl_hmac_final(&ctx, client_key);
|
||||||
|
|
||||||
|
/* Calculate StoredKey */
|
||||||
|
hash_method_get_digest(hmethod, client_key, sizeof(client_key),
|
||||||
|
@@ -176,9 +176,9 @@ void scram_generate(const struct hash_me
|
||||||
|
base64_encode(stored_key, sizeof(stored_key), str);
|
||||||
|
|
||||||
|
/* Calculate ServerKey */
|
||||||
|
- hmac_init(&ctx, salted_password, sizeof(salted_password), hmethod);
|
||||||
|
- hmac_update(&ctx, "Server Key", 10);
|
||||||
|
- hmac_final(&ctx, server_key);
|
||||||
|
+ openssl_hmac_init(&ctx, salted_password, sizeof(salted_password), hmethod);
|
||||||
|
+ openssl_hmac_update(&ctx, "Server Key", 10);
|
||||||
|
+ openssl_hmac_final(&ctx, server_key);
|
||||||
|
str_append_c(str, ',');
|
||||||
|
base64_encode(server_key, sizeof(server_key), str);
|
||||||
|
|
||||||
|
diff -up dovecot-2.3.18/src/lib/hmac.c.opensslhmac dovecot-2.3.18/src/lib/hmac.c
|
||||||
|
--- dovecot-2.3.18/src/lib/hmac.c.opensslhmac 2022-02-02 12:42:23.000000000 +0100
|
||||||
|
+++ dovecot-2.3.18/src/lib/hmac.c 2022-02-09 09:27:15.888883345 +0100
|
||||||
|
@@ -7,6 +7,10 @@
|
||||||
|
* This software is released under the MIT license.
|
||||||
|
*/
|
||||||
|
|
||||||
|
+#include <sys/types.h>
|
||||||
|
+#include <sys/stat.h>
|
||||||
|
+#include <fcntl.h>
|
||||||
|
+#include <unistd.h>
|
||||||
|
#include "lib.h"
|
||||||
|
#include "hmac.h"
|
||||||
|
#include "safe-memset.h"
|
||||||
|
@@ -14,10 +18,65 @@
|
||||||
|
|
||||||
|
#include "hex-binary.h"
|
||||||
|
|
||||||
|
-void hmac_init(struct hmac_context *_ctx, const unsigned char *key,
|
||||||
|
+#ifndef HAVE_HMAC_CTX_NEW
|
||||||
|
+# define HMAC_Init_ex(ctx, key, key_len, md, impl) \
|
||||||
|
+ HMAC_Init_ex(&(ctx), key, key_len, md, impl)
|
||||||
|
+# define HMAC_Update(ctx, data, len) HMAC_Update(&(ctx), data, len)
|
||||||
|
+# define HMAC_Final(ctx, md, len) HMAC_Final(&(ctx), md, len)
|
||||||
|
+# define HMAC_CTX_free(ctx) HMAC_cleanup(&(ctx))
|
||||||
|
+#else
|
||||||
|
+# define HMAC_CTX_free(ctx) \
|
||||||
|
+ STMT_START { HMAC_CTX_free(ctx); (ctx) = NULL; } STMT_END
|
||||||
|
+#endif
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+void openssl_hmac_init(struct openssl_hmac_context *_ctx, const unsigned char *key,
|
||||||
|
size_t key_len, const struct hash_method *meth)
|
||||||
|
{
|
||||||
|
- struct hmac_context_priv *ctx = &_ctx->u.priv;
|
||||||
|
+ struct openssl_hmac_context_priv *ctx = &_ctx->u.priv;
|
||||||
|
+
|
||||||
|
+ const EVP_MD *md;
|
||||||
|
+ const char *ebuf = NULL;
|
||||||
|
+ const char **error_r = &ebuf;
|
||||||
|
+
|
||||||
|
+ md = EVP_get_digestbyname(meth->name);
|
||||||
|
+ if(md == NULL) {
|
||||||
|
+ if (error_r != NULL) {
|
||||||
|
+ *error_r = t_strdup_printf("Invalid digest %s",
|
||||||
|
+ meth->name);
|
||||||
|
+ }
|
||||||
|
+ //return FALSE;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+// int ec;
|
||||||
|
+
|
||||||
|
+ i_assert(md != NULL);
|
||||||
|
+#ifdef HAVE_HMAC_CTX_NEW
|
||||||
|
+ ctx->ctx = HMAC_CTX_new();
|
||||||
|
+/* if (ctx->ctx == NULL)
|
||||||
|
+ dcrypt_openssl_error(error_r);*/
|
||||||
|
+#endif
|
||||||
|
+ /*ec = */HMAC_Init_ex(ctx->ctx, key, key_len, md, NULL);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+void orig_hmac_init(struct orig_hmac_context *_ctx, const unsigned char *key,
|
||||||
|
+ size_t key_len, const struct hash_method *meth)
|
||||||
|
+{
|
||||||
|
+ static int no_fips = -1;
|
||||||
|
+ if (no_fips == -1) {
|
||||||
|
+ int fd = open("/proc/sys/crypto/fips_enabled", O_RDONLY);
|
||||||
|
+ if (fd != -1)
|
||||||
|
+ {
|
||||||
|
+ char buf[4];
|
||||||
|
+ if (read(fd, buf, 4) > 0)
|
||||||
|
+ {
|
||||||
|
+ no_fips = buf[0] == '0';
|
||||||
|
+ }
|
||||||
|
+ close(fd);
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ i_assert(no_fips);
|
||||||
|
+ struct orig_hmac_context_priv *ctx = &_ctx->u.priv;
|
||||||
|
unsigned int i;
|
||||||
|
unsigned char k_ipad[meth->block_size];
|
||||||
|
unsigned char k_opad[meth->block_size];
|
||||||
|
@@ -53,9 +112,27 @@ void hmac_init(struct hmac_context *_ctx
|
||||||
|
safe_memset(k_opad, 0, meth->block_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
-void hmac_final(struct hmac_context *_ctx, unsigned char *digest)
|
||||||
|
+void openssl_hmac_final(struct openssl_hmac_context *_ctx, unsigned char *digest)
|
||||||
|
+{
|
||||||
|
+ int ec;
|
||||||
|
+ unsigned char buf[HMAC_MAX_MD_CBLOCK];
|
||||||
|
+ unsigned int outl;
|
||||||
|
+// const char *ebuf = NULL;
|
||||||
|
+// const char **error_r = &ebuf;
|
||||||
|
+
|
||||||
|
+ struct openssl_hmac_context_priv *ctx = &_ctx->u.priv;
|
||||||
|
+ ec = HMAC_Final(ctx->ctx, buf, &outl);
|
||||||
|
+ HMAC_CTX_free(ctx->ctx);
|
||||||
|
+ if (ec == 1)
|
||||||
|
+ memcpy(digest, buf, outl);
|
||||||
|
+// else
|
||||||
|
+// dcrypt_openssl_error(error_r);
|
||||||
|
+
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+void orig_hmac_final(struct orig_hmac_context *_ctx, unsigned char *digest)
|
||||||
|
{
|
||||||
|
- struct hmac_context_priv *ctx = &_ctx->u.priv;
|
||||||
|
+ struct orig_hmac_context_priv *ctx = &_ctx->u.priv;
|
||||||
|
|
||||||
|
ctx->hash->result(ctx->ctx, digest);
|
||||||
|
|
||||||
|
@@ -63,53 +140,50 @@ void hmac_final(struct hmac_context *_ct
|
||||||
|
ctx->hash->result(ctx->ctxo, digest);
|
||||||
|
}
|
||||||
|
|
||||||
|
-buffer_t *t_hmac_data(const struct hash_method *meth,
|
||||||
|
+buffer_t *openssl_t_hmac_data(const struct hash_method *meth,
|
||||||
|
const unsigned char *key, size_t key_len,
|
||||||
|
const void *data, size_t data_len)
|
||||||
|
{
|
||||||
|
- struct hmac_context ctx;
|
||||||
|
+ struct openssl_hmac_context ctx;
|
||||||
|
i_assert(meth != NULL);
|
||||||
|
i_assert(key != NULL && key_len > 0);
|
||||||
|
i_assert(data != NULL || data_len == 0);
|
||||||
|
|
||||||
|
buffer_t *res = t_buffer_create(meth->digest_size);
|
||||||
|
- hmac_init(&ctx, key, key_len, meth);
|
||||||
|
+ openssl_hmac_init(&ctx, key, key_len, meth);
|
||||||
|
if (data_len > 0)
|
||||||
|
- hmac_update(&ctx, data, data_len);
|
||||||
|
+ openssl_hmac_update(&ctx, data, data_len);
|
||||||
|
unsigned char *buf = buffer_get_space_unsafe(res, 0, meth->digest_size);
|
||||||
|
- hmac_final(&ctx, buf);
|
||||||
|
+ openssl_hmac_final(&ctx, buf);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
-buffer_t *t_hmac_buffer(const struct hash_method *meth,
|
||||||
|
+buffer_t *openssl_t_hmac_buffer(const struct hash_method *meth,
|
||||||
|
const unsigned char *key, size_t key_len,
|
||||||
|
const buffer_t *data)
|
||||||
|
{
|
||||||
|
- return t_hmac_data(meth, key, key_len, data->data, data->used);
|
||||||
|
+ return openssl_t_hmac_data(meth, key, key_len, data->data, data->used);
|
||||||
|
}
|
||||||
|
|
||||||
|
-buffer_t *t_hmac_str(const struct hash_method *meth,
|
||||||
|
+buffer_t *openssl_t_hmac_str(const struct hash_method *meth,
|
||||||
|
const unsigned char *key, size_t key_len,
|
||||||
|
const char *data)
|
||||||
|
{
|
||||||
|
- return t_hmac_data(meth, key, key_len, data, strlen(data));
|
||||||
|
+ return openssl_t_hmac_data(meth, key, key_len, data, strlen(data));
|
||||||
|
}
|
||||||
|
|
||||||
|
-void hmac_hkdf(const struct hash_method *method,
|
||||||
|
+void openssl_hmac_hkdf(const struct hash_method *method,
|
||||||
|
const unsigned char *salt, size_t salt_len,
|
||||||
|
const unsigned char *ikm, size_t ikm_len,
|
||||||
|
const unsigned char *info, size_t info_len,
|
||||||
|
buffer_t *okm_r, size_t okm_len)
|
||||||
|
{
|
||||||
|
+ const EVP_MD *md;
|
||||||
|
+ EVP_PKEY_CTX *pctx;
|
||||||
|
+ int r = 1;
|
||||||
|
+
|
||||||
|
i_assert(method != NULL);
|
||||||
|
i_assert(okm_len < 255*method->digest_size);
|
||||||
|
- struct hmac_context key_mac;
|
||||||
|
- struct hmac_context info_mac;
|
||||||
|
- size_t remain = okm_len;
|
||||||
|
- unsigned char prk[method->digest_size];
|
||||||
|
- unsigned char okm[method->digest_size];
|
||||||
|
- /* N = ceil(L/HashLen) */
|
||||||
|
- unsigned int rounds = (okm_len + method->digest_size - 1)/method->digest_size;
|
||||||
|
|
||||||
|
/* salt and info can be NULL */
|
||||||
|
i_assert(salt != NULL || salt_len == 0);
|
||||||
|
@@ -118,35 +192,30 @@ void hmac_hkdf(const struct hash_method
|
||||||
|
i_assert(ikm != NULL && ikm_len > 0);
|
||||||
|
i_assert(okm_r != NULL && okm_len > 0);
|
||||||
|
|
||||||
|
- /* but they still need valid pointer, reduces
|
||||||
|
- complains from static analysers */
|
||||||
|
- if (salt == NULL)
|
||||||
|
- salt = &uchar_nul;
|
||||||
|
- if (info == NULL)
|
||||||
|
- info = &uchar_nul;
|
||||||
|
-
|
||||||
|
- /* extract */
|
||||||
|
- hmac_init(&key_mac, salt, salt_len, method);
|
||||||
|
- hmac_update(&key_mac, ikm, ikm_len);
|
||||||
|
- hmac_final(&key_mac, prk);
|
||||||
|
-
|
||||||
|
- /* expand */
|
||||||
|
- for (unsigned int i = 0; remain > 0 && i < rounds; i++) {
|
||||||
|
- unsigned char round = (i+1);
|
||||||
|
- size_t amt = remain;
|
||||||
|
- if (amt > method->digest_size)
|
||||||
|
- amt = method->digest_size;
|
||||||
|
- hmac_init(&info_mac, prk, method->digest_size, method);
|
||||||
|
- if (i > 0)
|
||||||
|
- hmac_update(&info_mac, okm, method->digest_size);
|
||||||
|
- hmac_update(&info_mac, info, info_len);
|
||||||
|
- hmac_update(&info_mac, &round, 1);
|
||||||
|
- memset(okm, 0, method->digest_size);
|
||||||
|
- hmac_final(&info_mac, okm);
|
||||||
|
- buffer_append(okm_r, okm, amt);
|
||||||
|
- remain -= amt;
|
||||||
|
+
|
||||||
|
+ md = EVP_get_digestbyname(method->name);
|
||||||
|
+ pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_HKDF, NULL);
|
||||||
|
+ unsigned char *okm_buf = buffer_get_space_unsafe(okm_r, 0, okm_len);
|
||||||
|
+
|
||||||
|
+ if ((r=EVP_PKEY_derive_init(pctx)) <= 0)
|
||||||
|
+ goto out;
|
||||||
|
+ if ((r=EVP_PKEY_CTX_set_hkdf_md(pctx, md)) <= 0)
|
||||||
|
+ goto out;
|
||||||
|
+ if ((r=EVP_PKEY_CTX_set1_hkdf_salt(pctx, salt, salt_len)) <= 0)
|
||||||
|
+ goto out;
|
||||||
|
+ if ((r=EVP_PKEY_CTX_set1_hkdf_key(pctx, ikm, ikm_len)) <= 0)
|
||||||
|
+ goto out;
|
||||||
|
+ if ((r=EVP_PKEY_CTX_add1_hkdf_info(pctx, info, info_len)) <= 0)
|
||||||
|
+ goto out;
|
||||||
|
+ if ((r=EVP_PKEY_derive(pctx, okm_buf, &okm_len)) <= 0)
|
||||||
|
+ goto out;
|
||||||
|
+
|
||||||
|
+ out:
|
||||||
|
+ EVP_PKEY_CTX_free(pctx);
|
||||||
|
+ if (r <= 0) {
|
||||||
|
+ unsigned long ec = ERR_get_error();
|
||||||
|
+ unsigned char *error = t_strdup_printf("%s", ERR_error_string(ec, NULL));
|
||||||
|
+ i_error("%s", error);
|
||||||
|
}
|
||||||
|
|
||||||
|
- safe_memset(prk, 0, sizeof(prk));
|
||||||
|
- safe_memset(okm, 0, sizeof(okm));
|
||||||
|
}
|
||||||
|
diff -up dovecot-2.3.18/src/lib/hmac-cram-md5.c.opensslhmac dovecot-2.3.18/src/lib/hmac-cram-md5.c
|
||||||
|
--- dovecot-2.3.18/src/lib/hmac-cram-md5.c.opensslhmac 2022-02-02 12:42:23.000000000 +0100
|
||||||
|
+++ dovecot-2.3.18/src/lib/hmac-cram-md5.c 2022-02-09 09:27:15.888883345 +0100
|
||||||
|
@@ -9,10 +9,10 @@
|
||||||
|
#include "md5.h"
|
||||||
|
#include "hmac-cram-md5.h"
|
||||||
|
|
||||||
|
-void hmac_md5_get_cram_context(struct hmac_context *_hmac_ctx,
|
||||||
|
+void hmac_md5_get_cram_context(struct orig_hmac_context *_hmac_ctx,
|
||||||
|
unsigned char context_digest[CRAM_MD5_CONTEXTLEN])
|
||||||
|
{
|
||||||
|
- struct hmac_context_priv *hmac_ctx = &_hmac_ctx->u.priv;
|
||||||
|
+ struct orig_hmac_context_priv *hmac_ctx = &_hmac_ctx->u.priv;
|
||||||
|
unsigned char *cdp;
|
||||||
|
|
||||||
|
struct md5_context *ctx = (void*)hmac_ctx->ctx;
|
||||||
|
@@ -35,10 +35,10 @@ void hmac_md5_get_cram_context(struct hm
|
||||||
|
CDPUT(cdp, ctx->d);
|
||||||
|
}
|
||||||
|
|
||||||
|
-void hmac_md5_set_cram_context(struct hmac_context *_hmac_ctx,
|
||||||
|
+void hmac_md5_set_cram_context(struct orig_hmac_context *_hmac_ctx,
|
||||||
|
const unsigned char context_digest[CRAM_MD5_CONTEXTLEN])
|
||||||
|
{
|
||||||
|
- struct hmac_context_priv *hmac_ctx = &_hmac_ctx->u.priv;
|
||||||
|
+ struct orig_hmac_context_priv *hmac_ctx = &_hmac_ctx->u.priv;
|
||||||
|
const unsigned char *cdp;
|
||||||
|
|
||||||
|
struct md5_context *ctx = (void*)hmac_ctx->ctx;
|
||||||
|
diff -up dovecot-2.3.18/src/lib/hmac-cram-md5.h.opensslhmac dovecot-2.3.18/src/lib/hmac-cram-md5.h
|
||||||
|
--- dovecot-2.3.18/src/lib/hmac-cram-md5.h.opensslhmac 2022-02-02 12:42:23.000000000 +0100
|
||||||
|
+++ dovecot-2.3.18/src/lib/hmac-cram-md5.h 2022-02-09 09:27:15.888883345 +0100
|
||||||
|
@@ -5,9 +5,9 @@
|
||||||
|
|
||||||
|
#define CRAM_MD5_CONTEXTLEN 32
|
||||||
|
|
||||||
|
-void hmac_md5_get_cram_context(struct hmac_context *ctx,
|
||||||
|
+void hmac_md5_get_cram_context(struct orig_hmac_context *ctx,
|
||||||
|
unsigned char context_digest[CRAM_MD5_CONTEXTLEN]);
|
||||||
|
-void hmac_md5_set_cram_context(struct hmac_context *ctx,
|
||||||
|
+void hmac_md5_set_cram_context(struct orig_hmac_context *ctx,
|
||||||
|
const unsigned char context_digest[CRAM_MD5_CONTEXTLEN]);
|
||||||
|
|
||||||
|
|
||||||
|
diff -up dovecot-2.3.18/src/lib/hmac.h.opensslhmac dovecot-2.3.18/src/lib/hmac.h
|
||||||
|
--- dovecot-2.3.18/src/lib/hmac.h.opensslhmac 2022-02-02 12:42:23.000000000 +0100
|
||||||
|
+++ dovecot-2.3.18/src/lib/hmac.h 2022-02-09 09:27:15.888883345 +0100
|
||||||
|
@@ -4,60 +4,97 @@
|
||||||
|
#include "hash-method.h"
|
||||||
|
#include "sha1.h"
|
||||||
|
#include "sha2.h"
|
||||||
|
+#include <openssl/objects.h>
|
||||||
|
+#include <openssl/hmac.h>
|
||||||
|
+#include <openssl/kdf.h>
|
||||||
|
+#include <openssl/err.h>
|
||||||
|
|
||||||
|
#define HMAC_MAX_CONTEXT_SIZE sizeof(struct sha512_ctx)
|
||||||
|
|
||||||
|
-struct hmac_context_priv {
|
||||||
|
+struct openssl_hmac_context_priv {
|
||||||
|
+#ifdef HAVE_HMAC_CTX_NEW
|
||||||
|
+ HMAC_CTX *ctx;
|
||||||
|
+#else
|
||||||
|
+ HMAC_CTX ctx;
|
||||||
|
+#endif
|
||||||
|
+ const struct hash_method *hash;
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+struct orig_hmac_context_priv {
|
||||||
|
char ctx[HMAC_MAX_CONTEXT_SIZE];
|
||||||
|
char ctxo[HMAC_MAX_CONTEXT_SIZE];
|
||||||
|
const struct hash_method *hash;
|
||||||
|
};
|
||||||
|
|
||||||
|
-struct hmac_context {
|
||||||
|
+struct openssl_hmac_context {
|
||||||
|
+ union {
|
||||||
|
+ struct openssl_hmac_context_priv priv;
|
||||||
|
+ uint64_t padding_requirement;
|
||||||
|
+ } u;
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+struct orig_hmac_context {
|
||||||
|
union {
|
||||||
|
- struct hmac_context_priv priv;
|
||||||
|
+ struct orig_hmac_context_priv priv;
|
||||||
|
uint64_t padding_requirement;
|
||||||
|
} u;
|
||||||
|
};
|
||||||
|
|
||||||
|
-void hmac_init(struct hmac_context *ctx, const unsigned char *key,
|
||||||
|
+void openssl_hmac_init(struct openssl_hmac_context *ctx, const unsigned char *key,
|
||||||
|
+ size_t key_len, const struct hash_method *meth);
|
||||||
|
+void openssl_hmac_final(struct openssl_hmac_context *ctx, unsigned char *digest);
|
||||||
|
+
|
||||||
|
+static inline void
|
||||||
|
+openssl_hmac_update(struct openssl_hmac_context *_ctx, const void *data, size_t size)
|
||||||
|
+{
|
||||||
|
+ struct openssl_hmac_context_priv *ctx = &_ctx->u.priv;
|
||||||
|
+ HMAC_Update(ctx->ctx, data, size);
|
||||||
|
+/* if (ec != 1)
|
||||||
|
+ {
|
||||||
|
+ const char *ebuf = NULL;
|
||||||
|
+ const char **error_r = &ebuf;
|
||||||
|
+ dcrypt_openssl_error(error_r);
|
||||||
|
+ }*/
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+void orig_hmac_init(struct orig_hmac_context *ctx, const unsigned char *key,
|
||||||
|
size_t key_len, const struct hash_method *meth);
|
||||||
|
-void hmac_final(struct hmac_context *ctx, unsigned char *digest);
|
||||||
|
+void orig_hmac_final(struct orig_hmac_context *ctx, unsigned char *digest);
|
||||||
|
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
-hmac_update(struct hmac_context *_ctx, const void *data, size_t size)
|
||||||
|
+orig_hmac_update(struct orig_hmac_context *_ctx, const void *data, size_t size)
|
||||||
|
{
|
||||||
|
- struct hmac_context_priv *ctx = &_ctx->u.priv;
|
||||||
|
+ struct orig_hmac_context_priv *ctx = &_ctx->u.priv;
|
||||||
|
|
||||||
|
ctx->hash->loop(ctx->ctx, data, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
-buffer_t *t_hmac_data(const struct hash_method *meth,
|
||||||
|
+buffer_t *openssl_t_hmac_data(const struct hash_method *meth,
|
||||||
|
const unsigned char *key, size_t key_len,
|
||||||
|
const void *data, size_t data_len);
|
||||||
|
-buffer_t *t_hmac_buffer(const struct hash_method *meth,
|
||||||
|
+buffer_t *openssl_t_hmac_buffer(const struct hash_method *meth,
|
||||||
|
const unsigned char *key, size_t key_len,
|
||||||
|
const buffer_t *data);
|
||||||
|
-buffer_t *t_hmac_str(const struct hash_method *meth,
|
||||||
|
+buffer_t *openssl_t_hmac_str(const struct hash_method *meth,
|
||||||
|
const unsigned char *key, size_t key_len,
|
||||||
|
const char *data);
|
||||||
|
|
||||||
|
-void hmac_hkdf(const struct hash_method *method,
|
||||||
|
+void openssl_hmac_hkdf(const struct hash_method *method,
|
||||||
|
const unsigned char *salt, size_t salt_len,
|
||||||
|
const unsigned char *ikm, size_t ikm_len,
|
||||||
|
const unsigned char *info, size_t info_len,
|
||||||
|
buffer_t *okm_r, size_t okm_len);
|
||||||
|
|
||||||
|
static inline buffer_t *
|
||||||
|
-t_hmac_hkdf(const struct hash_method *method,
|
||||||
|
+openssl_t_hmac_hkdf(const struct hash_method *method,
|
||||||
|
const unsigned char *salt, size_t salt_len,
|
||||||
|
const unsigned char *ikm, size_t ikm_len,
|
||||||
|
const unsigned char *info, size_t info_len,
|
||||||
|
size_t okm_len)
|
||||||
|
{
|
||||||
|
buffer_t *okm_buffer = t_buffer_create(okm_len);
|
||||||
|
- hmac_hkdf(method, salt, salt_len, ikm, ikm_len, info, info_len,
|
||||||
|
+ openssl_hmac_hkdf(method, salt, salt_len, ikm, ikm_len, info, info_len,
|
||||||
|
okm_buffer, okm_len);
|
||||||
|
return okm_buffer;
|
||||||
|
}
|
||||||
|
diff -up dovecot-2.3.18/src/lib-imap-urlauth/imap-urlauth.c.opensslhmac dovecot-2.3.18/src/lib-imap-urlauth/imap-urlauth.c
|
||||||
|
--- dovecot-2.3.18/src/lib-imap-urlauth/imap-urlauth.c.opensslhmac 2022-02-02 12:42:23.000000000 +0100
|
||||||
|
+++ dovecot-2.3.18/src/lib-imap-urlauth/imap-urlauth.c 2022-02-09 09:27:15.888883345 +0100
|
||||||
|
@@ -85,15 +85,15 @@ imap_urlauth_internal_generate(const cha
|
||||||
|
const unsigned char mailbox_key[IMAP_URLAUTH_KEY_LEN],
|
||||||
|
size_t *token_len_r)
|
||||||
|
{
|
||||||
|
- struct hmac_context hmac;
|
||||||
|
+ struct openssl_hmac_context hmac;
|
||||||
|
unsigned char *token;
|
||||||
|
|
||||||
|
token = t_new(unsigned char, SHA1_RESULTLEN + 1);
|
||||||
|
token[0] = IMAP_URLAUTH_MECH_INTERNAL_VERSION;
|
||||||
|
|
||||||
|
- hmac_init(&hmac, mailbox_key, IMAP_URLAUTH_KEY_LEN, &hash_method_sha1);
|
||||||
|
- hmac_update(&hmac, rumpurl, strlen(rumpurl));
|
||||||
|
- hmac_final(&hmac, token+1);
|
||||||
|
+ openssl_hmac_init(&hmac, mailbox_key, IMAP_URLAUTH_KEY_LEN, &hash_method_sha1);
|
||||||
|
+ openssl_hmac_update(&hmac, rumpurl, strlen(rumpurl));
|
||||||
|
+ openssl_hmac_final(&hmac, token+1);
|
||||||
|
|
||||||
|
*token_len_r = SHA1_RESULTLEN + 1;
|
||||||
|
return token;
|
||||||
|
diff -up dovecot-2.3.18/src/lib/Makefile.am.opensslhmac dovecot-2.3.18/src/lib/Makefile.am
|
||||||
|
--- dovecot-2.3.18/src/lib/Makefile.am.opensslhmac 2022-02-02 12:42:23.000000000 +0100
|
||||||
|
+++ dovecot-2.3.18/src/lib/Makefile.am 2022-02-09 09:27:15.889883331 +0100
|
||||||
|
@@ -354,6 +354,9 @@ headers = \
|
||||||
|
wildcard-match.h \
|
||||||
|
write-full.h
|
||||||
|
|
||||||
|
+liblib_la_LIBADD = $(SSL_LIBS)
|
||||||
|
+liblib_la_CFLAGS = $(SSL_CFLAGS)
|
||||||
|
+
|
||||||
|
test_programs = test-lib
|
||||||
|
noinst_PROGRAMS = $(test_programs)
|
||||||
|
|
||||||
|
diff -up dovecot-2.3.18/src/lib-oauth2/oauth2-jwt.c.opensslhmac dovecot-2.3.18/src/lib-oauth2/oauth2-jwt.c
|
||||||
|
--- dovecot-2.3.18/src/lib-oauth2/oauth2-jwt.c.opensslhmac 2022-02-02 12:42:23.000000000 +0100
|
||||||
|
+++ dovecot-2.3.18/src/lib-oauth2/oauth2-jwt.c 2022-02-09 09:27:15.889883331 +0100
|
||||||
|
@@ -144,14 +144,14 @@ oauth2_validate_hmac(const struct oauth2
|
||||||
|
if (oauth2_lookup_hmac_key(set, azp, alg, key_id, &key, error_r) < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
- struct hmac_context ctx;
|
||||||
|
- hmac_init(&ctx, key->data, key->used, method);
|
||||||
|
- hmac_update(&ctx, blobs[0], strlen(blobs[0]));
|
||||||
|
- hmac_update(&ctx, ".", 1);
|
||||||
|
- hmac_update(&ctx, blobs[1], strlen(blobs[1]));
|
||||||
|
+ struct openssl_hmac_context ctx;
|
||||||
|
+ openssl_hmac_init(&ctx, key->data, key->used, method);
|
||||||
|
+ openssl_hmac_update(&ctx, blobs[0], strlen(blobs[0]));
|
||||||
|
+ openssl_hmac_update(&ctx, ".", 1);
|
||||||
|
+ openssl_hmac_update(&ctx, blobs[1], strlen(blobs[1]));
|
||||||
|
unsigned char digest[method->digest_size];
|
||||||
|
|
||||||
|
- hmac_final(&ctx, digest);
|
||||||
|
+ openssl_hmac_final(&ctx, digest);
|
||||||
|
|
||||||
|
buffer_t *their_digest =
|
||||||
|
t_base64url_decode_str(BASE64_DECODE_FLAG_NO_PADDING, blobs[2]);
|
||||||
|
diff -up dovecot-2.3.18/src/lib-oauth2/test-oauth2-jwt.c.opensslhmac dovecot-2.3.18/src/lib-oauth2/test-oauth2-jwt.c
|
||||||
|
--- dovecot-2.3.18/src/lib-oauth2/test-oauth2-jwt.c.opensslhmac 2022-02-02 12:42:23.000000000 +0100
|
||||||
|
+++ dovecot-2.3.18/src/lib-oauth2/test-oauth2-jwt.c 2022-02-09 09:27:15.889883331 +0100
|
||||||
|
@@ -248,7 +248,7 @@ static void save_key_azp_to(const char *
|
||||||
|
static void sign_jwt_token_hs256(buffer_t *tokenbuf, buffer_t *key)
|
||||||
|
{
|
||||||
|
i_assert(key != NULL);
|
||||||
|
- buffer_t *sig = t_hmac_buffer(&hash_method_sha256, key->data, key->used,
|
||||||
|
+ buffer_t *sig = openssl_t_hmac_buffer(&hash_method_sha256, key->data, key->used,
|
||||||
|
tokenbuf);
|
||||||
|
buffer_append(tokenbuf, ".", 1);
|
||||||
|
base64url_encode(BASE64_ENCODE_FLAG_NO_PADDING, SIZE_MAX,
|
||||||
|
@@ -258,7 +258,7 @@ static void sign_jwt_token_hs256(buffer_
|
||||||
|
static void sign_jwt_token_hs384(buffer_t *tokenbuf, buffer_t *key)
|
||||||
|
{
|
||||||
|
i_assert(key != NULL);
|
||||||
|
- buffer_t *sig = t_hmac_buffer(&hash_method_sha384, key->data, key->used,
|
||||||
|
+ buffer_t *sig = openssl_t_hmac_buffer(&hash_method_sha384, key->data, key->used,
|
||||||
|
tokenbuf);
|
||||||
|
buffer_append(tokenbuf, ".", 1);
|
||||||
|
base64url_encode(BASE64_ENCODE_FLAG_NO_PADDING, SIZE_MAX,
|
||||||
|
@@ -268,7 +268,7 @@ static void sign_jwt_token_hs384(buffer_
|
||||||
|
static void sign_jwt_token_hs512(buffer_t *tokenbuf, buffer_t *key)
|
||||||
|
{
|
||||||
|
i_assert(key != NULL);
|
||||||
|
- buffer_t *sig = t_hmac_buffer(&hash_method_sha512, key->data, key->used,
|
||||||
|
+ buffer_t *sig = openssl_t_hmac_buffer(&hash_method_sha512, key->data, key->used,
|
||||||
|
tokenbuf);
|
||||||
|
buffer_append(tokenbuf, ".", 1);
|
||||||
|
base64url_encode(BASE64_ENCODE_FLAG_NO_PADDING, SIZE_MAX,
|
||||||
|
diff -up dovecot-2.3.18/src/lib/pkcs5.c.opensslhmac dovecot-2.3.18/src/lib/pkcs5.c
|
||||||
|
--- dovecot-2.3.18/src/lib/pkcs5.c.opensslhmac 2022-02-02 12:42:23.000000000 +0100
|
||||||
|
+++ dovecot-2.3.18/src/lib/pkcs5.c 2022-02-09 09:27:15.889883331 +0100
|
||||||
|
@@ -52,7 +52,7 @@ int pkcs5_pbkdf2(const struct hash_metho
|
||||||
|
size_t l = (length + hash->digest_size - 1)/hash->digest_size; /* same as ceil(length/hash->digest_size) */
|
||||||
|
unsigned char dk[l * hash->digest_size];
|
||||||
|
unsigned char *block;
|
||||||
|
- struct hmac_context hctx;
|
||||||
|
+ struct openssl_hmac_context hctx;
|
||||||
|
unsigned int c,i,t;
|
||||||
|
unsigned char U_c[hash->digest_size];
|
||||||
|
|
||||||
|
@@ -60,17 +60,17 @@ int pkcs5_pbkdf2(const struct hash_metho
|
||||||
|
block = &(dk[t*hash->digest_size]);
|
||||||
|
/* U_1 = PRF(Password, Salt|| INT_BE32(Block_Number)) */
|
||||||
|
c = htonl(t+1);
|
||||||
|
- hmac_init(&hctx, password, password_len, hash);
|
||||||
|
- hmac_update(&hctx, salt, salt_len);
|
||||||
|
- hmac_update(&hctx, &c, sizeof(c));
|
||||||
|
- hmac_final(&hctx, U_c);
|
||||||
|
+ openssl_hmac_init(&hctx, password, password_len, hash);
|
||||||
|
+ openssl_hmac_update(&hctx, salt, salt_len);
|
||||||
|
+ openssl_hmac_update(&hctx, &c, sizeof(c));
|
||||||
|
+ openssl_hmac_final(&hctx, U_c);
|
||||||
|
/* block = U_1 ^ .. ^ U_iter */
|
||||||
|
memcpy(block, U_c, hash->digest_size);
|
||||||
|
/* U_c = PRF(Password, U_c-1) */
|
||||||
|
for(c = 1; c < iter; c++) {
|
||||||
|
- hmac_init(&hctx, password, password_len, hash);
|
||||||
|
- hmac_update(&hctx, U_c, hash->digest_size);
|
||||||
|
- hmac_final(&hctx, U_c);
|
||||||
|
+ openssl_hmac_init(&hctx, password, password_len, hash);
|
||||||
|
+ openssl_hmac_update(&hctx, U_c, hash->digest_size);
|
||||||
|
+ openssl_hmac_final(&hctx, U_c);
|
||||||
|
for(i = 0; i < hash->digest_size; i++)
|
||||||
|
block[i] ^= U_c[i];
|
||||||
|
}
|
||||||
|
diff -up dovecot-2.3.18/src/lib/test-hmac.c.opensslhmac dovecot-2.3.18/src/lib/test-hmac.c
|
||||||
|
--- dovecot-2.3.18/src/lib/test-hmac.c.opensslhmac 2022-02-02 12:42:23.000000000 +0100
|
||||||
|
+++ dovecot-2.3.18/src/lib/test-hmac.c 2022-02-09 09:27:15.889883331 +0100
|
||||||
|
@@ -206,11 +206,11 @@ static void test_hmac_rfc(void)
|
||||||
|
test_begin("hmac sha256 rfc4231 vectors");
|
||||||
|
for(size_t i = 0; i < N_ELEMENTS(test_vectors); i++) {
|
||||||
|
const struct test_vector *vec = &(test_vectors[i]);
|
||||||
|
- struct hmac_context ctx;
|
||||||
|
- hmac_init(&ctx, vec->key, vec->key_len, hash_method_lookup(vec->prf));
|
||||||
|
- hmac_update(&ctx, vec->data, vec->data_len);
|
||||||
|
+ struct openssl_hmac_context ctx;
|
||||||
|
+ openssl_hmac_init(&ctx, vec->key, vec->key_len, hash_method_lookup(vec->prf));
|
||||||
|
+ openssl_hmac_update(&ctx, vec->data, vec->data_len);
|
||||||
|
unsigned char res[SHA256_RESULTLEN];
|
||||||
|
- hmac_final(&ctx, res);
|
||||||
|
+ openssl_hmac_final(&ctx, res);
|
||||||
|
test_assert_idx(memcmp(res, vec->res, vec->res_len) == 0, i);
|
||||||
|
}
|
||||||
|
test_end();
|
||||||
|
@@ -221,11 +221,11 @@ static void test_hmac384_rfc(void)
|
||||||
|
test_begin("hmac sha384 rfc4231 vectors");
|
||||||
|
for (size_t i = 0; i < N_ELEMENTS(test_vectors_hmac384); i++) {
|
||||||
|
const struct test_vector *vec = &(test_vectors_hmac384[i]);
|
||||||
|
- struct hmac_context ctx;
|
||||||
|
- hmac_init(&ctx, vec->key, vec->key_len, hash_method_lookup(vec->prf));
|
||||||
|
- hmac_update(&ctx, vec->data, vec->data_len);
|
||||||
|
+ struct openssl_hmac_context ctx;
|
||||||
|
+ openssl_hmac_init(&ctx, vec->key, vec->key_len, hash_method_lookup(vec->prf));
|
||||||
|
+ openssl_hmac_update(&ctx, vec->data, vec->data_len);
|
||||||
|
unsigned char res[SHA384_RESULTLEN];
|
||||||
|
- hmac_final(&ctx, res);
|
||||||
|
+ openssl_hmac_final(&ctx, res);
|
||||||
|
test_assert_idx(memcmp(res, vec->res, vec->res_len) == 0, i);
|
||||||
|
}
|
||||||
|
test_end();
|
||||||
|
@@ -236,11 +236,11 @@ static void test_hmac512_rfc(void)
|
||||||
|
test_begin("hmac sha512 rfc4231 vectors");
|
||||||
|
for (size_t i = 0; i < N_ELEMENTS(test_vectors_hmac512); i++) {
|
||||||
|
const struct test_vector *vec = &(test_vectors_hmac512[i]);
|
||||||
|
- struct hmac_context ctx;
|
||||||
|
- hmac_init(&ctx, vec->key, vec->key_len, hash_method_lookup(vec->prf));
|
||||||
|
- hmac_update(&ctx, vec->data, vec->data_len);
|
||||||
|
+ struct openssl_hmac_context ctx;
|
||||||
|
+ openssl_hmac_init(&ctx, vec->key, vec->key_len, hash_method_lookup(vec->prf));
|
||||||
|
+ openssl_hmac_update(&ctx, vec->data, vec->data_len);
|
||||||
|
unsigned char res[SHA512_RESULTLEN];
|
||||||
|
- hmac_final(&ctx, res);
|
||||||
|
+ openssl_hmac_final(&ctx, res);
|
||||||
|
test_assert_idx(memcmp(res, vec->res, vec->res_len) == 0, i);
|
||||||
|
}
|
||||||
|
test_end();
|
||||||
|
@@ -253,7 +253,7 @@ static void test_hmac_buffer(void)
|
||||||
|
|
||||||
|
buffer_t *tmp;
|
||||||
|
|
||||||
|
- tmp = t_hmac_data(hash_method_lookup(vec->prf), vec->key, vec->key_len,
|
||||||
|
+ tmp = openssl_t_hmac_data(hash_method_lookup(vec->prf), vec->key, vec->key_len,
|
||||||
|
vec->data, vec->data_len);
|
||||||
|
|
||||||
|
test_assert(tmp->used == vec->res_len &&
|
||||||
|
@@ -270,7 +270,7 @@ static void test_hkdf_rfc(void)
|
||||||
|
buffer_set_used_size(res, 0);
|
||||||
|
const struct test_vector_5869 *vec = &(test_vectors_5869[i]);
|
||||||
|
const struct hash_method *m = hash_method_lookup(vec->prf);
|
||||||
|
- hmac_hkdf(m, vec->salt, vec->salt_len, vec->ikm, vec->ikm_len,
|
||||||
|
+ openssl_hmac_hkdf(m, vec->salt, vec->salt_len, vec->ikm, vec->ikm_len,
|
||||||
|
vec->info, vec->info_len, res, vec->okm_len);
|
||||||
|
test_assert_idx(memcmp(res->data, vec->okm, vec->okm_len) == 0, i);
|
||||||
|
}
|
||||||
|
@@ -283,7 +283,7 @@ static void test_hkdf_buffer(void)
|
||||||
|
test_begin("hkdf temporary buffer");
|
||||||
|
const struct test_vector_5869 *vec = &(test_vectors_5869[0]);
|
||||||
|
const struct hash_method *m = hash_method_lookup(vec->prf);
|
||||||
|
- buffer_t *tmp = t_hmac_hkdf(m, vec->salt, vec->salt_len, vec->ikm,
|
||||||
|
+ buffer_t *tmp = openssl_t_hmac_hkdf(m, vec->salt, vec->salt_len, vec->ikm,
|
||||||
|
vec->ikm_len, vec->info, vec->info_len,
|
||||||
|
vec->okm_len);
|
||||||
|
test_assert(tmp->used == vec->okm_len &&
|
@ -0,0 +1,25 @@
|
|||||||
|
m4: crypt_xxpg6.m4: Define _DEFAULT_SOURCE for current glibc
|
||||||
|
|
||||||
|
Current glibc no longer implements the CRYPT extension, so it does not
|
||||||
|
declare crypt in <unistd.h> in strict standard modes. The check
|
||||||
|
defines _XOPEN_SOURCE, which enables one of these modes. Defining
|
||||||
|
_DEFAULT_SOURCE as well again makes available the crypt function
|
||||||
|
prototype.
|
||||||
|
|
||||||
|
This avoids a configure check result change with compilers which do
|
||||||
|
not support implicit function declarations.
|
||||||
|
|
||||||
|
Submitted upstream: <https://github.com/dovecot/core/pull/193>
|
||||||
|
|
||||||
|
diff --git a/m4/crypt_xpg6.m4 b/m4/crypt_xpg6.m4
|
||||||
|
index 0085b2ac76..3a288a3713 100644
|
||||||
|
--- a/m4/crypt_xpg6.m4
|
||||||
|
+++ b/m4/crypt_xpg6.m4
|
||||||
|
@@ -6,6 +6,7 @@ AC_DEFUN([DOVECOT_CRYPT_XPG6], [
|
||||||
|
#define _XOPEN_SOURCE 4
|
||||||
|
#define _XOPEN_SOURCE_EXTENDED 1
|
||||||
|
#define _XOPEN_VERSION 4
|
||||||
|
+ #define _DEFAULT_SOURCE
|
||||||
|
#define _XPG4_2
|
||||||
|
#define _XPG6
|
||||||
|
#include <unistd.h>
|
@ -0,0 +1,19 @@
|
|||||||
|
.TH DOVECOT.CONF 5 2010/06/27 "dovecot" "File Formats and Conventions"
|
||||||
|
.SH NAME
|
||||||
|
\fBdovecot.conf\fP \- The configuration file for dovecot imap and pop3 server
|
||||||
|
|
||||||
|
.SH FULL PATH
|
||||||
|
.B /etc/dovecot.conf
|
||||||
|
|
||||||
|
.SH DESCRIPTION
|
||||||
|
The dovecot.conf file is a configuration file for the
|
||||||
|
.BR dovecot (1)
|
||||||
|
imap and pop3 server. The dovecot.conf configuration file contains description to all available options. Some of these options are described also in offline wiki documentation placed in /usr/share/doc/dovecot*/wiki/.
|
||||||
|
|
||||||
|
For backup purposes unmodified version of dovecot.conf can be found in /usr/share/doc/dovecot-<version>/example-config/dovecot.conf.default
|
||||||
|
|
||||||
|
.SH "SEE ALSO"
|
||||||
|
.BR doveadm (1),
|
||||||
|
.BR dovecot (1),
|
||||||
|
.I /usr/share/doc/dovecot*/wiki/
|
||||||
|
.I /usr/share/doc/dovecot*/dovecot.conf.default
|
@ -0,0 +1,108 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
#
|
||||||
|
# /etc/rc.d/init.d/dovecot
|
||||||
|
#
|
||||||
|
# Starts the dovecot daemon
|
||||||
|
#
|
||||||
|
# chkconfig: - 65 35
|
||||||
|
# description: Dovecot Imap Server
|
||||||
|
# processname: dovecot
|
||||||
|
# config: /etc/dovecot.conf
|
||||||
|
# config: /etc/sysconfig/dovecot
|
||||||
|
# pidfile: /var/run/dovecot/master.pid
|
||||||
|
|
||||||
|
### BEGIN INIT INFO
|
||||||
|
# Provides: dovecot
|
||||||
|
# Required-Start: $local_fs $network
|
||||||
|
# Required-Stop: $local_fs $network
|
||||||
|
# Should-Start: $remote_fs
|
||||||
|
# Should-Stop: $remote_fs
|
||||||
|
# Default-Start:
|
||||||
|
# Default-Stop: 0 1 2 3 4 5 6
|
||||||
|
# Short-Description: start and stop Dovecot Imap server
|
||||||
|
# Description: Dovecot is an IMAP server for Linux/UNIX-like systems,
|
||||||
|
# written with security primarily in mind. It also contains
|
||||||
|
# a small POP3 server.
|
||||||
|
### END INIT INFO
|
||||||
|
|
||||||
|
# Source function library.
|
||||||
|
. /etc/init.d/functions
|
||||||
|
|
||||||
|
if [ -f /etc/sysconfig/dovecot -a $UID -eq 0 ]; then
|
||||||
|
. /etc/sysconfig/dovecot
|
||||||
|
fi
|
||||||
|
|
||||||
|
RETVAL=0
|
||||||
|
prog="Dovecot Imap"
|
||||||
|
exec="/usr/sbin/dovecot"
|
||||||
|
config="/etc/dovecot/dovecot.conf"
|
||||||
|
pidfile="/var/run/dovecot/master.pid"
|
||||||
|
lockfile="/var/lock/subsys/dovecot"
|
||||||
|
|
||||||
|
start() {
|
||||||
|
[ $UID -eq 0 ] || exit 4
|
||||||
|
[ -x $exec ] || exit 5
|
||||||
|
[ -f $config ] || exit 6
|
||||||
|
|
||||||
|
echo -n $"Starting $prog: "
|
||||||
|
daemon --pidfile $pidfile $exec $OPTIONS
|
||||||
|
RETVAL=$?
|
||||||
|
[ $RETVAL -eq 0 ] && touch $lockfile
|
||||||
|
echo
|
||||||
|
}
|
||||||
|
|
||||||
|
stop() {
|
||||||
|
[ $UID -eq 0 ] || exit 4
|
||||||
|
echo -n $"Stopping $prog: "
|
||||||
|
killproc -p $pidfile $exec
|
||||||
|
RETVAL=$?
|
||||||
|
[ $RETVAL -eq 0 ] && rm -f $lockfile
|
||||||
|
echo
|
||||||
|
}
|
||||||
|
|
||||||
|
reload() {
|
||||||
|
[ $UID -eq 0 ] || exit 4
|
||||||
|
echo -n $"Reloading $prog: "
|
||||||
|
killproc -p $pidfile $exec -HUP
|
||||||
|
RETVAL=$?
|
||||||
|
echo
|
||||||
|
}
|
||||||
|
|
||||||
|
#
|
||||||
|
# See how we were called.
|
||||||
|
#
|
||||||
|
case "$1" in
|
||||||
|
start)
|
||||||
|
start
|
||||||
|
;;
|
||||||
|
stop)
|
||||||
|
stop
|
||||||
|
;;
|
||||||
|
reload)
|
||||||
|
reload
|
||||||
|
;;
|
||||||
|
force-reload|restart)
|
||||||
|
stop
|
||||||
|
sleep 1
|
||||||
|
start
|
||||||
|
RETVAL=$?
|
||||||
|
;;
|
||||||
|
condrestart|try-restart)
|
||||||
|
if [ -f $lockfile ]; then
|
||||||
|
stop
|
||||||
|
sleep 3
|
||||||
|
start
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
status)
|
||||||
|
status -p $pidfile $exec
|
||||||
|
RETVAL=$?
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo $"Usage: $0 {condrestart|try-restart|start|stop|restart|reload|force-reload|status}"
|
||||||
|
RETVAL=2
|
||||||
|
[ "$1" = 'usage' ] && RETVAL=0
|
||||||
|
esac
|
||||||
|
|
||||||
|
exit $RETVAL
|
||||||
|
|
@ -0,0 +1,5 @@
|
|||||||
|
#%PAM-1.0
|
||||||
|
auth required pam_nologin.so
|
||||||
|
auth include password-auth
|
||||||
|
account include password-auth
|
||||||
|
session include password-auth
|
@ -0,0 +1,3 @@
|
|||||||
|
# Here you can specify your dovecot command line options.
|
||||||
|
#
|
||||||
|
#OPTIONS=""
|
@ -0,0 +1,9 @@
|
|||||||
|
#Type Name ID GECOS Home directory Shell
|
||||||
|
g dovecot 97
|
||||||
|
u dovecot 97 "Dovecot IMAP server" /usr/libexec/dovecot /sbin/nologin
|
||||||
|
m dovecot dovecot
|
||||||
|
|
||||||
|
g dovenull -
|
||||||
|
u dovenull - "Dovecot - unauthorized user" /usr/libexec/dovecot /sbin/nologin
|
||||||
|
m dovenull dovenull
|
||||||
|
|
@ -0,0 +1,2 @@
|
|||||||
|
d /run/dovecot 0755 root dovecot -
|
||||||
|
|
@ -0,0 +1,3 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
/bin/systemctl -q is-enabled NetworkManager.service >/dev/null 2>&1 && /usr/bin/nm-online -q --timeout 30 ||:
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in new issue