1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
|
Master users/passwords
======================
It's possible to configure master users who are able to log in as other users.
It's also possible to directly log in as any user using a master password.
Master users
------------
There are two ways for master users to log in as other users:
1. Give the login username in the <SASL mechanism's>
[Authentication.Mechanisms.txt] authorization ID field.
2. Specify both the master username and the login username in the same
username field. The usernames are separated by a string configured by the
'auth_master_user_separator' setting. UW-IMAP uses "*" as the separator, so
that could be a good choice. Using "*" as the separator, the master user
would log in as "login_user*master_user".
Master users are configured by adding a new <passdb> [PasswordDatabase.txt]
with 'master=yes' setting. The users in the master passdb cannot log in as
themselves, only as other people. That means they don't need to exist in the
<userdb> [UserDatabase.txt], because the userdb lookup is done only for the
user they're logging in as.
You should also add the 'pass=yes' setting to the master passdb if possible. It
means that Dovecot verifies that the login user really exists before allowing
the master user to log in. Without the setting if a nonexistent login username
is given, depending on the configuration, it could either return an internal
login error (the userdb lookup failed) or create a whole new user (with eg.
<static userdb> [UserDatabase.Static.txt]). 'pass=yes' doesn't work with PAM or
LDAP with 'auth_bind=yes', because both of them require knowing the user's
password.
'pass=yes' is especially useful with a <Checkpassword>
[PasswordDatabase.CheckPassword.txt] passdb because the script gets both the
login and the master username as environment variables. Other passdbs see only
the login username in '%u'. In the future there will probably be another
setting to make the user verification to be done from userdb.
If you want master users to be able to log in as themselves, you'll need to
either add the user to the normal passdb or add the passdb to 'dovecot.conf'
twice, with and without 'master=yes'. Note that if the passdbs point to
different locations, the user can have a different password when logging in as
other users than when logging in as himself. This is a good idea since it can
avoid accidentally logging in as someone else.
Usually it's better to have only a few special master users that are used
*only* to log in as other people. One example could be a special "spam" master
user that trains the users' spam filters by reading the messages from the
user's spam mailbox.
ACLs
----
If <ACL.txt> plugin is enabled, the Master user is still subject to ACLs just
like any other user, which means that by default the master user has no access
to any mailboxes of the user. The options for handling this are:
1. Adding a global <ACL.txt> for the master user. You can create a "default
ACL", that applies to all mailboxes. See example below.
2. Set 'plugin { acl_user=%u } ' This preserves the master_user for other
purposes (e.g. %{master_user} variable).
3. Set 'plugin { master_user=%u } ' This fully hides that master user login is
being used.
Example configuration
---------------------
---%<-------------------------------------------------------------------------
auth_master_user_separator = *
passdb {
driver = passwd-file
args = /etc/dovecot/passwd.masterusers
master = yes
pass = yes
}
passdb {
driver = shadow
}
userdb {
driver = passwd
}
---%<-------------------------------------------------------------------------
To grant the masteruser access to all Mailboxes, the 'dovecot-acl' file can
contain:
---%<-------------------------------------------------------------------------
* user=masteruser lr
---%<-------------------------------------------------------------------------
Where the 'passwd.masterusers' file would contain the master usernames and
passwords:
---%<-------------------------------------------------------------------------
admin:{SHA1}nU4eI71bcnBGqeO0t9tXvY1u5oQ=
admin2:{SHA1}i+UhJqb95FCnFio2UdWJu1HpV50=
---%<-------------------------------------------------------------------------
One way to create this master file is to use the htaccess program as follows:
---%<-------------------------------------------------------------------------
htpasswd -b -c -s passwd.masterusers user password
---%<-------------------------------------------------------------------------
SQL Example
-----------
The master passdb doesn't have to be passwd-file, it could be an SQL query as
well:
---%<-------------------------------------------------------------------------
auth_master_user_separator = *
passdb {
driver = sql
args = /etc/dovecot/dovecot-sql-master.conf.ext
master = yes
pass = yes
}
passdb {
driver = sql
args = /etc/dovecot/dovecot-sql.conf.ext
}
userdb {
driver = sql
args = /etc/dovecot/dovecot-sql.conf.ext
}
}
---%<-------------------------------------------------------------------------
'dovecot-sql-master.conf.ext' would contain all the normal connection settings
and a 'password_query':
---%<-------------------------------------------------------------------------
password_query = SELECT password FROM users WHERE userid = '%u' and master_user
= true
---%<-------------------------------------------------------------------------
Testing
-------
---%<-------------------------------------------------------------------------
# telnet localhost 143
* OK Dovecot ready.
1 login loginuser*masteruser masterpass
1 OK Logged in.
---%<-------------------------------------------------------------------------
If you had any problems, set 'auth_debug=yes' and look at the logs.
Master passwords
----------------
You can configure a passdb which first performs authentication using the master
password. Then it continues to the primary passdb to verify that the user
exists and get other extra fields.
---%<-------------------------------------------------------------------------
# master password passdb
passdb {
driver = static
default_fields = password=master-password
result_success = continue
}
# primary passdb
passdb {
driver = pam
}
---%<-------------------------------------------------------------------------
Advanced SQL Examples
---------------------
In these example we will create 3 kinds of master users. The first will be
users who can read all email for all domains. The next example will be users
who can read all email for their domain only. The third example will be users
who can read email of domains listed in a separate ownership table. We will use
MySQL and create 2 tables with the following structure.
---%<-------------------------------------------------------------------------
CREATE TABLE `users` (
`uid` int(4) NOT NULL AUTO_INCREMENT,
`user_name` varchar(80) NOT NULL,
`domain_name` varchar(80) NOT NULL,
`password` varchar(60) DEFAULT NULL,
`last_login` datetime DEFAULT NULL,
`masteradmin` tinyint(1) NOT NULL DEFAULT '0',
`owns_domain` tinyint(1) NOT NULL DEFAULT '0',
UNIQUE KEY `emaillookup` (`domain_name`,`user_name`),
UNIQUE KEY `uid` (`uid`)
) ENGINE=MyISAM AUTO_INCREMENT=995 DEFAULT CHARSET=latin
CREATE TABLE `ownership` (
`login_id` varchar(128) NOT NULL,
`owned_object` varchar(128) NOT NULL,
UNIQUE KEY `login_id_full` (`login_id`,`owned_object`),
KEY `login_id` (`login_id`),
KEY `owned_object` (`owned_object`),
KEY `login_id_index` (`login_id`),
KEY `owned_object_index` (`owned_object`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1
---%<-------------------------------------------------------------------------
The dovecot.conf file for all 3 master user configurations will be as follows:
---%<-------------------------------------------------------------------------
passdb {
driver = sql
args = /etc/dovecot/ownership-sql.conf
master = yes
pass = yes
}
passdb {
driver = sql
args = /etc/dovecot/domain-owner-sql.conf
master = yes
pass = yes
}
passdb {
driver = sql
args = /etc/dovecot/masteradmin-sql.conf
master = yes
pass = yes
}
passdb {
args = /etc/dovecot/sql.conf
driver = sql
}
---%<-------------------------------------------------------------------------
Before we get into the master user tricks, we start with normal email
authentication. The query for that is as follows:
---%<-------------------------------------------------------------------------
password_query = SELECT user_name, domain_name, password FROM users WHERE
user_name = '%n' AND domain_name = '%d'
---%<-------------------------------------------------------------------------
In this first example master admin suppose you want to allow a few people to be
master users over all domains. These users will have the "masteradmin" field
set to 1. The query would be:
---%<-------------------------------------------------------------------------
password_query = SELECT user_name, domain_name, password FROM users WHERE
user_name = '%n' AND domain_name = '%d' AND masteradmin='1'
---%<-------------------------------------------------------------------------
In the second example suppose you are hosting multiple domains and you want to
allow a few users to become master users of their domain only.
Your query would be as follows:
---%<-------------------------------------------------------------------------
password_query = SELECT user_name, domain_name, password FROM users WHERE
user_name = '%n' \
AND domain_name = '%d' AND owns_domain='1' AND '%d'='%{login_domain}'
---%<-------------------------------------------------------------------------
This will allow you to log in using the following to read Joe's email if
master@dovecot.org is flagged as the domain_owner.
---%<-------------------------------------------------------------------------
joe@dovecot.org*master@dovecot.org
---%<-------------------------------------------------------------------------
In this third example we have a table of owners. There are a list of pairs
between owner email addresses and domains that are owned. That way if a person
controls a lot of domains then they can view all the users in all the domains
they control. The query would be as follows:
---%<-------------------------------------------------------------------------
password_query = SELECT user_name, domain_name, password FROM users, ownership
WHERE \
user_name = '%n' AND domain_name = '%d' AND login_id='%u' AND
owned_object='%{login_domain}'
---%<-------------------------------------------------------------------------
If you really want to get tricky and efficient you can combine all 3 queries
into one giant query that does everything.
---%<-------------------------------------------------------------------------
password_query = SELECT user_name, domain_name, password FROM users, ownership
WHERE \
user_name = '%n' AND domain_name = '%d' AND ( \
(masteradmin='1') OR \
(owns_domain='1' AND '%d'='%{login_domain}') OR \
(login_id='%u' and owned_object='%{login_domain}')) \
group by uid
---%<-------------------------------------------------------------------------
(This file was created from the wiki on 2019-06-19 12:42)
|