Dovecot trusted CAs

2024-02-09 Thread Felix Auringer
Hello,

for our testing environment, I would like to configure a CA that is trusted by 
Dovecot when making TLS connections. As you can see below in the config 
snippets, this is for example used when proxying to itself during a login with 
credentials for the OIDC provider. The Dovecot documentation 
(https://doc.dovecot.org/configuration_manual/authentication/proxies/) states: 
"ssl_client_ca_dir or ssl_client_ca_file aren’t currently used for verifying 
the remote certificate, although ideally they will be in a future Dovecot 
version. For now you need to add the trusted remote certificates to ssl_ca."
Configuring a trusted CA via the `ssl_ca` config option works but is a little 
bit weird as this option originally is for TLS client authentication.

I added the CA certificate to the system trust store and removed `ssl_ca` and 
`ssl_client_ca_file`, but it seems that Dovecot does not use the system store. 
Or is there any config option I am missing?
Otherwise, are there any plans when `ssl_client_ca_file` will be used for 
remote connections (the documentation mentions that this would ideally be fixed 
in a later version)? And could I then use the aggregated Debian system trust 
store (/etc/ssl/certs/ca-certificates.crt) there?

Best regards,
Felix


`dovecot -n` (shortened):

# 2.3.19 (b3ad6004dc): /etc/dovecot/dovecot.conf
# Pigeonhole version 0.5.19 (4eae2f79)
# OS: Linux 6.7.3-arch1-1 x86_64 Debian 11.8

passdb {
  args = /etc/dovecot/oauth2-token.conf.ext
  driver = oauth2
  mechanisms = xoauth2 oauthbearer
}
passdb {
  args = /etc/dovecot/oauth2-password.conf.ext
  driver = oauth2
  mechanisms = plain login
}

protocols = imap lmtp
service imap-login {
  inet_listener imap {
port = 0
  }
  inet_listener imaps {
port = 993
ssl = yes
  }
}
service lmtp {
  inet_listener {
port = 24
ssl = no
  }
}
ssl = required
ssl_min_protocol = TLSv1.3
ssl_prefer_server_ciphers = yes

protocol lmtp {
  ssl_cert = 

Dovecot unified event filtering

2023-03-20 Thread Felix Auringer
Hello,

I have an issue with debug logging when using a custom plugin for Dovecot. In 
my plugin, I create a child event of the session's user event:

```c
struct event *plugin_event = event_create(list->ns->user->event);
event_set_name(plugin_event, "oidc_shared_mailboxes_plugin");
event_set_min_log_level(plugin_event, LOG_TYPE_WARNING);
event_set_append_log_prefix(plugin_event, "oidc-shared-mailboxes-plugin: ");
```

I then use passthrough events like the following:

```
e_debug(event_create_passthrough(data->event)->event(), "Modified 
mailbox_list_iter_init was called.");
e_warning(event_create_passthrough(event)->event(), "Did not find required key 
'roles' in the JWT body.");
```

`e_warning` and `e_error` work fine.
If I understand the documentation for the unified event filtering 
(https://doc.dovecot.org/configuration_manual/event_filter/#unified-filter-language)
 correctly, I should be able to enable debug logging for with `log_debug = 
event="oidc_shared_mailboxes_plugin"`. However, this setting has no influence 
on the logging behavior. The setting I have to set for the debug logging to 
work is `mail_debug = yes` (I do not have to set `log_debug` at all).

Is this intended behavior or am I doing something wrong?

Best regards,
Felix Auringer


Here is the output of `dovecot -n` (I removed the passdb, userdb, namespace, 
service, and managesieve settings as they cluttered the output):

```
# 2.3.19 (b3ad6004dc): /etc/dovecot/dovecot.conf
# Pigeonhole version 0.5.19 (4eae2f79)
# OS: Linux 5.10.0-15-amd64 x86_64 Debian 11.6
# Hostname: c3dd5b346d22
auth_mechanisms = plain login xoauth2 oauthbearer
debug_log_path = /dev/stdout
disable_plaintext_auth = no
first_valid_uid = 1000
info_log_path = /dev/stdout
last_valid_uid = 1000
log_debug = event="oidc_shared_mailboxes_plugin"
log_path = /dev/stdout
login_greeting = Hello there!  GIZ Mail!
mail_location = maildir:~/mail
mail_plugins = " oidc_shared_mailboxes"
plugin {
  oidc_shared_mailboxes_client_id = dovecot-test
}
protocols = imap lmtp
```
---
Gesellschaft für interkulturelles
Zusammenleben gGmbH (GIZ)
Felix Auringer
IT
Reformationsplatz 2
13597 Berlin

Tel: 030/513 0100 00; Fax: 030/513 0100 09 
www.giz.berlin; felix.auringer@giz.berlin

Amtsgericht Charlottenburg HRB 200872 B
Geschäftsführerin: Dr. Britta Marschke


OAUTH2 local validation

2022-11-16 Thread Felix Auringer

Hello,

<https://doc.dovecot.org/configuration_manual/authentication/oauth2/#local-validation> 
describes how to set up local validation for OAUTH2 with dovecot. This 
works fine as long as the keys are not rotated. In my experience, it is 
common for a client to try to validate a token with the cached key and 
update the cached keys when the local validation fails (e.g. via the 
/auth/realms//protocol/openid-connect/certs endpoint in 
Keycloak). This way, the client does not need to fetch new keys 
periodically but only when the old ones expired. If I understand it 
correctly, Dovecot reads the keys from a defined path but does not care 
how to update them. Did you have a nice way in mind how the keys should 
be refreshed when deciding not to do that in dovecot? Are you planning 
to add automatic refreshing of local validation keys to dovecot?
I am running dovecot in Docker and one way would be a cron job on the 
host that fetches new keys and updates the files inside the container 
via docker exec. It would work but it's not really a nice solution 
because from outside dovecot, the information whether the old keys are 
no longer valid, is not available and the whole process needs to run 
periodically (and thus way more often than actually necessary).


Best regards,
Felix Auringer
---
Gesellschaft für interkulturelles
Zusammenleben gGmbH (GIZ)
Felix Auringer
IT
Reformationsplatz 2
13597 Berlin

Tel: 030/513 0100 00; Fax: 030/513 0100 09 
www.giz.berlin; felix.auringer@giz.berlin


Amtsgericht Charlottenburg HRB 200872 B
Geschäftsführerin: Dr. Britta Marschke


Re: Dovecot ACLs and XOAUTH2

2022-08-24 Thread Felix Auringer

Hi,

On 8/22/22 14:04, Aki Tuomi wrote:

Currently the support is very limited. You can extract strings and numbers from a 
flat object. >
You should be able to extract the whole access token like that, although I 
didn't say in my previous mail that the %{oauth2:} is valid only within the 
oauth2 passdb currently.


I am using the oauth2 passdb and can extract other fields, for example 
`userdb_email=%{oauth2:email}` successfully. However, 
`userdb_token=%{oauth2:access_token}` does not work.



Additionally, the user's token is available as %w / %{password} on all passdbs. 
The best way I can think of right now is to use Lua passdb to complex token 
handling.


`%{password}` on the other hand works fine, so it's not a problem that 
`%{oauth2:access_token}` isn't working.


Thank you very much for your help, Aki!

Felix
---
Gesellschaft für interkulturelles
Zusammenleben gGmbH (GIZ)
Felix Auringer
IT
Reformationsplatz 2
13597 Berlin

Tel: 030/513 0100 00; Fax: 030/513 0100 09 
www.giz.berlin; felix.auringer@giz.berlin


Amtsgericht Charlottenburg HRB 200872 B
Geschäftsführerin: Dr. Britta Marschke


Re: Dovecot ACLs and XOAUTH2

2022-08-22 Thread Felix Auringer

On 8/22/22 10:14, Aki Tuomi wrote:

Hi!

You need to export them in passdb. You can do 
`userdb_some_field=%{oauth2:some_field}`.


That is exactly what I have been looking for, thank you! Is it also 
possible to extract arrays and objects from the token with this syntax? 
For example, I tried to save `allowed-origins` which is a list of 
strings but the field in the userdb was empty (but present). However, 
the field was processed according to the logs.


Furthermore, it seems that only keys that have a string or an array 
value are processed, so it may not even be possible to extract a parent 
object. For a structure like this:


```
{
  "azp": "roundcube-test",
  "realm_access": {
"roles": [...]
  },
  "resource_access": {
"realm-management": {
  "roles": [...]
},
"account": {
  "roles": [...]
}
  }
}
```

the log only shows:

auth: Debug: oauth2(...): Processing field azp
auth: Debug: oauth2(...): Processing field roles

auth: Debug: oauth2(...): Processing field roles

auth: Debug: oauth2(...): Processing field roles

It also doesn't work to extract the whole token with 
`userdb_token=%{oauth2:access_token}` (this syntax however works for 
proxy authentication). Otherwise, I could just save the whole token in 
the user database.


Is there some syntax I did not find in the documentation that would 
enable me to extract either the whole token or a whole JSON object / array?


Best regards,
Felix
---
Gesellschaft für interkulturelles
Zusammenleben gGmbH (GIZ)
Felix Auringer
IT
Reformationsplatz 2
13597 Berlin

Tel: 030/513 0100 00; Fax: 030/513 0100 09 
www.giz.berlin; felix.auringer@giz.berlin


Amtsgericht Charlottenburg HRB 200872 B
Geschäftsführerin: Dr. Britta Marschke


Re: Dovecot ACLs and XOAUTH2

2022-08-22 Thread Felix Auringer

Hi,

I tried to configure / implement the suggestions - thanks for them @Aki!

On 6/15/22 07:50, Aki Tuomi wrote:



On 14/06/2022 12:52 Felix Auringer  wrote:

  
Hi,


we're trying to set up an IMAP server using Dovecot as part of a new
email system in a middle-sized company (around 150 employees). We have a
keycloak identity server that is used for all logins and we would also
like to use it for the new email system so that the non-technical
employees (the majority) will have no issues using it.

It's very nice that XOAUTH2 is already included in Dovecot, it works
very well with our Roundcube web client. However, it seems that other
clients like Thunderbird or Android Apps like FairEmail are not easy to
set up as they have their XOAUTH providers hardcoded somewhere
(https://bugzilla.mozilla.org/show_bug.cgi?id=1602166). Are you aware of
any solution to integrate a dovecot server using XOAUTH2 into local
clients (like Thunderbird)? We are currently trying to do it with
passwords that can be set in Keycloak only for the purpose of email that
can then be used to receive a valid token via a direct access grant but
it's not a really nice solution as it introduces an additional password.



Unfortunately this is a client-side restriction. You should use either device passwords or 
you can use the "password grant mode" where dovecot authenticates to keycloak with 
username & password.


I used the password grant mode and it works fine!


Dovecot supports openid_configuration_url which should be supported eventually.


Sadly, the clients we intend to use do not support this yet but I will 
keep it in mind to hopefully use it later on.



Additionally, we would like to have all permission-related information
saved in our identity server. For email, this includes shared mailboxes
that a user is allowed to access. The ACL plugin that is used for shared
mailboxes currently reads the permissions from disk which is not really
feasible if the user base is large and setting these permissions should
happen automatically. We are thinking the best way to do this is to
encode the user's permissions in the token that dovecot receives in the
login process. But as the token is only available in the authentication
process and it does not seem to be intended to return such information
from the password database
(https://doc.dovecot.org/configuration_manual/authentication/password_database_extra_fields/),
we are unsure on how to process these information from the token. We did
not find any plugin hooks in the authentication processes and the normal
plugin hooks do not have access to information from the token anymore.
What do you think is the best way to do this? We would be okay modifying
some dovecot source code and contributing it back if desired.



You can't really store this in your identity server. Currently the only 
supported backing for acl information is file, so there is no mechanism for 
passing ACL permissions via passdb, and it would not be that feasible either.


My plan is rather to implement a new ACL backend that does not read the 
permissions from files but instead uses the permissions encoded in the 
JWT Token.



In general, dovecot makes fields present in JWT tokens available if you use 
local validation, you can use %{oauth2:field} to export them into mail process 
from passdb using pass_attrs:

pass_attrs = userdb_foo=%{oauth2:field}


I setup dovecot to do local validation and this seems to work fine. The 
auth process sends the configured oauth2 fields to its client (the log shows
`client passdb out: OK	1	user=<...>	email=felix.auringer@giz.berlin 
token=<...>` where the email field is extracted from the JWT token). 
However, I can not really find the place in the imap-login client (if 
that is even the right place to look) where the information are 
processed. The result should be available in `sasl_callback` in 
`src/login-common/client-common-auth.c`. But as far as I understand it, 
this calls `imap_client_auth_result` which does nothing with the reply 
if the authentication was successful. I also tried to read the values 
from the user struct using my plugin but could also not find any fields 
that contain the fields from the JWT.
Could you explain where the JWT fields are available for plugins after 
the login is finished? And / or point me to the place in the imap-login 
source where the JWT fields from the authentication reply are processed.





Best regards,
Felix Auringer
---


Regards,
--
Aki


Regards,
Felix Auringer
---
Gesellschaft für interkulturelles
Zusammenleben gGmbH (GIZ)
Felix Auringer
IT
Reformationsplatz 2
13597 Berlin

Tel: 030/513 0100 00; Fax: 030/513 0100 09 
www.giz.berlin; felix.auringer@giz.berlin


Amtsgericht Charlottenburg HRB 200872 B
Geschäftsführerin: Dr. Britta Marschke


Dovecot ACLs and XOAUTH2

2022-06-14 Thread Felix Auringer

Hi,

we're trying to set up an IMAP server using Dovecot as part of a new 
email system in a middle-sized company (around 150 employees). We have a 
keycloak identity server that is used for all logins and we would also 
like to use it for the new email system so that the non-technical 
employees (the majority) will have no issues using it.


It's very nice that XOAUTH2 is already included in Dovecot, it works 
very well with our Roundcube web client. However, it seems that other 
clients like Thunderbird or Android Apps like FairEmail are not easy to 
set up as they have their XOAUTH providers hardcoded somewhere 
(https://bugzilla.mozilla.org/show_bug.cgi?id=1602166). Are you aware of 
any solution to integrate a dovecot server using XOAUTH2 into local 
clients (like Thunderbird)? We are currently trying to do it with 
passwords that can be set in Keycloak only for the purpose of email that 
can then be used to receive a valid token via a direct access grant but 
it's not a really nice solution as it introduces an additional password.


Additionally, we would like to have all permission-related information 
saved in our identity server. For email, this includes shared mailboxes 
that a user is allowed to access. The ACL plugin that is used for shared 
mailboxes currently reads the permissions from disk which is not really 
feasible if the user base is large and setting these permissions should 
happen automatically. We are thinking the best way to do this is to 
encode the user's permissions in the token that dovecot receives in the 
login process. But as the token is only available in the authentication 
process and it does not seem to be intended to return such information 
from the password database 
(https://doc.dovecot.org/configuration_manual/authentication/password_database_extra_fields/), 
we are unsure on how to process these information from the token. We did 
not find any plugin hooks in the authentication processes and the normal 
plugin hooks do not have access to information from the token anymore. 
What do you think is the best way to do this? We would be okay modifying 
some dovecot source code and contributing it back if desired.


Best regards,
Felix Auringer
---
Gesellschaft für interkulturelles
Zusammenleben gGmbH (GIZ)
Felix Auringer
IT
Reformationsplatz 2
13597 Berlin

Tel: 030/513 0100 00; Fax: 030/513 0100 09 
www.giz.berlin; felix.auringer@giz.berlin


Amtsgericht Charlottenburg HRB 200872 B
Geschäftsführerin: Dr. Britta Marschke