From 3612c73e7957721bcbf31d0118e2ac210eb46b88 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Wed, 22 Dec 2010 22:29:03 +0100 Subject: Add host access control support https://fedorahosted.org/sssd/ticket/746 --- src/providers/ldap/sdap_access.c | 146 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 146 insertions(+) (limited to 'src/providers/ldap/sdap_access.c') 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 = -- cgit