ipa_hbac_services.c revision 0700185377ad23885cc2ddae20abe0dc36a3abca
842ae4bd224140319ae7feec1872b93dfd491143fielding/*
842ae4bd224140319ae7feec1872b93dfd491143fielding SSSD
842ae4bd224140319ae7feec1872b93dfd491143fielding
842ae4bd224140319ae7feec1872b93dfd491143fielding Authors:
842ae4bd224140319ae7feec1872b93dfd491143fielding Stephen Gallagher <sgallagh@redhat.com>
842ae4bd224140319ae7feec1872b93dfd491143fielding
8c83461e53ca7d204e1d634f0c78199d60320d7bjerenkrantz Copyright (C) 2011 Red Hat
ce9621257ef9e54c1bbe5ad8a5f445a1f211c2dcnd
8c83461e53ca7d204e1d634f0c78199d60320d7bjerenkrantz This program is free software; you can redistribute it and/or modify
ce9621257ef9e54c1bbe5ad8a5f445a1f211c2dcnd it under the terms of the GNU General Public License as published by
ce9621257ef9e54c1bbe5ad8a5f445a1f211c2dcnd the Free Software Foundation; either version 3 of the License, or
ce9621257ef9e54c1bbe5ad8a5f445a1f211c2dcnd (at your option) any later version.
ce9621257ef9e54c1bbe5ad8a5f445a1f211c2dcnd
ce9621257ef9e54c1bbe5ad8a5f445a1f211c2dcnd This program is distributed in the hope that it will be useful,
8c83461e53ca7d204e1d634f0c78199d60320d7bjerenkrantz but WITHOUT ANY WARRANTY; without even the implied warranty of
8c83461e53ca7d204e1d634f0c78199d60320d7bjerenkrantz MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
8c83461e53ca7d204e1d634f0c78199d60320d7bjerenkrantz GNU General Public License for more details.
3a2bc69dbf5d2afe57bcc21c554aa1e3851fb159jim
3a2bc69dbf5d2afe57bcc21c554aa1e3851fb159jim You should have received a copy of the GNU General Public License
8c83461e53ca7d204e1d634f0c78199d60320d7bjerenkrantz along with this program. If not, see <http://www.gnu.org/licenses/>.
baf4649272f3dabd48b095a23b3180cc0105dce6rjung*/
baf4649272f3dabd48b095a23b3180cc0105dce6rjung
baf4649272f3dabd48b095a23b3180cc0105dce6rjung#include "util/util.h"
baf4649272f3dabd48b095a23b3180cc0105dce6rjung#include "providers/ipa/ipa_hbac_private.h"
baf4649272f3dabd48b095a23b3180cc0105dce6rjung#include "providers/ldap/sdap_async.h"
baf4649272f3dabd48b095a23b3180cc0105dce6rjung
e302f38fd646764ce1a1e1c578d794aef514a9e5sfstruct ipa_hbac_service_state {
e302f38fd646764ce1a1e1c578d794aef514a9e5sf struct tevent_context *ev;
e302f38fd646764ce1a1e1c578d794aef514a9e5sf struct sysdb_ctx *sysdb;
baf4649272f3dabd48b095a23b3180cc0105dce6rjung struct sdap_handle *sh;
8c83461e53ca7d204e1d634f0c78199d60320d7bjerenkrantz struct sdap_options *opts;
8c83461e53ca7d204e1d634f0c78199d60320d7bjerenkrantz const char **attrs;
8c83461e53ca7d204e1d634f0c78199d60320d7bjerenkrantz
8c83461e53ca7d204e1d634f0c78199d60320d7bjerenkrantz char *service_filter;
8c83461e53ca7d204e1d634f0c78199d60320d7bjerenkrantz char *cur_filter;
01e8aca9299a0b872414c24c8b7724d6f88ae665ianh
8c83461e53ca7d204e1d634f0c78199d60320d7bjerenkrantz struct sdap_search_base **search_bases;
8c83461e53ca7d204e1d634f0c78199d60320d7bjerenkrantz int search_base_iter;
8c83461e53ca7d204e1d634f0c78199d60320d7bjerenkrantz
8c83461e53ca7d204e1d634f0c78199d60320d7bjerenkrantz /* Return values */
8c83461e53ca7d204e1d634f0c78199d60320d7bjerenkrantz size_t service_count;
8c83461e53ca7d204e1d634f0c78199d60320d7bjerenkrantz struct sysdb_attrs **services;
8f54dc133e1a89300196d85dd6f910962007cf68brianp
8f54dc133e1a89300196d85dd6f910962007cf68brianp size_t servicegroup_count;
8f54dc133e1a89300196d85dd6f910962007cf68brianp struct sysdb_attrs **servicegroups;
8f54dc133e1a89300196d85dd6f910962007cf68brianp};
8f54dc133e1a89300196d85dd6f910962007cf68brianp
8f54dc133e1a89300196d85dd6f910962007cf68brianpstatic errno_t
8f54dc133e1a89300196d85dd6f910962007cf68brianpipa_hbac_service_info_next(struct tevent_req *req,
8f54dc133e1a89300196d85dd6f910962007cf68brianp struct ipa_hbac_service_state *state);
8c83461e53ca7d204e1d634f0c78199d60320d7bjerenkrantzstatic void
8c83461e53ca7d204e1d634f0c78199d60320d7bjerenkrantzipa_hbac_service_info_done(struct tevent_req *subreq);
8c83461e53ca7d204e1d634f0c78199d60320d7bjerenkrantzstatic errno_t
8c83461e53ca7d204e1d634f0c78199d60320d7bjerenkrantzipa_hbac_servicegroup_info_next(struct tevent_req *req,
01e8aca9299a0b872414c24c8b7724d6f88ae665ianh struct ipa_hbac_service_state *state);
8c83461e53ca7d204e1d634f0c78199d60320d7bjerenkrantzstatic void
8c83461e53ca7d204e1d634f0c78199d60320d7bjerenkrantzipa_hbac_servicegroup_info_done(struct tevent_req *subreq);
8c83461e53ca7d204e1d634f0c78199d60320d7bjerenkrantz
738236127338633bda6136e4715cc1973997b21cbrianpstruct tevent_req *
8c83461e53ca7d204e1d634f0c78199d60320d7bjerenkrantzipa_hbac_service_info_send(TALLOC_CTX *mem_ctx,
8f54dc133e1a89300196d85dd6f910962007cf68brianp struct tevent_context *ev,
8c83461e53ca7d204e1d634f0c78199d60320d7bjerenkrantz struct sysdb_ctx *sysdb,
8c83461e53ca7d204e1d634f0c78199d60320d7bjerenkrantz struct sdap_handle *sh,
8c83461e53ca7d204e1d634f0c78199d60320d7bjerenkrantz struct sdap_options *opts,
8c83461e53ca7d204e1d634f0c78199d60320d7bjerenkrantz struct sdap_search_base **search_bases)
8c83461e53ca7d204e1d634f0c78199d60320d7bjerenkrantz{
8c83461e53ca7d204e1d634f0c78199d60320d7bjerenkrantz errno_t ret;
8c83461e53ca7d204e1d634f0c78199d60320d7bjerenkrantz struct ipa_hbac_service_state *state;
8c83461e53ca7d204e1d634f0c78199d60320d7bjerenkrantz struct tevent_req *req;
01e8aca9299a0b872414c24c8b7724d6f88ae665ianh char *service_filter;
8c83461e53ca7d204e1d634f0c78199d60320d7bjerenkrantz
8c83461e53ca7d204e1d634f0c78199d60320d7bjerenkrantz req = tevent_req_create(mem_ctx, &state, struct ipa_hbac_service_state);
8c83461e53ca7d204e1d634f0c78199d60320d7bjerenkrantz if (req == NULL) {
8c83461e53ca7d204e1d634f0c78199d60320d7bjerenkrantz DEBUG(1, ("tevent_req_create failed.\n"));
8c83461e53ca7d204e1d634f0c78199d60320d7bjerenkrantz return NULL;
8c83461e53ca7d204e1d634f0c78199d60320d7bjerenkrantz }
8c83461e53ca7d204e1d634f0c78199d60320d7bjerenkrantz
8c83461e53ca7d204e1d634f0c78199d60320d7bjerenkrantz state->ev = ev;
8c83461e53ca7d204e1d634f0c78199d60320d7bjerenkrantz state->sysdb = sysdb;
8c83461e53ca7d204e1d634f0c78199d60320d7bjerenkrantz state->sh = sh;
8c83461e53ca7d204e1d634f0c78199d60320d7bjerenkrantz state->opts = opts;
8c83461e53ca7d204e1d634f0c78199d60320d7bjerenkrantz
8c83461e53ca7d204e1d634f0c78199d60320d7bjerenkrantz state->search_bases = search_bases;
8c83461e53ca7d204e1d634f0c78199d60320d7bjerenkrantz state->search_base_iter = 0;
8c83461e53ca7d204e1d634f0c78199d60320d7bjerenkrantz
8c83461e53ca7d204e1d634f0c78199d60320d7bjerenkrantz service_filter = talloc_asprintf(state, "(objectClass=%s)",
8c83461e53ca7d204e1d634f0c78199d60320d7bjerenkrantz IPA_HBAC_SERVICE);
8c83461e53ca7d204e1d634f0c78199d60320d7bjerenkrantz if (service_filter == NULL) {
8c83461e53ca7d204e1d634f0c78199d60320d7bjerenkrantz ret = ENOMEM;
8c83461e53ca7d204e1d634f0c78199d60320d7bjerenkrantz goto immediate;
8c83461e53ca7d204e1d634f0c78199d60320d7bjerenkrantz }
8c83461e53ca7d204e1d634f0c78199d60320d7bjerenkrantz
8c83461e53ca7d204e1d634f0c78199d60320d7bjerenkrantz state->service_filter = service_filter;
8c83461e53ca7d204e1d634f0c78199d60320d7bjerenkrantz state->cur_filter = NULL;
8c83461e53ca7d204e1d634f0c78199d60320d7bjerenkrantz
8c83461e53ca7d204e1d634f0c78199d60320d7bjerenkrantz state->attrs = talloc_array(state, const char *, 6);
8c83461e53ca7d204e1d634f0c78199d60320d7bjerenkrantz if (state->attrs == NULL) {
8c83461e53ca7d204e1d634f0c78199d60320d7bjerenkrantz DEBUG(1, ("Failed to allocate service attribute list.\n"));
8c83461e53ca7d204e1d634f0c78199d60320d7bjerenkrantz ret = ENOMEM;
8c83461e53ca7d204e1d634f0c78199d60320d7bjerenkrantz goto immediate;
8c83461e53ca7d204e1d634f0c78199d60320d7bjerenkrantz }
8c83461e53ca7d204e1d634f0c78199d60320d7bjerenkrantz state->attrs[0] = OBJECTCLASS;
8c83461e53ca7d204e1d634f0c78199d60320d7bjerenkrantz state->attrs[1] = IPA_CN;
8c83461e53ca7d204e1d634f0c78199d60320d7bjerenkrantz state->attrs[2] = IPA_UNIQUE_ID;
8c83461e53ca7d204e1d634f0c78199d60320d7bjerenkrantz state->attrs[3] = IPA_MEMBER;
8c83461e53ca7d204e1d634f0c78199d60320d7bjerenkrantz state->attrs[4] = IPA_MEMBEROF;
8c83461e53ca7d204e1d634f0c78199d60320d7bjerenkrantz state->attrs[5] = NULL;
8c83461e53ca7d204e1d634f0c78199d60320d7bjerenkrantz
8c83461e53ca7d204e1d634f0c78199d60320d7bjerenkrantz ret = ipa_hbac_service_info_next(req, state);
8c83461e53ca7d204e1d634f0c78199d60320d7bjerenkrantz if (ret == EOK) {
8c83461e53ca7d204e1d634f0c78199d60320d7bjerenkrantz ret = EINVAL;
8c83461e53ca7d204e1d634f0c78199d60320d7bjerenkrantz }
8c83461e53ca7d204e1d634f0c78199d60320d7bjerenkrantz
93ef028b3ac7dc86ec72204233b9d99c69587c54striker if (ret != EAGAIN) {
8c83461e53ca7d204e1d634f0c78199d60320d7bjerenkrantz goto immediate;
8c83461e53ca7d204e1d634f0c78199d60320d7bjerenkrantz }
35b9e4d5f3452cad4b3bec6829ce87a5ce9e9227striker
8c83461e53ca7d204e1d634f0c78199d60320d7bjerenkrantz return req;
8c83461e53ca7d204e1d634f0c78199d60320d7bjerenkrantz
8c83461e53ca7d204e1d634f0c78199d60320d7bjerenkrantzimmediate:
8c83461e53ca7d204e1d634f0c78199d60320d7bjerenkrantz if (ret == EOK) {
8c83461e53ca7d204e1d634f0c78199d60320d7bjerenkrantz tevent_req_done(req);
01e8aca9299a0b872414c24c8b7724d6f88ae665ianh } else {
8c83461e53ca7d204e1d634f0c78199d60320d7bjerenkrantz tevent_req_error(req, ret);
8c83461e53ca7d204e1d634f0c78199d60320d7bjerenkrantz }
8c83461e53ca7d204e1d634f0c78199d60320d7bjerenkrantz tevent_req_post(req, ev);
8c83461e53ca7d204e1d634f0c78199d60320d7bjerenkrantz return req;
8c83461e53ca7d204e1d634f0c78199d60320d7bjerenkrantz}
93ef028b3ac7dc86ec72204233b9d99c69587c54striker
8c83461e53ca7d204e1d634f0c78199d60320d7bjerenkrantzstatic errno_t ipa_hbac_service_info_next(struct tevent_req *req,
8c83461e53ca7d204e1d634f0c78199d60320d7bjerenkrantz struct ipa_hbac_service_state *state)
35b9e4d5f3452cad4b3bec6829ce87a5ce9e9227striker{
8c83461e53ca7d204e1d634f0c78199d60320d7bjerenkrantz struct tevent_req *subreq;
d86551ca954d666d5b15ad38e9daf45680516c25jerenkrantz struct sdap_search_base *base;
8c83461e53ca7d204e1d634f0c78199d60320d7bjerenkrantz
8c83461e53ca7d204e1d634f0c78199d60320d7bjerenkrantz base = state->search_bases[state->search_base_iter];
8c83461e53ca7d204e1d634f0c78199d60320d7bjerenkrantz if (base == NULL) {
01e8aca9299a0b872414c24c8b7724d6f88ae665ianh return EOK;
8c83461e53ca7d204e1d634f0c78199d60320d7bjerenkrantz }
8c83461e53ca7d204e1d634f0c78199d60320d7bjerenkrantz
738236127338633bda6136e4715cc1973997b21cbrianp talloc_zfree(state->cur_filter);
8c83461e53ca7d204e1d634f0c78199d60320d7bjerenkrantz state->cur_filter = sdap_get_id_specific_filter(state,
8c83461e53ca7d204e1d634f0c78199d60320d7bjerenkrantz state->service_filter,
8c83461e53ca7d204e1d634f0c78199d60320d7bjerenkrantz base->filter);
8c83461e53ca7d204e1d634f0c78199d60320d7bjerenkrantz if (state->cur_filter == NULL) {
01e8aca9299a0b872414c24c8b7724d6f88ae665ianh return ENOMEM;
8c83461e53ca7d204e1d634f0c78199d60320d7bjerenkrantz }
8c83461e53ca7d204e1d634f0c78199d60320d7bjerenkrantz
8c83461e53ca7d204e1d634f0c78199d60320d7bjerenkrantz DEBUG(SSSDBG_TRACE_FUNC, ("Sending request for next search base: "
8c83461e53ca7d204e1d634f0c78199d60320d7bjerenkrantz "[%s][%d][%s]\n", base->basedn, base->scope,
8c83461e53ca7d204e1d634f0c78199d60320d7bjerenkrantz state->cur_filter));
01e8aca9299a0b872414c24c8b7724d6f88ae665ianh subreq = sdap_get_generic_send(state, state->ev, state->opts, state->sh,
8c83461e53ca7d204e1d634f0c78199d60320d7bjerenkrantz base->basedn, base->scope,
8c83461e53ca7d204e1d634f0c78199d60320d7bjerenkrantz state->cur_filter,
8c83461e53ca7d204e1d634f0c78199d60320d7bjerenkrantz state->attrs, NULL, 0,
8c83461e53ca7d204e1d634f0c78199d60320d7bjerenkrantz dp_opt_get_int(state->opts->basic,
b5033962c73a470b6f36a3ac796c542a6ab4ddf6brianp SDAP_ENUM_SEARCH_TIMEOUT),
b5033962c73a470b6f36a3ac796c542a6ab4ddf6brianp true);
baf4649272f3dabd48b095a23b3180cc0105dce6rjung if (subreq == NULL) {
baf4649272f3dabd48b095a23b3180cc0105dce6rjung DEBUG(SSSDBG_CRIT_FAILURE, ("Error requesting service info\n"));
baf4649272f3dabd48b095a23b3180cc0105dce6rjung return EIO;
baf4649272f3dabd48b095a23b3180cc0105dce6rjung }
baf4649272f3dabd48b095a23b3180cc0105dce6rjung tevent_req_set_callback(subreq, ipa_hbac_service_info_done, req);
baf4649272f3dabd48b095a23b3180cc0105dce6rjung
baf4649272f3dabd48b095a23b3180cc0105dce6rjung return EAGAIN;
b5033962c73a470b6f36a3ac796c542a6ab4ddf6brianp}
b5033962c73a470b6f36a3ac796c542a6ab4ddf6brianp
35b9e4d5f3452cad4b3bec6829ce87a5ce9e9227strikerstatic void
b5033962c73a470b6f36a3ac796c542a6ab4ddf6brianpipa_hbac_service_info_done(struct tevent_req *subreq)
b5033962c73a470b6f36a3ac796c542a6ab4ddf6brianp{
b5033962c73a470b6f36a3ac796c542a6ab4ddf6brianp errno_t ret;
b5033962c73a470b6f36a3ac796c542a6ab4ddf6brianp struct tevent_req *req =
baf4649272f3dabd48b095a23b3180cc0105dce6rjung tevent_req_callback_data(subreq, struct tevent_req);
baf4649272f3dabd48b095a23b3180cc0105dce6rjung struct ipa_hbac_service_state *state =
baf4649272f3dabd48b095a23b3180cc0105dce6rjung tevent_req_data(req, struct ipa_hbac_service_state);
baf4649272f3dabd48b095a23b3180cc0105dce6rjung char *servicegroup_filter;
e302f38fd646764ce1a1e1c578d794aef514a9e5sf
e302f38fd646764ce1a1e1c578d794aef514a9e5sf ret = sdap_get_generic_recv(subreq, state,
e302f38fd646764ce1a1e1c578d794aef514a9e5sf &state->service_count,
e302f38fd646764ce1a1e1c578d794aef514a9e5sf &state->services);
e302f38fd646764ce1a1e1c578d794aef514a9e5sf talloc_zfree(subreq);
baf4649272f3dabd48b095a23b3180cc0105dce6rjung if (ret != EOK && ret != ENOENT) {
baf4649272f3dabd48b095a23b3180cc0105dce6rjung goto done;
baf4649272f3dabd48b095a23b3180cc0105dce6rjung }
baf4649272f3dabd48b095a23b3180cc0105dce6rjung
baf4649272f3dabd48b095a23b3180cc0105dce6rjung if (ret == ENOENT || state->service_count == 0) {
baf4649272f3dabd48b095a23b3180cc0105dce6rjung /* If there are no services, we'll shortcut out
baf4649272f3dabd48b095a23b3180cc0105dce6rjung * This is still valid, as rules can apply to
baf4649272f3dabd48b095a23b3180cc0105dce6rjung * all services
baf4649272f3dabd48b095a23b3180cc0105dce6rjung *
baf4649272f3dabd48b095a23b3180cc0105dce6rjung * There's no reason to try to process groups
baf4649272f3dabd48b095a23b3180cc0105dce6rjung */
baf4649272f3dabd48b095a23b3180cc0105dce6rjung
baf4649272f3dabd48b095a23b3180cc0105dce6rjung state->search_base_iter++;
baf4649272f3dabd48b095a23b3180cc0105dce6rjung ret = ipa_hbac_service_info_next(req, state);
b5033962c73a470b6f36a3ac796c542a6ab4ddf6brianp if (ret == EAGAIN) {
baf4649272f3dabd48b095a23b3180cc0105dce6rjung return;
baf4649272f3dabd48b095a23b3180cc0105dce6rjung }
e302f38fd646764ce1a1e1c578d794aef514a9e5sf
e302f38fd646764ce1a1e1c578d794aef514a9e5sf state->service_count = 0;
b5033962c73a470b6f36a3ac796c542a6ab4ddf6brianp state->services = NULL;
b5033962c73a470b6f36a3ac796c542a6ab4ddf6brianp goto done;
e302f38fd646764ce1a1e1c578d794aef514a9e5sf }
e302f38fd646764ce1a1e1c578d794aef514a9e5sf
e302f38fd646764ce1a1e1c578d794aef514a9e5sf ret = replace_attribute_name(IPA_MEMBEROF, SYSDB_ORIG_MEMBEROF,
e302f38fd646764ce1a1e1c578d794aef514a9e5sf state->service_count,
e302f38fd646764ce1a1e1c578d794aef514a9e5sf state->services);
e302f38fd646764ce1a1e1c578d794aef514a9e5sf if (ret != EOK) {
e302f38fd646764ce1a1e1c578d794aef514a9e5sf DEBUG(1, ("Could not replace attribute names\n"));
e302f38fd646764ce1a1e1c578d794aef514a9e5sf goto done;
e302f38fd646764ce1a1e1c578d794aef514a9e5sf }
e302f38fd646764ce1a1e1c578d794aef514a9e5sf
e302f38fd646764ce1a1e1c578d794aef514a9e5sf servicegroup_filter = talloc_asprintf(state, "(objectClass=%s)",
e302f38fd646764ce1a1e1c578d794aef514a9e5sf IPA_HBAC_SERVICE_GROUP);
e302f38fd646764ce1a1e1c578d794aef514a9e5sf if (servicegroup_filter == NULL) {
e302f38fd646764ce1a1e1c578d794aef514a9e5sf ret = ENOMEM;
e302f38fd646764ce1a1e1c578d794aef514a9e5sf goto done;
e302f38fd646764ce1a1e1c578d794aef514a9e5sf }
e302f38fd646764ce1a1e1c578d794aef514a9e5sf
e302f38fd646764ce1a1e1c578d794aef514a9e5sf talloc_zfree(state->service_filter);
e302f38fd646764ce1a1e1c578d794aef514a9e5sf state->service_filter = servicegroup_filter;
e302f38fd646764ce1a1e1c578d794aef514a9e5sf
e302f38fd646764ce1a1e1c578d794aef514a9e5sf state->search_base_iter = 0;
e302f38fd646764ce1a1e1c578d794aef514a9e5sf ret = ipa_hbac_servicegroup_info_next(req, state);
e302f38fd646764ce1a1e1c578d794aef514a9e5sf if (ret == EOK) {
e302f38fd646764ce1a1e1c578d794aef514a9e5sf ret = EINVAL;
b5033962c73a470b6f36a3ac796c542a6ab4ddf6brianp }
b5033962c73a470b6f36a3ac796c542a6ab4ddf6brianp
b5033962c73a470b6f36a3ac796c542a6ab4ddf6brianp if (ret != EAGAIN) {
b5033962c73a470b6f36a3ac796c542a6ab4ddf6brianp goto done;
b5033962c73a470b6f36a3ac796c542a6ab4ddf6brianp }
b5033962c73a470b6f36a3ac796c542a6ab4ddf6brianp
b5033962c73a470b6f36a3ac796c542a6ab4ddf6brianp return;
b5033962c73a470b6f36a3ac796c542a6ab4ddf6brianp
b5033962c73a470b6f36a3ac796c542a6ab4ddf6brianpdone:
b5033962c73a470b6f36a3ac796c542a6ab4ddf6brianp if (ret == EOK) {
b5033962c73a470b6f36a3ac796c542a6ab4ddf6brianp tevent_req_done(req);
baf4649272f3dabd48b095a23b3180cc0105dce6rjung } else {
baf4649272f3dabd48b095a23b3180cc0105dce6rjung tevent_req_error(req, ret);
baf4649272f3dabd48b095a23b3180cc0105dce6rjung }
baf4649272f3dabd48b095a23b3180cc0105dce6rjung}
baf4649272f3dabd48b095a23b3180cc0105dce6rjung
baf4649272f3dabd48b095a23b3180cc0105dce6rjungstatic errno_t
baf4649272f3dabd48b095a23b3180cc0105dce6rjungipa_hbac_servicegroup_info_next(struct tevent_req *req,
baf4649272f3dabd48b095a23b3180cc0105dce6rjung struct ipa_hbac_service_state *state)
baf4649272f3dabd48b095a23b3180cc0105dce6rjung{
e302f38fd646764ce1a1e1c578d794aef514a9e5sf struct tevent_req *subreq;
e302f38fd646764ce1a1e1c578d794aef514a9e5sf struct sdap_search_base *base;
e302f38fd646764ce1a1e1c578d794aef514a9e5sf
e302f38fd646764ce1a1e1c578d794aef514a9e5sf base = state->search_bases[state->search_base_iter];
e302f38fd646764ce1a1e1c578d794aef514a9e5sf if (base == NULL) {
e302f38fd646764ce1a1e1c578d794aef514a9e5sf return EOK;
e302f38fd646764ce1a1e1c578d794aef514a9e5sf }
b5033962c73a470b6f36a3ac796c542a6ab4ddf6brianp
b5033962c73a470b6f36a3ac796c542a6ab4ddf6brianp talloc_zfree(state->cur_filter);
b5033962c73a470b6f36a3ac796c542a6ab4ddf6brianp state->cur_filter = sdap_get_id_specific_filter(state,
b5033962c73a470b6f36a3ac796c542a6ab4ddf6brianp state->service_filter,
f48a3dc705ff69288cb5af136a2cd753f45d6572brianp base->filter);
f48a3dc705ff69288cb5af136a2cd753f45d6572brianp if (state->cur_filter == NULL) {
f48a3dc705ff69288cb5af136a2cd753f45d6572brianp return ENOMEM;
f48a3dc705ff69288cb5af136a2cd753f45d6572brianp }
f48a3dc705ff69288cb5af136a2cd753f45d6572brianp
f48a3dc705ff69288cb5af136a2cd753f45d6572brianp /* Look up service groups */
f48a3dc705ff69288cb5af136a2cd753f45d6572brianp DEBUG(SSSDBG_TRACE_FUNC, ("Sending request for next search base: "
f48a3dc705ff69288cb5af136a2cd753f45d6572brianp "[%s][%d][%s]\n", base->basedn, base->scope,
f48a3dc705ff69288cb5af136a2cd753f45d6572brianp state->cur_filter));
f48a3dc705ff69288cb5af136a2cd753f45d6572brianp subreq = sdap_get_generic_send(state, state->ev, state->opts, state->sh,
f48a3dc705ff69288cb5af136a2cd753f45d6572brianp base->basedn, base->scope,
f48a3dc705ff69288cb5af136a2cd753f45d6572brianp state->cur_filter, state->attrs, NULL, 0,
f48a3dc705ff69288cb5af136a2cd753f45d6572brianp dp_opt_get_int(state->opts->basic,
f48a3dc705ff69288cb5af136a2cd753f45d6572brianp SDAP_ENUM_SEARCH_TIMEOUT),
f48a3dc705ff69288cb5af136a2cd753f45d6572brianp true);
eec984329ef5e5916b7554a5b2b585d7a1a1202dbrianp if (subreq == NULL) {
f48a3dc705ff69288cb5af136a2cd753f45d6572brianp DEBUG(SSSDBG_CRIT_FAILURE, ("Error requesting servicegroup info\n"));
f48a3dc705ff69288cb5af136a2cd753f45d6572brianp return EIO;
f48a3dc705ff69288cb5af136a2cd753f45d6572brianp }
f48a3dc705ff69288cb5af136a2cd753f45d6572brianp tevent_req_set_callback(subreq, ipa_hbac_servicegroup_info_done, req);
f48a3dc705ff69288cb5af136a2cd753f45d6572brianp
f48a3dc705ff69288cb5af136a2cd753f45d6572brianp return EAGAIN;
f48a3dc705ff69288cb5af136a2cd753f45d6572brianp}
f48a3dc705ff69288cb5af136a2cd753f45d6572brianp
eec984329ef5e5916b7554a5b2b585d7a1a1202dbrianpstatic void
f48a3dc705ff69288cb5af136a2cd753f45d6572brianpipa_hbac_servicegroup_info_done(struct tevent_req *subreq)
f48a3dc705ff69288cb5af136a2cd753f45d6572brianp{
f48a3dc705ff69288cb5af136a2cd753f45d6572brianp errno_t ret;
f48a3dc705ff69288cb5af136a2cd753f45d6572brianp struct tevent_req *req =
f48a3dc705ff69288cb5af136a2cd753f45d6572brianp tevent_req_callback_data(subreq, struct tevent_req);
f48a3dc705ff69288cb5af136a2cd753f45d6572brianp struct ipa_hbac_service_state *state =
f48a3dc705ff69288cb5af136a2cd753f45d6572brianp tevent_req_data(req, struct ipa_hbac_service_state);
f48a3dc705ff69288cb5af136a2cd753f45d6572brianp size_t total_count;
f48a3dc705ff69288cb5af136a2cd753f45d6572brianp size_t group_count;
f48a3dc705ff69288cb5af136a2cd753f45d6572brianp struct sysdb_attrs **groups;
f48a3dc705ff69288cb5af136a2cd753f45d6572brianp struct sysdb_attrs **target;
f48a3dc705ff69288cb5af136a2cd753f45d6572brianp int i;
f48a3dc705ff69288cb5af136a2cd753f45d6572brianp
f48a3dc705ff69288cb5af136a2cd753f45d6572brianp ret = sdap_get_generic_recv(subreq, state,
f48a3dc705ff69288cb5af136a2cd753f45d6572brianp &group_count,
f48a3dc705ff69288cb5af136a2cd753f45d6572brianp &groups);
f48a3dc705ff69288cb5af136a2cd753f45d6572brianp talloc_zfree(subreq);
f48a3dc705ff69288cb5af136a2cd753f45d6572brianp if (ret != EOK) {
f48a3dc705ff69288cb5af136a2cd753f45d6572brianp goto done;
f48a3dc705ff69288cb5af136a2cd753f45d6572brianp }
f48a3dc705ff69288cb5af136a2cd753f45d6572brianp
f48a3dc705ff69288cb5af136a2cd753f45d6572brianp if (group_count > 0) {
f48a3dc705ff69288cb5af136a2cd753f45d6572brianp ret = replace_attribute_name(IPA_MEMBER, SYSDB_ORIG_MEMBER,
f48a3dc705ff69288cb5af136a2cd753f45d6572brianp group_count,
f48a3dc705ff69288cb5af136a2cd753f45d6572brianp groups);
f48a3dc705ff69288cb5af136a2cd753f45d6572brianp if (ret != EOK) {
3a2bc69dbf5d2afe57bcc21c554aa1e3851fb159jim DEBUG(SSSDBG_CRIT_FAILURE, ("Could not replace attribute names\n"));
3a2bc69dbf5d2afe57bcc21c554aa1e3851fb159jim goto done;
9721061a47962768f63db360a1fb2a4c068f87d6jailletc }
3a2bc69dbf5d2afe57bcc21c554aa1e3851fb159jim
3a2bc69dbf5d2afe57bcc21c554aa1e3851fb159jim ret = replace_attribute_name(IPA_MEMBEROF, SYSDB_ORIG_MEMBEROF,
3a2bc69dbf5d2afe57bcc21c554aa1e3851fb159jim state->servicegroup_count,
3a2bc69dbf5d2afe57bcc21c554aa1e3851fb159jim state->servicegroups);
3a2bc69dbf5d2afe57bcc21c554aa1e3851fb159jim if (ret != EOK) {
3a2bc69dbf5d2afe57bcc21c554aa1e3851fb159jim DEBUG(SSSDBG_CRIT_FAILURE, ("Could not replace attribute names\n"));
3a2bc69dbf5d2afe57bcc21c554aa1e3851fb159jim goto done;
3a2bc69dbf5d2afe57bcc21c554aa1e3851fb159jim }
3a2bc69dbf5d2afe57bcc21c554aa1e3851fb159jim
3a2bc69dbf5d2afe57bcc21c554aa1e3851fb159jim total_count = state->servicegroup_count + group_count;
3a2bc69dbf5d2afe57bcc21c554aa1e3851fb159jim state->servicegroups = talloc_realloc(state, state->servicegroups,
3a2bc69dbf5d2afe57bcc21c554aa1e3851fb159jim struct sysdb_attrs *,
3a2bc69dbf5d2afe57bcc21c554aa1e3851fb159jim total_count);
3a2bc69dbf5d2afe57bcc21c554aa1e3851fb159jim if (state->servicegroups == NULL) {
3a2bc69dbf5d2afe57bcc21c554aa1e3851fb159jim ret = ENOMEM;
3a2bc69dbf5d2afe57bcc21c554aa1e3851fb159jim goto done;
}
i = 0;
while (state->servicegroup_count < total_count) {
target = &state->servicegroups[state->servicegroup_count];
*target = talloc_steal(state->servicegroups, groups[i]);
state->servicegroup_count++;
i++;
}
}
state->search_base_iter++;
ret = ipa_hbac_servicegroup_info_next(req, state);
if (ret == EAGAIN) {
return;
} else if (ret != EOK) {
goto done;
}
done:
if (ret == EOK) {
tevent_req_done(req);
} else {
DEBUG(3, ("Error [%d][%s]\n", ret, strerror(ret)));
tevent_req_error(req, ret);
}
}
errno_t
ipa_hbac_service_info_recv(struct tevent_req *req,
TALLOC_CTX *mem_ctx,
size_t *service_count,
struct sysdb_attrs ***services,
size_t *servicegroup_count,
struct sysdb_attrs ***servicegroups)
{
size_t c;
struct ipa_hbac_service_state *state =
tevent_req_data(req, struct ipa_hbac_service_state);
TEVENT_REQ_RETURN_ON_ERROR(req);
*service_count = state->service_count;
*services = talloc_steal(mem_ctx, state->services);
for (c = 0; c < state->service_count; c++) {
/* Guarantee the memory heirarchy of the list */
talloc_steal(state->services, state->services[c]);
}
*servicegroup_count = state->servicegroup_count;
*servicegroups = talloc_steal(mem_ctx, state->servicegroups);
return EOK;
}
errno_t
hbac_service_attrs_to_rule(TALLOC_CTX *mem_ctx,
struct sss_domain_info *domain,
const char *rule_name,
struct sysdb_attrs *rule_attrs,
struct hbac_rule_element **services)
{
errno_t ret;
TALLOC_CTX *tmp_ctx;
struct hbac_rule_element *new_services;
const char *attrs[] = { IPA_CN, NULL };
struct ldb_message_element *el;
size_t num_services = 0;
size_t num_servicegroups = 0;
size_t i;
char *member_dn;
char *filter;
size_t count;
struct ldb_message **msgs;
const char *name;
DEBUG(7, ("Processing PAM services for rule [%s]\n", rule_name));
tmp_ctx = talloc_new(mem_ctx);
if (tmp_ctx == NULL) return ENOMEM;
new_services = talloc_zero(tmp_ctx, struct hbac_rule_element);
if (new_services == NULL) {
ret = ENOMEM;
goto done;
}
/* First check for service category */
ret = hbac_get_category(rule_attrs, IPA_SERVICE_CATEGORY,
&new_services->category);
if (ret != EOK) {
DEBUG(1, ("Could not identify service categories\n"));
goto done;
}
if (new_services->category & HBAC_CATEGORY_ALL) {
/* Short-cut to the exit */
ret = EOK;
goto done;
}
/* Get the list of DNs from the member attr */
ret = sysdb_attrs_get_el(rule_attrs, IPA_MEMBER_SERVICE, &el);
if (ret != EOK && ret != ENOENT) {
DEBUG(1, ("sysdb_attrs_get_el failed.\n"));
goto done;
}
if (ret == ENOENT || el->num_values == 0) {
el->num_values = 0;
DEBUG(4, ("No services specified, rule will never apply.\n"));
}
/* Assume maximum size; We'll trim it later */
new_services->names = talloc_array(new_services,
const char *,
el->num_values +1);
if (new_services->names == NULL) {
ret = ENOMEM;
goto done;
}
new_services->groups = talloc_array(new_services,
const char *,
el->num_values + 1);
if (new_services->groups == NULL) {
ret = ENOMEM;
goto done;
}
for (i = 0; i < el->num_values; i++) {
ret = sss_filter_sanitize(tmp_ctx,
(const char *)el->values[i].data,
&member_dn);
if (ret != EOK) goto done;
filter = talloc_asprintf(member_dn, "(%s=%s)",
SYSDB_ORIG_DN, member_dn);
if (filter == NULL) {
ret = ENOMEM;
goto done;
}
/* First check if this is a specific service */
ret = sysdb_search_custom(tmp_ctx, domain->sysdb, domain, filter,
HBAC_SERVICES_SUBDIR, attrs,
&count, &msgs);
if (ret != EOK && ret != ENOENT) goto done;
if (ret == EOK && count == 0) {
ret = ENOENT;
}
if (ret == EOK) {
if (count > 1) {
DEBUG(1, ("Original DN matched multiple services. "
"Skipping \n"));
talloc_zfree(member_dn);
continue;
}
/* Original DN matched a single service. Get the service name */
name = ldb_msg_find_attr_as_string(msgs[0], IPA_CN, NULL);
if (name == NULL) {
DEBUG(1, ("Attribute is missing!\n"));
ret = EFAULT;
goto done;
}
new_services->names[num_services] =
talloc_strdup(new_services->names, name);
if (new_services->names[num_services] == NULL) {
ret = ENOMEM;
goto done;
}
DEBUG(8, ("Added service [%s] to rule [%s]\n",
name, rule_name));
num_services++;
} else { /* ret == ENOENT */
/* Check if this is a service group */
ret = sysdb_search_custom(tmp_ctx, domain->sysdb, domain, filter,
HBAC_SERVICEGROUPS_SUBDIR, attrs,
&count, &msgs);
if (ret != EOK && ret != ENOENT) goto done;
if (ret == EOK && count == 0) {
ret = ENOENT;
}
if (ret == EOK) {
if (count > 1) {
DEBUG(1, ("Original DN matched multiple service groups. "
"Skipping\n"));
talloc_zfree(member_dn);
continue;
}
/* Original DN matched a single group. Get the groupname */
name = ldb_msg_find_attr_as_string(msgs[0], IPA_CN, NULL);
if (name == NULL) {
DEBUG(1, ("Attribute is missing!\n"));
ret = EFAULT;
goto done;
}
new_services->groups[num_servicegroups] =
talloc_strdup(new_services->groups, name);
if (new_services->groups[num_servicegroups] == NULL) {
ret = ENOMEM;
goto done;
}
DEBUG(8, ("Added service group [%s] to rule [%s]\n",
name, rule_name));
num_servicegroups++;
} else { /* ret == ENOENT */
/* Neither a service nor a service group? Skip it */
DEBUG(1, ("[%s] does not map to either a service or "
"service group. Skipping\n", member_dn));
}
}
talloc_zfree(member_dn);
}
new_services->names[num_services] = NULL;
new_services->groups[num_servicegroups] = NULL;
/* Shrink the arrays down to their real sizes */
new_services->names = talloc_realloc(new_services, new_services->names,
const char *, num_services + 1);
if (new_services->names == NULL) {
ret = ENOMEM;
goto done;
}
new_services->groups = talloc_realloc(new_services, new_services->groups,
const char *, num_servicegroups + 1);
if (new_services->groups == NULL) {
ret = ENOMEM;
goto done;
}
ret = EOK;
done:
if (ret == EOK) {
*services = talloc_steal(mem_ctx, new_services);
}
talloc_free(tmp_ctx);
return ret;
}
errno_t
get_ipa_servicegroupname(TALLOC_CTX *mem_ctx,
struct sysdb_ctx *sysdb,
const char *service_dn,
char **servicegroupname)
{
errno_t ret;
struct ldb_dn *dn;
const char *rdn_name;
const char *svc_comp_name;
const char *hbac_comp_name;
const struct ldb_val *rdn_val;
const struct ldb_val *svc_comp_val;
const struct ldb_val *hbac_comp_val;
/* This is an IPA-specific hack. It may not
* work for non-IPA servers and will need to
* be changed if SSSD ever supports HBAC on
* a non-IPA server.
*/
*servicegroupname = NULL;
dn = ldb_dn_new(mem_ctx, sysdb_ctx_get_ldb(sysdb), service_dn);
if (dn == NULL) {
ret = ENOMEM;
goto done;
}
if (!ldb_dn_validate(dn)) {
ret = EINVAL;
goto done;
}
if (ldb_dn_get_comp_num(dn) < 4) {
/* RDN, services, hbac, and at least one DC= */
/* If it's fewer, it's not a group DN */
ret = ENOENT;
goto done;
}
/* If the RDN name is 'cn' */
rdn_name = ldb_dn_get_rdn_name(dn);
if (rdn_name == NULL) {
/* Shouldn't happen if ldb_dn_validate()
* passed, but we'll be careful.
*/
ret = EINVAL;
goto done;
}
if (strcasecmp("cn", rdn_name) != 0) {
/* RDN has the wrong attribute name.
* It's not a service.
*/
ret = ENOENT;
goto done;
}
/* and the second component is "cn=hbacservicegroups" */
svc_comp_name = ldb_dn_get_component_name(dn, 1);
if (strcasecmp("cn", svc_comp_name) != 0) {
/* The second component name is not "cn" */
ret = ENOENT;
goto done;
}
svc_comp_val = ldb_dn_get_component_val(dn, 1);
if (strncasecmp("hbacservicegroups",
(const char *) svc_comp_val->data,
svc_comp_val->length) != 0) {
/* The second component value is not "hbacservicegroups" */
ret = ENOENT;
goto done;
}
/* and the third component is "hbac" */
hbac_comp_name = ldb_dn_get_component_name(dn, 2);
if (strcasecmp("cn", hbac_comp_name) != 0) {
/* The third component name is not "cn" */
ret = ENOENT;
goto done;
}
hbac_comp_val = ldb_dn_get_component_val(dn, 2);
if (strncasecmp("hbac",
(const char *) hbac_comp_val->data,
hbac_comp_val->length) != 0) {
/* The third component value is not "hbac" */
ret = ENOENT;
goto done;
}
/* Then the value of the RDN is the group name */
rdn_val = ldb_dn_get_rdn_val(dn);
*servicegroupname = talloc_strndup(mem_ctx,
(const char *)rdn_val->data,
rdn_val->length);
if (*servicegroupname == NULL) {
ret = ENOMEM;
goto done;
}
ret = EOK;
done:
talloc_free(dn);
return ret;
}