summaryrefslogtreecommitdiffstats
path: root/src/providers/ldap/sdap_access.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/providers/ldap/sdap_access.c')
-rw-r--r--src/providers/ldap/sdap_access.c88
1 files changed, 88 insertions, 0 deletions
diff --git a/src/providers/ldap/sdap_access.c b/src/providers/ldap/sdap_access.c
index 4f3357a79..1ee4dcd2b 100644
--- a/src/providers/ldap/sdap_access.c
+++ b/src/providers/ldap/sdap_access.c
@@ -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);
+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,
@@ -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");
@@ -1298,6 +1304,88 @@ static errno_t sdap_access_host(struct ldb_message *user_entry)
return ret;
}
+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 user_entry is NULL do not perform any checks */
+ if (user_entry == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE,
+ "user_entry is NULL, that is not possible, "
+ "so we just reject access\n");
+ return ERR_ACCESS_DENIED;
+ }
+
+ /* If pam_rhost is NULL do not perform any checks */
+ if (pam_rhost == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE,
+ "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_CRIT_FAILURE,
+ "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_CONF_SETTINGS, "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);