[Patch] Allow sieve redirects to specified domains only

2024-06-10 Thread Kadlecsik József via dovecot
Hello,

The use case is simple: we have to forbid sieve redirects to outside, but 
should be able to redirect inside. The patch below adds a new sieve 
configuration option sieve_allowed_redirects to list the domains to which 
redirects are permitted and otherwise are not allowed. Please consider it.

diff --git a/pigeonhole/doc/example-config/conf.d/90-sieve.conf 
b/pigeonhole/doc/example-config/conf.d/90-sieve.conf
index 238bcf4..3b4ac65 100644
--- a/pigeonhole/doc/example-config/conf.d/90-sieve.conf
+++ b/pigeonhole/doc/example-config/conf.d/90-sieve.conf
@@ -126,6 +126,10 @@ plugin {
   # script execution. If set to 0, no redirect actions are allowed.
   #sieve_max_redirects = 4
 
+  # The comma/space separated list of email domains where redirection is 
allowed.
+  # If the list is empty, there is no restriction.
+  sieve_allowed_redirects =
+
   # The maximum number of personal Sieve scripts a single user can have. If set
   # to 0, no limit on the number of scripts is enforced.
   # (Currently only relevant for ManageSieve)
diff --git a/pigeonhole/src/lib-sieve/cmd-redirect.c 
b/pigeonhole/src/lib-sieve/cmd-redirect.c
index 6a3b0a4..17e9031 100644
--- a/pigeonhole/src/lib-sieve/cmd-redirect.c
+++ b/pigeonhole/src/lib-sieve/cmd-redirect.c
@@ -107,6 +107,24 @@ const struct sieve_action_def act_redirect = {
.commit = act_redirect_commit,
 };
 
+static bool
+cmd_redirect_allowed(struct sieve_instance *svinst,
+const struct smtp_address *to_address)
+{
+   const char **domain;
+   bool result = TRUE;
+
+   if (!svinst->allowed_redirects)
+   return TRUE;
+   for (domain = svinst->allowed_redirects; *domain != NULL; ++domain) {
+   if (strcasecmp(*domain, to_address->domain) == 0) {
+   return TRUE;
+   }
+   result = FALSE;
+   }
+   return result;
+}
+
 /*
  * Validation
  */
@@ -127,6 +145,12 @@ cmd_redirect_validate(struct sieve_validator *validator,
if (!sieve_validator_argument_activate(validator, cmd, arg, FALSE))
return FALSE;
 
+   if (svinst->max_redirects == 0) {
+   sieve_command_validate_error(validator, cmd,
+   "local policy prohibits the use of a redirect action");
+   return FALSE;
+   }
+
/* We can only assess the validity of the outgoing address when it is
 * a string literal. For runtime-generated strings this needs to be
 * done at runtime.
@@ -148,14 +172,17 @@ cmd_redirect_validate(struct sieve_validator *validator,
}
} T_END;
 
+   if (!result &&
+   !cmd_redirect_allowed(svinst,
+ sieve_address_parse_str(raw_address, 
))) {
+   sieve_command_validate_error(validator, cmd,
+   "local policy prohibits the use of a redirect 
action");
+   return FALSE;
+   }
+
return result;
}
 
-   if (svinst->max_redirects == 0) {
-   sieve_command_validate_error(validator, cmd,
-   "local policy prohibits the use of a redirect action");
-   return FALSE;
-   }
return TRUE;
 }
 
@@ -238,6 +265,11 @@ cmd_redirect_operation_execute(const struct 
sieve_runtime_env *renv,
"local policy prohibits the use of a redirect action");
return SIEVE_EXEC_FAILURE;
}
+   if (!cmd_redirect_allowed(svinst, to_address)) {
+   sieve_runtime_error(renv, NULL,
+   "local policy prohibits the use of a redirect action");
+   return SIEVE_EXEC_FAILURE;
+   }
 
if (sieve_runtime_trace_active(renv, SIEVE_TRLVL_ACTIONS)) {
sieve_runtime_trace(renv, 0, "redirect action");
diff --git a/pigeonhole/src/lib-sieve/sieve-common.h 
b/pigeonhole/src/lib-sieve/sieve-common.h
index e79fb4d..d980c9d 100644
--- a/pigeonhole/src/lib-sieve/sieve-common.h
+++ b/pigeonhole/src/lib-sieve/sieve-common.h
@@ -209,6 +209,7 @@ struct sieve_instance {
const struct smtp_address *user_email, *user_email_implicit;
struct sieve_address_source redirect_from;
unsigned int redirect_duplicate_period;
+   const char **allowed_redirects;
 };
 
 /*
diff --git a/pigeonhole/src/lib-sieve/sieve-settings.c 
b/pigeonhole/src/lib-sieve/sieve-settings.c
index 47f70da..70addc7 100644
--- a/pigeonhole/src/lib-sieve/sieve-settings.c
+++ b/pigeonhole/src/lib-sieve/sieve-settings.c
@@ -267,4 +267,10 @@ void sieve_settings_load(struct sieve_instance *svinst)
svinst->user_email = address;
}
}
+   svinst->allowed_redirects = NULL;
+   str_setting = sieve_setting_get(svinst, "sieve_allowed_redirects");
+   if (str_setting != NULL && *str_setting != '\0') {
+   

Re: Strange "IMAP connection broken (server response)" errors

2018-03-20 Thread Kadlecsik József
On Fri, 20 Oct 2017, Kadlecsik József wrote:

> On Fri, 6 Oct 2017, Jozsef Kadlecsik wrote:
> 
> > We upgraded one of our dovecot servers to debian stretch with dovecot 
> > 2.2.27 and since then one of our users has been experiencing random IMAP 
> > failures.
> > 
> > On the client side the user runs alpine and the corresponding debug lines:
> > 
> > IMAP DEBUG 14:22:02.216167: 0011 FETCH 6 (BODYSTRUCTURE FLAGS)
> > 
> > 14:22:02.217396
> > IMAP 14:22:02 10/6 mm_notify bye: 
> > {[127.0.0.1]:1555/imap/user="ha4aa"}INBOX: [CLOSED] IMAP connection broken 
> > (server response)
> 
> The date of the last rawlog line corresponds to an ssl debug log of 
> dovecot (from the last run):
> 
> Oct 20 18:50:05 mail2 dovecot: imap-login: Debug: SSL error: SSL_read() 
> failed: error:140E0197:SSL routines:SSL_shutdown:shutdown while in init

It is an openssl compatibility issue introduced in OpenSSL 1.0.2f. The 
IMAP failures could be solved with the following patches, which are 
similar to what nginx uses (http://hg.nginx.org/nginx/rev/062c189fee20):

For Dovecot 2.2.35:

diff --git a/src/lib-ssl-iostream/iostream-openssl.c 
b/src/lib-ssl-iostream/iostream-openssl.c
index 68ec221..31d1017 100644
--- a/src/lib-ssl-iostream/iostream-openssl.c
+++ b/src/lib-ssl-iostream/iostream-openssl.c
@@ -324,7 +324,7 @@ static void openssl_iostream_unref(struct ssl_iostream 
*ssl_io)
 
 static void openssl_iostream_destroy(struct ssl_iostream *ssl_io)
 {
-   if (SSL_shutdown(ssl_io->ssl) != 1) {
+   if (!SSL_in_init(ssl_io->ssl) && SSL_shutdown(ssl_io->ssl) != 1) {
/* if bidirectional shutdown fails we need to clear
   the error queue */
openssl_iostream_clear_errors();
diff --git a/src/login-common/ssl-proxy-openssl.c 
b/src/login-common/ssl-proxy-openssl.c
index 947c8ef..3ac6823 100644
--- a/src/login-common/ssl-proxy-openssl.c
+++ b/src/login-common/ssl-proxy-openssl.c
@@ -833,7 +833,7 @@ void ssl_proxy_destroy(struct ssl_proxy *proxy)
if (proxy->io_plain_write != NULL)
io_remove(>io_plain_write);
 
-   if (SSL_shutdown(proxy->ssl) != 1) {
+   if (!SSL_in_init(proxy->ssl) && SSL_shutdown(proxy->ssl) != 1) {
/* if bidirectional shutdown fails we need to clear
   the error queue. */
openssl_iostream_clear_errors();

For Dovecot master branch:

diff --git a/src/lib-ssl-iostream/iostream-openssl.c 
b/src/lib-ssl-iostream/iostream-openssl.c
index 45de412..ed1f0a4 100644
--- a/src/lib-ssl-iostream/iostream-openssl.c
+++ b/src/lib-ssl-iostream/iostream-openssl.c
@@ -345,7 +345,7 @@ static void openssl_iostream_unref(struct ssl_iostream 
*ssl_io)
 
 static void openssl_iostream_destroy(struct ssl_iostream *ssl_io)
 {
-   if (SSL_shutdown(ssl_io->ssl) != 1) {
+   if (!SSL_in_init(ssl_io->ssl) && SSL_shutdown(ssl_io->ssl) != 1) {
/* if bidirectional shutdown fails we need to clear
   the error queue */
openssl_iostream_clear_errors();

Best regards,
Jozsef
--
E-mail : kadlecsik.joz...@wigner.mta.hu
PGP key: http://www.kfki.hu/~kadlec/pgp_public_key.txt
Address: Wigner Research Centre for Physics, Hungarian Academy of Sciences
 H-1525 Budapest 114, POB. 49, Hungary

Re: authenticate as userA, but get authorization to user userB's account

2017-10-25 Thread Kadlecsik József
On Wed, 25 Oct 2017, Heiko Schlittermann wrote:

> Kadlecsik József <kadlecsik.joz...@wigner.mta.hu> (Mi 25 Okt 2017 13:28:22 
> CEST):
> > > sa...@example.com, using the credentials of the very own account (say 
> > > h...@example.com)?
> > 
> > We faced the same problem and solved it with a PAM module:
> …
> > The users must use the username "groupusername*realusername" and the
> 
> Yes, this follows the maser-user idea. Great. I'm curious if the master 
> user mechanism isn't usable. Maybe it is, I'll check this.

The master users are allowed to impersonate anyone and at the same time 
cannot login as themselves. Those were the issues why we couldn't choose 
to use master users.
 
Best regards,
Jozsef
--
E-mail : kadlecsik.joz...@wigner.mta.hu
PGP key: http://www.kfki.hu/~kadlec/pgp_public_key.txt
Address: Wigner Research Centre for Physics, Hungarian Academy of Sciences
 H-1525 Budapest 114, POB. 49, Hungary


Re: authenticate as userA, but get authorization to user userB's account

2017-10-25 Thread Kadlecsik József
Hi,

On Wed, 25 Oct 2017, Heiko Schlittermann wrote:

> given a small organization. There are *personal* mailboxes (mailbox per 
> user, incl. subfolders et cetera). The users can share specic folders 
> via the ACL (we call it "other users/", Dovecot calls it "shared" 
> folder. Additionally there are mailboxes Dovecot calls "public" (we use 
> the term "groups/"). They are not associated with a specific account, 
> but acessible via ACL only. (Good example for the latter is 
> "i...@example.com")
> 
> But now they're seeking for a way to implement "role" Accounts.
> 
> We could create new "role" users, share the password and create an 
> additional account within the mail client (thunderbird) they use. From 
> users perspective it is exactly what they want. But I dislike the idea 
> of sharing the password.
> 
> Question: Is there any way to split the authentication from the 
> authorization within common mail clients (as Thunderbird) in combination 
> with Dovecot. That is, doing something like logging in to the account 
> sa...@example.com, using the credentials of the very own account (say 
> h...@example.com)?

We faced the same problem and solved it with a PAM module:

https://gitlab.kfki.hu/kadlec/pam-groupuser

Any kind of MUA are supported with whatever background authentication you 
have. Here follows the README:

This tiny PAM module makes possible to authenticate to group user 
accounts, where

- the group user has got an own group with the same name as its username
- the group members are real users, who want to access the resources
  (email, files) of the group user

The pam_groupuser.so module must be referred two times in the PAM
configuration for the given service/resources, i.e.

auth required pam_groupuser.so

auth required pam_groupuser.so second-pass

The users must use the username "groupusername*realusername" and the
password belonging to "realusername". The first call to pam_groupusers.so
sets the username for PAM to "realusername", so the authentication modules
will use the real username for authentication. The second call to
pam_groupusers.so sets the username for PAM to "groupusername", so the
account and session environment is set up according to groupusername.

The applications which supports this kind of setups:

- dovecot POP/IMAP server
- vsfptd FTP server

Addendum: for dovecot, add "*" to the allowed username chars to 
auth_username_chars in /etc/dovecot/conf.d/10-auth.conf.

Best regards,
Jozsef
--
E-mail : kadlecsik.joz...@wigner.mta.hu
PGP key: http://www.kfki.hu/~kadlec/pgp_public_key.txt
Address: Wigner Research Centre for Physics, Hungarian Academy of Sciences
 H-1525 Budapest 114, POB. 49, Hungary


Re: Strange "IMAP connection broken (server response)" errors

2017-10-20 Thread Kadlecsik József
Hello,

On Fri, 6 Oct 2017, Jozsef Kadlecsik wrote:

> We upgraded one of our dovecot servers to debian stretch with dovecot 
> 2.2.27 and since then one of our users has been experiencing random IMAP 
> failures.
> 
> We enabled raw logging at the server side and it shows normal IMAP 
> commands/responses:
> 
> 1507292522.222427 * 6 FETCH (FLAGS () BODYSTRUCTURE ("text" "plain" 
> ("charset" "us-ascii")
>  NIL NIL "7bit" 4645 112 NIL NIL NIL NIL))
> 1507292522.222653 0011 OK Fetch completed (0.006 + 0.000 secs).
> 
> On the client side the user runs alpine and the corresponding debug lines:
> 
> IMAP DEBUG 14:22:02.216167: 0011 FETCH 6 (BODYSTRUCTURE FLAGS)
> 
> 14:22:02.217396
> IMAP 14:22:02 10/6 mm_notify bye: 
> {[127.0.0.1]:1555/imap/user="ha4aa"}INBOX: [CLOSED] IMAP connection broken 
> (server response)
> 
> 14:22:02.217471
> IMAP 14:22:02 10/6 mm_log error: [CLOSED] IMAP connection broken (server 
> response)
> 
> The "[127.0.0.1]:1555/imap/user="ha4aa" part in the log comes from an 
> socat inserted between the client and the server to check independently 
> the imap session. According to socat, the server response didn't reach 
> the client!:
> 
> 0010 OK Fetch completed (0.005 + 0.000 secs).\r
> > 2017/10/06 14:22:02.216299  length=40 from=845 to=884
> 0011 FETCH 6 (BODYSTRUCTURE FLAGS)\r
> 
> and here ends the socat log.

The date of the last rawlog line corresponds to an ssl debug log of 
dovecot (from the last run):

Oct 20 18:50:05 mail2 dovecot: imap-login: Debug: SSL error: SSL_read() 
failed: error:140E0197:SSL routines:SSL_shutdown:shutdown while in init

I added the patch "openssl: Clear error queue after an incomplete 
SSL_shutdown", recompiled the package but it did not help.

Any help is highly welcomed!

Best regards,
Jozsef
--
E-mail : kadlecsik.joz...@wigner.mta.hu
PGP key: http://www.kfki.hu/~kadlec/pgp_public_key.txt
Address: Wigner Research Centre for Physics, Hungarian Academy of Sciences
 H-1525 Budapest 114, POB. 49, Hungary