summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/config/SSSDConfig.py1
-rw-r--r--src/config/etc/sssd.api.d/sssd-ldap.conf1
-rw-r--r--src/db/sysdb.h2
-rw-r--r--src/man/sssd-ldap.5.xml26
-rw-r--r--src/providers/ipa/ipa_common.c3
-rw-r--r--src/providers/ldap/ldap_common.c6
-rw-r--r--src/providers/ldap/ldap_init.c2
-rw-r--r--src/providers/ldap/sdap.h1
-rw-r--r--src/providers/ldap/sdap_access.c135
-rw-r--r--src/providers/ldap/sdap_access.h2
10 files changed, 176 insertions, 3 deletions
diff --git a/src/config/SSSDConfig.py b/src/config/SSSDConfig.py
index de7f66a6..b1177178 100644
--- a/src/config/SSSDConfig.py
+++ b/src/config/SSSDConfig.py
@@ -166,6 +166,7 @@ option_strings = {
'ldap_user_shadow_inactive' : _('shadowInactive attribute'),
'ldap_user_shadow_expire' : _('shadowExpire attribute'),
'ldap_user_shadow_flag' : _('shadowFlag attribute'),
+ 'ldap_user_authorized_service' : _('Attribute listing authorized PAM services'),
'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'),
diff --git a/src/config/etc/sssd.api.d/sssd-ldap.conf b/src/config/etc/sssd.api.d/sssd-ldap.conf
index c41ff7cc..c2179f2d 100644
--- a/src/config/etc/sssd.api.d/sssd-ldap.conf
+++ b/src/config/etc/sssd.api.d/sssd-ldap.conf
@@ -55,6 +55,7 @@ ldap_user_shadow_expire = str, None, false
ldap_user_shadow_flag = str, None, false
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_pwd_attribute = str, None, false
ldap_group_search_base = str, None, false
ldap_group_search_scope = str, None, false
diff --git a/src/db/sysdb.h b/src/db/sysdb.h
index b5eed49b..3fefdf21 100644
--- a/src/db/sysdb.h
+++ b/src/db/sysdb.h
@@ -78,6 +78,8 @@
#define SYSDB_CACHE_EXPIRE "dataExpireTimestamp"
#define SYSDB_INITGR_EXPIRE "initgrExpireTimestamp"
+#define SYSDB_AUTHORIZED_SERVICE "authorizedService"
+
#define SYSDB_NETGROUP_TRIPLE "netgroupTriple"
#define SYSDB_ORIG_NETGROUP_MEMBER "originalMemberNisNetgroup"
#define SYSDB_NETGROUP_MEMBER "memberNisNetgroup"
diff --git a/src/man/sssd-ldap.5.xml b/src/man/sssd-ldap.5.xml
index 3406dc46..7a733462 100644
--- a/src/man/sssd-ldap.5.xml
+++ b/src/man/sssd-ldap.5.xml
@@ -524,6 +524,27 @@
</varlistentry>
<varlistentry>
+ <term>ldap_user_authorized_service (string)</term>
+ <listitem>
+ <para>
+ If access_provider=ldap and
+ ldap_access_order=authorized_service, SSSD will
+ use the presence of the authorizedService
+ attribute in the user's LDAP entry to determine
+ access privilege.
+ </para>
+ <para>
+ An explicit deny (!svc) is resolved first. Second,
+ SSSD searches for explicit allow (svc) and finally
+ for allow_all (*).
+ </para>
+ <para>
+ Default: authorizedService
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
<term>ldap_group_object_class (string)</term>
<listitem>
<para>
@@ -1109,6 +1130,11 @@ ldap_access_filter = memberOf=cn=allowedusers,ou=Groups,dc=example,dc=com
ldap_account_expire_policy
</para>
<para>
+ <emphasis>authorized_service</emphasis>: use
+ the authorizedService attribute to determine
+ access
+ </para>
+ <para>
Default: filter
</para>
<para>
diff --git a/src/providers/ipa/ipa_common.c b/src/providers/ipa/ipa_common.c
index 2e7724a6..a42cc3b4 100644
--- a/src/providers/ipa/ipa_common.c
+++ b/src/providers/ipa/ipa_common.c
@@ -113,7 +113,8 @@ struct sdap_attr_map ipa_user_map[] = {
{ "ldap_user_shadow_flag", "shadowFlag", SYSDB_SHADOWPW_FLAG, NULL },
{ "ldap_user_krb_last_pwd_change", "krbLastPwdChange", SYSDB_KRBPW_LASTCHANGE, NULL },
{ "ldap_user_krb_password_expiration", "krbPasswordExpiration", SYSDB_KRBPW_EXPIRATION, NULL },
- { "ldap_pwd_attribute", "pwdAttribute", SYSDB_PWD_ATTRIBUTE, NULL }
+ { "ldap_pwd_attribute", "pwdAttribute", SYSDB_PWD_ATTRIBUTE, NULL },
+ { "ldap_user_authorized_service", "authorizedService", SYSDB_AUTHORIZED_SERVICE, NULL }
};
struct sdap_attr_map ipa_group_map[] = {
diff --git a/src/providers/ldap/ldap_common.c b/src/providers/ldap/ldap_common.c
index a38d5cc2..f0db53f2 100644
--- a/src/providers/ldap/ldap_common.c
+++ b/src/providers/ldap/ldap_common.c
@@ -118,7 +118,8 @@ struct sdap_attr_map rfc2307_user_map[] = {
{ "ldap_user_shadow_flag", "shadowFlag", SYSDB_SHADOWPW_FLAG, NULL },
{ "ldap_user_krb_last_pwd_change", "krbLastPwdChange", SYSDB_KRBPW_LASTCHANGE, NULL },
{ "ldap_user_krb_password_expiration", "krbPasswordExpiration", SYSDB_KRBPW_EXPIRATION, NULL },
- { "ldap_pwd_attribute", "pwdAttribute", SYSDB_PWD_ATTRIBUTE, NULL }
+ { "ldap_pwd_attribute", "pwdAttribute", SYSDB_PWD_ATTRIBUTE, NULL },
+ { "ldap_user_authorized_service", "authorizedService", SYSDB_AUTHORIZED_SERVICE, NULL }
};
struct sdap_attr_map rfc2307_group_map[] = {
@@ -157,7 +158,8 @@ struct sdap_attr_map rfc2307bis_user_map[] = {
{ "ldap_user_shadow_flag", "shadowFlag", SYSDB_SHADOWPW_FLAG, NULL },
{ "ldap_user_krb_last_pwd_change", "krbLastPwdChange", SYSDB_KRBPW_LASTCHANGE, NULL },
{ "ldap_user_krb_password_expiration", "krbPasswordExpiration", SYSDB_KRBPW_EXPIRATION, NULL },
- { "ldap_pwd_attribute", "pwdAttribute", SYSDB_PWD_ATTRIBUTE, NULL }
+ { "ldap_pwd_attribute", "pwdAttribute", SYSDB_PWD_ATTRIBUTE, NULL },
+ { "ldap_user_authorized_service", "authorizedService", SYSDB_AUTHORIZED_SERVICE, NULL }
};
struct sdap_attr_map rfc2307bis_group_map[] = {
diff --git a/src/providers/ldap/ldap_init.c b/src/providers/ldap/ldap_init.c
index a1d8f05d..d5dad360 100644
--- a/src/providers/ldap/ldap_init.c
+++ b/src/providers/ldap/ldap_init.c
@@ -352,6 +352,8 @@ int sssm_ldap_access_init(struct be_ctx *bectx,
goto done;
}
}
+ } else if (strcasecmp(order_list[c], LDAP_ACCESS_SERVICE_NAME) == 0) {
+ access_ctx->access_rule[c] = LDAP_ACCESS_SERVICE;
} else {
DEBUG(1, ("Unexpected access rule name [%s].\n", order_list[c]));
ret = EINVAL;
diff --git a/src/providers/ldap/sdap.h b/src/providers/ldap/sdap.h
index 8c629a3b..57865fe0 100644
--- a/src/providers/ldap/sdap.h
+++ b/src/providers/ldap/sdap.h
@@ -229,6 +229,7 @@ enum sdap_user_attrs {
SDAP_AT_KP_LASTCHANGE,
SDAP_AT_KP_EXPIRATION,
SDAP_AT_PWD_ATTRIBUTE,
+ SDAP_AT_AUTH_SVC,
SDAP_OPTS_USER /* attrs counter */
};
diff --git a/src/providers/ldap/sdap_access.c b/src/providers/ldap/sdap_access.c
index fa3f522a..4767812c 100644
--- a/src/providers/ldap/sdap_access.c
+++ b/src/providers/ldap/sdap_access.c
@@ -72,6 +72,17 @@ static struct tevent_req *sdap_account_expired_send(TALLOC_CTX *mem_ctx,
struct sdap_access_ctx *access_ctx,
const char *username,
struct ldb_message *user_entry);
+static errno_t sdap_access_service_recv(struct tevent_req *req,
+ int *pam_status);
+static void sdap_access_service_done(struct tevent_req *subreq);
+
+static struct tevent_req *sdap_access_service_send(
+ TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct sdap_access_ctx *access_ctx,
+ struct pam_data *pd,
+ struct ldb_message *user_entry);
+
static void sdap_account_expired_done(struct tevent_req *subreq);
static void sdap_access_done(struct tevent_req *req);
@@ -235,6 +246,19 @@ static errno_t select_next_rule(struct tevent_req *req)
tevent_req_set_callback(subreq, sdap_account_expired_done, req);
return EOK;
+
+ case LDAP_ACCESS_SERVICE:
+ subreq = sdap_access_service_send(state, state->ev,
+ state->access_ctx,
+ state->pd,
+ state->user_entry);
+ if (subreq == NULL) {
+ DEBUG(1, ("sdap_access_service_send failed.\n"));
+ return ENOMEM;
+ }
+ tevent_req_set_callback(subreq, sdap_access_service_done, req);
+ return EOK;
+
default:
DEBUG(1, ("Unexpected access rule type. Access denied.\n"));
}
@@ -759,6 +783,117 @@ static void sdap_access_filter_done(struct tevent_req *subreq)
return;
}
+
+struct sdap_access_service_ctx {
+ int pam_status;
+};
+
+static struct tevent_req *sdap_access_service_send(
+ TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct sdap_access_ctx *access_ctx,
+ struct pam_data *pd,
+ struct ldb_message *user_entry)
+{
+ errno_t ret;
+ struct tevent_req *req;
+ struct sdap_access_service_ctx *state;
+ struct ldb_message_element *el;
+ unsigned int i;
+ char *service;
+
+ req = tevent_req_create(mem_ctx, &state, struct sdap_access_service_ctx);
+ if (!req) {
+ return NULL;
+ }
+
+ state->pam_status = PAM_PERM_DENIED;
+
+ el = ldb_msg_find_element(user_entry, SYSDB_AUTHORIZED_SERVICE);
+ if (!el || el->num_values == 0) {
+ DEBUG(1, ("Missing authorized services. Access denied\n"));
+ ret = EOK;
+ goto done;
+ }
+
+ for (i = 0; i < el->num_values; i++) {
+ service = (char *)el->values[i].data;
+ if (service[0] == '!' &&
+ strcasecmp(pd->service, service+1) == 0) {
+ /* This service is explicitly denied */
+ state->pam_status = PAM_PERM_DENIED;
+ DEBUG(4, ("Access denied by [%s]\n", service));
+ /* A denial trumps all. Break here */
+ break;
+
+ } else if (strcasecmp(pd->service, service) == 0) {
+ /* This service is explicitly allowed */
+ state->pam_status = PAM_SUCCESS;
+ DEBUG(4, ("Access granted for [%s]\n", service));
+ /* We still need to loop through to make sure
+ * that it's not also explicitly denied
+ */
+ } else if (strcmp("*", service) == 0) {
+ /* This user has access to all services */
+ state->pam_status = PAM_SUCCESS;
+ DEBUG(4, ("Access granted to all services\n"));
+ /* We still need to loop through to make sure
+ * that it's not also explicitly denied
+ */
+ }
+ }
+
+ if (state->pam_status != PAM_SUCCESS) {
+ DEBUG(4, ("No matching service rule found\n"));
+ }
+
+ ret = EOK;
+
+done:
+ if (ret == EOK) {
+ tevent_req_done(req);
+ } else {
+ tevent_req_error(req, ret);
+ }
+ tevent_req_post(req, ev);
+
+ return req;
+}
+
+static errno_t sdap_access_service_recv(struct tevent_req *req,
+ int *pam_status)
+{
+ struct sdap_access_service_ctx *state =
+ tevent_req_data(req, struct sdap_access_service_ctx);
+
+ TEVENT_REQ_RETURN_ON_ERROR(req);
+
+ *pam_status = state->pam_status;
+
+ return EOK;
+}
+
+static void sdap_access_service_done(struct tevent_req *subreq)
+{
+ errno_t ret;
+ struct tevent_req *req = tevent_req_callback_data(subreq, struct tevent_req);
+ struct sdap_access_req_ctx *state =
+ tevent_req_data(req, struct sdap_access_req_ctx);
+
+ ret = sdap_access_service_recv(subreq, &state->pam_status);
+ talloc_zfree(subreq);
+ if (ret != EOK) {
+ DEBUG(1, ("Error retrieving access check result.\n"));
+ state->pam_status = PAM_SYSTEM_ERR;
+ tevent_req_error(req, ret);
+ return;
+ }
+
+ next_access_rule(req);
+
+ return;
+}
+
static errno_t sdap_access_recv(struct tevent_req *req, int *pam_status)
{
struct sdap_access_req_ctx *state =
diff --git a/src/providers/ldap/sdap_access.h b/src/providers/ldap/sdap_access.h
index 9b8e45bd..66193a6d 100644
--- a/src/providers/ldap/sdap_access.h
+++ b/src/providers/ldap/sdap_access.h
@@ -31,6 +31,7 @@
#define LDAP_ACCESS_FILTER_NAME "filter"
#define LDAP_ACCESS_EXPIRE_NAME "expire"
+#define LDAP_ACCESS_SERVICE_NAME "authorized_service"
#define LDAP_ACCOUNT_EXPIRE_SHADOW "shadow"
@@ -38,6 +39,7 @@ enum ldap_access_rule {
LDAP_ACCESS_EMPTY = -1,
LDAP_ACCESS_FILTER = 0,
LDAP_ACCESS_EXPIRE,
+ LDAP_ACCESS_SERVICE,
LDAP_ACCESS_LAST
};