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
# Extra files from gnulib, which override files from other sources.
gnulib_extra_files="
$build_aux/install-sh
$build_aux/missing
$build_aux/mdate-sh
$build_aux/texinfo.tex
$build_aux/depcomp
......
......@@ -78,9 +78,10 @@ _auth_try (void *item, void *data)
}
void
imap4d_auth_capability ()
imap4d_auth_capability (struct imap4d_session *session)
{
mu_list_foreach (imap_auth_list, _auth_capa, NULL);
if (session->tls_mode != tls_required)
mu_list_foreach (imap_auth_list, _auth_capa, NULL);
}
/*
......@@ -102,7 +103,7 @@ imap4d_authenticate (struct imap4d_session *session,
auth_type = imap4d_tokbuf_getarg (tok, IMAP4_ARG_1);
if (tls_required)
if (session->tls_mode == tls_required)
return io_completion_response (command, RESP_NO,
"Command disabled: Use STARTTLS first");
......
......@@ -78,7 +78,7 @@ imap4d_capability (struct imap4d_session *session,
mu_list_foreach (capa_list, print_capa, NULL);
imap4d_auth_capability ();
imap4d_auth_capability (session);
io_sendf ("\n");
return io_completion_response (command, RESP_OK, "Completed");
......
......@@ -287,18 +287,52 @@ cb_tls (void *data, mu_config_value_t *val)
static int
cb_tls_required (void *data, mu_config_value_t *val)
{
int *res = data;
int bv;
if (mu_cfg_assert_value_type (val, MU_CFG_STRING))
return 1;
if (mu_cfg_parse_boolean (val->v.string, &bv))
mu_error (_("Not a boolean value"));
else
*res = tls_required;
else if (bv)
tls_mode = tls_required;
return 0;
}
static mu_list_t auth_deny_user_list, auth_allow_user_list;
static mu_list_t auth_deny_group_list, auth_allow_group_list;
static int
check_user_groups (void *item, void *data)
{
char *gname = item;
struct group *gp;
char **p;
gp = getgrnam (gname);
if (!gp)
return 0;
if (gp->gr_gid == auth_data->gid)
return MU_ERR_EXISTS;
for (p = gp->gr_mem; *p; p++)
if (strcmp (*p, auth_data->name) == 0)
return MU_ERR_EXISTS;
return 0;
}
static int
imap_check_group_list (mu_list_t l)
{
int rc = mu_list_foreach (l, check_user_groups, NULL);
if (rc == MU_ERR_EXISTS)
return 0;
else if (rc == 0)
return MU_ERR_NOENT;
return rc;
}
static struct mu_cfg_param imap4d_srv_param[] = {
#ifdef WITH_TLS
{ "tls", mu_cfg_callback,
......@@ -309,6 +343,19 @@ static struct mu_cfg_param imap4d_srv_param[] = {
};
static struct mu_cfg_param imap4d_cfg_param[] = {
{ "allow-users", MU_CFG_LIST_OF(mu_cfg_string), &auth_allow_user_list,
0, NULL,
N_("Allow access to users from this list.") },
{ "deny-users", MU_CFG_LIST_OF(mu_cfg_string), &auth_deny_user_list,
0, NULL,
N_("Deny access to users from this list.") },
{ "allow-groups", MU_CFG_LIST_OF(mu_cfg_string), &auth_allow_group_list,
0, NULL,
N_("Allow access if the user group is in this list.") },
{ "deny-groups", MU_CFG_LIST_OF(mu_cfg_string), &auth_deny_group_list,
0, NULL,
N_("Deny access if the user group is in this list.") },
{ "homedir", mu_cfg_string, &modify_homedir, 0, NULL,
N_("Modify home directory.") },
{ "personal-namespace", MU_CFG_LIST_OF(mu_cfg_string), &namespace[NS_PRIVATE],
......@@ -367,6 +414,31 @@ static struct mu_cfg_param imap4d_cfg_param[] = {
int
imap4d_session_setup0 ()
{
if (auth_deny_user_list &&
mu_list_locate (auth_deny_user_list, auth_data->name, NULL) == 0)
{
mu_error (_("%s is in deny-users, rejecting"), auth_data->name);
return 1;
}
if (auth_allow_user_list &&
mu_list_locate (auth_allow_user_list, auth_data->name, NULL))
{
mu_error (_("%s is not in allow-users, rejecting"), auth_data->name);
return 1;
}
if (auth_deny_group_list &&
imap_check_group_list (auth_deny_group_list) == 0)
{
mu_error (_("%s is in deny-groups, rejecting"), auth_data->name);
return 1;
}
if (auth_allow_group_list &&
imap_check_group_list (auth_allow_group_list))
{
mu_error (_("%s is not in allow-groups, rejecting"), auth_data->name);
return 1;
}
real_homedir = mu_normalize_path (mu_strdup (auth_data->dir));
if (imap4d_check_home_dir (real_homedir, auth_data->uid, auth_data->gid))
return 1;
......
......@@ -293,7 +293,7 @@ extern int imap4d_append (struct imap4d_session *,
struct imap4d_command *, imap4d_tokbuf_t);
extern int imap4d_authenticate (struct imap4d_session *,
struct imap4d_command *, imap4d_tokbuf_t);
extern void imap4d_auth_capability (void);
extern void imap4d_auth_capability (struct imap4d_session *);
extern int imap4d_capability (struct imap4d_session *,
struct imap4d_command *, imap4d_tokbuf_t);
extern int imap4d_check (struct imap4d_session *,
......
......@@ -176,15 +176,14 @@ cb_tls (void *data, mu_config_value_t *val)
static int
cb_tls_required (void *data, mu_config_value_t *val)
{
int *res = data;
int bv;
if (mu_cfg_assert_value_type (val, MU_CFG_STRING))
return 1;
if (mu_cfg_parse_boolean (val->v.string, &bv))
mu_error (_("Not a boolean value"));
else
*res = tls_required;
else if (bv)
tls_mode = tls_required;
return 0;
}
......