Skip to content

Commit

Permalink
Patch for issue #3458
Browse files Browse the repository at this point in the history
This patch implements verification of pam_rhost against
rules stored in LDAP entry of a user.

2017-09-22: Fixed potential issue with pam_rhost being NULL
            and when pam_rhost is empty (local access)
  • Loading branch information
akamensky committed Sep 22, 2017
1 parent 2ccfa95 commit dfad3dd
Show file tree
Hide file tree
Showing 12 changed files with 114 additions and 0 deletions.
1 change: 1 addition & 0 deletions src/config/SSSDConfig/__init__.py.in
Original file line number Diff line number Diff line change
Expand Up @@ -343,6 +343,7 @@ option_strings = {
'ldap_user_shadow_flag' : _('shadowFlag attribute'),
'ldap_user_authorized_service' : _('Attribute listing authorized PAM services'),
'ldap_user_authorized_host' : _('Attribute listing authorized server hosts'),
'ldap_user_authorized_rhost' : _('Attribute listing authorized server rhosts'),
'ldap_user_krb_last_pwd_change' : _('krbLastPwdChange attribute'),
'ldap_user_krb_password_expiration' : _('krbPasswordExpiration attribute'),
'ldap_pwd_attribute' : _('Attribute indicating that server side password policies are active'),
Expand Down
1 change: 1 addition & 0 deletions src/config/cfg_rules.ini
Original file line number Diff line number Diff line change
Expand Up @@ -658,6 +658,7 @@ option = ldap_uri
option = ldap_user_ad_account_expires
option = ldap_user_ad_user_account_control
option = ldap_user_authorized_host
option = ldap_user_authorized_rhost
option = ldap_user_authorized_service
option = ldap_user_auth_type
option = ldap_user_certificate
Expand Down
1 change: 1 addition & 0 deletions src/config/etc/sssd.api.d/sssd-ldap.conf
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ ldap_user_krb_last_pwd_change = str, None, false
ldap_user_krb_password_expiration = str, None, false
ldap_user_authorized_service = str, None, false
ldap_user_authorized_host = str, None, false
ldap_user_authorized_rhost = str, None, false
ldap_pwd_attribute = str, None, false
ldap_user_ad_account_expires = str, None, false
ldap_user_ad_user_account_control = str, None, false
Expand Down
1 change: 1 addition & 0 deletions src/db/sysdb.h
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@

#define SYSDB_AUTHORIZED_SERVICE "authorizedService"
#define SYSDB_AUTHORIZED_HOST "authorizedHost"
#define SYSDB_AUTHORIZED_RHOST "authorizedRHost"

#define SYSDB_NETGROUP_TRIPLE "netgroupTriple"
#define SYSDB_ORIG_NETGROUP_MEMBER "originalMemberNisNetgroup"
Expand Down
32 changes: 32 additions & 0 deletions src/man/sssd-ldap.5.xml
Original file line number Diff line number Diff line change
Expand Up @@ -829,6 +829,34 @@
</listitem>
</varlistentry>

<varlistentry>
<term>ldap_user_authorized_rhost (string)</term>
<listitem>
<para>
If access_provider=ldap and
ldap_access_order=rhost, SSSD will use the presence
of the rhost attribute in the user's LDAP entry to
determine access privilege. Similarly to host
verification process.
</para>
<para>
An explicit deny (!rhost) is resolved first. Second,
SSSD searches for explicit allow (rhost) and finally
for allow_all (*).
</para>
<para>
Please note that the ldap_access_order
configuration option <emphasis>must</emphasis>
include <quote>rhost</quote> in order for the
ldap_user_authorized_rhost option
to work.
</para>
<para>
Default: rhost
</para>
</listitem>
</varlistentry>

<varlistentry>
<term>ldap_user_certificate (string)</term>
<listitem>
Expand Down Expand Up @@ -2088,6 +2116,10 @@ ldap_access_filter = (employeeType=admin)
<emphasis>host</emphasis>: use the host attribute
to determine access
</para>
<para>
<emphasis>rhost</emphasis>: use the rhost attribute
to determine whether remote host can access
</para>
<para>
Default: filter
</para>
Expand Down
1 change: 1 addition & 0 deletions src/providers/ad/ad_opts.c
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,7 @@ struct sdap_attr_map ad_2008r2_user_map[] = {
{ "ldap_user_ad_user_account_control", "userAccountControl", SYSDB_AD_USER_ACCOUNT_CONTROL, NULL},
{ "ldap_ns_account_lock", NULL, SYSDB_NS_ACCOUNT_LOCK, NULL},
{ "ldap_user_authorized_host", NULL, SYSDB_AUTHORIZED_HOST, NULL },
{ "ldap_user_authorized_rhost", NULL, SYSDB_AUTHORIZED_RHOST, NULL },
{ "ldap_user_nds_login_disabled", NULL, SYSDB_NDS_LOGIN_DISABLED, NULL },
{ "ldap_user_nds_login_expiration_time", NULL, SYSDB_NDS_LOGIN_EXPIRATION_TIME, NULL },
{ "ldap_user_nds_login_allowed_time_map", NULL, SYSDB_NDS_LOGIN_ALLOWED_TIME_MAP, NULL },
Expand Down
1 change: 1 addition & 0 deletions src/providers/ipa/ipa_opts.c
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,7 @@ struct sdap_attr_map ipa_user_map[] = {
{ "ldap_user_ad_user_account_control", "userAccountControl", SYSDB_AD_USER_ACCOUNT_CONTROL, NULL},
{ "ldap_ns_account_lock", "nsAccountLock", SYSDB_NS_ACCOUNT_LOCK, NULL},
{ "ldap_user_authorized_host", "host", SYSDB_AUTHORIZED_HOST, NULL },
{ "ldap_user_authorized_rhost", NULL, SYSDB_AUTHORIZED_RHOST, NULL },
{ "ldap_user_nds_login_disabled", "loginDisabled", SYSDB_NDS_LOGIN_DISABLED, NULL },
{ "ldap_user_nds_login_expiration_time", "loginExpirationTime", SYSDB_NDS_LOGIN_EXPIRATION_TIME, NULL },
{ "ldap_user_nds_login_allowed_time_map", "loginAllowedTimeMap", SYSDB_NDS_LOGIN_ALLOWED_TIME_MAP, NULL },
Expand Down
2 changes: 2 additions & 0 deletions src/providers/ldap/ldap_init.c
Original file line number Diff line number Diff line change
Expand Up @@ -286,6 +286,8 @@ static errno_t set_access_rules(TALLOC_CTX *mem_ctx,
access_ctx->access_rule[c] = LDAP_ACCESS_SERVICE;
} else if (strcasecmp(order_list[c], LDAP_ACCESS_HOST_NAME) == 0) {
access_ctx->access_rule[c] = LDAP_ACCESS_HOST;
} else if (strcasecmp(order_list[c], LDAP_ACCESS_RHOST_NAME) == 0) {
access_ctx->access_rule[c] = LDAP_ACCESS_RHOST;
} else if (strcasecmp(order_list[c], LDAP_ACCESS_LOCK_NAME) == 0) {
access_ctx->access_rule[c] = LDAP_ACCESS_LOCKOUT;
} else if (strcasecmp(order_list[c],
Expand Down
3 changes: 3 additions & 0 deletions src/providers/ldap/ldap_opts.c
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,7 @@ struct sdap_attr_map rfc2307_user_map[] = {
{ "ldap_user_ad_user_account_control", "userAccountControl", SYSDB_AD_USER_ACCOUNT_CONTROL, NULL},
{ "ldap_ns_account_lock", "nsAccountLock", SYSDB_NS_ACCOUNT_LOCK, NULL},
{ "ldap_user_authorized_host", "host", SYSDB_AUTHORIZED_HOST, NULL },
{ "ldap_user_authorized_rhost", "rhost", SYSDB_AUTHORIZED_RHOST, NULL },
{ "ldap_user_nds_login_disabled", "loginDisabled", SYSDB_NDS_LOGIN_DISABLED, NULL },
{ "ldap_user_nds_login_expiration_time", "loginExpirationTime", SYSDB_NDS_LOGIN_EXPIRATION_TIME, NULL },
{ "ldap_user_nds_login_allowed_time_map", "loginAllowedTimeMap", SYSDB_NDS_LOGIN_ALLOWED_TIME_MAP, NULL },
Expand Down Expand Up @@ -232,6 +233,7 @@ struct sdap_attr_map rfc2307bis_user_map[] = {
{ "ldap_user_ad_user_account_control", "userAccountControl", SYSDB_AD_USER_ACCOUNT_CONTROL, NULL},
{ "ldap_ns_account_lock", "nsAccountLock", SYSDB_NS_ACCOUNT_LOCK, NULL},
{ "ldap_user_authorized_host", "host", SYSDB_AUTHORIZED_HOST, NULL },
{ "ldap_user_authorized_rhost", "rhost", SYSDB_AUTHORIZED_RHOST, NULL },
{ "ldap_user_nds_login_disabled", "loginDisabled", SYSDB_NDS_LOGIN_DISABLED, NULL },
{ "ldap_user_nds_login_expiration_time", "loginExpirationTime", SYSDB_NDS_LOGIN_EXPIRATION_TIME, NULL },
{ "ldap_user_nds_login_allowed_time_map", "loginAllowedTimeMap", SYSDB_NDS_LOGIN_ALLOWED_TIME_MAP, NULL },
Expand Down Expand Up @@ -290,6 +292,7 @@ struct sdap_attr_map gen_ad2008r2_user_map[] = {
{ "ldap_user_ad_user_account_control", "userAccountControl", SYSDB_AD_USER_ACCOUNT_CONTROL, NULL},
{ "ldap_ns_account_lock", NULL, SYSDB_NS_ACCOUNT_LOCK, NULL},
{ "ldap_user_authorized_host", NULL, SYSDB_AUTHORIZED_HOST, NULL },
{ "ldap_user_authorized_rhost", NULL, SYSDB_AUTHORIZED_RHOST, NULL },
{ "ldap_user_nds_login_disabled", NULL, SYSDB_NDS_LOGIN_DISABLED, NULL },
{ "ldap_user_nds_login_expiration_time", NULL, SYSDB_NDS_LOGIN_EXPIRATION_TIME, NULL },
{ "ldap_user_nds_login_allowed_time_map", NULL, SYSDB_NDS_LOGIN_ALLOWED_TIME_MAP, NULL },
Expand Down
1 change: 1 addition & 0 deletions src/providers/ldap/sdap.h
Original file line number Diff line number Diff line change
Expand Up @@ -279,6 +279,7 @@ enum sdap_user_attrs {
SDAP_AT_AD_USER_ACCOUNT_CONTROL,
SDAP_AT_NS_ACCOUNT_LOCK,
SDAP_AT_AUTHORIZED_HOST,
SDAP_AT_AUTHORIZED_RHOST,
SDAP_AT_NDS_LOGIN_DISABLED,
SDAP_AT_NDS_LOGIN_EXPIRATION_TIME,
SDAP_AT_NDS_LOGIN_ALLOWED_TIME_MAP,
Expand Down
68 changes: 68 additions & 0 deletions src/providers/ldap/sdap_access.c
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,8 @@ static errno_t sdap_access_service(struct pam_data *pd,

static errno_t sdap_access_host(struct ldb_message *user_entry);

static errno_t sdap_access_rhost(struct ldb_message *user_entry, char *rhost);

enum sdap_access_control_type {
SDAP_ACCESS_CONTROL_FILTER,
SDAP_ACCESS_CONTROL_PPOLICY_LOCK,
Expand Down Expand Up @@ -309,6 +311,10 @@ static errno_t sdap_access_check_next_rule(struct sdap_access_req_ctx *state,
ret = sdap_access_host(state->user_entry);
break;

case LDAP_ACCESS_RHOST:
ret = sdap_access_rhost(state->user_entry, state->pd->rhost);
break;

default:
DEBUG(SSSDBG_CRIT_FAILURE,
"Unexpected access rule type. Access denied.\n");
Expand Down Expand Up @@ -1298,6 +1304,68 @@ static errno_t sdap_access_host(struct ldb_message *user_entry)
return ret;
}

static errno_t sdap_access_rhost(struct ldb_message *user_entry, char *pam_rhost)
{
errno_t ret;
struct ldb_message_element *el;
char *be_rhost_rule;
unsigned int i;

/* If pam_rhost is NULL do not perform any checks */
if (pam_rhost == NULL) {
DEBUG(SSSDBG_CONF_SETTINGS, "pam_rhost is NULL, no rhost check is possible\n");
return EOK;
}

/* When the access is local we get empty string as pam_rhost
in which case we should not evaluate rhost access rules */
/* FIXME: I think ideally should have LDAP to define what to do in this case */
if (pam_rhost[0] == '\0') {
DEBUG(SSSDBG_CONF_SETTINGS, "pam_rhost is empty, possible local access, no rhost check possible\n");
return EOK;
}

/* If rhost validation is enabled and entry has no relevant attribute - deny access */
el = ldb_msg_find_element(user_entry, SYSDB_AUTHORIZED_RHOST);
if (!el || el->num_values == 0) {
DEBUG(SSSDBG_CRIT_FAILURE, "Missing rhost entries. Access denied\n");
return ERR_ACCESS_DENIED;
}

ret = ENOENT;

for (i = 0; i < el->num_values; i++) {
be_rhost_rule = (char *)el->values[i].data;
if (be_rhost_rule[0] == '!' && strcasecmp(pam_rhost, be_rhost_rule+1) == 0) {
/* This rhost is explicitly denied */
DEBUG(SSSDBG_CONF_SETTINGS, "Access from [%s] denied by [%s]\n", pam_rhost, be_rhost_rule);
/* A denial trumps all. Break here */
return ERR_ACCESS_DENIED;
} else if (strcasecmp(pam_rhost, be_rhost_rule) == 0) {
/* This rhost is explicitly allowed */
DEBUG(SSSDBG_CONF_SETTINGS, "Access from [%s] granted by [%s]\n", pam_rhost, be_rhost_rule);
/* We still need to loop through to make sure
* that it's not also explicitly denied
*/
ret = EOK;
} else if (strcmp("*", be_rhost_rule) == 0) {
/* This user has access from anywhere */
DEBUG(SSSDBG_CONF_SETTINGS, "Access from [%s] granted by [*]\n", pam_rhost);
/* We still need to loop through to make sure
* that it's not also explicitly denied
*/
ret = EOK;
}
}

if (ret == ENOENT) {
DEBUG(SSSDBG_CONF_SETTINGS, "No matching rhost rules found\n");
ret = ERR_ACCESS_DENIED;
}

return ret;
}

static void sdap_access_ppolicy_get_lockout_done(struct tevent_req *subreq);
static int sdap_access_ppolicy_retry(struct tevent_req *req);
static errno_t sdap_access_ppolicy_step(struct tevent_req *req);
Expand Down
2 changes: 2 additions & 0 deletions src/providers/ldap/sdap_access.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
#define LDAP_ACCESS_EXPIRE_POLICY_RENEW_NAME "pwd_expire_policy_renew"
#define LDAP_ACCESS_SERVICE_NAME "authorized_service"
#define LDAP_ACCESS_HOST_NAME "host"
#define LDAP_ACCESS_RHOST_NAME "rhost"
#define LDAP_ACCESS_LOCK_NAME "lockout"
#define LDAP_ACCESS_PPOLICY_NAME "ppolicy"

Expand All @@ -61,6 +62,7 @@ enum ldap_access_rule {
LDAP_ACCESS_EXPIRE,
LDAP_ACCESS_SERVICE,
LDAP_ACCESS_HOST,
LDAP_ACCESS_RHOST,
LDAP_ACCESS_LOCKOUT,
LDAP_ACCESS_EXPIRE_POLICY_REJECT,
LDAP_ACCESS_EXPIRE_POLICY_WARN,
Expand Down

0 comments on commit dfad3dd

Please sign in to comment.