summaryrefslogtreecommitdiffstats
path: root/src/providers/ldap/sdap_access.c
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/providers/ldap/sdap_access.c
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/providers/ldap/sdap_access.c')
-rw-r--r--src/providers/ldap/sdap_access.c146
1 files changed, 146 insertions, 0 deletions
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 =