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, *next;
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 = strtol( right, *next, 10 );
1274 if ( next == NULL || next[0] != '\0' ) {
1276 "%s: line %d: unable to parse ssf value (%s)\n",
1277 fname, lineno, right );
1281 if( !b->a_authz.sai_ssf ) {
1283 "%s: line %d: invalid ssf value (%s)\n",
1284 fname, lineno, right );
1290 if ( strcasecmp( left, "transport_ssf" ) == 0 ) {
1291 if (sty != ACL_STYLE_REGEX && sty != ACL_STYLE_BASE) {
1293 "%s: line %d: inappropriate style \"%s\" in by clause\n",
1294 fname, lineno, style );
1298 if( b->a_authz.sai_transport_ssf ) {
1300 "%s: line %d: transport_ssf attribute already specified.\n",
1305 if ( right == NULL || *right == '\0' ) {
1307 "%s: line %d: no transport_ssf is defined\n",
1312 b->a_authz.sai_transport_ssf = strtol( right, &next, 10 );
1313 if ( next == NULL || next[0] != '\0' ) {
1315 "%s: line %d: unable to parse transport_ssf value (%s)\n",
1316 fname, lineno, right );
1320 if( !b->a_authz.sai_transport_ssf ) {
1322 "%s: line %d: invalid transport_ssf value (%s)\n",
1323 fname, lineno, right );
1329 if ( strcasecmp( left, "tls_ssf" ) == 0 ) {
1330 if (sty != ACL_STYLE_REGEX && sty != ACL_STYLE_BASE) {
1332 "%s: line %d: inappropriate style \"%s\" in by clause\n",
1333 fname, lineno, style );
1337 if( b->a_authz.sai_tls_ssf ) {
1339 "%s: line %d: tls_ssf attribute already specified.\n",
1344 if ( right == NULL || *right == '\0' ) {
1346 "%s: line %d: no tls_ssf is defined\n",
1351 b->a_authz.sai_tls_ssf = strtol( right, &next, 10 );
1352 if ( next == NULL || next[0] != '\0' ) {
1354 "%s: line %d: unable to parse tls_ssf value (%s)\n",
1355 fname, lineno, right );
1359 if( !b->a_authz.sai_tls_ssf ) {
1361 "%s: line %d: invalid tls_ssf value (%s)\n",
1362 fname, lineno, right );
1368 if ( strcasecmp( left, "sasl_ssf" ) == 0 ) {
1369 if (sty != ACL_STYLE_REGEX && sty != ACL_STYLE_BASE) {
1371 "%s: line %d: inappropriate style \"%s\" in by clause\n",
1372 fname, lineno, style );
1376 if( b->a_authz.sai_sasl_ssf ) {
1378 "%s: line %d: sasl_ssf attribute already specified.\n",
1383 if ( right == NULL || *right == '\0' ) {
1385 "%s: line %d: no sasl_ssf is defined\n",
1390 b->a_authz.sai_sasl_ssf = strtol( right, &next, 10 );
1391 if ( next == NULL || next[0] != '\0' ) {
1393 "%s: line %d: unable to parse sasl_ssf value (%s)\n",
1394 fname, lineno, right );
1398 if( !b->a_authz.sai_sasl_ssf ) {
1400 "%s: line %d: invalid sasl_ssf value (%s)\n",
1401 fname, lineno, right );
1407 if( right != NULL ) {
1414 if( i == argc || ( strcasecmp( left, "stop" ) == 0 )) {
1415 /* out of arguments or plain stop */
1417 ACL_PRIV_ASSIGN(b->a_access_mask, ACL_PRIV_ADDITIVE);
1418 b->a_type = ACL_STOP;
1420 access_append( &a->acl_access, b );
1424 if( strcasecmp( left, "continue" ) == 0 ) {
1425 /* plain continue */
1427 ACL_PRIV_ASSIGN(b->a_access_mask, ACL_PRIV_ADDITIVE);
1428 b->a_type = ACL_CONTINUE;
1430 access_append( &a->acl_access, b );
1434 if( strcasecmp( left, "break" ) == 0 ) {
1435 /* plain continue */
1437 ACL_PRIV_ASSIGN(b->a_access_mask, ACL_PRIV_ADDITIVE);
1438 b->a_type = ACL_BREAK;
1440 access_append( &a->acl_access, b );
1444 if ( strcasecmp( left, "by" ) == 0 ) {
1445 /* we've gone too far */
1447 ACL_PRIV_ASSIGN(b->a_access_mask, ACL_PRIV_ADDITIVE);
1448 b->a_type = ACL_STOP;
1450 access_append( &a->acl_access, b );
1455 if( strncasecmp( left, "self", 4 ) == 0 ) {
1457 ACL_PRIV_ASSIGN( b->a_access_mask, str2accessmask( &left[4] ) );
1460 ACL_PRIV_ASSIGN( b->a_access_mask, str2accessmask( left ) );
1463 if( ACL_IS_INVALID( b->a_access_mask ) ) {
1465 "%s: line %d: expecting <access> got \"%s\"\n",
1466 fname, lineno, left );
1470 b->a_type = ACL_STOP;
1473 /* out of arguments or plain stop */
1474 access_append( &a->acl_access, b );
1478 if( strcasecmp( argv[i], "continue" ) == 0 ) {
1479 /* plain continue */
1480 b->a_type = ACL_CONTINUE;
1482 } else if( strcasecmp( argv[i], "break" ) == 0 ) {
1483 /* plain continue */
1484 b->a_type = ACL_BREAK;
1486 } else if ( strcasecmp( argv[i], "stop" ) != 0 ) {
1491 access_append( &a->acl_access, b );
1495 "%s: line %d: expecting \"to\" or \"by\" got \"%s\"\n",
1496 fname, lineno, argv[i] );
1501 /* if we have no real access clause, complain and do nothing */
1504 "%s: line %d: warning: no access clause(s) specified in access line\n",
1509 if (ldap_debug & LDAP_DEBUG_ACL)
1513 if ( a->acl_access == NULL ) {
1515 "%s: line %d: warning: no by clause(s) specified in access line\n",
1521 switch ( check_scope( be, a ) ) {
1522 case ACL_SCOPE_UNKNOWN:
1523 fprintf( stderr, "%s: line %d: warning: "
1524 "cannot assess the validity "
1525 "of the ACL scope within "
1526 "backend naming context\n",
1530 case ACL_SCOPE_WARN:
1531 fprintf( stderr, "%s: line %d: warning: "
1532 "ACL could be out of "
1534 "backend naming context\n",
1538 case ACL_SCOPE_PARTIAL:
1539 fprintf( stderr, "%s: line %d: warning: "
1540 "ACL appears to be partially "
1541 "out of scope within "
1542 "backend naming context\n",
1547 fprintf( stderr, "%s: line %d: warning: "
1548 "ACL appears to be out of "
1550 "backend naming context\n",
1557 #endif /* LDAP_DEVEL */
1558 acl_append( &be->be_acl, a );
1560 acl_append( &global_acl, a );
1566 accessmask2str( slap_mask_t mask, char *buf )
1571 assert( buf != NULL );
1573 if ( ACL_IS_INVALID( mask ) ) {
1579 if ( ACL_IS_LEVEL( mask ) ) {
1580 if ( ACL_LVL_IS_NONE(mask) ) {
1581 ptr = lutil_strcopy( ptr, "none" );
1583 } else if ( ACL_LVL_IS_AUTH(mask) ) {
1584 ptr = lutil_strcopy( ptr, "auth" );
1586 } else if ( ACL_LVL_IS_COMPARE(mask) ) {
1587 ptr = lutil_strcopy( ptr, "compare" );
1589 } else if ( ACL_LVL_IS_SEARCH(mask) ) {
1590 ptr = lutil_strcopy( ptr, "search" );
1592 } else if ( ACL_LVL_IS_READ(mask) ) {
1593 ptr = lutil_strcopy( ptr, "read" );
1595 } else if ( ACL_LVL_IS_WRITE(mask) ) {
1596 ptr = lutil_strcopy( ptr, "write" );
1598 ptr = lutil_strcopy( ptr, "unknown" );
1604 if( ACL_IS_ADDITIVE( mask ) ) {
1607 } else if( ACL_IS_SUBTRACTIVE( mask ) ) {
1614 if ( ACL_PRIV_ISSET(mask, ACL_PRIV_WRITE) ) {
1619 if ( ACL_PRIV_ISSET(mask, ACL_PRIV_READ) ) {
1624 if ( ACL_PRIV_ISSET(mask, ACL_PRIV_SEARCH) ) {
1629 if ( ACL_PRIV_ISSET(mask, ACL_PRIV_COMPARE) ) {
1634 if ( ACL_PRIV_ISSET(mask, ACL_PRIV_AUTH) ) {
1639 if ( none && ACL_PRIV_ISSET(mask, ACL_PRIV_NONE) ) {
1648 if ( ACL_IS_LEVEL( mask ) ) {
1658 str2accessmask( const char *str )
1662 if( !ASCII_ALPHA(str[0]) ) {
1665 if ( str[0] == '=' ) {
1668 } else if( str[0] == '+' ) {
1669 ACL_PRIV_ASSIGN(mask, ACL_PRIV_ADDITIVE);
1671 } else if( str[0] == '-' ) {
1672 ACL_PRIV_ASSIGN(mask, ACL_PRIV_SUBSTRACTIVE);
1675 ACL_INVALIDATE(mask);
1679 for( i=1; str[i] != '\0'; i++ ) {
1680 if( TOLOWER((unsigned char) str[i]) == 'w' ) {
1681 ACL_PRIV_SET(mask, ACL_PRIV_WRITE);
1683 } else if( TOLOWER((unsigned char) str[i]) == 'r' ) {
1684 ACL_PRIV_SET(mask, ACL_PRIV_READ);
1686 } else if( TOLOWER((unsigned char) str[i]) == 's' ) {
1687 ACL_PRIV_SET(mask, ACL_PRIV_SEARCH);
1689 } else if( TOLOWER((unsigned char) str[i]) == 'c' ) {
1690 ACL_PRIV_SET(mask, ACL_PRIV_COMPARE);
1692 } else if( TOLOWER((unsigned char) str[i]) == 'x' ) {
1693 ACL_PRIV_SET(mask, ACL_PRIV_AUTH);
1695 } else if( str[i] != '0' ) {
1696 ACL_INVALIDATE(mask);
1704 if ( strcasecmp( str, "none" ) == 0 ) {
1705 ACL_LVL_ASSIGN_NONE(mask);
1707 } else if ( strcasecmp( str, "auth" ) == 0 ) {
1708 ACL_LVL_ASSIGN_AUTH(mask);
1710 } else if ( strcasecmp( str, "compare" ) == 0 ) {
1711 ACL_LVL_ASSIGN_COMPARE(mask);
1713 } else if ( strcasecmp( str, "search" ) == 0 ) {
1714 ACL_LVL_ASSIGN_SEARCH(mask);
1716 } else if ( strcasecmp( str, "read" ) == 0 ) {
1717 ACL_LVL_ASSIGN_READ(mask);
1719 } else if ( strcasecmp( str, "write" ) == 0 ) {
1720 ACL_LVL_ASSIGN_WRITE(mask);
1723 ACL_INVALIDATE( mask );
1732 fprintf( stderr, "%s%s\n",
1733 "<access clause> ::= access to <what> "
1734 "[ by <who> <access> [ <control> ] ]+ \n"
1735 "<what> ::= * | [dn[.<dnstyle>]=<DN>] [filter=<filter>] [attrs=<attrlist>]\n"
1736 "<attrlist> ::= <attr> [val[.<style>]=<value>] | <attr> , <attrlist>\n"
1737 "<attr> ::= <attrname> | entry | children\n"
1738 "<who> ::= [ * | anonymous | users | self | dn[.<dnstyle>]=<DN> ]\n"
1739 "\t[dnattr=<attrname>]\n"
1740 "\t[group[/<objectclass>[/<attrname>]][.<style>]=<group>]\n"
1741 "\t[peername[.<peernamestyle>]=<peer>] [sockname[.<style>]=<name>]\n",
1742 "\t[domain[.<domainstyle>]=<domain>] [sockurl[.<style>]=<url>]\n"
1743 #ifdef SLAPD_ACI_ENABLED
1744 "\t[aci=<attrname>]\n"
1746 "\t[ssf=<n>] [transport_ssf=<n>] [tls_ssf=<n>] [sasl_ssf=<n>]\n"
1747 "<dnstyle> ::= base | exact | one(level) | sub(tree) | children | regex\n"
1748 "<style> ::= regex | base | exact\n"
1749 "<peernamestyle> ::= regex | exact | ip | path\n"
1750 "<domainstyle> ::= regex | base | exact | sub(tree)\n"
1751 "<access> ::= [self]{<level>|<priv>}\n"
1752 "<level> ::= none | auth | compare | search | read | write\n"
1753 "<priv> ::= {=|+|-}{w|r|s|c|x|0}+\n"
1754 "<control> ::= [ stop | continue | break ]\n"
1756 exit( EXIT_FAILURE );
1760 * Set pattern to a "normalized" DN from src.
1761 * At present it simply eats the (optional) space after
1762 * a RDN separator (,)
1763 * Eventually will evolve in a more complete normalization
1766 acl_regex_normalized_dn(
1768 struct berval *pattern
1774 str = ch_strdup( src );
1775 len = strlen( src );
1777 for ( p = str; p && p[ 0 ]; p++ ) {
1779 if ( p[ 0 ] == '\\' && p[ 1 ] ) {
1781 * if escaping a hex pair we should
1782 * increment p twice; however, in that
1783 * case the second hex number does
1789 if ( p[ 0 ] == ',' ) {
1790 if ( p[ 1 ] == ' ' ) {
1794 * too much space should be
1795 * an error if we are pedantic
1797 for ( q = &p[ 2 ]; q[ 0 ] == ' '; q++ ) {
1800 AC_MEMCPY( p+1, q, len-(q-str)+1);
1804 pattern->bv_val = str;
1805 pattern->bv_len = p-str;
1819 if ( (*right = strchr( line, splitchar )) != NULL ) {
1820 *((*right)++) = '\0';
1825 access_append( Access **l, Access *a )
1827 for ( ; *l != NULL; l = &(*l)->a_next )
1834 acl_append( AccessControl **l, AccessControl *a )
1836 for ( ; *l != NULL; l = &(*l)->acl_next )
1843 access_free( Access *a )
1845 if ( a->a_dn_pat.bv_val )
1846 free ( a->a_dn_pat.bv_val );
1847 if ( a->a_peername_pat.bv_val )
1848 free ( a->a_peername_pat.bv_val );
1849 if ( a->a_sockname_pat.bv_val )
1850 free ( a->a_sockname_pat.bv_val );
1851 if ( a->a_domain_pat.bv_val )
1852 free ( a->a_domain_pat.bv_val );
1853 if ( a->a_sockurl_pat.bv_val )
1854 free ( a->a_sockurl_pat.bv_val );
1855 if ( a->a_set_pat.bv_len )
1856 free ( a->a_set_pat.bv_val );
1857 if ( a->a_group_pat.bv_len )
1858 free ( a->a_group_pat.bv_val );
1863 acl_free( AccessControl *a )
1868 if ( a->acl_filter )
1869 filter_free( a->acl_filter );
1870 if ( a->acl_dn_pat.bv_len )
1871 free ( a->acl_dn_pat.bv_val );
1872 if ( a->acl_attrs ) {
1873 for ( an = a->acl_attrs; an->an_name.bv_val; an++ ) {
1874 free( an->an_name.bv_val );
1876 free( a->acl_attrs );
1878 for (; a->acl_access; a->acl_access = n) {
1879 n = a->acl_access->a_next;
1880 access_free( a->acl_access );
1885 /* Because backend_startup uses acl_append to tack on the global_acl to
1886 * the end of each backend's acl, we cannot just take one argument and
1887 * merrily free our way to the end of the list. backend_destroy calls us
1888 * with the be_acl in arg1, and global_acl in arg2 to give us a stopping
1889 * point. config_destroy calls us with global_acl in arg1 and NULL in
1890 * arg2, so we then proceed to polish off the global_acl.
1893 acl_destroy( AccessControl *a, AccessControl *end )
1897 for (; a && a!= end; a=n) {
1904 access2str( slap_access_t access )
1906 if ( access == ACL_NONE ) {
1909 } else if ( access == ACL_AUTH ) {
1912 } else if ( access == ACL_COMPARE ) {
1915 } else if ( access == ACL_SEARCH ) {
1918 } else if ( access == ACL_READ ) {
1921 } else if ( access == ACL_WRITE ) {
1929 str2access( const char *str )
1931 if ( strcasecmp( str, "none" ) == 0 ) {
1934 } else if ( strcasecmp( str, "auth" ) == 0 ) {
1937 } else if ( strcasecmp( str, "compare" ) == 0 ) {
1940 } else if ( strcasecmp( str, "search" ) == 0 ) {
1943 } else if ( strcasecmp( str, "read" ) == 0 ) {
1946 } else if ( strcasecmp( str, "write" ) == 0 ) {
1950 return( ACL_INVALID_ACCESS );
1956 print_access( Access *b )
1958 char maskbuf[ACCESSMASK_MAXLEN];
1960 fprintf( stderr, "\tby" );
1962 if ( b->a_dn_pat.bv_len != 0 ) {
1963 if( strcmp(b->a_dn_pat.bv_val, "*") == 0
1964 || strcmp(b->a_dn_pat.bv_val, "users") == 0
1965 || strcmp(b->a_dn_pat.bv_val, "anonymous") == 0
1966 || strcmp(b->a_dn_pat.bv_val, "self") == 0 )
1968 fprintf( stderr, " %s", b->a_dn_pat.bv_val );
1971 fprintf( stderr, " dn.%s=\"%s\"",
1972 style_strings[b->a_dn_style], b->a_dn_pat.bv_val );
1976 if ( b->a_dn_at != NULL ) {
1977 fprintf( stderr, " dnattr=%s", b->a_dn_at->ad_cname.bv_val );
1980 if ( b->a_group_pat.bv_len ) {
1981 fprintf( stderr, " group/%s/%s.%s=\"%s\"",
1982 b->a_group_oc ? b->a_group_oc->soc_cname.bv_val : "groupOfNames",
1983 b->a_group_at ? b->a_group_at->ad_cname.bv_val : "member",
1984 style_strings[b->a_group_style],
1985 b->a_group_pat.bv_val );
1988 if ( b->a_peername_pat.bv_len != 0 ) {
1989 fprintf( stderr, " peername=\"%s\"", b->a_peername_pat.bv_val );
1992 if ( b->a_sockname_pat.bv_len != 0 ) {
1993 fprintf( stderr, " sockname=\"%s\"", b->a_sockname_pat.bv_val );
1996 if ( b->a_domain_pat.bv_len != 0 ) {
1997 fprintf( stderr, " domain=%s", b->a_domain_pat.bv_val );
2000 if ( b->a_sockurl_pat.bv_len != 0 ) {
2001 fprintf( stderr, " sockurl=\"%s\"", b->a_sockurl_pat.bv_val );
2004 if ( b->a_set_pat.bv_len != 0 ) {
2005 fprintf( stderr, " set=\"%s\"", b->a_set_pat.bv_val );
2008 #ifdef SLAPD_ACI_ENABLED
2009 if ( b->a_aci_at != NULL ) {
2010 fprintf( stderr, " aci=%s", b->a_aci_at->ad_cname.bv_val );
2014 /* Security Strength Factors */
2015 if ( b->a_authz.sai_ssf ) {
2016 fprintf( stderr, " ssf=%u",
2017 b->a_authz.sai_ssf );
2019 if ( b->a_authz.sai_transport_ssf ) {
2020 fprintf( stderr, " transport_ssf=%u",
2021 b->a_authz.sai_transport_ssf );
2023 if ( b->a_authz.sai_tls_ssf ) {
2024 fprintf( stderr, " tls_ssf=%u",
2025 b->a_authz.sai_tls_ssf );
2027 if ( b->a_authz.sai_sasl_ssf ) {
2028 fprintf( stderr, " sasl_ssf=%u",
2029 b->a_authz.sai_sasl_ssf );
2032 fprintf( stderr, " %s%s",
2033 b->a_dn_self ? "self" : "",
2034 accessmask2str( b->a_access_mask, maskbuf ) );
2036 if( b->a_type == ACL_BREAK ) {
2037 fprintf( stderr, " break" );
2039 } else if( b->a_type == ACL_CONTINUE ) {
2040 fprintf( stderr, " continue" );
2042 } else if( b->a_type != ACL_STOP ) {
2043 fprintf( stderr, " unknown-control" );
2046 fprintf( stderr, "\n" );
2051 print_acl( Backend *be, AccessControl *a )
2056 fprintf( stderr, "%s ACL: access to",
2057 be == NULL ? "Global" : "Backend" );
2059 if ( a->acl_dn_pat.bv_len != 0 ) {
2061 fprintf( stderr, " dn.%s=\"%s\"\n",
2062 style_strings[a->acl_dn_style], a->acl_dn_pat.bv_val );
2065 if ( a->acl_filter != NULL ) {
2066 struct berval bv = BER_BVNULL;
2068 filter2bv( a->acl_filter, &bv );
2069 fprintf( stderr, " filter=%s\n", bv.bv_val );
2070 ch_free( bv.bv_val );
2073 if ( a->acl_attrs != NULL ) {
2078 fprintf( stderr, " attrs=" );
2079 for ( an = a->acl_attrs; an && an->an_name.bv_val; an++ ) {
2081 fprintf( stderr, "," );
2084 fputc( an->an_oc_exclude ? '!' : '@', stderr);
2086 fputs( an->an_name.bv_val, stderr );
2089 fprintf( stderr, "\n" );
2092 if ( a->acl_attrval.bv_len != 0 ) {
2094 fprintf( stderr, " val.%s=\"%s\"\n",
2095 style_strings[a->acl_attrval_style], a->acl_attrval.bv_val );
2100 fprintf( stderr, " *\n" );
2103 for ( b = a->acl_access; b != NULL; b = b->a_next ) {
2107 fprintf( stderr, "\n" );
2110 #endif /* LDAP_DEBUG */