-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
On 12/21/2010 04:37 PM, Stephen Gallagher wrote:
> On 12/21/2010 04:01 PM, Stephen Gallagher wrote:
>> On 12/21/2010 03:46 PM, Sumit Bose wrote:
>>> On Tue, Dec 21, 2010 at 08:23:31AM -0500, Stephen Gallagher wrote:
>>> Patch 0001: Modify the LDAP access provider to pass the full PAM data to
>>> all access functions. Previously we only were passing the username, but
>>> some functions (like the one added in patch 0002) will require access to
>>> other data like the service, host, rhost, etc.
>
>>> Patch 0002: Add support for the authorizedService attribute in the ldap
>>> access provider.
>
>
>>>> The patch look good, but I would suggest to add
>>>> ldap_user_authorized_service to the IPA provider to keep the user
>>>> attribute list and SDAP_OPTS_USER in sync.
>
>> Thanks for catching that. New patches attached.
>
>
> Sumit caught that I missed an attribute when adding the option to the
> IPA provider. New patches attached.
>
>
My vacation can't come soon enough. Correct patches attached this time.
From
3185fb4cc3e7e049634ea2ac7471788ca30e6287 Mon Sep 17 00:00:00 2001
From: Stephen Gallagher <sgallagh(a)redhat.com>
Date: Mon, 20 Dec 2010 12:51:32 -0500
Subject: [PATCH 1/2] Pass all PAM data to the LDAP access provider
Previously we were only passing the username.
---
src/providers/ldap/sdap_access.c | 21 ++++++++++++---------
1 files changed, 12 insertions(+), 9 deletions(-)
diff --git a/src/providers/ldap/sdap_access.c b/src/providers/ldap/sdap_access.c
index 4ebd72769bcfb49e7414f8d6ee6e784f4817cd03..fa3f522a15b5f0a9d06c1c9035e993bd36e37e36
100644
--- a/src/providers/ldap/sdap_access.c
+++ b/src/providers/ldap/sdap_access.c
@@ -56,7 +56,7 @@ static struct tevent_req *sdap_access_send(TALLOC_CTX *mem_ctx,
struct tevent_context *ev,
struct be_ctx *be_ctx,
struct sdap_access_ctx *access_ctx,
- const char *username);
+ struct pam_data *pd);
static struct tevent_req *sdap_access_filter_send(TALLOC_CTX *mem_ctx,
struct tevent_context *ev,
@@ -91,7 +91,7 @@ void sdap_pam_access_handler(struct be_req *breq)
breq->be_ctx->ev,
breq->be_ctx,
access_ctx,
- pd->user);
+ pd);
if (req == NULL) {
DEBUG(1, ("Unable to start sdap_access request\n"));
sdap_access_reply(breq, PAM_SYSTEM_ERR);
@@ -102,7 +102,7 @@ void sdap_pam_access_handler(struct be_req *breq)
}
struct sdap_access_req_ctx {
- const char *username;
+ struct pam_data *pd;
struct tevent_context *ev;
struct sdap_access_ctx *access_ctx;
struct be_ctx *be_ctx;
@@ -116,7 +116,7 @@ static struct tevent_req *sdap_access_send(TALLOC_CTX *mem_ctx,
struct tevent_context *ev,
struct be_ctx *be_ctx,
struct sdap_access_ctx *access_ctx,
- const char *username)
+ struct pam_data *pd)
{
errno_t ret;
struct sdap_access_req_ctx *state;
@@ -131,13 +131,13 @@ static struct tevent_req *sdap_access_send(TALLOC_CTX *mem_ctx,
}
state->be_ctx = be_ctx;
- state->username = username;
+ state->pd = pd;
state->pam_status = PAM_SYSTEM_ERR;
state->ev = ev;
state->access_ctx = access_ctx;
state->current_rule = 0;
- DEBUG(6, ("Performing access check for user [%s]\n", username));
+ DEBUG(6, ("Performing access check for user [%s]\n", pd->user));
if (access_ctx->access_rule[0] == LDAP_ACCESS_EMPTY) {
DEBUG(3, ("No access rules defined, access denied.\n"));
@@ -148,7 +148,7 @@ static struct tevent_req *sdap_access_send(TALLOC_CTX *mem_ctx,
/* Get original user DN */
ret = sysdb_get_user_attr(state, be_ctx->sysdb, be_ctx->domain,
- username, attrs,
+ pd->user, attrs,
&res);
if (ret != EOK) {
if (ret == ENOENT) {
@@ -209,9 +209,11 @@ static errno_t select_next_rule(struct tevent_req *req)
case LDAP_ACCESS_EMPTY:
return ENOENT;
break;
+
case LDAP_ACCESS_FILTER:
subreq = sdap_access_filter_send(state, state->ev, state->be_ctx,
- state->access_ctx, state->username,
+ state->access_ctx,
+ state->pd->user,
state->user_entry);
if (subreq == NULL) {
DEBUG(1, ("sdap_access_filter_send failed.\n"));
@@ -220,10 +222,11 @@ static errno_t select_next_rule(struct tevent_req *req)
tevent_req_set_callback(subreq, sdap_access_filter_done, req);
return EOK;
+
case LDAP_ACCESS_EXPIRE:
subreq = sdap_account_expired_send(state, state->ev, state->be_ctx,
state->access_ctx,
- state->username,
+ state->pd->user,
state->user_entry);
if (subreq == NULL) {
DEBUG(1, ("sdap_account_expired_send failed.\n"));
--
1.7.3.3
From 119ea57e460e68618c734cfd22bd5753e4ba8b6d Mon Sep 17 00:00:00
2001
From: Stephen Gallagher <sgallagh(a)redhat.com>
Date: Mon, 20 Dec 2010 16:05:14 -0500
Subject: [PATCH 2/2] Add authorizedService support
https://fedorahosted.org/sssd/ticket/670
---
src/config/SSSDConfig.py | 1 +
src/config/etc/sssd.api.d/sssd-ldap.conf | 1 +
src/db/sysdb.h | 2 +
src/man/sssd-ldap.5.xml | 26 ++++++
src/providers/ipa/ipa_common.c | 3 +-
src/providers/ldap/ldap_common.c | 6 +-
src/providers/ldap/ldap_init.c | 2 +
src/providers/ldap/sdap.h | 1 +
src/providers/ldap/sdap_access.c | 135 ++++++++++++++++++++++++++++++
src/providers/ldap/sdap_access.h | 2 +
10 files changed, 176 insertions(+), 3 deletions(-)
diff --git a/src/config/SSSDConfig.py b/src/config/SSSDConfig.py
index de7f66a6aa690de8f320e2b29627186b5f94be0d..b117717882193c206be88332abf2698d68052943
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 c41ff7cc6bdde234cef6d78ad3e315892f402945..c2179f2daee57ade1fbce830fef8b4bdd4e805aa
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 b5eed49b4ae83b195eed80a8b35df4c2906330bf..3fefdf21536257edff6a314bef5310502d204e09
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 3406dc469c41d009e90fb351d81079e77ccf474e..7a73346226e4ff2197de4a496cb384cc0e6d842c
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 2e7724a62cf530966c03ebf64f25cf0233358e95..a42cc3b4d4984e1994c1f38931aa45b0fb480142
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 a38d5cc2081677962c07c6b621519b5c82d1a78d..f0db53f222e21662e79b20180216ebd3da076465
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 a1d8f05d7f70f1fb70bf4e8f29eae0be97f34532..d5dad36078fdbda2bea52040b871076eacddf55f
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 8c629a3b46793d58a9d55655b642c4a144772ab6..57865fe097ba11f59b325cdcd07efac086a72ad8
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 fa3f522a15b5f0a9d06c1c9035e993bd36e37e36..4767812c08077ca1fe60a1f3a8dde66308ad1d4c
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 9b8e45bddd6d98bcabf13ab30a7697049b06b968..66193a6ddab01222311c40cc7e0da5c103bdc78b
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
};
--
1.7.3.3