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.
Showing
6 changed files
with
83 additions
and
12 deletions
... | @@ -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,9 +78,10 @@ _auth_try (void *item, void *data) | ... | @@ -78,9 +78,10 @@ _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 | mu_list_foreach (imap_auth_list, _auth_capa, NULL); | 83 | if (session->tls_mode != tls_required) |
84 | mu_list_foreach (imap_auth_list, _auth_capa, NULL); | ||
84 | } | 85 | } |
85 | 86 | ||
86 | /* | 87 | /* |
... | @@ -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,18 +287,52 @@ cb_tls (void *data, mu_config_value_t *val) | ... | @@ -287,18 +287,52 @@ 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) | ||
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 | |||
299 | return 0; | 322 | return 0; |
300 | } | 323 | } |
301 | 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; | ||
334 | } | ||
335 | |||
302 | static struct mu_cfg_param imap4d_srv_param[] = { | 336 | static struct mu_cfg_param imap4d_srv_param[] = { |
303 | #ifdef WITH_TLS | 337 | #ifdef WITH_TLS |
304 | { "tls", mu_cfg_callback, | 338 | { "tls", mu_cfg_callback, |
... | @@ -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 | ... | ... |
-
Please register or sign in to post a comment