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 );
128 * Check if the pattern of an ACL, if any, matches the scope
129 * of the backend it is defined within.
131 #define ACL_SCOPE_UNKNOWN (-2)
132 #define ACL_SCOPE_ERR (-1)
133 #define ACL_SCOPE_OK (0)
134 #define ACL_SCOPE_PARTIAL (1)
135 #define ACL_SCOPE_WARN (2)
138 check_scope( BackendDB *be, AccessControl *a )
143 dn = be->be_nsuffix[0];
145 if ( !BER_BVISEMPTY( &a->acl_dn_pat ) ||
146 a->acl_dn_style != ACL_STYLE_REGEX )
148 slap_style_t style = a->acl_dn_style;
150 if ( style == ACL_STYLE_REGEX ) {
151 char dnbuf[SLAP_LDAPDN_MAXLEN + 2];
152 char rebuf[SLAP_LDAPDN_MAXLEN + 1];
156 /* add trailing '$' */
157 AC_MEMCPY( dnbuf, be->be_nsuffix[0].bv_val,
158 be->be_nsuffix[0].bv_len );
159 dnbuf[be->be_nsuffix[0].bv_len] = '$';
160 dnbuf[be->be_nsuffix[0].bv_len + 1] = '\0';
162 if ( regcomp( &re, dnbuf, REG_EXTENDED|REG_ICASE ) ) {
163 return ACL_SCOPE_WARN;
166 /* remove trailing '$' */
167 AC_MEMCPY( rebuf, a->acl_dn_pat.bv_val,
168 a->acl_dn_pat.bv_len + 1 );
169 if ( a->acl_dn_pat.bv_val[a->acl_dn_pat.bv_len - 1] == '$' ) {
170 rebuf[a->acl_dn_pat.bv_len - 1] = '\0';
173 /* not a clear indication of scoping error, though */
174 rc = regexec( &re, rebuf, 0, NULL, 0 )
175 ? 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 ) return ACL_SCOPE_ERR;
190 /* one can be wrong if there is more
191 * than one level between the suffix
193 if ( style == ACL_STYLE_ONE ) {
194 int rdnlen = -1, sep = 0;
197 if ( !DN_SEPARATOR( dn.bv_val[dn.bv_len - patlen - 1] )) {
198 return ACL_SCOPE_ERR;
203 rdnlen = dn_rdnlen( NULL, &dn );
204 if ( rdnlen != dn.bv_len - patlen - sep )
205 return ACL_SCOPE_ERR;
208 /* if the trailing part doesn't match,
209 * then it's an error */
210 if ( strcmp( a->acl_dn_pat.bv_val,
211 &dn.bv_val[dn.bv_len - patlen] ) != 0 )
213 return ACL_SCOPE_ERR;
216 return ACL_SCOPE_PARTIAL;
222 case ACL_STYLE_CHILDREN:
223 case ACL_STYLE_SUBTREE:
231 if ( dn.bv_len < patlen &&
232 !DN_SEPARATOR( a->acl_dn_pat.bv_val[patlen - dn.bv_len - 1] ))
234 return ACL_SCOPE_ERR;
237 if ( strcmp( &a->acl_dn_pat.bv_val[patlen - dn.bv_len], dn.bv_val )
240 return ACL_SCOPE_ERR;
246 return ACL_SCOPE_UNKNOWN;
248 #endif /* LDAP_DEVEL */
260 char *left, *right, *style, *next;
268 for ( i = 1; i < argc; i++ ) {
269 /* to clause - select which entries are protected */
270 if ( strcasecmp( argv[i], "to" ) == 0 ) {
272 fprintf( stderr, "%s: line %d: "
273 "only one to clause allowed in access line\n",
277 a = (AccessControl *) ch_calloc( 1, sizeof(AccessControl) );
278 for ( ++i; i < argc; i++ ) {
279 if ( strcasecmp( argv[i], "by" ) == 0 ) {
284 if ( strcasecmp( argv[i], "*" ) == 0 ) {
285 if ( !BER_BVISEMPTY( &a->acl_dn_pat ) ||
286 a->acl_dn_style != ACL_STYLE_REGEX )
289 "%s: line %d: dn pattern"
290 " already specified in to clause.\n",
295 ber_str2bv( "*", STRLENOF( "*" ), 1, &a->acl_dn_pat );
299 split( argv[i], '=', &left, &right );
300 split( left, '.', &left, &style );
302 if ( right == NULL ) {
303 fprintf( stderr, "%s: line %d: "
304 "missing \"=\" in \"%s\" in to clause\n",
305 fname, lineno, left );
309 if ( strcasecmp( left, "dn" ) == 0 ) {
310 if ( !BER_BVISEMPTY( &a->acl_dn_pat ) ||
311 a->acl_dn_style != ACL_STYLE_REGEX )
314 "%s: line %d: dn pattern"
315 " already specified in to clause.\n",
320 if ( style == NULL || *style == '\0' ||
321 strcasecmp( style, "baseObject" ) == 0 ||
322 strcasecmp( style, "base" ) == 0 ||
323 strcasecmp( style, "exact" ) == 0 )
325 a->acl_dn_style = ACL_STYLE_BASE;
326 ber_str2bv( right, 0, 1, &a->acl_dn_pat );
328 } else if ( strcasecmp( style, "oneLevel" ) == 0 ||
329 strcasecmp( style, "one" ) == 0 )
331 a->acl_dn_style = ACL_STYLE_ONE;
332 ber_str2bv( right, 0, 1, &a->acl_dn_pat );
334 } else if ( strcasecmp( style, "subtree" ) == 0 ||
335 strcasecmp( style, "sub" ) == 0 )
337 if( *right == '\0' ) {
338 ber_str2bv( "*", STRLENOF( "*" ), 1, &a->acl_dn_pat );
341 a->acl_dn_style = ACL_STYLE_SUBTREE;
342 ber_str2bv( right, 0, 1, &a->acl_dn_pat );
345 } else if ( strcasecmp( style, "children" ) == 0 ) {
346 a->acl_dn_style = ACL_STYLE_CHILDREN;
347 ber_str2bv( right, 0, 1, &a->acl_dn_pat );
349 } else if ( strcasecmp( style, "regex" ) == 0 ) {
350 a->acl_dn_style = ACL_STYLE_REGEX;
352 if ( *right == '\0' ) {
353 /* empty regex should match empty DN */
354 a->acl_dn_style = ACL_STYLE_BASE;
355 ber_str2bv( right, 0, 1, &a->acl_dn_pat );
357 } else if ( strcmp(right, "*") == 0
358 || strcmp(right, ".*") == 0
359 || strcmp(right, ".*$") == 0
360 || strcmp(right, "^.*") == 0
361 || strcmp(right, "^.*$") == 0
362 || strcmp(right, ".*$$") == 0
363 || strcmp(right, "^.*$$") == 0 )
365 ber_str2bv( "*", STRLENOF("*"), 1, &a->acl_dn_pat );
368 acl_regex_normalized_dn( right, &a->acl_dn_pat );
372 fprintf( stderr, "%s: line %d: "
373 "unknown dn style \"%s\" in to clause\n",
374 fname, lineno, style );
381 if ( strcasecmp( left, "filter" ) == 0 ) {
382 if ( (a->acl_filter = str2filter( right )) == NULL ) {
384 "%s: line %d: bad filter \"%s\" in to clause\n",
385 fname, lineno, right );
389 } else if ( strcasecmp( left, "attr" ) == 0
390 || strcasecmp( left, "attrs" ) == 0 ) {
391 a->acl_attrs = str2anlist( a->acl_attrs,
393 if ( a->acl_attrs == NULL ) {
395 "%s: line %d: unknown attr \"%s\" in to clause\n",
396 fname, lineno, right );
400 } else if ( strncasecmp( left, "val", 3 ) == 0 ) {
401 if ( !BER_BVISEMPTY( &a->acl_attrval ) ) {
403 "%s: line %d: attr val already specified in to clause.\n",
407 if ( a->acl_attrs == NULL || !BER_BVISEMPTY( &a->acl_attrs[1].an_name ) )
410 "%s: line %d: attr val requires a single attribute.\n",
414 ber_str2bv( right, 0, 1, &a->acl_attrval );
415 if ( style && strcasecmp( style, "regex" ) == 0 ) {
416 int e = regcomp( &a->acl_attrval_re, a->acl_attrval.bv_val,
417 REG_EXTENDED | REG_ICASE | REG_NOSUB );
420 regerror( e, &a->acl_attrval_re, buf, sizeof(buf) );
421 fprintf( stderr, "%s: line %d: "
422 "regular expression \"%s\" bad because of %s\n",
423 fname, lineno, right, buf );
426 a->acl_attrval_style = ACL_STYLE_REGEX;
428 /* FIXME: if the attribute has DN syntax, we might
429 * allow one, subtree and children styles as well */
430 if ( !strcasecmp( style, "exact" ) ) {
431 a->acl_attrval_style = ACL_STYLE_BASE;
433 } else if ( a->acl_attrs[0].an_desc->ad_type->
434 sat_syntax == slap_schema.si_syn_distinguishedName )
436 if ( !strcasecmp( style, "baseObject" ) ||
437 !strcasecmp( style, "base" ) )
439 a->acl_attrval_style = ACL_STYLE_BASE;
440 } else if ( !strcasecmp( style, "onelevel" ) ||
441 !strcasecmp( style, "one" ) )
443 a->acl_attrval_style = ACL_STYLE_ONE;
444 } else if ( !strcasecmp( style, "subtree" ) ||
445 !strcasecmp( style, "sub" ) )
447 a->acl_attrval_style = ACL_STYLE_SUBTREE;
448 } else if ( !strcasecmp( style, "children" ) ) {
449 a->acl_attrval_style = ACL_STYLE_CHILDREN;
452 "%s: line %d: unknown val.<style> \"%s\" "
453 "for attributeType \"%s\" with DN syntax; "
455 fname, lineno, style,
456 a->acl_attrs[0].an_desc->ad_cname.bv_val );
457 a->acl_attrval_style = ACL_STYLE_BASE;
462 "%s: line %d: unknown val.<style> \"%s\" "
463 "for attributeType \"%s\"; using \"exact\"\n",
464 fname, lineno, style,
465 a->acl_attrs[0].an_desc->ad_cname.bv_val );
466 a->acl_attrval_style = ACL_STYLE_BASE;
472 "%s: line %d: expecting <what> got \"%s\"\n",
473 fname, lineno, left );
478 if ( !BER_BVISNULL( &a->acl_dn_pat ) &&
479 ber_bvccmp( &a->acl_dn_pat, '*' ) )
481 free( a->acl_dn_pat.bv_val );
482 BER_BVZERO( &a->acl_dn_pat );
485 if ( !BER_BVISEMPTY( &a->acl_dn_pat ) ||
486 a->acl_dn_style != ACL_STYLE_REGEX )
488 if ( a->acl_dn_style != ACL_STYLE_REGEX ) {
490 rc = dnNormalize( 0, NULL, NULL, &a->acl_dn_pat, &bv, NULL);
491 if ( rc != LDAP_SUCCESS ) {
493 "%s: line %d: bad DN \"%s\" in to DN clause\n",
494 fname, lineno, a->acl_dn_pat.bv_val );
497 free( a->acl_dn_pat.bv_val );
501 int e = regcomp( &a->acl_dn_re, a->acl_dn_pat.bv_val,
502 REG_EXTENDED | REG_ICASE );
505 regerror( e, &a->acl_dn_re, buf, sizeof(buf) );
506 fprintf( stderr, "%s: line %d: "
507 "regular expression \"%s\" bad because of %s\n",
508 fname, lineno, right, buf );
514 /* by clause - select who has what access to entries */
515 } else if ( strcasecmp( argv[i], "by" ) == 0 ) {
517 fprintf( stderr, "%s: line %d: "
518 "to clause required before by clause in access line\n",
524 * by clause consists of <who> and <access>
527 b = (Access *) ch_calloc( 1, sizeof(Access) );
529 ACL_INVALIDATE( b->a_access_mask );
533 "%s: line %d: premature eol: expecting <who>\n",
539 for ( ; i < argc; i++ ) {
540 slap_style_t sty = ACL_STYLE_REGEX;
541 char *style_modifier = NULL;
544 split( argv[i], '=', &left, &right );
545 split( left, '.', &left, &style );
547 split( style, ',', &style, &style_modifier);
550 if ( style == NULL || *style == '\0' ||
551 strcasecmp( style, "exact" ) == 0 ||
552 strcasecmp( style, "baseObject" ) == 0 ||
553 strcasecmp( style, "base" ) == 0 )
555 sty = ACL_STYLE_BASE;
557 } else if ( strcasecmp( style, "onelevel" ) == 0 ||
558 strcasecmp( style, "one" ) == 0 )
562 } else if ( strcasecmp( style, "subtree" ) == 0 ||
563 strcasecmp( style, "sub" ) == 0 )
565 sty = ACL_STYLE_SUBTREE;
567 } else if ( strcasecmp( style, "children" ) == 0 ) {
568 sty = ACL_STYLE_CHILDREN;
570 } else if ( strcasecmp( style, "regex" ) == 0 ) {
571 sty = ACL_STYLE_REGEX;
573 } else if ( strcasecmp( style, "expand" ) == 0 ) {
574 sty = ACL_STYLE_EXPAND;
576 } else if ( strcasecmp( style, "ip" ) == 0 ) {
579 } else if ( strcasecmp( style, "path" ) == 0 ) {
580 sty = ACL_STYLE_PATH;
581 #ifndef LDAP_PF_LOCAL
582 fprintf( stderr, "%s: line %d: "
583 "path style modifier is useless without local\n",
585 #endif /* LDAP_PF_LOCAL */
589 "%s: line %d: unknown style \"%s\" in by clause\n",
590 fname, lineno, style );
594 if ( style_modifier &&
595 strcasecmp( style_modifier, "expand" ) == 0 )
598 case ACL_STYLE_REGEX:
599 fprintf( stderr, "%s: line %d: "
600 "\"regex\" style implies "
601 "\"expand\" modifier (ignored)\n",
605 case ACL_STYLE_EXPAND:
607 /* FIXME: now it's legal... */
608 fprintf( stderr, "%s: line %d: "
609 "\"expand\" style used "
610 "in conjunction with "
611 "\"expand\" modifier (ignored)\n",
617 /* we'll see later if it's pertinent */
623 /* expand in <who> needs regex in <what> */
624 if ( ( sty == ACL_STYLE_EXPAND || expand )
625 && a->acl_dn_style != ACL_STYLE_REGEX )
627 fprintf( stderr, "%s: line %d: "
628 "\"expand\" style or modifier used "
629 "in conjunction with "
630 "a non-regex <what> clause\n",
634 if ( strcasecmp( argv[i], "*" ) == 0 ) {
635 ber_str2bv( "*", STRLENOF( "*" ), 1, &bv );
636 sty = ACL_STYLE_REGEX;
638 } else if ( strcasecmp( argv[i], "anonymous" ) == 0 ) {
639 ber_str2bv("anonymous", STRLENOF( "anonymous" ), 1, &bv);
640 sty = ACL_STYLE_ANONYMOUS;
642 } else if ( strcasecmp( argv[i], "users" ) == 0 ) {
643 ber_str2bv("users", STRLENOF( "users" ), 1, &bv);
644 sty = ACL_STYLE_USERS;
646 } else if ( strcasecmp( argv[i], "self" ) == 0 ) {
647 ber_str2bv("self", STRLENOF( "self" ), 1, &bv);
648 sty = ACL_STYLE_SELF;
650 } else if ( strcasecmp( argv[i], "creator" ) == 0 ) {
651 ber_str2bv("creator", STRLENOF( "creator" ), 1, &bv);
652 sty = ACL_STYLE_CREATOR;
654 } else if ( strcasecmp( left, "dn" ) == 0 ) {
655 if ( sty == ACL_STYLE_REGEX ) {
656 b->a_dn_style = ACL_STYLE_REGEX;
657 if ( right == NULL ) {
662 b->a_dn_style = ACL_STYLE_USERS;
664 } else if (*right == '\0' ) {
666 ber_str2bv("anonymous",
667 STRLENOF( "anonymous" ),
669 b->a_dn_style = ACL_STYLE_ANONYMOUS;
671 } else if ( strcmp( right, "*" ) == 0 ) {
673 /* any or users? users for now */
677 b->a_dn_style = ACL_STYLE_USERS;
679 } else if ( strcmp( right, ".+" ) == 0
680 || strcmp( right, "^.+" ) == 0
681 || strcmp( right, ".+$" ) == 0
682 || strcmp( right, "^.+$" ) == 0
683 || strcmp( right, ".+$$" ) == 0
684 || strcmp( right, "^.+$$" ) == 0 )
689 b->a_dn_style = ACL_STYLE_USERS;
691 } else if ( strcmp( right, ".*" ) == 0
692 || strcmp( right, "^.*" ) == 0
693 || strcmp( right, ".*$" ) == 0
694 || strcmp( right, "^.*$" ) == 0
695 || strcmp( right, ".*$$" ) == 0
696 || strcmp( right, "^.*$$" ) == 0 )
703 acl_regex_normalized_dn( right, &bv );
704 if ( !ber_bvccmp( &bv, '*' ) ) {
705 regtest( fname, lineno, bv.bv_val );
709 } else if ( right == NULL || *right == '\0' ) {
710 fprintf( stderr, "%s: line %d: "
711 "missing \"=\" in (or value after) \"%s\" "
713 fname, lineno, left );
717 ber_str2bv( right, 0, 1, &bv );
724 if ( !BER_BVISNULL( &bv ) ) {
725 if ( !BER_BVISEMPTY( &b->a_dn_pat ) ) {
727 "%s: line %d: dn pattern already specified.\n",
732 if ( sty != ACL_STYLE_REGEX &&
733 sty != ACL_STYLE_ANONYMOUS &&
734 sty != ACL_STYLE_USERS &&
735 sty != ACL_STYLE_SELF &&
736 sty != ACL_STYLE_CREATOR &&
739 rc = dnNormalize(0, NULL, NULL,
740 &bv, &b->a_dn_pat, NULL);
741 if ( rc != LDAP_SUCCESS ) {
743 "%s: line %d: bad DN \"%s\" in by DN clause\n",
744 fname, lineno, bv.bv_val );
753 b->a_dn_expand = expand;
757 if ( strcasecmp( left, "dnattr" ) == 0 ) {
758 if ( right == NULL || right[0] == '\0' ) {
759 fprintf( stderr, "%s: line %d: "
760 "missing \"=\" in (or value after) \"%s\" "
762 fname, lineno, left );
766 if( b->a_dn_at != NULL ) {
768 "%s: line %d: dnattr already specified.\n",
773 rc = slap_str2ad( right, &b->a_dn_at, &text );
775 if( rc != LDAP_SUCCESS ) {
777 "%s: line %d: dnattr \"%s\": %s\n",
778 fname, lineno, right, text );
783 if( !is_at_syntax( b->a_dn_at->ad_type,
785 !is_at_syntax( b->a_dn_at->ad_type,
786 SLAPD_NAMEUID_SYNTAX ))
789 "%s: line %d: dnattr \"%s\": "
790 "inappropriate syntax: %s\n",
791 fname, lineno, right,
792 b->a_dn_at->ad_type->sat_syntax_oid );
796 if( b->a_dn_at->ad_type->sat_equality == NULL ) {
798 "%s: line %d: dnattr \"%s\": "
799 "inappropriate matching (no EQUALITY)\n",
800 fname, lineno, right );
807 if ( strncasecmp( left, "group", STRLENOF( "group" ) ) == 0 ) {
812 case ACL_STYLE_REGEX:
813 /* legacy, tolerated */
814 fprintf( stderr, "%s: line %d: "
815 "deprecated group style \"regex\"; "
816 "use \"expand\" instead\n",
817 fname, lineno, style );
818 sty = ACL_STYLE_EXPAND;
822 /* legal, traditional */
823 case ACL_STYLE_EXPAND:
824 /* legal, substring expansion; supersedes regex */
829 fprintf( stderr, "%s: line %d: "
830 "inappropriate style \"%s\" in by clause\n",
831 fname, lineno, style );
835 if ( right == NULL || right[0] == '\0' ) {
836 fprintf( stderr, "%s: line %d: "
837 "missing \"=\" in (or value after) \"%s\" "
839 fname, lineno, left );
843 if ( !BER_BVISEMPTY( &b->a_group_pat ) ) {
845 "%s: line %d: group pattern already specified.\n",
850 /* format of string is
851 "group/objectClassValue/groupAttrName" */
852 if ( ( value = strchr(left, '/') ) != NULL ) {
854 if ( *value && ( name = strchr( value, '/' ) ) != NULL ) {
859 b->a_group_style = sty;
860 if ( sty == ACL_STYLE_EXPAND ) {
861 acl_regex_normalized_dn( right, &bv );
862 if ( !ber_bvccmp( &bv, '*' ) ) {
863 regtest( fname, lineno, bv.bv_val );
868 ber_str2bv( right, 0, 0, &bv );
869 rc = dnNormalize( 0, NULL, NULL, &bv,
870 &b->a_group_pat, NULL );
871 if ( rc != LDAP_SUCCESS ) {
873 "%s: line %d: bad DN \"%s\"\n",
874 fname, lineno, right );
879 if ( value && *value ) {
880 b->a_group_oc = oc_find( value );
883 if ( b->a_group_oc == NULL ) {
885 "%s: line %d: group objectclass "
887 fname, lineno, value );
892 b->a_group_oc = oc_find(SLAPD_GROUP_CLASS);
894 if( b->a_group_oc == NULL ) {
896 "%s: line %d: group default objectclass "
898 fname, lineno, SLAPD_GROUP_CLASS );
903 if ( is_object_subclass( slap_schema.si_oc_referral,
907 "%s: line %d: group objectclass \"%s\" "
908 "is subclass of referral\n",
909 fname, lineno, value );
913 if ( is_object_subclass( slap_schema.si_oc_alias,
917 "%s: line %d: group objectclass \"%s\" "
918 "is subclass of alias\n",
919 fname, lineno, value );
923 if ( name && *name ) {
924 rc = slap_str2ad( name, &b->a_group_at, &text );
926 if( rc != LDAP_SUCCESS ) {
928 "%s: line %d: group \"%s\": %s\n",
929 fname, lineno, right, text );
935 rc = slap_str2ad( SLAPD_GROUP_ATTR, &b->a_group_at, &text );
937 if ( rc != LDAP_SUCCESS ) {
939 "%s: line %d: group \"%s\": %s\n",
940 fname, lineno, SLAPD_GROUP_ATTR, text );
945 if ( !is_at_syntax( b->a_group_at->ad_type,
947 !is_at_syntax( b->a_group_at->ad_type,
948 SLAPD_NAMEUID_SYNTAX ) &&
949 !is_at_subtype( b->a_group_at->ad_type, slap_schema.si_ad_labeledURI->ad_type ) )
952 "%s: line %d: group \"%s\": inappropriate syntax: %s\n",
953 fname, lineno, right,
954 b->a_group_at->ad_type->sat_syntax_oid );
961 struct berval vals[2];
963 ber_str2bv( b->a_group_oc->soc_oid, 0, 0, &vals[0] );
964 BER_BVZERO( &vals[1] );
966 rc = oc_check_allowed( b->a_group_at->ad_type,
970 fprintf( stderr, "%s: line %d: "
971 "group: \"%s\" not allowed by \"%s\"\n",
973 b->a_group_at->ad_cname.bv_val,
974 b->a_group_oc->soc_oid );
981 if ( strcasecmp( left, "peername" ) == 0 ) {
983 case ACL_STYLE_REGEX:
985 /* legal, traditional */
986 case ACL_STYLE_EXPAND:
987 /* cheap replacement to regex for simple expansion */
990 /* legal, peername specific */
994 fprintf( stderr, "%s: line %d: "
995 "inappropriate style \"%s\" in by clause\n",
996 fname, lineno, style );
1000 if ( right == NULL || right[0] == '\0' ) {
1001 fprintf( stderr, "%s: line %d: "
1002 "missing \"=\" in (or value after) \"%s\" "
1004 fname, lineno, left );
1008 if ( BER_BVISEMPTY( &b->a_peername_pat ) ) {
1009 fprintf( stderr, "%s: line %d: "
1010 "peername pattern already specified.\n",
1015 b->a_peername_style = sty;
1016 if ( sty == ACL_STYLE_REGEX ) {
1017 acl_regex_normalized_dn( right, &bv );
1018 if ( !ber_bvccmp( &bv, '*' ) ) {
1019 regtest( fname, lineno, bv.bv_val );
1021 b->a_peername_pat = bv;
1024 ber_str2bv( right, 0, 1, &b->a_peername_pat );
1026 if ( sty == ACL_STYLE_IP ) {
1031 split( right, '{', &addr, &port );
1032 split( addr, '%', &addr, &mask );
1034 b->a_peername_addr = inet_addr( addr );
1035 if ( b->a_peername_addr == (unsigned long)(-1) ) {
1036 /* illegal address */
1037 fprintf( stderr, "%s: line %d: "
1038 "illegal peername address \"%s\".\n",
1039 fname, lineno, addr );
1043 b->a_peername_mask = (unsigned long)(-1);
1044 if ( mask != NULL ) {
1045 b->a_peername_mask = inet_addr( mask );
1046 if ( b->a_peername_mask ==
1047 (unsigned long)(-1) )
1050 fprintf( stderr, "%s: line %d: "
1051 "illegal peername address mask "
1053 fname, lineno, mask );
1058 b->a_peername_port = -1;
1062 b->a_peername_port = strtol( port, &end, 10 );
1063 if ( end[0] != '}' ) {
1065 fprintf( stderr, "%s: line %d: "
1066 "illegal peername port specification "
1068 fname, lineno, port );
1077 if ( strcasecmp( left, "sockname" ) == 0 ) {
1079 case ACL_STYLE_REGEX:
1080 case ACL_STYLE_BASE:
1081 /* legal, traditional */
1082 case ACL_STYLE_EXPAND:
1083 /* cheap replacement to regex for simple expansion */
1088 fprintf( stderr, "%s: line %d: "
1089 "inappropriate style \"%s\" in by clause\n",
1090 fname, lineno, style );
1094 if ( right == NULL || right[0] == '\0' ) {
1095 fprintf( stderr, "%s: line %d: "
1096 "missing \"=\" in (or value after) \"%s\" "
1098 fname, lineno, left );
1102 if ( !BER_BVISNULL( &b->a_sockname_pat ) ) {
1103 fprintf( stderr, "%s: line %d: "
1104 "sockname pattern already specified.\n",
1109 b->a_sockname_style = sty;
1110 if ( sty == ACL_STYLE_REGEX ) {
1111 acl_regex_normalized_dn( right, &bv );
1112 if ( !ber_bvccmp( &bv, '*' ) ) {
1113 regtest( fname, lineno, bv.bv_val );
1115 b->a_sockname_pat = bv;
1118 ber_str2bv( right, 0, 1, &b->a_sockname_pat );
1123 if ( strcasecmp( left, "domain" ) == 0 ) {
1125 case ACL_STYLE_REGEX:
1126 case ACL_STYLE_BASE:
1127 case ACL_STYLE_SUBTREE:
1128 /* legal, traditional */
1131 case ACL_STYLE_EXPAND:
1132 /* tolerated: means exact,expand */
1136 "\"expand\" modifier "
1137 "with \"expand\" style\n",
1140 sty = ACL_STYLE_BASE;
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' ) {
1153 fprintf( stderr, "%s: line %d: "
1154 "missing \"=\" in (or value after) \"%s\" "
1156 fname, lineno, left );
1160 if ( !BER_BVISEMPTY( &b->a_domain_pat ) ) {
1162 "%s: line %d: domain pattern already specified.\n",
1167 b->a_domain_style = sty;
1168 b->a_domain_expand = expand;
1169 if ( sty == ACL_STYLE_REGEX ) {
1170 acl_regex_normalized_dn( right, &bv );
1171 if ( !ber_bvccmp( &bv, '*' ) ) {
1172 regtest( fname, lineno, bv.bv_val );
1174 b->a_domain_pat = bv;
1177 ber_str2bv( right, 0, 1, &b->a_domain_pat );
1182 if ( strcasecmp( left, "sockurl" ) == 0 ) {
1184 case ACL_STYLE_REGEX:
1185 case ACL_STYLE_BASE:
1186 /* legal, traditional */
1187 case ACL_STYLE_EXPAND:
1188 /* cheap replacement to regex for simple expansion */
1193 fprintf( stderr, "%s: line %d: "
1194 "inappropriate style \"%s\" in by clause\n",
1195 fname, lineno, style );
1199 if ( right == NULL || right[0] == '\0' ) {
1200 fprintf( stderr, "%s: line %d: "
1201 "missing \"=\" in (or value after) \"%s\" "
1203 fname, lineno, left );
1207 if ( !BER_BVISEMPTY( &b->a_sockurl_pat ) ) {
1209 "%s: line %d: sockurl pattern already specified.\n",
1214 b->a_sockurl_style = sty;
1215 if ( sty == ACL_STYLE_REGEX ) {
1216 acl_regex_normalized_dn( right, &bv );
1217 if ( !ber_bvccmp( &bv, '*' ) ) {
1218 regtest( fname, lineno, bv.bv_val );
1220 b->a_sockurl_pat = bv;
1223 ber_str2bv( right, 0, 1, &b->a_sockurl_pat );
1228 if ( strcasecmp( left, "set" ) == 0 ) {
1231 case ACL_STYLE_REGEX:
1232 fprintf( stderr, "%s: line %d: "
1233 "deprecated set style "
1234 "\"regex\" in <by> clause; "
1235 "use \"expand\" instead\n",
1237 sty = ACL_STYLE_EXPAND;
1240 case ACL_STYLE_BASE:
1241 case ACL_STYLE_EXPAND:
1245 fprintf( stderr, "%s: line %d: "
1246 "inappropriate style \"%s\" in by clause\n",
1247 fname, lineno, style );
1251 if ( !BER_BVISEMPTY( &b->a_set_pat ) ) {
1253 "%s: line %d: set attribute already specified.\n",
1258 if ( right == NULL || *right == '\0' ) {
1260 "%s: line %d: no set is defined\n",
1265 b->a_set_style = sty;
1266 ber_str2bv( right, 0, 1, &b->a_set_pat );
1271 #ifdef SLAPD_ACI_ENABLED
1272 if ( strcasecmp( left, "aci" ) == 0 ) {
1273 if (sty != ACL_STYLE_REGEX && sty != ACL_STYLE_BASE) {
1274 fprintf( stderr, "%s: line %d: "
1275 "inappropriate style \"%s\" in by clause\n",
1276 fname, lineno, style );
1280 if( b->a_aci_at != NULL ) {
1282 "%s: line %d: aci attribute already specified.\n",
1287 if ( right != NULL && *right != '\0' ) {
1288 rc = slap_str2ad( right, &b->a_aci_at, &text );
1290 if( rc != LDAP_SUCCESS ) {
1292 "%s: line %d: aci \"%s\": %s\n",
1293 fname, lineno, right, text );
1298 b->a_aci_at = slap_schema.si_ad_aci;
1301 if( !is_at_syntax( b->a_aci_at->ad_type,
1304 fprintf( stderr, "%s: line %d: "
1305 "aci \"%s\": inappropriate syntax: %s\n",
1306 fname, lineno, right,
1307 b->a_aci_at->ad_type->sat_syntax_oid );
1313 #endif /* SLAPD_ACI_ENABLED */
1315 if ( strcasecmp( left, "ssf" ) == 0 ) {
1316 if ( sty != ACL_STYLE_REGEX && sty != ACL_STYLE_BASE ) {
1317 fprintf( stderr, "%s: line %d: "
1318 "inappropriate style \"%s\" in by clause\n",
1319 fname, lineno, style );
1323 if ( b->a_authz.sai_ssf ) {
1325 "%s: line %d: ssf attribute already specified.\n",
1330 if ( right == NULL || *right == '\0' ) {
1332 "%s: line %d: no ssf is defined\n",
1337 b->a_authz.sai_ssf = strtol( right, &next, 10 );
1338 if ( next == NULL || next[0] != '\0' ) {
1340 "%s: line %d: unable to parse ssf value (%s)\n",
1341 fname, lineno, right );
1345 if ( !b->a_authz.sai_ssf ) {
1347 "%s: line %d: invalid ssf value (%s)\n",
1348 fname, lineno, right );
1354 if ( strcasecmp( left, "transport_ssf" ) == 0 ) {
1355 if ( sty != ACL_STYLE_REGEX && sty != ACL_STYLE_BASE ) {
1356 fprintf( stderr, "%s: line %d: "
1357 "inappropriate style \"%s\" in by clause\n",
1358 fname, lineno, style );
1362 if ( b->a_authz.sai_transport_ssf ) {
1363 fprintf( stderr, "%s: line %d: "
1364 "transport_ssf attribute already specified.\n",
1369 if ( right == NULL || *right == '\0' ) {
1371 "%s: line %d: no transport_ssf is defined\n",
1376 b->a_authz.sai_transport_ssf = strtol( right, &next, 10 );
1377 if ( next == NULL || next[0] != '\0' ) {
1378 fprintf( stderr, "%s: line %d: "
1379 "unable to parse transport_ssf value (%s)\n",
1380 fname, lineno, right );
1384 if ( !b->a_authz.sai_transport_ssf ) {
1386 "%s: line %d: invalid transport_ssf value (%s)\n",
1387 fname, lineno, right );
1393 if ( strcasecmp( left, "tls_ssf" ) == 0 ) {
1394 if ( sty != ACL_STYLE_REGEX && sty != ACL_STYLE_BASE ) {
1395 fprintf( stderr, "%s: line %d: "
1396 "inappropriate style \"%s\" in by clause\n",
1397 fname, lineno, style );
1401 if ( b->a_authz.sai_tls_ssf ) {
1402 fprintf( stderr, "%s: line %d: "
1403 "tls_ssf attribute already specified.\n",
1408 if ( right == NULL || *right == '\0' ) {
1410 "%s: line %d: no tls_ssf is defined\n",
1415 b->a_authz.sai_tls_ssf = strtol( right, &next, 10 );
1416 if ( next == NULL || next[0] != '\0' ) {
1417 fprintf( stderr, "%s: line %d: "
1418 "unable to parse tls_ssf value (%s)\n",
1419 fname, lineno, right );
1423 if ( !b->a_authz.sai_tls_ssf ) {
1425 "%s: line %d: invalid tls_ssf value (%s)\n",
1426 fname, lineno, right );
1432 if ( strcasecmp( left, "sasl_ssf" ) == 0 ) {
1433 if ( sty != ACL_STYLE_REGEX && sty != ACL_STYLE_BASE ) {
1434 fprintf( stderr, "%s: line %d: "
1435 "inappropriate style \"%s\" in by clause\n",
1436 fname, lineno, style );
1440 if ( b->a_authz.sai_sasl_ssf ) {
1441 fprintf( stderr, "%s: line %d: "
1442 "sasl_ssf attribute already specified.\n",
1447 if ( right == NULL || *right == '\0' ) {
1449 "%s: line %d: no sasl_ssf is defined\n",
1454 b->a_authz.sai_sasl_ssf = strtol( right, &next, 10 );
1455 if ( next == NULL || next[0] != '\0' ) {
1456 fprintf( stderr, "%s: line %d: "
1457 "unable to parse sasl_ssf value (%s)\n",
1458 fname, lineno, right );
1462 if ( !b->a_authz.sai_sasl_ssf ) {
1464 "%s: line %d: invalid sasl_ssf value (%s)\n",
1465 fname, lineno, right );
1471 if ( right != NULL ) {
1478 if ( i == argc || ( strcasecmp( left, "stop" ) == 0 ) ) {
1479 /* out of arguments or plain stop */
1481 ACL_PRIV_ASSIGN( b->a_access_mask, ACL_PRIV_ADDITIVE );
1482 b->a_type = ACL_STOP;
1484 access_append( &a->acl_access, b );
1488 if ( strcasecmp( left, "continue" ) == 0 ) {
1489 /* plain continue */
1491 ACL_PRIV_ASSIGN( b->a_access_mask, ACL_PRIV_ADDITIVE );
1492 b->a_type = ACL_CONTINUE;
1494 access_append( &a->acl_access, b );
1498 if ( strcasecmp( left, "break" ) == 0 ) {
1499 /* plain continue */
1501 ACL_PRIV_ASSIGN(b->a_access_mask, ACL_PRIV_ADDITIVE);
1502 b->a_type = ACL_BREAK;
1504 access_append( &a->acl_access, b );
1508 if ( strcasecmp( left, "by" ) == 0 ) {
1509 /* we've gone too far */
1511 ACL_PRIV_ASSIGN( b->a_access_mask, ACL_PRIV_ADDITIVE );
1512 b->a_type = ACL_STOP;
1514 access_append( &a->acl_access, b );
1519 if ( strncasecmp( left, "self", 4 ) == 0 ) {
1521 ACL_PRIV_ASSIGN( b->a_access_mask, str2accessmask( &left[4] ) );
1524 ACL_PRIV_ASSIGN( b->a_access_mask, str2accessmask( left ) );
1527 if ( ACL_IS_INVALID( b->a_access_mask ) ) {
1529 "%s: line %d: expecting <access> got \"%s\"\n",
1530 fname, lineno, left );
1534 b->a_type = ACL_STOP;
1536 if ( ++i == argc ) {
1537 /* out of arguments or plain stop */
1538 access_append( &a->acl_access, b );
1542 if ( strcasecmp( argv[i], "continue" ) == 0 ) {
1543 /* plain continue */
1544 b->a_type = ACL_CONTINUE;
1546 } else if ( strcasecmp( argv[i], "break" ) == 0 ) {
1547 /* plain continue */
1548 b->a_type = ACL_BREAK;
1550 } else if ( strcasecmp( argv[i], "stop" ) != 0 ) {
1555 access_append( &a->acl_access, b );
1559 "%s: line %d: expecting \"to\" "
1560 "or \"by\" got \"%s\"\n",
1561 fname, lineno, argv[i] );
1566 /* if we have no real access clause, complain and do nothing */
1568 fprintf( stderr, "%s: line %d: "
1569 "warning: no access clause(s) specified in access line\n",
1574 if ( ldap_debug & LDAP_DEBUG_ACL ) {
1579 if ( a->acl_access == NULL ) {
1580 fprintf( stderr, "%s: line %d: "
1581 "warning: no by clause(s) specified in access line\n",
1587 switch ( check_scope( be, a ) ) {
1588 case ACL_SCOPE_UNKNOWN:
1589 fprintf( stderr, "%s: line %d: warning: "
1590 "cannot assess the validity of the ACL scope within "
1591 "backend naming context\n",
1595 case ACL_SCOPE_WARN:
1596 fprintf( stderr, "%s: line %d: warning: "
1597 "ACL could be out of scope within backend naming context\n",
1601 case ACL_SCOPE_PARTIAL:
1602 fprintf( stderr, "%s: line %d: warning: "
1603 "ACL appears to be partially out of scope within "
1604 "backend naming context\n",
1609 fprintf( stderr, "%s: line %d: warning: "
1610 "ACL appears to be out of scope within "
1611 "backend naming context\n",
1618 #endif /* LDAP_DEVEL */
1619 acl_append( &be->be_acl, a );
1622 acl_append( &frontendDB->be_acl, a );
1628 accessmask2str( slap_mask_t mask, char *buf )
1633 assert( buf != NULL );
1635 if ( ACL_IS_INVALID( mask ) ) {
1641 if ( ACL_IS_LEVEL( mask ) ) {
1642 if ( ACL_LVL_IS_NONE(mask) ) {
1643 ptr = lutil_strcopy( ptr, "none" );
1645 } else if ( ACL_LVL_IS_AUTH(mask) ) {
1646 ptr = lutil_strcopy( ptr, "auth" );
1648 } else if ( ACL_LVL_IS_COMPARE(mask) ) {
1649 ptr = lutil_strcopy( ptr, "compare" );
1651 } else if ( ACL_LVL_IS_SEARCH(mask) ) {
1652 ptr = lutil_strcopy( ptr, "search" );
1654 } else if ( ACL_LVL_IS_READ(mask) ) {
1655 ptr = lutil_strcopy( ptr, "read" );
1657 } else if ( ACL_LVL_IS_WRITE(mask) ) {
1658 ptr = lutil_strcopy( ptr, "write" );
1660 ptr = lutil_strcopy( ptr, "unknown" );
1666 if( ACL_IS_ADDITIVE( mask ) ) {
1669 } else if( ACL_IS_SUBTRACTIVE( mask ) ) {
1676 if ( ACL_PRIV_ISSET(mask, ACL_PRIV_WRITE) ) {
1681 if ( ACL_PRIV_ISSET(mask, ACL_PRIV_READ) ) {
1686 if ( ACL_PRIV_ISSET(mask, ACL_PRIV_SEARCH) ) {
1691 if ( ACL_PRIV_ISSET(mask, ACL_PRIV_COMPARE) ) {
1696 if ( ACL_PRIV_ISSET(mask, ACL_PRIV_AUTH) ) {
1701 if ( none && ACL_PRIV_ISSET(mask, ACL_PRIV_NONE) ) {
1710 if ( ACL_IS_LEVEL( mask ) ) {
1720 str2accessmask( const char *str )
1724 if( !ASCII_ALPHA(str[0]) ) {
1727 if ( str[0] == '=' ) {
1730 } else if( str[0] == '+' ) {
1731 ACL_PRIV_ASSIGN(mask, ACL_PRIV_ADDITIVE);
1733 } else if( str[0] == '-' ) {
1734 ACL_PRIV_ASSIGN(mask, ACL_PRIV_SUBSTRACTIVE);
1737 ACL_INVALIDATE(mask);
1741 for( i=1; str[i] != '\0'; i++ ) {
1742 if( TOLOWER((unsigned char) str[i]) == 'w' ) {
1743 ACL_PRIV_SET(mask, ACL_PRIV_WRITE);
1745 } else if( TOLOWER((unsigned char) str[i]) == 'r' ) {
1746 ACL_PRIV_SET(mask, ACL_PRIV_READ);
1748 } else if( TOLOWER((unsigned char) str[i]) == 's' ) {
1749 ACL_PRIV_SET(mask, ACL_PRIV_SEARCH);
1751 } else if( TOLOWER((unsigned char) str[i]) == 'c' ) {
1752 ACL_PRIV_SET(mask, ACL_PRIV_COMPARE);
1754 } else if( TOLOWER((unsigned char) str[i]) == 'x' ) {
1755 ACL_PRIV_SET(mask, ACL_PRIV_AUTH);
1757 } else if( str[i] != '0' ) {
1758 ACL_INVALIDATE(mask);
1766 if ( strcasecmp( str, "none" ) == 0 ) {
1767 ACL_LVL_ASSIGN_NONE(mask);
1769 } else if ( strcasecmp( str, "auth" ) == 0 ) {
1770 ACL_LVL_ASSIGN_AUTH(mask);
1772 } else if ( strcasecmp( str, "compare" ) == 0 ) {
1773 ACL_LVL_ASSIGN_COMPARE(mask);
1775 } else if ( strcasecmp( str, "search" ) == 0 ) {
1776 ACL_LVL_ASSIGN_SEARCH(mask);
1778 } else if ( strcasecmp( str, "read" ) == 0 ) {
1779 ACL_LVL_ASSIGN_READ(mask);
1781 } else if ( strcasecmp( str, "write" ) == 0 ) {
1782 ACL_LVL_ASSIGN_WRITE(mask);
1785 ACL_INVALIDATE( mask );
1794 fprintf( stderr, "%s%s%s\n",
1795 "<access clause> ::= access to <what> "
1796 "[ by <who> <access> [ <control> ] ]+ \n"
1797 "<what> ::= * | [dn[.<dnstyle>]=<DN>] [filter=<filter>] [attrs=<attrlist>]\n"
1798 "<attrlist> ::= <attr> [val[.<style>]=<value>] | <attr> , <attrlist>\n"
1799 "<attr> ::= <attrname> | entry | children\n",
1800 "<who> ::= [ * | anonymous | users | self | creator | dn[.<dnstyle>]=<DN> ]\n"
1801 "\t[dnattr=<attrname>]\n"
1802 "\t[group[/<objectclass>[/<attrname>]][.<style>]=<group>]\n"
1803 "\t[peername[.<peernamestyle>]=<peer>] [sockname[.<style>]=<name>]\n"
1804 "\t[domain[.<domainstyle>]=<domain>] [sockurl[.<style>]=<url>]\n"
1805 #ifdef SLAPD_ACI_ENABLED
1806 "\t[aci=<attrname>]\n"
1808 "\t[ssf=<n>] [transport_ssf=<n>] [tls_ssf=<n>] [sasl_ssf=<n>]\n",
1809 "<dnstyle> ::= base(Object) | one(level) | sub(tree) | children | "
1811 "<style> ::= exact | regex | base(Object)\n"
1812 "<peernamestyle> ::= exact | regex | ip | path\n"
1813 "<domainstyle> ::= exact | regex | base(Object) | sub(tree)\n"
1814 "<access> ::= [self]{<level>|<priv>}\n"
1815 "<level> ::= none | auth | compare | search | read | write\n"
1816 "<priv> ::= {=|+|-}{w|r|s|c|x|0}+\n"
1817 "<control> ::= [ stop | continue | break ]\n"
1819 exit( EXIT_FAILURE );
1823 * Set pattern to a "normalized" DN from src.
1824 * At present it simply eats the (optional) space after
1825 * a RDN separator (,)
1826 * Eventually will evolve in a more complete normalization
1829 acl_regex_normalized_dn(
1831 struct berval *pattern )
1836 str = ch_strdup( src );
1837 len = strlen( src );
1839 for ( p = str; p && p[0]; p++ ) {
1841 if ( p[0] == '\\' && p[1] ) {
1843 * if escaping a hex pair we should
1844 * increment p twice; however, in that
1845 * case the second hex number does
1851 if ( p[0] == ',' && p[1] == ' ' ) {
1855 * too much space should be an error if we are pedantic
1857 for ( q = &p[2]; q[0] == ' '; q++ ) {
1860 AC_MEMCPY( p+1, q, len-(q-str)+1);
1863 pattern->bv_val = str;
1864 pattern->bv_len = p - str;
1877 if ( (*right = strchr( line, splitchar )) != NULL ) {
1878 *((*right)++) = '\0';
1883 access_append( Access **l, Access *a )
1885 for ( ; *l != NULL; l = &(*l)->a_next ) {
1893 acl_append( AccessControl **l, AccessControl *a )
1895 for ( ; *l != NULL; l = &(*l)->acl_next ) {
1903 access_free( Access *a )
1905 if ( !BER_BVISNULL( &a->a_dn_pat ) ) {
1906 free( a->a_dn_pat.bv_val );
1908 if ( !BER_BVISNULL( &a->a_peername_pat ) ) {
1909 free( a->a_peername_pat.bv_val );
1911 if ( !BER_BVISNULL( &a->a_sockname_pat ) ) {
1912 free( a->a_sockname_pat.bv_val );
1914 if ( !BER_BVISNULL( &a->a_domain_pat ) ) {
1915 free( a->a_domain_pat.bv_val );
1917 if ( !BER_BVISNULL( &a->a_sockurl_pat ) ) {
1918 free( a->a_sockurl_pat.bv_val );
1920 if ( !BER_BVISNULL( &a->a_set_pat ) ) {
1921 free( a->a_set_pat.bv_val );
1923 if ( !BER_BVISNULL( &a->a_group_pat ) ) {
1924 free( a->a_group_pat.bv_val );
1930 acl_free( AccessControl *a )
1935 if ( a->acl_filter ) {
1936 filter_free( a->acl_filter );
1938 if ( !BER_BVISNULL( &a->acl_dn_pat ) ) {
1939 free ( a->acl_dn_pat.bv_val );
1941 if ( a->acl_attrs ) {
1942 for ( an = a->acl_attrs; !BER_BVISNULL( &an->an_name ); an++ ) {
1943 free( an->an_name.bv_val );
1945 free( a->acl_attrs );
1947 for ( ; a->acl_access; a->acl_access = n ) {
1948 n = a->acl_access->a_next;
1949 access_free( a->acl_access );
1954 /* Because backend_startup uses acl_append to tack on the global_acl to
1955 * the end of each backend's acl, we cannot just take one argument and
1956 * merrily free our way to the end of the list. backend_destroy calls us
1957 * with the be_acl in arg1, and global_acl in arg2 to give us a stopping
1958 * point. config_destroy calls us with global_acl in arg1 and NULL in
1959 * arg2, so we then proceed to polish off the global_acl.
1962 acl_destroy( AccessControl *a, AccessControl *end )
1966 for (; a && a!= end; a=n) {
1973 access2str( slap_access_t access )
1975 if ( access == ACL_NONE ) {
1978 } else if ( access == ACL_AUTH ) {
1981 } else if ( access == ACL_COMPARE ) {
1984 } else if ( access == ACL_SEARCH ) {
1987 } else if ( access == ACL_READ ) {
1990 } else if ( access == ACL_WRITE ) {
1998 str2access( const char *str )
2000 if ( strcasecmp( str, "none" ) == 0 ) {
2003 } else if ( strcasecmp( str, "auth" ) == 0 ) {
2006 } else if ( strcasecmp( str, "compare" ) == 0 ) {
2009 } else if ( strcasecmp( str, "search" ) == 0 ) {
2012 } else if ( strcasecmp( str, "read" ) == 0 ) {
2015 } else if ( strcasecmp( str, "write" ) == 0 ) {
2019 return( ACL_INVALID_ACCESS );
2025 print_access( Access *b )
2027 char maskbuf[ACCESSMASK_MAXLEN];
2029 fprintf( stderr, "\tby" );
2031 if ( !BER_BVISEMPTY( &b->a_dn_pat ) ) {
2032 if ( ber_bvccmp( &b->a_dn_pat, '*' ) ||
2033 b->a_dn_style == ACL_STYLE_ANONYMOUS /* strcmp( b->a_dn_pat.bv_val, "anonymous" ) == 0 */ ||
2034 b->a_dn_style == ACL_STYLE_USERS /* strcmp( b->a_dn_pat.bv_val, "users" ) == 0 */ ||
2035 b->a_dn_style == ACL_STYLE_SELF /* strcmp( b->a_dn_pat.bv_val, "self" ) == 0 */ ||
2036 b->a_dn_style == ACL_STYLE_CREATOR /* strcmp( b->a_dn_pat.bv_val, "creator" ) == 0 */ )
2038 fprintf( stderr, " %s", b->a_dn_pat.bv_val );
2041 fprintf( stderr, " dn.%s=\"%s\"",
2042 style_strings[b->a_dn_style], b->a_dn_pat.bv_val );
2046 if ( b->a_dn_at != NULL ) {
2047 fprintf( stderr, " dnattr=%s", b->a_dn_at->ad_cname.bv_val );
2050 if ( !BER_BVISEMPTY( &b->a_group_pat ) ) {
2051 fprintf( stderr, " group/%s/%s.%s=\"%s\"",
2052 b->a_group_oc ? b->a_group_oc->soc_cname.bv_val : "groupOfNames",
2053 b->a_group_at ? b->a_group_at->ad_cname.bv_val : "member",
2054 style_strings[b->a_group_style],
2055 b->a_group_pat.bv_val );
2058 if ( !BER_BVISEMPTY( &b->a_peername_pat ) ) {
2059 fprintf( stderr, " peername=\"%s\"", b->a_peername_pat.bv_val );
2062 if ( !BER_BVISEMPTY( &b->a_sockname_pat ) ) {
2063 fprintf( stderr, " sockname=\"%s\"", b->a_sockname_pat.bv_val );
2066 if ( !BER_BVISEMPTY( &b->a_domain_pat ) ) {
2067 fprintf( stderr, " domain=%s", b->a_domain_pat.bv_val );
2070 if ( !BER_BVISEMPTY( &b->a_sockurl_pat ) ) {
2071 fprintf( stderr, " sockurl=\"%s\"", b->a_sockurl_pat.bv_val );
2074 if ( !BER_BVISEMPTY( &b->a_set_pat ) ) {
2075 fprintf( stderr, " set=\"%s\"", b->a_set_pat.bv_val );
2078 #ifdef SLAPD_ACI_ENABLED
2079 if ( b->a_aci_at != NULL ) {
2080 fprintf( stderr, " aci=%s", b->a_aci_at->ad_cname.bv_val );
2084 /* Security Strength Factors */
2085 if ( b->a_authz.sai_ssf ) {
2086 fprintf( stderr, " ssf=%u",
2087 b->a_authz.sai_ssf );
2089 if ( b->a_authz.sai_transport_ssf ) {
2090 fprintf( stderr, " transport_ssf=%u",
2091 b->a_authz.sai_transport_ssf );
2093 if ( b->a_authz.sai_tls_ssf ) {
2094 fprintf( stderr, " tls_ssf=%u",
2095 b->a_authz.sai_tls_ssf );
2097 if ( b->a_authz.sai_sasl_ssf ) {
2098 fprintf( stderr, " sasl_ssf=%u",
2099 b->a_authz.sai_sasl_ssf );
2102 fprintf( stderr, " %s%s",
2103 b->a_dn_self ? "self" : "",
2104 accessmask2str( b->a_access_mask, maskbuf ) );
2106 if( b->a_type == ACL_BREAK ) {
2107 fprintf( stderr, " break" );
2109 } else if( b->a_type == ACL_CONTINUE ) {
2110 fprintf( stderr, " continue" );
2112 } else if( b->a_type != ACL_STOP ) {
2113 fprintf( stderr, " unknown-control" );
2116 fprintf( stderr, "\n" );
2121 print_acl( Backend *be, AccessControl *a )
2126 fprintf( stderr, "%s ACL: access to",
2127 be == NULL ? "Global" : "Backend" );
2129 if ( !BER_BVISEMPTY( &a->acl_dn_pat ) ) {
2131 fprintf( stderr, " dn.%s=\"%s\"\n",
2132 style_strings[a->acl_dn_style], a->acl_dn_pat.bv_val );
2135 if ( a->acl_filter != NULL ) {
2136 struct berval bv = BER_BVNULL;
2139 filter2bv( a->acl_filter, &bv );
2140 fprintf( stderr, " filter=%s\n", bv.bv_val );
2141 ch_free( bv.bv_val );
2144 if ( a->acl_attrs != NULL ) {
2149 fprintf( stderr, " attrs=" );
2150 for ( an = a->acl_attrs; an && !BER_BVISNULL( &an->an_name ); an++ ) {
2151 if ( ! first ) fprintf( stderr, "," );
2153 fputc( an->an_oc_exclude ? '!' : '@', stderr);
2155 fputs( an->an_name.bv_val, stderr );
2158 fprintf( stderr, "\n" );
2161 if ( !BER_BVISEMPTY( &a->acl_attrval ) ) {
2163 fprintf( stderr, " val.%s=\"%s\"\n",
2164 style_strings[a->acl_attrval_style], a->acl_attrval.bv_val );
2168 if( !to ) fprintf( stderr, " *\n" );
2170 for ( b = a->acl_access; b != NULL; b = b->a_next ) {
2174 fprintf( stderr, "\n" );
2176 #endif /* LDAP_DEBUG */