diff options
author | Pierre Ossman <pierre@ossman.eu> | 2010-12-22 22:29:03 +0100 |
---|---|---|
committer | Stephen Gallagher <sgallagh@redhat.com> | 2011-03-24 14:13:43 -0400 |
commit | 3612c73e7957721bcbf31d0118e2ac210eb46b88 (patch) | |
tree | acc174c39c5a854e89c7fafe7a4b513c3027ca6d /src/providers | |
parent | ff265d170e73d7347c718ee6cf690695bba8caeb (diff) | |
download | sssd-3612c73e7957721bcbf31d0118e2ac210eb46b88.tar.gz sssd-3612c73e7957721bcbf31d0118e2ac210eb46b88.tar.bz2 sssd-3612c73e7957721bcbf31d0118e2ac210eb46b88.zip |
Add host access control support
https://fedorahosted.org/sssd/ticket/746
Diffstat (limited to 'src/providers')
-rw-r--r-- | src/providers/ipa/ipa_common.c | 3 | ||||
-rw-r--r-- | src/providers/ldap/ldap_common.c | 6 | ||||
-rw-r--r-- | src/providers/ldap/ldap_init.c | 2 | ||||
-rw-r--r-- | src/providers/ldap/sdap.h | 1 | ||||
-rw-r--r-- | src/providers/ldap/sdap_access.c | 146 | ||||
-rw-r--r-- | src/providers/ldap/sdap_access.h | 2 |
6 files changed, 157 insertions, 3 deletions
diff --git a/src/providers/ipa/ipa_common.c b/src/providers/ipa/ipa_common.c index 579b8b60..067f2ee8 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 ce6d41d5..9eb9cc37 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 6b05690e..62588b77 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 31e72cd5..32dc3444 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 5a6b4a5d..9b598bc5 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 32c45b81..d78fdb1e 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 }; |