summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorPierre Ossman <pierre@ossman.eu>2010-12-22 22:29:03 +0100
committerStephen Gallagher <sgallagh@redhat.com>2011-03-24 14:13:43 -0400
commit3612c73e7957721bcbf31d0118e2ac210eb46b88 (patch)
treeacc174c39c5a854e89c7fafe7a4b513c3027ca6d /src
parentff265d170e73d7347c718ee6cf690695bba8caeb (diff)
downloadsssd-3612c73e7957721bcbf31d0118e2ac210eb46b88.tar.gz
sssd-3612c73e7957721bcbf31d0118e2ac210eb46b88.tar.xz
sssd-3612c73e7957721bcbf31d0118e2ac210eb46b88.zip
Add host access control support
https://fedorahosted.org/sssd/ticket/746
Diffstat (limited to 'src')
-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.h1
-rw-r--r--src/man/sssd-ldap.5.xml24
-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.c146
-rw-r--r--src/providers/ldap/sdap_access.h2
10 files changed, 184 insertions, 3 deletions
diff --git a/src/config/SSSDConfig.py b/src/config/SSSDConfig.py
index 9c61f06f5..5135174a8 100644
--- a/src/config/SSSDConfig.py
+++ b/src/config/SSSDConfig.py
@@ -174,6 +174,7 @@ option_strings = {
'ldap_user_shadow_expire' : _('shadowExpire attribute'),
'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_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 0e1b2ca55..5fd0cfb58 100644
--- a/src/config/etc/sssd.api.d/sssd-ldap.conf
+++ b/src/config/etc/sssd.api.d/sssd-ldap.conf
@@ -60,6 +60,7 @@ 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_user_authorized_host = 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
diff --git a/src/db/sysdb.h b/src/db/sysdb.h
index b7256911a..e6f9b4a7c 100644
--- a/src/db/sysdb.h
+++ b/src/db/sysdb.h
@@ -79,6 +79,7 @@
#define SYSDB_INITGR_EXPIRE "initgrExpireTimestamp"
#define SYSDB_AUTHORIZED_SERVICE "authorizedService"
+#define SYSDB_AUTHORIZED_HOST "authorizedHost"
#define SYSDB_NETGROUP_TRIPLE "netgroupTriple"
#define SYSDB_ORIG_NETGROUP_MEMBER "originalMemberNisNetgroup"
diff --git a/src/man/sssd-ldap.5.xml b/src/man/sssd-ldap.5.xml
index 58665eb4e..2a39732b6 100644
--- a/src/man/sssd-ldap.5.xml
+++ b/src/man/sssd-ldap.5.xml
@@ -587,6 +587,26 @@
</varlistentry>
<varlistentry>
+ <term>ldap_user_authorized_host (string)</term>
+ <listitem>
+ <para>
+ If access_provider=ldap and
+ ldap_access_order=host, SSSD will use the presence
+ of the host attribute in the user's LDAP entry to
+ determine access privilege.
+ </para>
+ <para>
+ An explicit deny (!host) is resolved first. Second,
+ SSSD searches for explicit allow (host) and finally
+ for allow_all (*).
+ </para>
+ <para>
+ Default: host
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
<term>ldap_group_object_class (string)</term>
<listitem>
<para>
@@ -1249,6 +1269,10 @@ ldap_access_filter = memberOf=cn=allowedusers,ou=Groups,dc=example,dc=com
access
</para>
<para>
+ <emphasis>host</emphasis>: use the host 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 579b8b60e..067f2ee85 100644
--- a/src/providers/ipa/ipa_common.c
+++ b/src/providers/ipa/ipa_common.c
@@ -127,7 +127,8 @@ struct sdap_attr_map ipa_user_map[] = {
{ "ldap_user_authorized_service", "authorizedService", SYSDB_AUTHORIZED_SERVICE, NULL },
{ "ldap_user_ad_account_expires", "accountExpires", SYSDB_AD_ACCOUNT_EXPIRES, NULL},
{ "ldap_user_ad_user_account_control", "userAccountControl", SYSDB_AD_USER_ACCOUNT_CONTROL, NULL},
- { "ldap_ns_account_lock", "nsAccountLock", SYSDB_NS_ACCOUNT_LOCK, NULL}
+ { "ldap_ns_account_lock", "nsAccountLock", SYSDB_NS_ACCOUNT_LOCK, NULL},
+ { "ldap_user_authorized_host", "host", SYSDB_AUTHORIZED_HOST, 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 ce6d41d58..9eb9cc379 100644
--- a/src/providers/ldap/ldap_common.c
+++ b/src/providers/ldap/ldap_common.c
@@ -131,7 +131,8 @@ struct sdap_attr_map rfc2307_user_map[] = {
{ "ldap_user_authorized_service", "authorizedService", SYSDB_AUTHORIZED_SERVICE, NULL },
{ "ldap_user_ad_account_expires", "accountExpires", SYSDB_AD_ACCOUNT_EXPIRES, NULL},
{ "ldap_user_ad_user_account_control", "userAccountControl", SYSDB_AD_USER_ACCOUNT_CONTROL, NULL},
- { "ldap_ns_account_lock", "nsAccountLock", SYSDB_NS_ACCOUNT_LOCK, NULL}
+ { "ldap_ns_account_lock", "nsAccountLock", SYSDB_NS_ACCOUNT_LOCK, NULL},
+ { "ldap_user_authorized_host", "host", SYSDB_AUTHORIZED_HOST, NULL }
};
struct sdap_attr_map rfc2307_group_map[] = {
@@ -174,7 +175,8 @@ struct sdap_attr_map rfc2307bis_user_map[] = {
{ "ldap_user_authorized_service", "authorizedService", SYSDB_AUTHORIZED_SERVICE, NULL },
{ "ldap_user_ad_account_expires", "accountExpires", SYSDB_AD_ACCOUNT_EXPIRES, NULL},
{ "ldap_user_ad_user_account_control", "userAccountControl", SYSDB_AD_USER_ACCOUNT_CONTROL, NULL},
- { "ldap_ns_account_lock", "nsAccountLock", SYSDB_NS_ACCOUNT_LOCK, NULL}
+ { "ldap_ns_account_lock", "nsAccountLock", SYSDB_NS_ACCOUNT_LOCK, NULL},
+ { "ldap_user_authorized_host", "host", SYSDB_AUTHORIZED_HOST, 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 6b05690ed..62588b776 100644
--- a/src/providers/ldap/ldap_init.c
+++ b/src/providers/ldap/ldap_init.c
@@ -358,6 +358,8 @@ int sssm_ldap_access_init(struct be_ctx *bectx,
}
} else if (strcasecmp(order_list[c], LDAP_ACCESS_SERVICE_NAME) == 0) {
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 {
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 31e72cd5b..32dc34448 100644
--- a/src/providers/ldap/sdap.h
+++ b/src/providers/ldap/sdap.h
@@ -243,6 +243,7 @@ enum sdap_user_attrs {
SDAP_AT_AD_ACCOUNT_EXPIRES,
SDAP_AT_AD_USER_ACCOUNT_CONTROL,
SDAP_AT_NS_ACCOUNT_LOCK,
+ SDAP_AT_AUTHORIZED_HOST,
SDAP_OPTS_USER /* attrs counter */
};
diff --git a/src/providers/ldap/sdap_access.c b/src/providers/ldap/sdap_access.c
index 5a6b4a5d3..9b598bc54 100644
--- a/src/providers/ldap/sdap_access.c
+++ b/src/providers/ldap/sdap_access.c
@@ -85,6 +85,17 @@ static struct tevent_req *sdap_access_service_send(
static void sdap_account_expired_done(struct tevent_req *subreq);
+static errno_t sdap_access_host_recv(struct tevent_req *req,
+ int *pam_status);
+static void sdap_access_host_done(struct tevent_req *subreq);
+
+static struct tevent_req *sdap_access_host_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_access_done(struct tevent_req *req);
void sdap_pam_access_handler(struct be_req *breq)
{
@@ -259,6 +270,18 @@ static errno_t select_next_rule(struct tevent_req *req)
tevent_req_set_callback(subreq, sdap_access_service_done, req);
return EOK;
+ case LDAP_ACCESS_HOST:
+ subreq = sdap_access_host_send(state, state->ev,
+ state->access_ctx,
+ state->pd,
+ state->user_entry);
+ if (subreq == NULL) {
+ DEBUG(1, ("sdap_access_host_send failed.\n"));
+ return ENOMEM;
+ }
+ tevent_req_set_callback(subreq, sdap_access_host_done, req);
+ return EOK;
+
default:
DEBUG(1, ("Unexpected access rule type. Access denied.\n"));
}
@@ -1057,6 +1080,129 @@ static void sdap_access_service_done(struct tevent_req *subreq)
return;
}
+struct sdap_access_host_ctx {
+ int pam_status;
+};
+
+static struct tevent_req *sdap_access_host_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_host_ctx *state;
+ struct ldb_message_element *el;
+ unsigned int i;
+ char *host;
+ char hostname[HOST_NAME_MAX+1];
+
+ req = tevent_req_create(mem_ctx, &state, struct sdap_access_host_ctx);
+ if (!req) {
+ return NULL;
+ }
+
+ state->pam_status = PAM_PERM_DENIED;
+
+ el = ldb_msg_find_element(user_entry, SYSDB_AUTHORIZED_HOST);
+ if (!el || el->num_values == 0) {
+ DEBUG(1, ("Missing hosts. Access denied\n"));
+ ret = EOK;
+ goto done;
+ }
+
+ if (gethostname(hostname, sizeof(hostname)) == -1) {
+ DEBUG(1, ("Unable to get system hostname. Access denied\n"));
+ ret = EOK;
+ goto done;
+ }
+
+ /* FIXME: PADL's pam_ldap also calls gethostbyname() on the hostname
+ * in some attempt to get aliases and/or FQDN for the machine.
+ * Not sure this is a good idea, but we might want to add it in
+ * order to be compatible...
+ */
+
+ for (i = 0; i < el->num_values; i++) {
+ host = (char *)el->values[i].data;
+ if (host[0] == '!' &&
+ strcasecmp(hostname, host+1) == 0) {
+ /* This host is explicitly denied */
+ state->pam_status = PAM_PERM_DENIED;
+ DEBUG(4, ("Access denied by [%s]\n", host));
+ /* A denial trumps all. Break here */
+ break;
+
+ } else if (strcasecmp(hostname, host) == 0) {
+ /* This host is explicitly allowed */
+ state->pam_status = PAM_SUCCESS;
+ DEBUG(4, ("Access granted for [%s]\n", host));
+ /* We still need to loop through to make sure
+ * that it's not also explicitly denied
+ */
+ } else if (strcmp("*", host) == 0) {
+ /* This user has access to all hosts */
+ state->pam_status = PAM_SUCCESS;
+ DEBUG(4, ("Access granted to all hosts\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 host 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_host_recv(struct tevent_req *req,
+ int *pam_status)
+{
+ struct sdap_access_host_ctx *state =
+ tevent_req_data(req, struct sdap_access_host_ctx);
+
+ TEVENT_REQ_RETURN_ON_ERROR(req);
+
+ *pam_status = state->pam_status;
+
+ return EOK;
+}
+
+static void sdap_access_host_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_host_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 32c45b817..d78fdb1ed 100644
--- a/src/providers/ldap/sdap_access.h
+++ b/src/providers/ldap/sdap_access.h
@@ -32,6 +32,7 @@
#define LDAP_ACCESS_FILTER_NAME "filter"
#define LDAP_ACCESS_EXPIRE_NAME "expire"
#define LDAP_ACCESS_SERVICE_NAME "authorized_service"
+#define LDAP_ACCESS_HOST_NAME "host"
#define LDAP_ACCOUNT_EXPIRE_SHADOW "shadow"
#define LDAP_ACCOUNT_EXPIRE_AD "ad"
@@ -44,6 +45,7 @@ enum ldap_access_rule {
LDAP_ACCESS_FILTER = 0,
LDAP_ACCESS_EXPIRE,
LDAP_ACCESS_SERVICE,
+ LDAP_ACCESS_HOST,
LDAP_ACCESS_LAST
};