1 /* aclparse.c - routines to parse and check acl's */
3 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
5 * Copyright 1998-2004 The OpenLDAP Foundation.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted only as authorized by the OpenLDAP
12 * A copy of this license is available in the file LICENSE in the
13 * top-level directory of the distribution or, alternatively, at
14 * <http://www.OpenLDAP.org/license.html>.
16 /* Portions Copyright (c) 1995 Regents of the University of Michigan.
17 * All rights reserved.
19 * Redistribution and use in source and binary forms are permitted
20 * provided that this notice is preserved and that due credit is given
21 * to the University of Michigan at Ann Arbor. The name of the University
22 * may not be used to endorse or promote products derived from this
23 * software without specific prior written permission. This software
24 * is provided ``as is'' without express or implied warranty.
33 #include <ac/socket.h>
34 #include <ac/string.h>
35 #include <ac/unistd.h>
41 static char *style_strings[] = {
54 static void split(char *line, int splitchar, char **left, char **right);
55 static void access_append(Access **l, Access *a);
56 static void acl_usage(void) LDAP_GCCATTR((noreturn));
58 static void acl_regex_normalized_dn(const char *src, struct berval *pat);
61 static void print_acl(Backend *be, AccessControl *a);
62 static void print_access(Access *b);
67 check_scope( BackendDB *be, AccessControl *a );
68 #endif /* LDAP_DEVEL */
71 regtest(const char *fname, int lineno, char *pat) {
87 for (size = 0, flag = 0; (size < sizeof(buf)) && *sp; sp++) {
89 if (*sp == '$'|| (*sp >= '0' && *sp <= '9')) {
106 if ( size >= (sizeof(buf)-1) ) {
108 "%s: line %d: regular expression \"%s\" too large\n",
109 fname, lineno, pat );
113 if ((e = regcomp(&re, buf, REG_EXTENDED|REG_ICASE))) {
115 regerror(e, &re, error, sizeof(error));
117 "%s: line %d: regular expression \"%s\" bad because of %s\n",
118 fname, lineno, pat, error );
129 * Check if the pattern of an ACL, if any, matches the scope
130 * of the backend it is defined within.
132 #define ACL_SCOPE_UNKNOWN (-2)
133 #define ACL_SCOPE_ERR (-1)
134 #define ACL_SCOPE_OK (0)
135 #define ACL_SCOPE_PARTIAL (1)
136 #define ACL_SCOPE_WARN (2)
139 check_scope( BackendDB *be, AccessControl *a )
144 dn = be->be_nsuffix[ 0 ];
146 if ( a->acl_dn_pat.bv_len || ( a->acl_dn_style != ACL_STYLE_REGEX ) ) {
147 slap_style_t style = a->acl_dn_style;
149 if ( style == ACL_STYLE_REGEX ) {
150 char dnbuf[ SLAP_LDAPDN_MAXLEN + 2 ];
151 char rebuf[ SLAP_LDAPDN_MAXLEN + 1 ];
155 /* add trailing '$' */
156 AC_MEMCPY( dnbuf, be->be_nsuffix[ 0 ].bv_val,
157 be->be_nsuffix[ 0 ].bv_len );
158 dnbuf[ be->be_nsuffix[ 0 ].bv_len ] = '$';
159 dnbuf[ be->be_nsuffix[ 0 ].bv_len + 1 ] = '\0';
161 if ( regcomp( &re, dnbuf, REG_EXTENDED|REG_ICASE ) ) {
162 return ACL_SCOPE_WARN;
165 /* remove trailing '$' */
166 AC_MEMCPY( rebuf, a->acl_dn_pat.bv_val,
167 a->acl_dn_pat.bv_len + 1 );
168 if ( a->acl_dn_pat.bv_val[ a->acl_dn_pat.bv_len - 1 ] == '$' ) {
169 rebuf[ a->acl_dn_pat.bv_len - 1 ] = '\0';
172 /* not a clear indication of scoping error, though */
173 rc = regexec( &re, rebuf, 0, NULL, 0 )
174 ? ACL_SCOPE_WARN : ACL_SCOPE_OK;
181 patlen = a->acl_dn_pat.bv_len;
182 /* If backend suffix is longer than pattern,
183 * it is a potential mismatch (in the sense
184 * that a superior naming context could
186 if ( dn.bv_len > patlen ) {
187 /* base is blatantly wrong */
188 if ( style == ACL_STYLE_BASE ) {
189 return ACL_SCOPE_ERR;
192 /* one can be wrong if there is more
193 * than one level between the suffix
195 if ( style == ACL_STYLE_ONE ) {
196 int rdnlen = -1, sep = 0;
199 if ( !DN_SEPARATOR( dn.bv_val[ dn.bv_len - patlen - 1 ] ) )
200 return ACL_SCOPE_ERR;
204 rdnlen = dn_rdnlen( NULL, &dn );
205 if ( rdnlen != dn.bv_len - patlen - sep )
206 return ACL_SCOPE_ERR;
209 /* if the trailing part doesn't match,
210 * then it's an error */
211 if ( strcmp( a->acl_dn_pat.bv_val, &dn.bv_val[ dn.bv_len - patlen ] ) != 0 ) {
212 return ACL_SCOPE_ERR;
215 return ACL_SCOPE_PARTIAL;
221 case ACL_STYLE_CHILDREN:
222 case ACL_STYLE_SUBTREE:
230 if ( dn.bv_len < patlen && !DN_SEPARATOR( a->acl_dn_pat.bv_val[ patlen -dn.bv_len - 1 ] ) ) {
231 return ACL_SCOPE_ERR;
234 if ( strcmp( &a->acl_dn_pat.bv_val[ patlen - dn.bv_len ], dn.bv_val ) != 0 ) {
235 return ACL_SCOPE_ERR;
241 return ACL_SCOPE_UNKNOWN;
243 #endif /* LDAP_DEVEL */
255 char *left, *right, *style;
263 for ( i = 1; i < argc; i++ ) {
264 /* to clause - select which entries are protected */
265 if ( strcasecmp( argv[i], "to" ) == 0 ) {
267 fprintf( stderr, "%s: line %d: "
268 "only one to clause allowed in access line\n",
272 a = (AccessControl *) ch_calloc( 1, sizeof(AccessControl) );
273 for ( ++i; i < argc; i++ ) {
274 if ( strcasecmp( argv[i], "by" ) == 0 ) {
279 if ( strcasecmp( argv[i], "*" ) == 0 ) {
280 if( a->acl_dn_pat.bv_len ||
281 ( a->acl_dn_style != ACL_STYLE_REGEX ) )
284 "%s: line %d: dn pattern"
285 " already specified in to clause.\n",
290 a->acl_dn_pat.bv_val = ch_strdup( "*" );
291 a->acl_dn_pat.bv_len = 1;
295 split( argv[i], '=', &left, &right );
296 split( left, '.', &left, &style );
298 if ( right == NULL ) {
299 fprintf( stderr, "%s: line %d: "
300 "missing \"=\" in \"%s\" in to clause\n",
301 fname, lineno, left );
305 if ( strcasecmp( left, "dn" ) == 0 ) {
306 if( a->acl_dn_pat.bv_len != 0 ||
307 ( a->acl_dn_style != ACL_STYLE_REGEX ) )
310 "%s: line %d: dn pattern"
311 " already specified in to clause.\n",
316 if ( style == NULL || *style == '\0' ||
317 ( strcasecmp( style, "base" ) == 0 ) ||
318 ( strcasecmp( style, "exact" ) == 0 ))
320 a->acl_dn_style = ACL_STYLE_BASE;
321 ber_str2bv( right, 0, 1, &a->acl_dn_pat );
323 } else if ( strcasecmp( style, "onelevel" ) == 0
324 || strcasecmp( style, "one" ) == 0 ) {
325 a->acl_dn_style = ACL_STYLE_ONE;
326 ber_str2bv( right, 0, 1, &a->acl_dn_pat );
328 } else if ( strcasecmp( style, "subtree" ) == 0
329 || strcasecmp( style, "sub" ) == 0 )
331 if( *right == '\0' ) {
332 a->acl_dn_pat.bv_val = ch_strdup( "*" );
333 a->acl_dn_pat.bv_len = 1;
336 a->acl_dn_style = ACL_STYLE_SUBTREE;
337 ber_str2bv( right, 0, 1, &a->acl_dn_pat );
340 } else if ( strcasecmp( style, "children" ) == 0 ) {
341 a->acl_dn_style = ACL_STYLE_CHILDREN;
342 ber_str2bv( right, 0, 1, &a->acl_dn_pat );
344 } else if ( strcasecmp( style, "regex" ) == 0 ) {
345 a->acl_dn_style = ACL_STYLE_REGEX;
347 if ( *right == '\0' ) {
348 /* empty regex should match empty DN */
349 a->acl_dn_style = ACL_STYLE_BASE;
350 ber_str2bv( right, 0, 1, &a->acl_dn_pat );
352 } else if ( strcmp(right, "*") == 0
353 || strcmp(right, ".*") == 0
354 || strcmp(right, ".*$") == 0
355 || strcmp(right, "^.*") == 0
356 || strcmp(right, "^.*$") == 0
357 || strcmp(right, ".*$$") == 0
358 || strcmp(right, "^.*$$") == 0 )
360 a->acl_dn_pat.bv_val = ch_strdup( "*" );
361 a->acl_dn_pat.bv_len = sizeof("*")-1;
364 acl_regex_normalized_dn( right, &a->acl_dn_pat );
368 fprintf( stderr, "%s: line %d: "
369 "unknown dn style \"%s\" in to clause\n",
370 fname, lineno, style );
377 if ( strcasecmp( left, "filter" ) == 0 ) {
378 if ( (a->acl_filter = str2filter( right )) == NULL ) {
380 "%s: line %d: bad filter \"%s\" in to clause\n",
381 fname, lineno, right );
385 } else if ( strcasecmp( left, "attr" ) == 0
386 || strcasecmp( left, "attrs" ) == 0 ) {
387 a->acl_attrs = str2anlist( a->acl_attrs,
389 if ( a->acl_attrs == NULL ) {
391 "%s: line %d: unknown attr \"%s\" in to clause\n",
392 fname, lineno, right );
396 } else if ( strncasecmp( left, "val", 3 ) == 0 ) {
397 if ( a->acl_attrval.bv_len ) {
399 "%s: line %d: attr val already specified in to clause.\n",
403 if ( a->acl_attrs == NULL || a->acl_attrs[1].an_name.bv_val ) {
405 "%s: line %d: attr val requires a single attribute.\n",
409 ber_str2bv( right, 0, 1, &a->acl_attrval );
410 if ( style && strcasecmp( style, "regex" ) == 0 ) {
411 int e = regcomp( &a->acl_attrval_re, a->acl_attrval.bv_val,
412 REG_EXTENDED | REG_ICASE | REG_NOSUB );
415 regerror( e, &a->acl_attrval_re, buf, sizeof(buf) );
416 fprintf( stderr, "%s: line %d: "
417 "regular expression \"%s\" bad because of %s\n",
418 fname, lineno, right, buf );
421 a->acl_attrval_style = ACL_STYLE_REGEX;
423 /* FIXME: if the attribute has DN syntax,
424 * we might allow one, subtree and children styles as well */
425 if ( !strcasecmp( style, "exact" ) ) {
426 a->acl_attrval_style = ACL_STYLE_BASE;
428 } else if ( a->acl_attrs[0].an_desc->ad_type->sat_syntax == slap_schema.si_syn_distinguishedName ) {
429 if ( !strcasecmp( style, "base" ) ) {
430 a->acl_attrval_style = ACL_STYLE_BASE;
431 } else if ( !strcasecmp( style, "onelevel" ) || !strcasecmp( style, "one" ) ) {
432 a->acl_attrval_style = ACL_STYLE_ONE;
433 } else if ( !strcasecmp( style, "subtree" ) || !strcasecmp( style, "sub" ) ) {
434 a->acl_attrval_style = ACL_STYLE_SUBTREE;
435 } else if ( !strcasecmp( style, "children" ) ) {
436 a->acl_attrval_style = ACL_STYLE_CHILDREN;
439 "%s: line %d: unknown val.<style> \"%s\" "
440 "for attributeType \"%s\" with DN syntax; using \"base\"\n",
441 fname, lineno, style,
442 a->acl_attrs[0].an_desc->ad_cname.bv_val );
443 a->acl_attrval_style = ACL_STYLE_BASE;
448 "%s: line %d: unknown val.<style> \"%s\" "
449 "for attributeType \"%s\"; using \"exact\"\n",
450 fname, lineno, style,
451 a->acl_attrs[0].an_desc->ad_cname.bv_val );
452 a->acl_attrval_style = ACL_STYLE_BASE;
458 "%s: line %d: expecting <what> got \"%s\"\n",
459 fname, lineno, left );
464 if ( a->acl_dn_pat.bv_len != 0 &&
465 strcmp(a->acl_dn_pat.bv_val, "*") == 0 )
467 free( a->acl_dn_pat.bv_val );
468 a->acl_dn_pat.bv_val = NULL;
469 a->acl_dn_pat.bv_len = 0;
472 if( a->acl_dn_pat.bv_len != 0 ||
473 ( a->acl_dn_style != ACL_STYLE_REGEX ) )
475 if ( a->acl_dn_style != ACL_STYLE_REGEX ) {
477 rc = dnNormalize( 0, NULL, NULL, &a->acl_dn_pat, &bv, NULL);
478 if ( rc != LDAP_SUCCESS ) {
480 "%s: line %d: bad DN \"%s\" in to DN clause\n",
481 fname, lineno, a->acl_dn_pat.bv_val );
484 free( a->acl_dn_pat.bv_val );
487 int e = regcomp( &a->acl_dn_re, a->acl_dn_pat.bv_val,
488 REG_EXTENDED | REG_ICASE );
491 regerror( e, &a->acl_dn_re, buf, sizeof(buf) );
492 fprintf( stderr, "%s: line %d: "
493 "regular expression \"%s\" bad because of %s\n",
494 fname, lineno, right, buf );
500 /* by clause - select who has what access to entries */
501 } else if ( strcasecmp( argv[i], "by" ) == 0 ) {
503 fprintf( stderr, "%s: line %d: "
504 "to clause required before by clause in access line\n",
510 * by clause consists of <who> and <access>
513 b = (Access *) ch_calloc( 1, sizeof(Access) );
515 ACL_INVALIDATE( b->a_access_mask );
519 "%s: line %d: premature eol: expecting <who>\n",
525 for ( ; i < argc; i++ ) {
526 slap_style_t sty = ACL_STYLE_REGEX;
527 char *style_modifier = NULL;
530 split( argv[i], '=', &left, &right );
531 split( left, '.', &left, &style );
533 split( style, ',', &style, &style_modifier);
536 if ( style == NULL || *style == '\0' ||
537 strcasecmp( style, "exact" ) == 0 ||
538 strcasecmp( style, "base" ) == 0 )
540 sty = ACL_STYLE_BASE;
542 } else if ( strcasecmp( style, "onelevel" ) == 0 ||
543 strcasecmp( style, "one" ) == 0 ) {
546 } else if ( strcasecmp( style, "subtree" ) == 0 ||
547 strcasecmp( style, "sub" ) == 0 )
549 sty = ACL_STYLE_SUBTREE;
551 } else if ( strcasecmp( style, "children" ) == 0 ) {
552 sty = ACL_STYLE_CHILDREN;
554 } else if ( strcasecmp( style, "regex" ) == 0 ) {
555 sty = ACL_STYLE_REGEX;
557 } else if ( strcasecmp( style, "expand" ) == 0 ) {
558 sty = ACL_STYLE_EXPAND;
560 } else if ( strcasecmp( style, "ip" ) == 0 ) {
563 } else if ( strcasecmp( style, "path" ) == 0 ) {
564 sty = ACL_STYLE_PATH;
565 #ifndef LDAP_PF_LOCAL
566 fprintf( stderr, "%s: line %d: "
567 "path style modifier is useless without local\n",
569 #endif /* LDAP_PF_LOCAL */
573 "%s: line %d: unknown style \"%s\" in by clause\n",
574 fname, lineno, style );
578 if ( style_modifier &&
579 strcasecmp( style_modifier, "expand" ) == 0 )
582 case ACL_STYLE_REGEX:
583 fprintf( stderr, "%s: line %d: "
584 "\"regex\" style implies "
585 "\"expand\" modifier (ignored)\n",
589 case ACL_STYLE_EXPAND:
590 fprintf( stderr, "%s: line %d: "
591 "\"expand\" style used "
592 "in conjunction with "
593 "\"expand\" modifier (ignored)\n",
598 /* we'll see later if it's pertinent */
604 /* expand in <who> needs regex in <what> */
605 if ( ( sty == ACL_STYLE_EXPAND || expand )
606 && a->acl_dn_style != ACL_STYLE_REGEX )
608 fprintf( stderr, "%s: line %d: "
609 "\"expand\" style or modifier used "
610 "in conjunction with "
611 "a non-regex <what> clause\n",
616 if ( strcasecmp( argv[i], "*" ) == 0 ) {
617 bv.bv_val = ch_strdup( "*" );
619 sty = ACL_STYLE_REGEX;
621 } else if ( strcasecmp( argv[i], "anonymous" ) == 0 ) {
622 ber_str2bv("anonymous", sizeof("anonymous")-1, 1, &bv);
623 sty = ACL_STYLE_REGEX;
625 } else if ( strcasecmp( argv[i], "self" ) == 0 ) {
626 ber_str2bv("self", sizeof("self")-1, 1, &bv);
627 sty = ACL_STYLE_REGEX;
629 } else if ( strcasecmp( argv[i], "users" ) == 0 ) {
630 ber_str2bv("users", sizeof("users")-1, 1, &bv);
631 sty = ACL_STYLE_REGEX;
633 } else if ( strcasecmp( left, "dn" ) == 0 ) {
634 if ( sty == ACL_STYLE_REGEX ) {
635 b->a_dn_style = ACL_STYLE_REGEX;
636 if( right == NULL ) {
641 } else if (*right == '\0' ) {
643 ber_str2bv("anonymous",
644 sizeof("anonymous")-1,
646 } else if ( strcmp( right, "*" ) == 0 ) {
648 /* any or users? users for now */
652 } else if ( strcmp( right, ".+" ) == 0
653 || strcmp( right, "^.+" ) == 0
654 || strcmp( right, ".+$" ) == 0
655 || strcmp( right, "^.+$" ) == 0
656 || strcmp( right, ".+$$" ) == 0
657 || strcmp( right, "^.+$$" ) == 0 )
662 } else if ( strcmp( right, ".*" ) == 0
663 || strcmp( right, "^.*" ) == 0
664 || strcmp( right, ".*$" ) == 0
665 || strcmp( right, "^.*$" ) == 0
666 || strcmp( right, ".*$$" ) == 0
667 || strcmp( right, "^.*$$" ) == 0 )
674 acl_regex_normalized_dn( right, &bv );
675 if ( !ber_bvccmp( &bv, '*' ) ) {
676 regtest(fname, lineno, bv.bv_val);
679 } else if ( right == NULL || *right == '\0' ) {
680 fprintf( stderr, "%s: line %d: "
681 "missing \"=\" in (or value after) \"%s\" "
683 fname, lineno, left );
687 ber_str2bv( right, 0, 1, &bv );
694 if( bv.bv_val != NULL ) {
695 if( b->a_dn_pat.bv_len != 0 ) {
697 "%s: line %d: dn pattern already specified.\n",
702 if ( sty != ACL_STYLE_REGEX && expand == 0 ) {
703 rc = dnNormalize(0, NULL, NULL,
704 &bv, &b->a_dn_pat, NULL);
705 if ( rc != LDAP_SUCCESS ) {
707 "%s: line %d: bad DN \"%s\" in by DN clause\n",
708 fname, lineno, bv.bv_val );
716 b->a_dn_expand = expand;
720 if ( strcasecmp( left, "dnattr" ) == 0 ) {
721 if ( right == NULL || right[ 0 ] == '\0' ) {
723 "%s: line %d: missing \"=\" in (or value after) \"%s\" in by clause\n",
724 fname, lineno, left );
728 if( b->a_dn_at != NULL ) {
730 "%s: line %d: dnattr already specified.\n",
735 rc = slap_str2ad( right, &b->a_dn_at, &text );
737 if( rc != LDAP_SUCCESS ) {
739 "%s: line %d: dnattr \"%s\": %s\n",
740 fname, lineno, right, text );
745 if( !is_at_syntax( b->a_dn_at->ad_type,
747 !is_at_syntax( b->a_dn_at->ad_type,
748 SLAPD_NAMEUID_SYNTAX ))
751 "%s: line %d: dnattr \"%s\": "
752 "inappropriate syntax: %s\n",
753 fname, lineno, right,
754 b->a_dn_at->ad_type->sat_syntax_oid );
758 if( b->a_dn_at->ad_type->sat_equality == NULL ) {
760 "%s: line %d: dnattr \"%s\": "
761 "inappropriate matching (no EQUALITY)\n",
762 fname, lineno, right );
769 if ( strncasecmp( left, "group", sizeof("group")-1 ) == 0 ) {
774 case ACL_STYLE_REGEX:
775 /* legacy, tolerated */
776 fprintf( stderr, "%s: line %d: "
777 "deprecated group style \"regex\"; "
778 "use \"expand\" instead\n",
779 fname, lineno, style );
780 sty = ACL_STYLE_EXPAND;
784 /* legal, traditional */
785 case ACL_STYLE_EXPAND:
786 /* legal, substring expansion; supersedes regex */
791 fprintf( stderr, "%s: line %d: "
792 "inappropriate style \"%s\" in by clause\n",
793 fname, lineno, style );
797 if ( right == NULL || right[ 0 ] == '\0' ) {
798 fprintf( stderr, "%s: line %d: "
799 "missing \"=\" in (or value after) \"%s\" "
801 fname, lineno, left );
805 if( b->a_group_pat.bv_len ) {
807 "%s: line %d: group pattern already specified.\n",
812 /* format of string is
813 "group/objectClassValue/groupAttrName" */
814 if ((value = strchr(left, '/')) != NULL) {
816 if (*value && (name = strchr(value, '/')) != NULL) {
821 b->a_group_style = sty;
822 if (sty == ACL_STYLE_EXPAND) {
823 acl_regex_normalized_dn( right, &bv );
824 if ( !ber_bvccmp( &bv, '*' ) ) {
825 regtest(fname, lineno, bv.bv_val);
829 ber_str2bv( right, 0, 0, &bv );
830 rc = dnNormalize( 0, NULL, NULL, &bv,
831 &b->a_group_pat, NULL );
832 if ( rc != LDAP_SUCCESS ) {
834 "%s: line %d: bad DN \"%s\"\n",
835 fname, lineno, right );
840 if (value && *value) {
841 b->a_group_oc = oc_find( value );
844 if( b->a_group_oc == NULL ) {
846 "%s: line %d: group objectclass "
848 fname, lineno, value );
852 b->a_group_oc = oc_find(SLAPD_GROUP_CLASS);
854 if( b->a_group_oc == NULL ) {
856 "%s: line %d: group default objectclass "
858 fname, lineno, SLAPD_GROUP_CLASS );
863 if( is_object_subclass( slap_schema.si_oc_referral,
867 "%s: line %d: group objectclass \"%s\" "
868 "is subclass of referral\n",
869 fname, lineno, value );
873 if( is_object_subclass( slap_schema.si_oc_alias,
877 "%s: line %d: group objectclass \"%s\" "
878 "is subclass of alias\n",
879 fname, lineno, value );
884 rc = slap_str2ad( name, &b->a_group_at, &text );
886 if( rc != LDAP_SUCCESS ) {
888 "%s: line %d: group \"%s\": %s\n",
889 fname, lineno, right, text );
894 rc = slap_str2ad( SLAPD_GROUP_ATTR, &b->a_group_at, &text );
896 if( rc != LDAP_SUCCESS ) {
898 "%s: line %d: group \"%s\": %s\n",
899 fname, lineno, SLAPD_GROUP_ATTR, text );
904 if( !is_at_syntax( b->a_group_at->ad_type,
906 !is_at_syntax( b->a_group_at->ad_type,
907 SLAPD_NAMEUID_SYNTAX ) &&
908 !is_at_subtype( b->a_group_at->ad_type, slap_schema.si_ad_labeledURI->ad_type ))
911 "%s: line %d: group \"%s\": inappropriate syntax: %s\n",
912 fname, lineno, right,
913 b->a_group_at->ad_type->sat_syntax_oid );
920 struct berval vals[2];
922 vals[0].bv_val = b->a_group_oc->soc_oid;
923 vals[0].bv_len = strlen(vals[0].bv_val);
924 vals[1].bv_val = NULL;
927 rc = oc_check_allowed( b->a_group_at->ad_type,
931 fprintf( stderr, "%s: line %d: "
932 "group: \"%s\" not allowed by \"%s\"\n",
934 b->a_group_at->ad_cname.bv_val,
935 b->a_group_oc->soc_oid );
942 if ( strcasecmp( left, "peername" ) == 0 ) {
944 case ACL_STYLE_REGEX:
946 /* legal, traditional */
947 case ACL_STYLE_EXPAND:
948 /* cheap replacement to regex for simple expansion */
951 /* legal, peername specific */
955 fprintf( stderr, "%s: line %d: "
956 "inappropriate style \"%s\" in by clause\n",
957 fname, lineno, style );
961 if ( right == NULL || right[ 0 ] == '\0' ) {
962 fprintf( stderr, "%s: line %d: "
963 "missing \"=\" in (or value after) \"%s\" "
965 fname, lineno, left );
969 if( b->a_peername_pat.bv_len ) {
970 fprintf( stderr, "%s: line %d: "
971 "peername pattern already specified.\n",
976 b->a_peername_style = sty;
977 if (sty == ACL_STYLE_REGEX) {
978 acl_regex_normalized_dn( right, &bv );
979 if ( !ber_bvccmp( &bv, '*' ) ) {
980 regtest(fname, lineno, bv.bv_val);
982 b->a_peername_pat = bv;
985 ber_str2bv( right, 0, 1, &b->a_peername_pat );
987 if ( sty == ACL_STYLE_IP ) {
992 split( right, '{', &addr, &port );
993 split( addr, '%', &addr, &mask );
995 b->a_peername_addr = inet_addr( addr );
996 if ( b->a_peername_addr == (unsigned long)(-1)) {
997 /* illegal address */
998 fprintf( stderr, "%s: line %d: "
999 "illegal peername address \"%s\".\n",
1000 fname, lineno, addr );
1004 b->a_peername_mask = (unsigned long)(-1);
1005 if ( mask != NULL ) {
1006 b->a_peername_mask = inet_addr( mask );
1007 if ( b->a_peername_mask == (unsigned long)(-1)) {
1009 fprintf( stderr, "%s: line %d: "
1010 "illegal peername address mask \"%s\".\n",
1011 fname, lineno, mask );
1016 b->a_peername_port = -1;
1020 b->a_peername_port = strtol( port, &end, 10 );
1021 if ( end[ 0 ] != '}' ) {
1023 fprintf( stderr, "%s: line %d: "
1024 "illegal peername port specification \"{%s}\".\n",
1025 fname, lineno, port );
1034 if ( strcasecmp( left, "sockname" ) == 0 ) {
1036 case ACL_STYLE_REGEX:
1037 case ACL_STYLE_BASE:
1038 /* legal, traditional */
1039 case ACL_STYLE_EXPAND:
1040 /* cheap replacement to regex for simple expansion */
1045 fprintf( stderr, "%s: line %d: "
1046 "inappropriate style \"%s\" in by clause\n",
1047 fname, lineno, style );
1051 if ( right == NULL || right[ 0 ] == '\0' ) {
1052 fprintf( stderr, "%s: line %d: "
1053 "missing \"=\" in (or value after) \"%s\" "
1055 fname, lineno, left );
1059 if( b->a_sockname_pat.bv_len ) {
1060 fprintf( stderr, "%s: line %d: "
1061 "sockname pattern already specified.\n",
1066 b->a_sockname_style = sty;
1067 if (sty == ACL_STYLE_REGEX) {
1068 acl_regex_normalized_dn( right, &bv );
1069 if ( !ber_bvccmp( &bv, '*' ) ) {
1070 regtest(fname, lineno, bv.bv_val);
1072 b->a_sockname_pat = bv;
1074 ber_str2bv( right, 0, 1, &b->a_sockname_pat );
1079 if ( strcasecmp( left, "domain" ) == 0 ) {
1081 case ACL_STYLE_REGEX:
1082 case ACL_STYLE_BASE:
1083 case ACL_STYLE_SUBTREE:
1084 /* legal, traditional */
1087 case ACL_STYLE_EXPAND:
1088 /* tolerated: means exact,expand */
1092 "\"expand\" modifier with \"expand\" style\n",
1095 sty = ACL_STYLE_BASE;
1102 "%s: line %d: inappropriate style \"%s\" in by clause\n",
1103 fname, lineno, style );
1107 if ( right == NULL || right[ 0 ] == '\0' ) {
1109 "%s: line %d: missing \"=\" in (or value after) \"%s\" in by clause\n",
1110 fname, lineno, left );
1114 if( b->a_domain_pat.bv_len ) {
1116 "%s: line %d: domain pattern already specified.\n",
1121 b->a_domain_style = sty;
1122 b->a_domain_expand = expand;
1123 if (sty == ACL_STYLE_REGEX) {
1124 acl_regex_normalized_dn( right, &bv );
1125 if ( !ber_bvccmp( &bv, '*' ) ) {
1126 regtest(fname, lineno, bv.bv_val);
1128 b->a_domain_pat = bv;
1130 ber_str2bv( right, 0, 1, &b->a_domain_pat );
1135 if ( strcasecmp( left, "sockurl" ) == 0 ) {
1137 case ACL_STYLE_REGEX:
1138 case ACL_STYLE_BASE:
1139 /* legal, traditional */
1140 case ACL_STYLE_EXPAND:
1141 /* cheap replacement to regex for simple expansion */
1146 fprintf( stderr, "%s: line %d: "
1147 "inappropriate style \"%s\" in by clause\n",
1148 fname, lineno, style );
1152 if ( right == NULL || right[ 0 ] == '\0' ) {
1154 "%s: line %d: missing \"=\" in (or value after) \"%s\" in by clause\n",
1155 fname, lineno, left );
1159 if( b->a_sockurl_pat.bv_len ) {
1161 "%s: line %d: sockurl pattern already specified.\n",
1166 b->a_sockurl_style = sty;
1167 if (sty == ACL_STYLE_REGEX) {
1168 acl_regex_normalized_dn( right, &bv );
1169 if ( !ber_bvccmp( &bv, '*' ) ) {
1170 regtest(fname, lineno, bv.bv_val);
1172 b->a_sockurl_pat = bv;
1174 ber_str2bv( right, 0, 1, &b->a_sockurl_pat );
1179 if ( strcasecmp( left, "set" ) == 0 ) {
1180 if (sty != ACL_STYLE_REGEX && sty != ACL_STYLE_BASE) {
1182 "%s: line %d: inappropriate style \"%s\" in by clause\n",
1183 fname, lineno, style );
1187 if( b->a_set_pat.bv_len != 0 ) {
1189 "%s: line %d: set attribute already specified.\n",
1194 if ( right == NULL || *right == '\0' ) {
1196 "%s: line %d: no set is defined\n",
1201 b->a_set_style = sty;
1202 ber_str2bv( right, 0, 1, &b->a_set_pat );
1207 #ifdef SLAPD_ACI_ENABLED
1208 if ( strcasecmp( left, "aci" ) == 0 ) {
1209 if (sty != ACL_STYLE_REGEX && sty != ACL_STYLE_BASE) {
1211 "%s: line %d: inappropriate style \"%s\" in by clause\n",
1212 fname, lineno, style );
1216 if( b->a_aci_at != NULL ) {
1218 "%s: line %d: aci attribute already specified.\n",
1223 if ( right != NULL && *right != '\0' ) {
1224 rc = slap_str2ad( right, &b->a_aci_at, &text );
1226 if( rc != LDAP_SUCCESS ) {
1228 "%s: line %d: aci \"%s\": %s\n",
1229 fname, lineno, right, text );
1234 b->a_aci_at = slap_schema.si_ad_aci;
1237 if( !is_at_syntax( b->a_aci_at->ad_type,
1241 "%s: line %d: aci \"%s\": inappropriate syntax: %s\n",
1242 fname, lineno, right,
1243 b->a_aci_at->ad_type->sat_syntax_oid );
1249 #endif /* SLAPD_ACI_ENABLED */
1251 if ( strcasecmp( left, "ssf" ) == 0 ) {
1252 if (sty != ACL_STYLE_REGEX && sty != ACL_STYLE_BASE) {
1254 "%s: line %d: inappropriate style \"%s\" in by clause\n",
1255 fname, lineno, style );
1259 if( b->a_authz.sai_ssf ) {
1261 "%s: line %d: ssf attribute already specified.\n",
1266 if ( right == NULL || *right == '\0' ) {
1268 "%s: line %d: no ssf is defined\n",
1273 b->a_authz.sai_ssf = atoi( right );
1275 if( !b->a_authz.sai_ssf ) {
1277 "%s: line %d: invalid ssf value (%s)\n",
1278 fname, lineno, right );
1284 if ( strcasecmp( left, "transport_ssf" ) == 0 ) {
1285 if (sty != ACL_STYLE_REGEX && sty != ACL_STYLE_BASE) {
1287 "%s: line %d: inappropriate style \"%s\" in by clause\n",
1288 fname, lineno, style );
1292 if( b->a_authz.sai_transport_ssf ) {
1294 "%s: line %d: transport_ssf attribute already specified.\n",
1299 if ( right == NULL || *right == '\0' ) {
1301 "%s: line %d: no transport_ssf is defined\n",
1306 b->a_authz.sai_transport_ssf = atoi( right );
1308 if( !b->a_authz.sai_transport_ssf ) {
1310 "%s: line %d: invalid transport_ssf value (%s)\n",
1311 fname, lineno, right );
1317 if ( strcasecmp( left, "tls_ssf" ) == 0 ) {
1318 if (sty != ACL_STYLE_REGEX && sty != ACL_STYLE_BASE) {
1320 "%s: line %d: inappropriate style \"%s\" in by clause\n",
1321 fname, lineno, style );
1325 if( b->a_authz.sai_tls_ssf ) {
1327 "%s: line %d: tls_ssf attribute already specified.\n",
1332 if ( right == NULL || *right == '\0' ) {
1334 "%s: line %d: no tls_ssf is defined\n",
1339 b->a_authz.sai_tls_ssf = atoi( right );
1341 if( !b->a_authz.sai_tls_ssf ) {
1343 "%s: line %d: invalid tls_ssf value (%s)\n",
1344 fname, lineno, right );
1350 if ( strcasecmp( left, "sasl_ssf" ) == 0 ) {
1351 if (sty != ACL_STYLE_REGEX && sty != ACL_STYLE_BASE) {
1353 "%s: line %d: inappropriate style \"%s\" in by clause\n",
1354 fname, lineno, style );
1358 if( b->a_authz.sai_sasl_ssf ) {
1360 "%s: line %d: sasl_ssf attribute already specified.\n",
1365 if ( right == NULL || *right == '\0' ) {
1367 "%s: line %d: no sasl_ssf is defined\n",
1372 b->a_authz.sai_sasl_ssf = atoi( right );
1374 if( !b->a_authz.sai_sasl_ssf ) {
1376 "%s: line %d: invalid sasl_ssf value (%s)\n",
1377 fname, lineno, right );
1383 if( right != NULL ) {
1390 if( i == argc || ( strcasecmp( left, "stop" ) == 0 )) {
1391 /* out of arguments or plain stop */
1393 ACL_PRIV_ASSIGN(b->a_access_mask, ACL_PRIV_ADDITIVE);
1394 b->a_type = ACL_STOP;
1396 access_append( &a->acl_access, b );
1400 if( strcasecmp( left, "continue" ) == 0 ) {
1401 /* plain continue */
1403 ACL_PRIV_ASSIGN(b->a_access_mask, ACL_PRIV_ADDITIVE);
1404 b->a_type = ACL_CONTINUE;
1406 access_append( &a->acl_access, b );
1410 if( strcasecmp( left, "break" ) == 0 ) {
1411 /* plain continue */
1413 ACL_PRIV_ASSIGN(b->a_access_mask, ACL_PRIV_ADDITIVE);
1414 b->a_type = ACL_BREAK;
1416 access_append( &a->acl_access, b );
1420 if ( strcasecmp( left, "by" ) == 0 ) {
1421 /* we've gone too far */
1423 ACL_PRIV_ASSIGN(b->a_access_mask, ACL_PRIV_ADDITIVE);
1424 b->a_type = ACL_STOP;
1426 access_append( &a->acl_access, b );
1431 if( strncasecmp( left, "self", 4 ) == 0 ) {
1433 ACL_PRIV_ASSIGN( b->a_access_mask, str2accessmask( &left[4] ) );
1436 ACL_PRIV_ASSIGN( b->a_access_mask, str2accessmask( left ) );
1439 if( ACL_IS_INVALID( b->a_access_mask ) ) {
1441 "%s: line %d: expecting <access> got \"%s\"\n",
1442 fname, lineno, left );
1446 b->a_type = ACL_STOP;
1449 /* out of arguments or plain stop */
1450 access_append( &a->acl_access, b );
1454 if( strcasecmp( argv[i], "continue" ) == 0 ) {
1455 /* plain continue */
1456 b->a_type = ACL_CONTINUE;
1458 } else if( strcasecmp( argv[i], "break" ) == 0 ) {
1459 /* plain continue */
1460 b->a_type = ACL_BREAK;
1462 } else if ( strcasecmp( argv[i], "stop" ) != 0 ) {
1467 access_append( &a->acl_access, b );
1471 "%s: line %d: expecting \"to\" or \"by\" got \"%s\"\n",
1472 fname, lineno, argv[i] );
1477 /* if we have no real access clause, complain and do nothing */
1480 "%s: line %d: warning: no access clause(s) specified in access line\n",
1485 if (ldap_debug & LDAP_DEBUG_ACL)
1489 if ( a->acl_access == NULL ) {
1491 "%s: line %d: warning: no by clause(s) specified in access line\n",
1497 switch ( check_scope( be, a ) ) {
1498 case ACL_SCOPE_UNKNOWN:
1499 fprintf( stderr, "%s: line %d: warning: "
1500 "cannot assess the validity "
1501 "of the ACL scope within "
1502 "backend naming context\n",
1506 case ACL_SCOPE_WARN:
1507 fprintf( stderr, "%s: line %d: warning: "
1508 "ACL could be out of "
1510 "backend naming context\n",
1514 case ACL_SCOPE_PARTIAL:
1515 fprintf( stderr, "%s: line %d: warning: "
1516 "ACL appears to be partially "
1517 "out of scope within "
1518 "backend naming context\n",
1523 fprintf( stderr, "%s: line %d: warning: "
1524 "ACL appears to be out of "
1526 "backend naming context\n",
1533 #endif /* LDAP_DEVEL */
1534 acl_append( &be->be_acl, a );
1536 acl_append( &global_acl, a );
1542 accessmask2str( slap_mask_t mask, char *buf )
1547 assert( buf != NULL );
1549 if ( ACL_IS_INVALID( mask ) ) {
1555 if ( ACL_IS_LEVEL( mask ) ) {
1556 if ( ACL_LVL_IS_NONE(mask) ) {
1557 ptr = lutil_strcopy( ptr, "none" );
1559 } else if ( ACL_LVL_IS_AUTH(mask) ) {
1560 ptr = lutil_strcopy( ptr, "auth" );
1562 } else if ( ACL_LVL_IS_COMPARE(mask) ) {
1563 ptr = lutil_strcopy( ptr, "compare" );
1565 } else if ( ACL_LVL_IS_SEARCH(mask) ) {
1566 ptr = lutil_strcopy( ptr, "search" );
1568 } else if ( ACL_LVL_IS_READ(mask) ) {
1569 ptr = lutil_strcopy( ptr, "read" );
1571 } else if ( ACL_LVL_IS_WRITE(mask) ) {
1572 ptr = lutil_strcopy( ptr, "write" );
1574 ptr = lutil_strcopy( ptr, "unknown" );
1580 if( ACL_IS_ADDITIVE( mask ) ) {
1583 } else if( ACL_IS_SUBTRACTIVE( mask ) ) {
1590 if ( ACL_PRIV_ISSET(mask, ACL_PRIV_WRITE) ) {
1595 if ( ACL_PRIV_ISSET(mask, ACL_PRIV_READ) ) {
1600 if ( ACL_PRIV_ISSET(mask, ACL_PRIV_SEARCH) ) {
1605 if ( ACL_PRIV_ISSET(mask, ACL_PRIV_COMPARE) ) {
1610 if ( ACL_PRIV_ISSET(mask, ACL_PRIV_AUTH) ) {
1615 if ( none && ACL_PRIV_ISSET(mask, ACL_PRIV_NONE) ) {
1624 if ( ACL_IS_LEVEL( mask ) ) {
1634 str2accessmask( const char *str )
1638 if( !ASCII_ALPHA(str[0]) ) {
1641 if ( str[0] == '=' ) {
1644 } else if( str[0] == '+' ) {
1645 ACL_PRIV_ASSIGN(mask, ACL_PRIV_ADDITIVE);
1647 } else if( str[0] == '-' ) {
1648 ACL_PRIV_ASSIGN(mask, ACL_PRIV_SUBSTRACTIVE);
1651 ACL_INVALIDATE(mask);
1655 for( i=1; str[i] != '\0'; i++ ) {
1656 if( TOLOWER((unsigned char) str[i]) == 'w' ) {
1657 ACL_PRIV_SET(mask, ACL_PRIV_WRITE);
1659 } else if( TOLOWER((unsigned char) str[i]) == 'r' ) {
1660 ACL_PRIV_SET(mask, ACL_PRIV_READ);
1662 } else if( TOLOWER((unsigned char) str[i]) == 's' ) {
1663 ACL_PRIV_SET(mask, ACL_PRIV_SEARCH);
1665 } else if( TOLOWER((unsigned char) str[i]) == 'c' ) {
1666 ACL_PRIV_SET(mask, ACL_PRIV_COMPARE);
1668 } else if( TOLOWER((unsigned char) str[i]) == 'x' ) {
1669 ACL_PRIV_SET(mask, ACL_PRIV_AUTH);
1671 } else if( str[i] != '0' ) {
1672 ACL_INVALIDATE(mask);
1680 if ( strcasecmp( str, "none" ) == 0 ) {
1681 ACL_LVL_ASSIGN_NONE(mask);
1683 } else if ( strcasecmp( str, "auth" ) == 0 ) {
1684 ACL_LVL_ASSIGN_AUTH(mask);
1686 } else if ( strcasecmp( str, "compare" ) == 0 ) {
1687 ACL_LVL_ASSIGN_COMPARE(mask);
1689 } else if ( strcasecmp( str, "search" ) == 0 ) {
1690 ACL_LVL_ASSIGN_SEARCH(mask);
1692 } else if ( strcasecmp( str, "read" ) == 0 ) {
1693 ACL_LVL_ASSIGN_READ(mask);
1695 } else if ( strcasecmp( str, "write" ) == 0 ) {
1696 ACL_LVL_ASSIGN_WRITE(mask);
1699 ACL_INVALIDATE( mask );
1708 fprintf( stderr, "%s%s\n",
1709 "<access clause> ::= access to <what> "
1710 "[ by <who> <access> [ <control> ] ]+ \n"
1711 "<what> ::= * | [dn[.<dnstyle>]=<DN>] [filter=<filter>] [attrs=<attrlist>]\n"
1712 "<attrlist> ::= <attr> [val[.<style>]=<value>] | <attr> , <attrlist>\n"
1713 "<attr> ::= <attrname> | entry | children\n"
1714 "<who> ::= [ * | anonymous | users | self | dn[.<dnstyle>]=<DN> ]\n"
1715 "\t[dnattr=<attrname>]\n"
1716 "\t[group[/<objectclass>[/<attrname>]][.<style>]=<group>]\n"
1717 "\t[peername[.<peernamestyle>]=<peer>] [sockname[.<style>]=<name>]\n",
1718 "\t[domain[.<domainstyle>]=<domain>] [sockurl[.<style>]=<url>]\n"
1719 #ifdef SLAPD_ACI_ENABLED
1720 "\t[aci=<attrname>]\n"
1722 "\t[ssf=<n>] [transport_ssf=<n>] [tls_ssf=<n>] [sasl_ssf=<n>]\n"
1723 "<dnstyle> ::= base | exact | one(level) | sub(tree) | children | regex\n"
1724 "<style> ::= regex | base | exact\n"
1725 "<peernamestyle> ::= regex | exact | ip | path\n"
1726 "<domainstyle> ::= regex | base | exact | sub(tree)\n"
1727 "<access> ::= [self]{<level>|<priv>}\n"
1728 "<level> ::= none | auth | compare | search | read | write\n"
1729 "<priv> ::= {=|+|-}{w|r|s|c|x|0}+\n"
1730 "<control> ::= [ stop | continue | break ]\n"
1732 exit( EXIT_FAILURE );
1736 * Set pattern to a "normalized" DN from src.
1737 * At present it simply eats the (optional) space after
1738 * a RDN separator (,)
1739 * Eventually will evolve in a more complete normalization
1742 acl_regex_normalized_dn(
1744 struct berval *pattern
1750 str = ch_strdup( src );
1751 len = strlen( src );
1753 for ( p = str; p && p[ 0 ]; p++ ) {
1755 if ( p[ 0 ] == '\\' && p[ 1 ] ) {
1757 * if escaping a hex pair we should
1758 * increment p twice; however, in that
1759 * case the second hex number does
1765 if ( p[ 0 ] == ',' ) {
1766 if ( p[ 1 ] == ' ' ) {
1770 * too much space should be
1771 * an error if we are pedantic
1773 for ( q = &p[ 2 ]; q[ 0 ] == ' '; q++ ) {
1776 AC_MEMCPY( p+1, q, len-(q-str)+1);
1780 pattern->bv_val = str;
1781 pattern->bv_len = p-str;
1795 if ( (*right = strchr( line, splitchar )) != NULL ) {
1796 *((*right)++) = '\0';
1801 access_append( Access **l, Access *a )
1803 for ( ; *l != NULL; l = &(*l)->a_next )
1810 acl_append( AccessControl **l, AccessControl *a )
1812 for ( ; *l != NULL; l = &(*l)->acl_next )
1819 access_free( Access *a )
1821 if ( a->a_dn_pat.bv_val )
1822 free ( a->a_dn_pat.bv_val );
1823 if ( a->a_peername_pat.bv_val )
1824 free ( a->a_peername_pat.bv_val );
1825 if ( a->a_sockname_pat.bv_val )
1826 free ( a->a_sockname_pat.bv_val );
1827 if ( a->a_domain_pat.bv_val )
1828 free ( a->a_domain_pat.bv_val );
1829 if ( a->a_sockurl_pat.bv_val )
1830 free ( a->a_sockurl_pat.bv_val );
1831 if ( a->a_set_pat.bv_len )
1832 free ( a->a_set_pat.bv_val );
1833 if ( a->a_group_pat.bv_len )
1834 free ( a->a_group_pat.bv_val );
1839 acl_free( AccessControl *a )
1844 if ( a->acl_filter )
1845 filter_free( a->acl_filter );
1846 if ( a->acl_dn_pat.bv_len )
1847 free ( a->acl_dn_pat.bv_val );
1848 if ( a->acl_attrs ) {
1849 for ( an = a->acl_attrs; an->an_name.bv_val; an++ ) {
1850 free( an->an_name.bv_val );
1852 free( a->acl_attrs );
1854 for (; a->acl_access; a->acl_access = n) {
1855 n = a->acl_access->a_next;
1856 access_free( a->acl_access );
1861 /* Because backend_startup uses acl_append to tack on the global_acl to
1862 * the end of each backend's acl, we cannot just take one argument and
1863 * merrily free our way to the end of the list. backend_destroy calls us
1864 * with the be_acl in arg1, and global_acl in arg2 to give us a stopping
1865 * point. config_destroy calls us with global_acl in arg1 and NULL in
1866 * arg2, so we then proceed to polish off the global_acl.
1869 acl_destroy( AccessControl *a, AccessControl *end )
1873 for (; a && a!= end; a=n) {
1880 access2str( slap_access_t access )
1882 if ( access == ACL_NONE ) {
1885 } else if ( access == ACL_AUTH ) {
1888 } else if ( access == ACL_COMPARE ) {
1891 } else if ( access == ACL_SEARCH ) {
1894 } else if ( access == ACL_READ ) {
1897 } else if ( access == ACL_WRITE ) {
1905 str2access( const char *str )
1907 if ( strcasecmp( str, "none" ) == 0 ) {
1910 } else if ( strcasecmp( str, "auth" ) == 0 ) {
1913 } else if ( strcasecmp( str, "compare" ) == 0 ) {
1916 } else if ( strcasecmp( str, "search" ) == 0 ) {
1919 } else if ( strcasecmp( str, "read" ) == 0 ) {
1922 } else if ( strcasecmp( str, "write" ) == 0 ) {
1926 return( ACL_INVALID_ACCESS );
1932 print_access( Access *b )
1934 char maskbuf[ACCESSMASK_MAXLEN];
1936 fprintf( stderr, "\tby" );
1938 if ( b->a_dn_pat.bv_len != 0 ) {
1939 if( strcmp(b->a_dn_pat.bv_val, "*") == 0
1940 || strcmp(b->a_dn_pat.bv_val, "users") == 0
1941 || strcmp(b->a_dn_pat.bv_val, "anonymous") == 0
1942 || strcmp(b->a_dn_pat.bv_val, "self") == 0 )
1944 fprintf( stderr, " %s", b->a_dn_pat.bv_val );
1947 fprintf( stderr, " dn.%s=\"%s\"",
1948 style_strings[b->a_dn_style], b->a_dn_pat.bv_val );
1952 if ( b->a_dn_at != NULL ) {
1953 fprintf( stderr, " dnattr=%s", b->a_dn_at->ad_cname.bv_val );
1956 if ( b->a_group_pat.bv_len ) {
1957 fprintf( stderr, " group/%s/%s.%s=\"%s\"",
1958 b->a_group_oc ? b->a_group_oc->soc_cname.bv_val : "groupOfNames",
1959 b->a_group_at ? b->a_group_at->ad_cname.bv_val : "member",
1960 style_strings[b->a_group_style],
1961 b->a_group_pat.bv_val );
1964 if ( b->a_peername_pat.bv_len != 0 ) {
1965 fprintf( stderr, " peername=\"%s\"", b->a_peername_pat.bv_val );
1968 if ( b->a_sockname_pat.bv_len != 0 ) {
1969 fprintf( stderr, " sockname=\"%s\"", b->a_sockname_pat.bv_val );
1972 if ( b->a_domain_pat.bv_len != 0 ) {
1973 fprintf( stderr, " domain=%s", b->a_domain_pat.bv_val );
1976 if ( b->a_sockurl_pat.bv_len != 0 ) {
1977 fprintf( stderr, " sockurl=\"%s\"", b->a_sockurl_pat.bv_val );
1980 if ( b->a_set_pat.bv_len != 0 ) {
1981 fprintf( stderr, " set=\"%s\"", b->a_set_pat.bv_val );
1984 #ifdef SLAPD_ACI_ENABLED
1985 if ( b->a_aci_at != NULL ) {
1986 fprintf( stderr, " aci=%s", b->a_aci_at->ad_cname.bv_val );
1990 /* Security Strength Factors */
1991 if ( b->a_authz.sai_ssf ) {
1992 fprintf( stderr, " ssf=%u",
1993 b->a_authz.sai_ssf );
1995 if ( b->a_authz.sai_transport_ssf ) {
1996 fprintf( stderr, " transport_ssf=%u",
1997 b->a_authz.sai_transport_ssf );
1999 if ( b->a_authz.sai_tls_ssf ) {
2000 fprintf( stderr, " tls_ssf=%u",
2001 b->a_authz.sai_tls_ssf );
2003 if ( b->a_authz.sai_sasl_ssf ) {
2004 fprintf( stderr, " sasl_ssf=%u",
2005 b->a_authz.sai_sasl_ssf );
2008 fprintf( stderr, " %s%s",
2009 b->a_dn_self ? "self" : "",
2010 accessmask2str( b->a_access_mask, maskbuf ) );
2012 if( b->a_type == ACL_BREAK ) {
2013 fprintf( stderr, " break" );
2015 } else if( b->a_type == ACL_CONTINUE ) {
2016 fprintf( stderr, " continue" );
2018 } else if( b->a_type != ACL_STOP ) {
2019 fprintf( stderr, " unknown-control" );
2022 fprintf( stderr, "\n" );
2027 print_acl( Backend *be, AccessControl *a )
2032 fprintf( stderr, "%s ACL: access to",
2033 be == NULL ? "Global" : "Backend" );
2035 if ( a->acl_dn_pat.bv_len != 0 ) {
2037 fprintf( stderr, " dn.%s=\"%s\"\n",
2038 style_strings[a->acl_dn_style], a->acl_dn_pat.bv_val );
2041 if ( a->acl_filter != NULL ) {
2042 struct berval bv = BER_BVNULL;
2044 filter2bv( a->acl_filter, &bv );
2045 fprintf( stderr, " filter=%s\n", bv.bv_val );
2046 ch_free( bv.bv_val );
2049 if ( a->acl_attrs != NULL ) {
2054 fprintf( stderr, " attrs=" );
2055 for ( an = a->acl_attrs; an && an->an_name.bv_val; an++ ) {
2057 fprintf( stderr, "," );
2060 fputc( an->an_oc_exclude ? '!' : '@', stderr);
2062 fputs( an->an_name.bv_val, stderr );
2065 fprintf( stderr, "\n" );
2068 if ( a->acl_attrval.bv_len != 0 ) {
2070 fprintf( stderr, " val.%s=\"%s\"\n",
2071 style_strings[a->acl_attrval_style], a->acl_attrval.bv_val );
2076 fprintf( stderr, " *\n" );
2079 for ( b = a->acl_access; b != NULL; b = b->a_next ) {
2083 fprintf( stderr, "\n" );
2086 #endif /* LDAP_DEBUG */