Line data Source code
1 : /*
2 : SSSD
3 :
4 : Authors:
5 : Stephen Gallagher <sgallagh@redhat.com>
6 :
7 : Copyright (C) 2011 Red Hat
8 :
9 : This program is free software; you can redistribute it and/or modify
10 : it under the terms of the GNU General Public License as published by
11 : the Free Software Foundation; either version 3 of the License, or
12 : (at your option) any later version.
13 :
14 : This program is distributed in the hope that it will be useful,
15 : but WITHOUT ANY WARRANTY; without even the implied warranty of
16 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 : GNU General Public License for more details.
18 :
19 : You should have received a copy of the GNU General Public License
20 : along with this program. If not, see <http://www.gnu.org/licenses/>.
21 : */
22 :
23 : #include "util/util.h"
24 : #include "providers/ipa/ipa_hbac_private.h"
25 : #include "providers/ldap/sdap_async.h"
26 :
27 : struct ipa_hbac_service_state {
28 : struct tevent_context *ev;
29 : struct sdap_handle *sh;
30 : struct sdap_options *opts;
31 : const char **attrs;
32 :
33 : char *service_filter;
34 : char *cur_filter;
35 :
36 : struct sdap_search_base **search_bases;
37 : int search_base_iter;
38 :
39 : /* Return values */
40 : size_t service_count;
41 : struct sysdb_attrs **services;
42 :
43 : size_t servicegroup_count;
44 : struct sysdb_attrs **servicegroups;
45 : };
46 :
47 : static errno_t
48 : ipa_hbac_service_info_next(struct tevent_req *req,
49 : struct ipa_hbac_service_state *state);
50 : static void
51 : ipa_hbac_service_info_done(struct tevent_req *subreq);
52 : static errno_t
53 : ipa_hbac_servicegroup_info_next(struct tevent_req *req,
54 : struct ipa_hbac_service_state *state);
55 : static void
56 : ipa_hbac_servicegroup_info_done(struct tevent_req *subreq);
57 :
58 : struct tevent_req *
59 0 : ipa_hbac_service_info_send(TALLOC_CTX *mem_ctx,
60 : struct tevent_context *ev,
61 : struct sdap_handle *sh,
62 : struct sdap_options *opts,
63 : struct sdap_search_base **search_bases)
64 : {
65 : errno_t ret;
66 : struct ipa_hbac_service_state *state;
67 : struct tevent_req *req;
68 : char *service_filter;
69 :
70 0 : req = tevent_req_create(mem_ctx, &state, struct ipa_hbac_service_state);
71 0 : if (req == NULL) {
72 0 : DEBUG(SSSDBG_CRIT_FAILURE, "tevent_req_create failed.\n");
73 0 : return NULL;
74 : }
75 :
76 0 : state->ev = ev;
77 0 : state->sh = sh;
78 0 : state->opts = opts;
79 :
80 0 : state->search_bases = search_bases;
81 0 : state->search_base_iter = 0;
82 :
83 0 : service_filter = talloc_asprintf(state, "(objectClass=%s)",
84 : IPA_HBAC_SERVICE);
85 0 : if (service_filter == NULL) {
86 0 : ret = ENOMEM;
87 0 : goto immediate;
88 : }
89 :
90 0 : state->service_filter = service_filter;
91 0 : state->cur_filter = NULL;
92 :
93 0 : state->attrs = talloc_array(state, const char *, 6);
94 0 : if (state->attrs == NULL) {
95 0 : DEBUG(SSSDBG_CRIT_FAILURE,
96 : "Failed to allocate service attribute list.\n");
97 0 : ret = ENOMEM;
98 0 : goto immediate;
99 : }
100 0 : state->attrs[0] = OBJECTCLASS;
101 0 : state->attrs[1] = IPA_CN;
102 0 : state->attrs[2] = IPA_UNIQUE_ID;
103 0 : state->attrs[3] = IPA_MEMBER;
104 0 : state->attrs[4] = IPA_MEMBEROF;
105 0 : state->attrs[5] = NULL;
106 :
107 0 : ret = ipa_hbac_service_info_next(req, state);
108 0 : if (ret == EOK) {
109 0 : ret = EINVAL;
110 : }
111 :
112 0 : if (ret != EAGAIN) {
113 0 : goto immediate;
114 : }
115 :
116 0 : return req;
117 :
118 : immediate:
119 0 : if (ret == EOK) {
120 0 : tevent_req_done(req);
121 : } else {
122 0 : tevent_req_error(req, ret);
123 : }
124 0 : tevent_req_post(req, ev);
125 0 : return req;
126 : }
127 :
128 0 : static errno_t ipa_hbac_service_info_next(struct tevent_req *req,
129 : struct ipa_hbac_service_state *state)
130 : {
131 : struct tevent_req *subreq;
132 : struct sdap_search_base *base;
133 :
134 0 : base = state->search_bases[state->search_base_iter];
135 0 : if (base == NULL) {
136 0 : return EOK;
137 : }
138 :
139 0 : talloc_zfree(state->cur_filter);
140 0 : state->cur_filter = sdap_combine_filters(state, state->service_filter,
141 : base->filter);
142 0 : if (state->cur_filter == NULL) {
143 0 : return ENOMEM;
144 : }
145 :
146 0 : DEBUG(SSSDBG_TRACE_FUNC, "Sending request for next search base: "
147 : "[%s][%d][%s]\n", base->basedn, base->scope,
148 : state->cur_filter);
149 0 : subreq = sdap_get_generic_send(state, state->ev, state->opts, state->sh,
150 : base->basedn, base->scope,
151 0 : state->cur_filter,
152 : state->attrs, NULL, 0,
153 0 : dp_opt_get_int(state->opts->basic,
154 : SDAP_ENUM_SEARCH_TIMEOUT),
155 : true);
156 0 : if (subreq == NULL) {
157 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Error requesting service info\n");
158 0 : return EIO;
159 : }
160 0 : tevent_req_set_callback(subreq, ipa_hbac_service_info_done, req);
161 :
162 0 : return EAGAIN;
163 : }
164 :
165 : static void
166 0 : ipa_hbac_service_info_done(struct tevent_req *subreq)
167 : {
168 : errno_t ret;
169 0 : struct tevent_req *req =
170 0 : tevent_req_callback_data(subreq, struct tevent_req);
171 0 : struct ipa_hbac_service_state *state =
172 0 : tevent_req_data(req, struct ipa_hbac_service_state);
173 : char *servicegroup_filter;
174 :
175 0 : ret = sdap_get_generic_recv(subreq, state,
176 : &state->service_count,
177 : &state->services);
178 0 : talloc_zfree(subreq);
179 0 : if (ret != EOK && ret != ENOENT) {
180 0 : goto done;
181 : }
182 :
183 0 : if (ret == ENOENT || state->service_count == 0) {
184 : /* If there are no services, we'll shortcut out
185 : * This is still valid, as rules can apply to
186 : * all services
187 : *
188 : * There's no reason to try to process groups
189 : */
190 :
191 0 : state->search_base_iter++;
192 0 : ret = ipa_hbac_service_info_next(req, state);
193 0 : if (ret == EAGAIN) {
194 0 : return;
195 : }
196 :
197 0 : state->service_count = 0;
198 0 : state->services = NULL;
199 0 : goto done;
200 : }
201 :
202 0 : ret = replace_attribute_name(IPA_MEMBEROF, SYSDB_ORIG_MEMBEROF,
203 : state->service_count,
204 : state->services);
205 0 : if (ret != EOK) {
206 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Could not replace attribute names\n");
207 0 : goto done;
208 : }
209 :
210 0 : servicegroup_filter = talloc_asprintf(state, "(objectClass=%s)",
211 : IPA_HBAC_SERVICE_GROUP);
212 0 : if (servicegroup_filter == NULL) {
213 0 : ret = ENOMEM;
214 0 : goto done;
215 : }
216 :
217 0 : talloc_zfree(state->service_filter);
218 0 : state->service_filter = servicegroup_filter;
219 :
220 0 : state->search_base_iter = 0;
221 0 : ret = ipa_hbac_servicegroup_info_next(req, state);
222 0 : if (ret == EOK) {
223 0 : ret = EINVAL;
224 : }
225 :
226 0 : if (ret != EAGAIN) {
227 0 : goto done;
228 : }
229 :
230 0 : return;
231 :
232 : done:
233 0 : if (ret == EOK) {
234 0 : tevent_req_done(req);
235 : } else {
236 0 : tevent_req_error(req, ret);
237 : }
238 : }
239 :
240 : static errno_t
241 0 : ipa_hbac_servicegroup_info_next(struct tevent_req *req,
242 : struct ipa_hbac_service_state *state)
243 : {
244 : struct tevent_req *subreq;
245 : struct sdap_search_base *base;
246 :
247 0 : base = state->search_bases[state->search_base_iter];
248 0 : if (base == NULL) {
249 0 : return EOK;
250 : }
251 :
252 0 : talloc_zfree(state->cur_filter);
253 0 : state->cur_filter = sdap_combine_filters(state, state->service_filter,
254 : base->filter);
255 0 : if (state->cur_filter == NULL) {
256 0 : return ENOMEM;
257 : }
258 :
259 : /* Look up service groups */
260 0 : DEBUG(SSSDBG_TRACE_FUNC, "Sending request for next search base: "
261 : "[%s][%d][%s]\n", base->basedn, base->scope,
262 : state->cur_filter);
263 0 : subreq = sdap_get_generic_send(state, state->ev, state->opts, state->sh,
264 : base->basedn, base->scope,
265 0 : state->cur_filter, state->attrs, NULL, 0,
266 0 : dp_opt_get_int(state->opts->basic,
267 : SDAP_ENUM_SEARCH_TIMEOUT),
268 : true);
269 0 : if (subreq == NULL) {
270 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Error requesting servicegroup info\n");
271 0 : return EIO;
272 : }
273 0 : tevent_req_set_callback(subreq, ipa_hbac_servicegroup_info_done, req);
274 :
275 0 : return EAGAIN;
276 : }
277 :
278 : static void
279 0 : ipa_hbac_servicegroup_info_done(struct tevent_req *subreq)
280 : {
281 : errno_t ret;
282 0 : struct tevent_req *req =
283 0 : tevent_req_callback_data(subreq, struct tevent_req);
284 0 : struct ipa_hbac_service_state *state =
285 0 : tevent_req_data(req, struct ipa_hbac_service_state);
286 : size_t total_count;
287 : size_t group_count;
288 : struct sysdb_attrs **groups;
289 : struct sysdb_attrs **target;
290 : int i;
291 :
292 0 : ret = sdap_get_generic_recv(subreq, state,
293 : &group_count,
294 : &groups);
295 0 : talloc_zfree(subreq);
296 0 : if (ret != EOK) {
297 0 : goto done;
298 : }
299 :
300 0 : if (group_count > 0) {
301 0 : ret = replace_attribute_name(IPA_MEMBER, SYSDB_ORIG_MEMBER,
302 : group_count,
303 : groups);
304 0 : if (ret != EOK) {
305 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Could not replace attribute names\n");
306 0 : goto done;
307 : }
308 :
309 0 : ret = replace_attribute_name(IPA_MEMBEROF, SYSDB_ORIG_MEMBEROF,
310 : state->servicegroup_count,
311 : state->servicegroups);
312 0 : if (ret != EOK) {
313 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Could not replace attribute names\n");
314 0 : goto done;
315 : }
316 :
317 0 : total_count = state->servicegroup_count + group_count;
318 0 : state->servicegroups = talloc_realloc(state, state->servicegroups,
319 : struct sysdb_attrs *,
320 : total_count);
321 0 : if (state->servicegroups == NULL) {
322 0 : ret = ENOMEM;
323 0 : goto done;
324 : }
325 :
326 0 : i = 0;
327 0 : while (state->servicegroup_count < total_count) {
328 0 : target = &state->servicegroups[state->servicegroup_count];
329 0 : *target = talloc_steal(state->servicegroups, groups[i]);
330 :
331 0 : state->servicegroup_count++;
332 0 : i++;
333 : }
334 : }
335 :
336 0 : state->search_base_iter++;
337 0 : ret = ipa_hbac_servicegroup_info_next(req, state);
338 0 : if (ret == EAGAIN) {
339 0 : return;
340 0 : } else if (ret != EOK) {
341 0 : goto done;
342 : }
343 :
344 : done:
345 0 : if (ret == EOK) {
346 0 : tevent_req_done(req);
347 : } else {
348 0 : DEBUG(SSSDBG_MINOR_FAILURE, "Error [%d][%s]\n", ret, strerror(ret));
349 0 : tevent_req_error(req, ret);
350 : }
351 : }
352 :
353 : errno_t
354 0 : ipa_hbac_service_info_recv(struct tevent_req *req,
355 : TALLOC_CTX *mem_ctx,
356 : size_t *service_count,
357 : struct sysdb_attrs ***services,
358 : size_t *servicegroup_count,
359 : struct sysdb_attrs ***servicegroups)
360 : {
361 : size_t c;
362 0 : struct ipa_hbac_service_state *state =
363 0 : tevent_req_data(req, struct ipa_hbac_service_state);
364 :
365 0 : TEVENT_REQ_RETURN_ON_ERROR(req);
366 :
367 0 : *service_count = state->service_count;
368 0 : *services = talloc_steal(mem_ctx, state->services);
369 0 : for (c = 0; c < state->service_count; c++) {
370 : /* Guarantee the memory heirarchy of the list */
371 0 : talloc_steal(state->services, state->services[c]);
372 : }
373 :
374 0 : *servicegroup_count = state->servicegroup_count;
375 0 : *servicegroups = talloc_steal(mem_ctx, state->servicegroups);
376 :
377 0 : return EOK;
378 : }
379 :
380 : errno_t
381 0 : hbac_service_attrs_to_rule(TALLOC_CTX *mem_ctx,
382 : struct sss_domain_info *domain,
383 : const char *rule_name,
384 : struct sysdb_attrs *rule_attrs,
385 : struct hbac_rule_element **services)
386 : {
387 : errno_t ret;
388 : TALLOC_CTX *tmp_ctx;
389 : struct hbac_rule_element *new_services;
390 0 : const char *attrs[] = { IPA_CN, NULL };
391 : struct ldb_message_element *el;
392 0 : size_t num_services = 0;
393 0 : size_t num_servicegroups = 0;
394 : size_t i;
395 : char *member_dn;
396 : char *filter;
397 : size_t count;
398 : struct ldb_message **msgs;
399 : const char *name;
400 :
401 0 : DEBUG(SSSDBG_TRACE_LIBS,
402 : "Processing PAM services for rule [%s]\n", rule_name);
403 :
404 0 : tmp_ctx = talloc_new(mem_ctx);
405 0 : if (tmp_ctx == NULL) return ENOMEM;
406 :
407 0 : new_services = talloc_zero(tmp_ctx, struct hbac_rule_element);
408 0 : if (new_services == NULL) {
409 0 : ret = ENOMEM;
410 0 : goto done;
411 : }
412 :
413 : /* First check for service category */
414 0 : ret = hbac_get_category(rule_attrs, IPA_SERVICE_CATEGORY,
415 : &new_services->category);
416 0 : if (ret != EOK) {
417 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Could not identify service categories\n");
418 0 : goto done;
419 : }
420 0 : if (new_services->category & HBAC_CATEGORY_ALL) {
421 : /* Short-cut to the exit */
422 0 : ret = EOK;
423 0 : goto done;
424 : }
425 :
426 : /* Get the list of DNs from the member attr */
427 0 : ret = sysdb_attrs_get_el(rule_attrs, IPA_MEMBER_SERVICE, &el);
428 0 : if (ret != EOK && ret != ENOENT) {
429 0 : DEBUG(SSSDBG_CRIT_FAILURE, "sysdb_attrs_get_el failed.\n");
430 0 : goto done;
431 : }
432 0 : if (ret == ENOENT || el->num_values == 0) {
433 0 : el->num_values = 0;
434 0 : DEBUG(SSSDBG_CONF_SETTINGS,
435 : "No services specified, rule will never apply.\n");
436 : }
437 :
438 : /* Assume maximum size; We'll trim it later */
439 0 : new_services->names = talloc_array(new_services,
440 : const char *,
441 : el->num_values +1);
442 0 : if (new_services->names == NULL) {
443 0 : ret = ENOMEM;
444 0 : goto done;
445 : }
446 :
447 0 : new_services->groups = talloc_array(new_services,
448 : const char *,
449 : el->num_values + 1);
450 0 : if (new_services->groups == NULL) {
451 0 : ret = ENOMEM;
452 0 : goto done;
453 : }
454 :
455 0 : for (i = 0; i < el->num_values; i++) {
456 0 : ret = sss_filter_sanitize(tmp_ctx,
457 0 : (const char *)el->values[i].data,
458 : &member_dn);
459 0 : if (ret != EOK) goto done;
460 :
461 0 : filter = talloc_asprintf(member_dn, "(%s=%s)",
462 : SYSDB_ORIG_DN, member_dn);
463 0 : if (filter == NULL) {
464 0 : ret = ENOMEM;
465 0 : goto done;
466 : }
467 :
468 : /* First check if this is a specific service */
469 0 : ret = sysdb_search_custom(tmp_ctx, domain, filter,
470 : HBAC_SERVICES_SUBDIR, attrs,
471 : &count, &msgs);
472 0 : if (ret != EOK && ret != ENOENT) goto done;
473 0 : if (ret == EOK && count == 0) {
474 0 : ret = ENOENT;
475 : }
476 :
477 0 : if (ret == EOK) {
478 0 : if (count > 1) {
479 0 : DEBUG(SSSDBG_CRIT_FAILURE,
480 : "Original DN matched multiple services. "
481 : "Skipping \n");
482 0 : talloc_zfree(member_dn);
483 0 : continue;
484 : }
485 :
486 : /* Original DN matched a single service. Get the service name */
487 0 : name = ldb_msg_find_attr_as_string(msgs[0], IPA_CN, NULL);
488 0 : if (name == NULL) {
489 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Attribute is missing!\n");
490 0 : ret = EFAULT;
491 0 : goto done;
492 : }
493 :
494 0 : new_services->names[num_services] =
495 0 : talloc_strdup(new_services->names, name);
496 0 : if (new_services->names[num_services] == NULL) {
497 0 : ret = ENOMEM;
498 0 : goto done;
499 : }
500 0 : DEBUG(SSSDBG_TRACE_INTERNAL, "Added service [%s] to rule [%s]\n",
501 : name, rule_name);
502 0 : num_services++;
503 : } else { /* ret == ENOENT */
504 : /* Check if this is a service group */
505 0 : ret = sysdb_search_custom(tmp_ctx, domain, filter,
506 : HBAC_SERVICEGROUPS_SUBDIR, attrs,
507 : &count, &msgs);
508 0 : if (ret != EOK && ret != ENOENT) goto done;
509 0 : if (ret == EOK && count == 0) {
510 0 : ret = ENOENT;
511 : }
512 :
513 0 : if (ret == EOK) {
514 0 : if (count > 1) {
515 0 : DEBUG(SSSDBG_CRIT_FAILURE,
516 : "Original DN matched multiple service groups. "
517 : "Skipping\n");
518 0 : talloc_zfree(member_dn);
519 0 : continue;
520 : }
521 :
522 : /* Original DN matched a single group. Get the groupname */
523 0 : name = ldb_msg_find_attr_as_string(msgs[0], IPA_CN, NULL);
524 0 : if (name == NULL) {
525 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Attribute is missing!\n");
526 0 : ret = EFAULT;
527 0 : goto done;
528 : }
529 :
530 0 : new_services->groups[num_servicegroups] =
531 0 : talloc_strdup(new_services->groups, name);
532 0 : if (new_services->groups[num_servicegroups] == NULL) {
533 0 : ret = ENOMEM;
534 0 : goto done;
535 : }
536 :
537 0 : DEBUG(SSSDBG_TRACE_INTERNAL,
538 : "Added service group [%s] to rule [%s]\n",
539 : name, rule_name);
540 0 : num_servicegroups++;
541 : } else { /* ret == ENOENT */
542 : /* Neither a service nor a service group? Skip it */
543 0 : DEBUG(SSSDBG_CRIT_FAILURE,
544 : "[%s] does not map to either a service or "
545 : "service group. Skipping\n", member_dn);
546 : }
547 : }
548 0 : talloc_zfree(member_dn);
549 : }
550 0 : new_services->names[num_services] = NULL;
551 0 : new_services->groups[num_servicegroups] = NULL;
552 :
553 : /* Shrink the arrays down to their real sizes */
554 0 : new_services->names = talloc_realloc(new_services, new_services->names,
555 : const char *, num_services + 1);
556 0 : if (new_services->names == NULL) {
557 0 : ret = ENOMEM;
558 0 : goto done;
559 : }
560 :
561 0 : new_services->groups = talloc_realloc(new_services, new_services->groups,
562 : const char *, num_servicegroups + 1);
563 0 : if (new_services->groups == NULL) {
564 0 : ret = ENOMEM;
565 0 : goto done;
566 : }
567 :
568 0 : ret = EOK;
569 :
570 : done:
571 0 : if (ret == EOK) {
572 0 : *services = talloc_steal(mem_ctx, new_services);
573 : }
574 0 : talloc_free(tmp_ctx);
575 0 : return ret;
576 : }
577 :
578 : errno_t
579 0 : get_ipa_servicegroupname(TALLOC_CTX *mem_ctx,
580 : struct sysdb_ctx *sysdb,
581 : const char *service_dn,
582 : char **servicegroupname)
583 : {
584 : errno_t ret;
585 : struct ldb_dn *dn;
586 : const char *rdn_name;
587 : const char *svc_comp_name;
588 : const char *hbac_comp_name;
589 : const struct ldb_val *rdn_val;
590 : const struct ldb_val *svc_comp_val;
591 : const struct ldb_val *hbac_comp_val;
592 :
593 : /* This is an IPA-specific hack. It may not
594 : * work for non-IPA servers and will need to
595 : * be changed if SSSD ever supports HBAC on
596 : * a non-IPA server.
597 : */
598 0 : *servicegroupname = NULL;
599 :
600 0 : dn = ldb_dn_new(mem_ctx, sysdb_ctx_get_ldb(sysdb), service_dn);
601 0 : if (dn == NULL) {
602 0 : ret = ENOMEM;
603 0 : goto done;
604 : }
605 :
606 0 : if (!ldb_dn_validate(dn)) {
607 0 : ret = ERR_MALFORMED_ENTRY;
608 0 : goto done;
609 : }
610 :
611 0 : if (ldb_dn_get_comp_num(dn) < 4) {
612 : /* RDN, services, hbac, and at least one DC= */
613 : /* If it's fewer, it's not a group DN */
614 0 : ret = ERR_UNEXPECTED_ENTRY_TYPE;
615 0 : goto done;
616 : }
617 :
618 : /* If the RDN name is 'cn' */
619 0 : rdn_name = ldb_dn_get_rdn_name(dn);
620 0 : if (rdn_name == NULL) {
621 : /* Shouldn't happen if ldb_dn_validate()
622 : * passed, but we'll be careful.
623 : */
624 0 : ret = ERR_MALFORMED_ENTRY;
625 0 : goto done;
626 : }
627 :
628 0 : if (strcasecmp("cn", rdn_name) != 0) {
629 : /* RDN has the wrong attribute name.
630 : * It's not a service.
631 : */
632 0 : ret = ERR_UNEXPECTED_ENTRY_TYPE;
633 0 : goto done;
634 : }
635 :
636 : /* and the second component is "cn=hbacservicegroups" */
637 0 : svc_comp_name = ldb_dn_get_component_name(dn, 1);
638 0 : if (strcasecmp("cn", svc_comp_name) != 0) {
639 : /* The second component name is not "cn" */
640 0 : ret = ERR_UNEXPECTED_ENTRY_TYPE;
641 0 : goto done;
642 : }
643 :
644 0 : svc_comp_val = ldb_dn_get_component_val(dn, 1);
645 0 : if (strncasecmp("hbacservicegroups",
646 0 : (const char *) svc_comp_val->data,
647 : svc_comp_val->length) != 0) {
648 : /* The second component value is not "hbacservicegroups" */
649 0 : ret = ERR_UNEXPECTED_ENTRY_TYPE;
650 0 : goto done;
651 : }
652 :
653 : /* and the third component is "hbac" */
654 0 : hbac_comp_name = ldb_dn_get_component_name(dn, 2);
655 0 : if (strcasecmp("cn", hbac_comp_name) != 0) {
656 : /* The third component name is not "cn" */
657 0 : ret = ERR_UNEXPECTED_ENTRY_TYPE;
658 0 : goto done;
659 : }
660 :
661 0 : hbac_comp_val = ldb_dn_get_component_val(dn, 2);
662 0 : if (strncasecmp("hbac",
663 0 : (const char *) hbac_comp_val->data,
664 : hbac_comp_val->length) != 0) {
665 : /* The third component value is not "hbac" */
666 0 : ret = ERR_UNEXPECTED_ENTRY_TYPE;
667 0 : goto done;
668 : }
669 :
670 : /* Then the value of the RDN is the group name */
671 0 : rdn_val = ldb_dn_get_rdn_val(dn);
672 0 : *servicegroupname = talloc_strndup(mem_ctx,
673 0 : (const char *)rdn_val->data,
674 : rdn_val->length);
675 0 : if (*servicegroupname == NULL) {
676 0 : ret = ENOMEM;
677 0 : goto done;
678 : }
679 :
680 0 : ret = EOK;
681 :
682 : done:
683 0 : talloc_free(dn);
684 0 : return ret;
685 : }
|