Commit b5b49d26 b5b49d266063e4b6f1f5809b3b9f9a30eb335e47 by Sergey Poznyakoff

Fix bug in handling AUTHENTICATE command (imap4d). Add user/group ACLs.

The bug was introduced in commit 6e2a3758.

The ACLs allow administrators to limit access to IMAP services to
particular users or users belonging to particular groups.

* imap4d/authenticate.c (imap4d_auth_capability): Take session
pointer as argument.  Don't report authentication capabilities
if tls is required.
(imap4d_authenticate): Fix conditional.
* imap4d/capability.c (imap4d_capability): Update call to
imap4d_auth_capability.
* imap4d/imap4d.c (cb_tls_required): Set tls_mode.
(auth_deny_user_list,auth_allow_user_list)
(auth_deny_group_list,auth_allow_group_list): New statics.
(check_user_groups,imap_check_group_list): New static functions.
(imap4d_cfg_param) <allow-users,deny-users>
<allow-groups,deny-groups>: New configuration statements.
(imap4d_session_setup0): Check allow/deny lists.
* imap4d/imap4d.h (imap4d_auth_capability): Change signature.

* pop3d/pop3d.c (cb_tls_required): Set tls_mode.

* bootstrap (gnulib_extra_files): Update.
1 parent 9312d1f8
...@@ -104,7 +104,6 @@ tests_base=tests ...@@ -104,7 +104,6 @@ tests_base=tests
104 # Extra files from gnulib, which override files from other sources. 104 # Extra files from gnulib, which override files from other sources.
105 gnulib_extra_files=" 105 gnulib_extra_files="
106 $build_aux/install-sh 106 $build_aux/install-sh
107 $build_aux/missing
108 $build_aux/mdate-sh 107 $build_aux/mdate-sh
109 $build_aux/texinfo.tex 108 $build_aux/texinfo.tex
110 $build_aux/depcomp 109 $build_aux/depcomp
......
...@@ -78,8 +78,9 @@ _auth_try (void *item, void *data) ...@@ -78,8 +78,9 @@ _auth_try (void *item, void *data)
78 } 78 }
79 79
80 void 80 void
81 imap4d_auth_capability () 81 imap4d_auth_capability (struct imap4d_session *session)
82 { 82 {
83 if (session->tls_mode != tls_required)
83 mu_list_foreach (imap_auth_list, _auth_capa, NULL); 84 mu_list_foreach (imap_auth_list, _auth_capa, NULL);
84 } 85 }
85 86
...@@ -102,7 +103,7 @@ imap4d_authenticate (struct imap4d_session *session, ...@@ -102,7 +103,7 @@ imap4d_authenticate (struct imap4d_session *session,
102 103
103 auth_type = imap4d_tokbuf_getarg (tok, IMAP4_ARG_1); 104 auth_type = imap4d_tokbuf_getarg (tok, IMAP4_ARG_1);
104 105
105 if (tls_required) 106 if (session->tls_mode == tls_required)
106 return io_completion_response (command, RESP_NO, 107 return io_completion_response (command, RESP_NO,
107 "Command disabled: Use STARTTLS first"); 108 "Command disabled: Use STARTTLS first");
108 109
......
...@@ -78,7 +78,7 @@ imap4d_capability (struct imap4d_session *session, ...@@ -78,7 +78,7 @@ imap4d_capability (struct imap4d_session *session,
78 78
79 mu_list_foreach (capa_list, print_capa, NULL); 79 mu_list_foreach (capa_list, print_capa, NULL);
80 80
81 imap4d_auth_capability (); 81 imap4d_auth_capability (session);
82 io_sendf ("\n"); 82 io_sendf ("\n");
83 83
84 return io_completion_response (command, RESP_OK, "Completed"); 84 return io_completion_response (command, RESP_OK, "Completed");
......
...@@ -287,16 +287,50 @@ cb_tls (void *data, mu_config_value_t *val) ...@@ -287,16 +287,50 @@ cb_tls (void *data, mu_config_value_t *val)
287 static int 287 static int
288 cb_tls_required (void *data, mu_config_value_t *val) 288 cb_tls_required (void *data, mu_config_value_t *val)
289 { 289 {
290 int *res = data;
291 int bv; 290 int bv;
292 291
293 if (mu_cfg_assert_value_type (val, MU_CFG_STRING)) 292 if (mu_cfg_assert_value_type (val, MU_CFG_STRING))
294 return 1; 293 return 1;
295 if (mu_cfg_parse_boolean (val->v.string, &bv)) 294 if (mu_cfg_parse_boolean (val->v.string, &bv))
296 mu_error (_("Not a boolean value")); 295 mu_error (_("Not a boolean value"));
297 else 296 else if (bv)
298 *res = tls_required; 297 tls_mode = tls_required;
298 return 0;
299 }
300
301 static mu_list_t auth_deny_user_list, auth_allow_user_list;
302 static mu_list_t auth_deny_group_list, auth_allow_group_list;
303
304 static int
305 check_user_groups (void *item, void *data)
306 {
307 char *gname = item;
308 struct group *gp;
309 char **p;
310
311 gp = getgrnam (gname);
312 if (!gp)
299 return 0; 313 return 0;
314
315 if (gp->gr_gid == auth_data->gid)
316 return MU_ERR_EXISTS;
317
318 for (p = gp->gr_mem; *p; p++)
319 if (strcmp (*p, auth_data->name) == 0)
320 return MU_ERR_EXISTS;
321
322 return 0;
323 }
324
325 static int
326 imap_check_group_list (mu_list_t l)
327 {
328 int rc = mu_list_foreach (l, check_user_groups, NULL);
329 if (rc == MU_ERR_EXISTS)
330 return 0;
331 else if (rc == 0)
332 return MU_ERR_NOENT;
333 return rc;
300 } 334 }
301 335
302 static struct mu_cfg_param imap4d_srv_param[] = { 336 static struct mu_cfg_param imap4d_srv_param[] = {
...@@ -309,6 +343,19 @@ static struct mu_cfg_param imap4d_srv_param[] = { ...@@ -309,6 +343,19 @@ static struct mu_cfg_param imap4d_srv_param[] = {
309 }; 343 };
310 344
311 static struct mu_cfg_param imap4d_cfg_param[] = { 345 static struct mu_cfg_param imap4d_cfg_param[] = {
346 { "allow-users", MU_CFG_LIST_OF(mu_cfg_string), &auth_allow_user_list,
347 0, NULL,
348 N_("Allow access to users from this list.") },
349 { "deny-users", MU_CFG_LIST_OF(mu_cfg_string), &auth_deny_user_list,
350 0, NULL,
351 N_("Deny access to users from this list.") },
352 { "allow-groups", MU_CFG_LIST_OF(mu_cfg_string), &auth_allow_group_list,
353 0, NULL,
354 N_("Allow access if the user group is in this list.") },
355 { "deny-groups", MU_CFG_LIST_OF(mu_cfg_string), &auth_deny_group_list,
356 0, NULL,
357 N_("Deny access if the user group is in this list.") },
358
312 { "homedir", mu_cfg_string, &modify_homedir, 0, NULL, 359 { "homedir", mu_cfg_string, &modify_homedir, 0, NULL,
313 N_("Modify home directory.") }, 360 N_("Modify home directory.") },
314 { "personal-namespace", MU_CFG_LIST_OF(mu_cfg_string), &namespace[NS_PRIVATE], 361 { "personal-namespace", MU_CFG_LIST_OF(mu_cfg_string), &namespace[NS_PRIVATE],
...@@ -367,6 +414,31 @@ static struct mu_cfg_param imap4d_cfg_param[] = { ...@@ -367,6 +414,31 @@ static struct mu_cfg_param imap4d_cfg_param[] = {
367 int 414 int
368 imap4d_session_setup0 () 415 imap4d_session_setup0 ()
369 { 416 {
417 if (auth_deny_user_list &&
418 mu_list_locate (auth_deny_user_list, auth_data->name, NULL) == 0)
419 {
420 mu_error (_("%s is in deny-users, rejecting"), auth_data->name);
421 return 1;
422 }
423 if (auth_allow_user_list &&
424 mu_list_locate (auth_allow_user_list, auth_data->name, NULL))
425 {
426 mu_error (_("%s is not in allow-users, rejecting"), auth_data->name);
427 return 1;
428 }
429 if (auth_deny_group_list &&
430 imap_check_group_list (auth_deny_group_list) == 0)
431 {
432 mu_error (_("%s is in deny-groups, rejecting"), auth_data->name);
433 return 1;
434 }
435 if (auth_allow_group_list &&
436 imap_check_group_list (auth_allow_group_list))
437 {
438 mu_error (_("%s is not in allow-groups, rejecting"), auth_data->name);
439 return 1;
440 }
441
370 real_homedir = mu_normalize_path (mu_strdup (auth_data->dir)); 442 real_homedir = mu_normalize_path (mu_strdup (auth_data->dir));
371 if (imap4d_check_home_dir (real_homedir, auth_data->uid, auth_data->gid)) 443 if (imap4d_check_home_dir (real_homedir, auth_data->uid, auth_data->gid))
372 return 1; 444 return 1;
......
...@@ -293,7 +293,7 @@ extern int imap4d_append (struct imap4d_session *, ...@@ -293,7 +293,7 @@ extern int imap4d_append (struct imap4d_session *,
293 struct imap4d_command *, imap4d_tokbuf_t); 293 struct imap4d_command *, imap4d_tokbuf_t);
294 extern int imap4d_authenticate (struct imap4d_session *, 294 extern int imap4d_authenticate (struct imap4d_session *,
295 struct imap4d_command *, imap4d_tokbuf_t); 295 struct imap4d_command *, imap4d_tokbuf_t);
296 extern void imap4d_auth_capability (void); 296 extern void imap4d_auth_capability (struct imap4d_session *);
297 extern int imap4d_capability (struct imap4d_session *, 297 extern int imap4d_capability (struct imap4d_session *,
298 struct imap4d_command *, imap4d_tokbuf_t); 298 struct imap4d_command *, imap4d_tokbuf_t);
299 extern int imap4d_check (struct imap4d_session *, 299 extern int imap4d_check (struct imap4d_session *,
......
...@@ -176,15 +176,14 @@ cb_tls (void *data, mu_config_value_t *val) ...@@ -176,15 +176,14 @@ cb_tls (void *data, mu_config_value_t *val)
176 static int 176 static int
177 cb_tls_required (void *data, mu_config_value_t *val) 177 cb_tls_required (void *data, mu_config_value_t *val)
178 { 178 {
179 int *res = data;
180 int bv; 179 int bv;
181 180
182 if (mu_cfg_assert_value_type (val, MU_CFG_STRING)) 181 if (mu_cfg_assert_value_type (val, MU_CFG_STRING))
183 return 1; 182 return 1;
184 if (mu_cfg_parse_boolean (val->v.string, &bv)) 183 if (mu_cfg_parse_boolean (val->v.string, &bv))
185 mu_error (_("Not a boolean value")); 184 mu_error (_("Not a boolean value"));
186 else 185 else if (bv)
187 *res = tls_required; 186 tls_mode = tls_required;
188 return 0; 187 return 0;
189 } 188 }
190 189
......