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_get_id_specific_filter(state,
141 0 : state->service_filter,
142 : base->filter);
143 0 : if (state->cur_filter == NULL) {
144 0 : return ENOMEM;
145 : }
146 :
147 0 : DEBUG(SSSDBG_TRACE_FUNC, "Sending request for next search base: "
148 : "[%s][%d][%s]\n", base->basedn, base->scope,
149 : state->cur_filter);
150 0 : subreq = sdap_get_generic_send(state, state->ev, state->opts, state->sh,
151 : base->basedn, base->scope,
152 0 : state->cur_filter,
153 : state->attrs, NULL, 0,
154 0 : dp_opt_get_int(state->opts->basic,
155 : SDAP_ENUM_SEARCH_TIMEOUT),
156 : true);
157 0 : if (subreq == NULL) {
158 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Error requesting service info\n");
159 0 : return EIO;
160 : }
161 0 : tevent_req_set_callback(subreq, ipa_hbac_service_info_done, req);
162 :
163 0 : return EAGAIN;
164 : }
165 :
166 : static void
167 0 : ipa_hbac_service_info_done(struct tevent_req *subreq)
168 : {
169 : errno_t ret;
170 0 : struct tevent_req *req =
171 0 : tevent_req_callback_data(subreq, struct tevent_req);
172 0 : struct ipa_hbac_service_state *state =
173 0 : tevent_req_data(req, struct ipa_hbac_service_state);
174 : char *servicegroup_filter;
175 :
176 0 : ret = sdap_get_generic_recv(subreq, state,
177 : &state->service_count,
178 : &state->services);
179 0 : talloc_zfree(subreq);
180 0 : if (ret != EOK && ret != ENOENT) {
181 0 : goto done;
182 : }
183 :
184 0 : if (ret == ENOENT || state->service_count == 0) {
185 : /* If there are no services, we'll shortcut out
186 : * This is still valid, as rules can apply to
187 : * all services
188 : *
189 : * There's no reason to try to process groups
190 : */
191 :
192 0 : state->search_base_iter++;
193 0 : ret = ipa_hbac_service_info_next(req, state);
194 0 : if (ret == EAGAIN) {
195 0 : return;
196 : }
197 :
198 0 : state->service_count = 0;
199 0 : state->services = NULL;
200 0 : goto done;
201 : }
202 :
203 0 : ret = replace_attribute_name(IPA_MEMBEROF, SYSDB_ORIG_MEMBEROF,
204 : state->service_count,
205 : state->services);
206 0 : if (ret != EOK) {
207 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Could not replace attribute names\n");
208 0 : goto done;
209 : }
210 :
211 0 : servicegroup_filter = talloc_asprintf(state, "(objectClass=%s)",
212 : IPA_HBAC_SERVICE_GROUP);
213 0 : if (servicegroup_filter == NULL) {
214 0 : ret = ENOMEM;
215 0 : goto done;
216 : }
217 :
218 0 : talloc_zfree(state->service_filter);
219 0 : state->service_filter = servicegroup_filter;
220 :
221 0 : state->search_base_iter = 0;
222 0 : ret = ipa_hbac_servicegroup_info_next(req, state);
223 0 : if (ret == EOK) {
224 0 : ret = EINVAL;
225 : }
226 :
227 0 : if (ret != EAGAIN) {
228 0 : goto done;
229 : }
230 :
231 0 : return;
232 :
233 : done:
234 0 : if (ret == EOK) {
235 0 : tevent_req_done(req);
236 : } else {
237 0 : tevent_req_error(req, ret);
238 : }
239 : }
240 :
241 : static errno_t
242 0 : ipa_hbac_servicegroup_info_next(struct tevent_req *req,
243 : struct ipa_hbac_service_state *state)
244 : {
245 : struct tevent_req *subreq;
246 : struct sdap_search_base *base;
247 :
248 0 : base = state->search_bases[state->search_base_iter];
249 0 : if (base == NULL) {
250 0 : return EOK;
251 : }
252 :
253 0 : talloc_zfree(state->cur_filter);
254 0 : state->cur_filter = sdap_get_id_specific_filter(state,
255 0 : state->service_filter,
256 : base->filter);
257 0 : if (state->cur_filter == NULL) {
258 0 : return ENOMEM;
259 : }
260 :
261 : /* Look up service groups */
262 0 : DEBUG(SSSDBG_TRACE_FUNC, "Sending request for next search base: "
263 : "[%s][%d][%s]\n", base->basedn, base->scope,
264 : state->cur_filter);
265 0 : subreq = sdap_get_generic_send(state, state->ev, state->opts, state->sh,
266 : base->basedn, base->scope,
267 0 : state->cur_filter, state->attrs, NULL, 0,
268 0 : dp_opt_get_int(state->opts->basic,
269 : SDAP_ENUM_SEARCH_TIMEOUT),
270 : true);
271 0 : if (subreq == NULL) {
272 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Error requesting servicegroup info\n");
273 0 : return EIO;
274 : }
275 0 : tevent_req_set_callback(subreq, ipa_hbac_servicegroup_info_done, req);
276 :
277 0 : return EAGAIN;
278 : }
279 :
280 : static void
281 0 : ipa_hbac_servicegroup_info_done(struct tevent_req *subreq)
282 : {
283 : errno_t ret;
284 0 : struct tevent_req *req =
285 0 : tevent_req_callback_data(subreq, struct tevent_req);
286 0 : struct ipa_hbac_service_state *state =
287 0 : tevent_req_data(req, struct ipa_hbac_service_state);
288 : size_t total_count;
289 : size_t group_count;
290 : struct sysdb_attrs **groups;
291 : struct sysdb_attrs **target;
292 : int i;
293 :
294 0 : ret = sdap_get_generic_recv(subreq, state,
295 : &group_count,
296 : &groups);
297 0 : talloc_zfree(subreq);
298 0 : if (ret != EOK) {
299 0 : goto done;
300 : }
301 :
302 0 : if (group_count > 0) {
303 0 : ret = replace_attribute_name(IPA_MEMBER, SYSDB_ORIG_MEMBER,
304 : group_count,
305 : groups);
306 0 : if (ret != EOK) {
307 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Could not replace attribute names\n");
308 0 : goto done;
309 : }
310 :
311 0 : ret = replace_attribute_name(IPA_MEMBEROF, SYSDB_ORIG_MEMBEROF,
312 : state->servicegroup_count,
313 : state->servicegroups);
314 0 : if (ret != EOK) {
315 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Could not replace attribute names\n");
316 0 : goto done;
317 : }
318 :
319 0 : total_count = state->servicegroup_count + group_count;
320 0 : state->servicegroups = talloc_realloc(state, state->servicegroups,
321 : struct sysdb_attrs *,
322 : total_count);
323 0 : if (state->servicegroups == NULL) {
324 0 : ret = ENOMEM;
325 0 : goto done;
326 : }
327 :
328 0 : i = 0;
329 0 : while (state->servicegroup_count < total_count) {
330 0 : target = &state->servicegroups[state->servicegroup_count];
331 0 : *target = talloc_steal(state->servicegroups, groups[i]);
332 :
333 0 : state->servicegroup_count++;
334 0 : i++;
335 : }
336 : }
337 :
338 0 : state->search_base_iter++;
339 0 : ret = ipa_hbac_servicegroup_info_next(req, state);
340 0 : if (ret == EAGAIN) {
341 0 : return;
342 0 : } else if (ret != EOK) {
343 0 : goto done;
344 : }
345 :
346 : done:
347 0 : if (ret == EOK) {
348 0 : tevent_req_done(req);
349 : } else {
350 0 : DEBUG(SSSDBG_MINOR_FAILURE, "Error [%d][%s]\n", ret, strerror(ret));
351 0 : tevent_req_error(req, ret);
352 : }
353 : }
354 :
355 : errno_t
356 0 : ipa_hbac_service_info_recv(struct tevent_req *req,
357 : TALLOC_CTX *mem_ctx,
358 : size_t *service_count,
359 : struct sysdb_attrs ***services,
360 : size_t *servicegroup_count,
361 : struct sysdb_attrs ***servicegroups)
362 : {
363 : size_t c;
364 0 : struct ipa_hbac_service_state *state =
365 0 : tevent_req_data(req, struct ipa_hbac_service_state);
366 :
367 0 : TEVENT_REQ_RETURN_ON_ERROR(req);
368 :
369 0 : *service_count = state->service_count;
370 0 : *services = talloc_steal(mem_ctx, state->services);
371 0 : for (c = 0; c < state->service_count; c++) {
372 : /* Guarantee the memory heirarchy of the list */
373 0 : talloc_steal(state->services, state->services[c]);
374 : }
375 :
376 0 : *servicegroup_count = state->servicegroup_count;
377 0 : *servicegroups = talloc_steal(mem_ctx, state->servicegroups);
378 :
379 0 : return EOK;
380 : }
381 :
382 : errno_t
383 0 : hbac_service_attrs_to_rule(TALLOC_CTX *mem_ctx,
384 : struct sss_domain_info *domain,
385 : const char *rule_name,
386 : struct sysdb_attrs *rule_attrs,
387 : struct hbac_rule_element **services)
388 : {
389 : errno_t ret;
390 : TALLOC_CTX *tmp_ctx;
391 : struct hbac_rule_element *new_services;
392 0 : const char *attrs[] = { IPA_CN, NULL };
393 : struct ldb_message_element *el;
394 0 : size_t num_services = 0;
395 0 : size_t num_servicegroups = 0;
396 : size_t i;
397 : char *member_dn;
398 : char *filter;
399 : size_t count;
400 : struct ldb_message **msgs;
401 : const char *name;
402 :
403 0 : DEBUG(SSSDBG_TRACE_LIBS,
404 : "Processing PAM services for rule [%s]\n", rule_name);
405 :
406 0 : tmp_ctx = talloc_new(mem_ctx);
407 0 : if (tmp_ctx == NULL) return ENOMEM;
408 :
409 0 : new_services = talloc_zero(tmp_ctx, struct hbac_rule_element);
410 0 : if (new_services == NULL) {
411 0 : ret = ENOMEM;
412 0 : goto done;
413 : }
414 :
415 : /* First check for service category */
416 0 : ret = hbac_get_category(rule_attrs, IPA_SERVICE_CATEGORY,
417 : &new_services->category);
418 0 : if (ret != EOK) {
419 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Could not identify service categories\n");
420 0 : goto done;
421 : }
422 0 : if (new_services->category & HBAC_CATEGORY_ALL) {
423 : /* Short-cut to the exit */
424 0 : ret = EOK;
425 0 : goto done;
426 : }
427 :
428 : /* Get the list of DNs from the member attr */
429 0 : ret = sysdb_attrs_get_el(rule_attrs, IPA_MEMBER_SERVICE, &el);
430 0 : if (ret != EOK && ret != ENOENT) {
431 0 : DEBUG(SSSDBG_CRIT_FAILURE, "sysdb_attrs_get_el failed.\n");
432 0 : goto done;
433 : }
434 0 : if (ret == ENOENT || el->num_values == 0) {
435 0 : el->num_values = 0;
436 0 : DEBUG(SSSDBG_CONF_SETTINGS,
437 : "No services specified, rule will never apply.\n");
438 : }
439 :
440 : /* Assume maximum size; We'll trim it later */
441 0 : new_services->names = talloc_array(new_services,
442 : const char *,
443 : el->num_values +1);
444 0 : if (new_services->names == NULL) {
445 0 : ret = ENOMEM;
446 0 : goto done;
447 : }
448 :
449 0 : new_services->groups = talloc_array(new_services,
450 : const char *,
451 : el->num_values + 1);
452 0 : if (new_services->groups == NULL) {
453 0 : ret = ENOMEM;
454 0 : goto done;
455 : }
456 :
457 0 : for (i = 0; i < el->num_values; i++) {
458 0 : ret = sss_filter_sanitize(tmp_ctx,
459 0 : (const char *)el->values[i].data,
460 : &member_dn);
461 0 : if (ret != EOK) goto done;
462 :
463 0 : filter = talloc_asprintf(member_dn, "(%s=%s)",
464 : SYSDB_ORIG_DN, member_dn);
465 0 : if (filter == NULL) {
466 0 : ret = ENOMEM;
467 0 : goto done;
468 : }
469 :
470 : /* First check if this is a specific service */
471 0 : ret = sysdb_search_custom(tmp_ctx, domain, filter,
472 : HBAC_SERVICES_SUBDIR, attrs,
473 : &count, &msgs);
474 0 : if (ret != EOK && ret != ENOENT) goto done;
475 0 : if (ret == EOK && count == 0) {
476 0 : ret = ENOENT;
477 : }
478 :
479 0 : if (ret == EOK) {
480 0 : if (count > 1) {
481 0 : DEBUG(SSSDBG_CRIT_FAILURE,
482 : "Original DN matched multiple services. "
483 : "Skipping \n");
484 0 : talloc_zfree(member_dn);
485 0 : continue;
486 : }
487 :
488 : /* Original DN matched a single service. Get the service name */
489 0 : name = ldb_msg_find_attr_as_string(msgs[0], IPA_CN, NULL);
490 0 : if (name == NULL) {
491 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Attribute is missing!\n");
492 0 : ret = EFAULT;
493 0 : goto done;
494 : }
495 :
496 0 : new_services->names[num_services] =
497 0 : talloc_strdup(new_services->names, name);
498 0 : if (new_services->names[num_services] == NULL) {
499 0 : ret = ENOMEM;
500 0 : goto done;
501 : }
502 0 : DEBUG(SSSDBG_TRACE_INTERNAL, "Added service [%s] to rule [%s]\n",
503 : name, rule_name);
504 0 : num_services++;
505 : } else { /* ret == ENOENT */
506 : /* Check if this is a service group */
507 0 : ret = sysdb_search_custom(tmp_ctx, domain, filter,
508 : HBAC_SERVICEGROUPS_SUBDIR, attrs,
509 : &count, &msgs);
510 0 : if (ret != EOK && ret != ENOENT) goto done;
511 0 : if (ret == EOK && count == 0) {
512 0 : ret = ENOENT;
513 : }
514 :
515 0 : if (ret == EOK) {
516 0 : if (count > 1) {
517 0 : DEBUG(SSSDBG_CRIT_FAILURE,
518 : "Original DN matched multiple service groups. "
519 : "Skipping\n");
520 0 : talloc_zfree(member_dn);
521 0 : continue;
522 : }
523 :
524 : /* Original DN matched a single group. Get the groupname */
525 0 : name = ldb_msg_find_attr_as_string(msgs[0], IPA_CN, NULL);
526 0 : if (name == NULL) {
527 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Attribute is missing!\n");
528 0 : ret = EFAULT;
529 0 : goto done;
530 : }
531 :
532 0 : new_services->groups[num_servicegroups] =
533 0 : talloc_strdup(new_services->groups, name);
534 0 : if (new_services->groups[num_servicegroups] == NULL) {
535 0 : ret = ENOMEM;
536 0 : goto done;
537 : }
538 :
539 0 : DEBUG(SSSDBG_TRACE_INTERNAL,
540 : "Added service group [%s] to rule [%s]\n",
541 : name, rule_name);
542 0 : num_servicegroups++;
543 : } else { /* ret == ENOENT */
544 : /* Neither a service nor a service group? Skip it */
545 0 : DEBUG(SSSDBG_CRIT_FAILURE,
546 : "[%s] does not map to either a service or "
547 : "service group. Skipping\n", member_dn);
548 : }
549 : }
550 0 : talloc_zfree(member_dn);
551 : }
552 0 : new_services->names[num_services] = NULL;
553 0 : new_services->groups[num_servicegroups] = NULL;
554 :
555 : /* Shrink the arrays down to their real sizes */
556 0 : new_services->names = talloc_realloc(new_services, new_services->names,
557 : const char *, num_services + 1);
558 0 : if (new_services->names == NULL) {
559 0 : ret = ENOMEM;
560 0 : goto done;
561 : }
562 :
563 0 : new_services->groups = talloc_realloc(new_services, new_services->groups,
564 : const char *, num_servicegroups + 1);
565 0 : if (new_services->groups == NULL) {
566 0 : ret = ENOMEM;
567 0 : goto done;
568 : }
569 :
570 0 : ret = EOK;
571 :
572 : done:
573 0 : if (ret == EOK) {
574 0 : *services = talloc_steal(mem_ctx, new_services);
575 : }
576 0 : talloc_free(tmp_ctx);
577 0 : return ret;
578 : }
579 :
580 : errno_t
581 0 : get_ipa_servicegroupname(TALLOC_CTX *mem_ctx,
582 : struct sysdb_ctx *sysdb,
583 : const char *service_dn,
584 : char **servicegroupname)
585 : {
586 : errno_t ret;
587 : struct ldb_dn *dn;
588 : const char *rdn_name;
589 : const char *svc_comp_name;
590 : const char *hbac_comp_name;
591 : const struct ldb_val *rdn_val;
592 : const struct ldb_val *svc_comp_val;
593 : const struct ldb_val *hbac_comp_val;
594 :
595 : /* This is an IPA-specific hack. It may not
596 : * work for non-IPA servers and will need to
597 : * be changed if SSSD ever supports HBAC on
598 : * a non-IPA server.
599 : */
600 0 : *servicegroupname = NULL;
601 :
602 0 : dn = ldb_dn_new(mem_ctx, sysdb_ctx_get_ldb(sysdb), service_dn);
603 0 : if (dn == NULL) {
604 0 : ret = ENOMEM;
605 0 : goto done;
606 : }
607 :
608 0 : if (!ldb_dn_validate(dn)) {
609 0 : ret = ERR_MALFORMED_ENTRY;
610 0 : goto done;
611 : }
612 :
613 0 : if (ldb_dn_get_comp_num(dn) < 4) {
614 : /* RDN, services, hbac, and at least one DC= */
615 : /* If it's fewer, it's not a group DN */
616 0 : ret = ERR_UNEXPECTED_ENTRY_TYPE;
617 0 : goto done;
618 : }
619 :
620 : /* If the RDN name is 'cn' */
621 0 : rdn_name = ldb_dn_get_rdn_name(dn);
622 0 : if (rdn_name == NULL) {
623 : /* Shouldn't happen if ldb_dn_validate()
624 : * passed, but we'll be careful.
625 : */
626 0 : ret = ERR_MALFORMED_ENTRY;
627 0 : goto done;
628 : }
629 :
630 0 : if (strcasecmp("cn", rdn_name) != 0) {
631 : /* RDN has the wrong attribute name.
632 : * It's not a service.
633 : */
634 0 : ret = ERR_UNEXPECTED_ENTRY_TYPE;
635 0 : goto done;
636 : }
637 :
638 : /* and the second component is "cn=hbacservicegroups" */
639 0 : svc_comp_name = ldb_dn_get_component_name(dn, 1);
640 0 : if (strcasecmp("cn", svc_comp_name) != 0) {
641 : /* The second component name is not "cn" */
642 0 : ret = ERR_UNEXPECTED_ENTRY_TYPE;
643 0 : goto done;
644 : }
645 :
646 0 : svc_comp_val = ldb_dn_get_component_val(dn, 1);
647 0 : if (strncasecmp("hbacservicegroups",
648 0 : (const char *) svc_comp_val->data,
649 : svc_comp_val->length) != 0) {
650 : /* The second component value is not "hbacservicegroups" */
651 0 : ret = ERR_UNEXPECTED_ENTRY_TYPE;
652 0 : goto done;
653 : }
654 :
655 : /* and the third component is "hbac" */
656 0 : hbac_comp_name = ldb_dn_get_component_name(dn, 2);
657 0 : if (strcasecmp("cn", hbac_comp_name) != 0) {
658 : /* The third component name is not "cn" */
659 0 : ret = ERR_UNEXPECTED_ENTRY_TYPE;
660 0 : goto done;
661 : }
662 :
663 0 : hbac_comp_val = ldb_dn_get_component_val(dn, 2);
664 0 : if (strncasecmp("hbac",
665 0 : (const char *) hbac_comp_val->data,
666 : hbac_comp_val->length) != 0) {
667 : /* The third component value is not "hbac" */
668 0 : ret = ERR_UNEXPECTED_ENTRY_TYPE;
669 0 : goto done;
670 : }
671 :
672 : /* Then the value of the RDN is the group name */
673 0 : rdn_val = ldb_dn_get_rdn_val(dn);
674 0 : *servicegroupname = talloc_strndup(mem_ctx,
675 0 : (const char *)rdn_val->data,
676 : rdn_val->length);
677 0 : if (*servicegroupname == NULL) {
678 0 : ret = ENOMEM;
679 0 : goto done;
680 : }
681 :
682 0 : ret = EOK;
683 :
684 : done:
685 0 : talloc_free(dn);
686 0 : return ret;
687 : }
|