]> git.sur5r.net Git - openldap/blob - servers/slapd/aclparse.c
ACI attributes should be of ACI syntax. Need to assign
[openldap] / servers / slapd / aclparse.c
1 /* acl.c - routines to parse and check acl's */
2 /* $OpenLDAP$ */
3 /*
4  * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved.
5  * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
6  */
7
8 #include "portable.h"
9
10 #include <stdio.h>
11
12 #include <ac/ctype.h>
13 #include <ac/regex.h>
14 #include <ac/socket.h>
15 #include <ac/string.h>
16 #include <ac/unistd.h>
17
18 #include "slap.h"
19
20 static void             split(char *line, int splitchar, char **left, char **right);
21 static void             access_append(Access **l, Access *a);
22 static void             acl_usage(void) LDAP_GCCATTR((noreturn));
23
24 #ifdef LDAP_DEBUG
25 static void             print_acl(Backend *be, AccessControl *a);
26 static void             print_access(Access *b);
27 #endif
28
29 static int
30 regtest(const char *fname, int lineno, char *pat) {
31         int e;
32         regex_t re;
33
34         char buf[512];
35         unsigned size;
36
37         char *sp;
38         char *dp;
39         int  flag;
40
41         sp = pat;
42         dp = buf;
43         size = 0;
44         buf[0] = '\0';
45
46         for (size = 0, flag = 0; (size < sizeof(buf)) && *sp; sp++) {
47                 if (flag) {
48                         if (*sp == '$'|| (*sp >= '0' && *sp <= '9')) {
49                                 *dp++ = *sp;
50                                 size++;
51                         }
52                         flag = 0;
53
54                 } else {
55                         if (*sp == '$') {
56                                 flag = 1;
57                         } else {
58                                 *dp++ = *sp;
59                                 size++;
60                         }
61                 }
62         }
63
64         *dp = '\0';
65         if ( size >= (sizeof(buf)-1) ) {
66                 fprintf( stderr,
67                         "%s: line %d: regular expression \"%s\" too large\n",
68                         fname, lineno, pat );
69                 acl_usage();
70         }
71
72         if ((e = regcomp(&re, buf, REG_EXTENDED|REG_ICASE))) {
73                 char error[512];
74                 regerror(e, &re, error, sizeof(error));
75                 fprintf( stderr,
76                         "%s: line %d: regular expression \"%s\" bad because of %s\n",
77                         fname, lineno, pat, error );
78                 acl_usage();
79                 return(0);
80         }
81         regfree(&re);
82         return(1);
83 }
84
85 void
86 parse_acl(
87     Backend     *be,
88     const char  *fname,
89     int         lineno,
90     int         argc,
91     char        **argv
92 )
93 {
94         int             i;
95         char            *left, *right;
96         AccessControl   *a;
97         Access  *b;
98
99         a = NULL;
100         for ( i = 1; i < argc; i++ ) {
101                 /* to clause - select which entries are protected */
102                 if ( strcasecmp( argv[i], "to" ) == 0 ) {
103                         if ( a != NULL ) {
104                                 fprintf( stderr,
105                 "%s: line %d: only one to clause allowed in access line\n",
106                                     fname, lineno );
107                                 acl_usage();
108                         }
109                         a = (AccessControl *) ch_calloc( 1, sizeof(AccessControl) );
110                         a->acl_filter = NULL;
111                         a->acl_dn_pat = NULL;
112                         a->acl_attrs  = NULL;
113                         a->acl_access = NULL;
114                         a->acl_next   = NULL;
115                         for ( ++i; i < argc; i++ ) {
116                                 if ( strcasecmp( argv[i], "by" ) == 0 ) {
117                                         i--;
118                                         break;
119                                 }
120
121                                 if ( strcasecmp( argv[i], "*" ) == 0 ) {
122                                         if( a->acl_dn_pat != NULL ) {
123                                                 fprintf( stderr,
124                                                         "%s: line %d: dn pattern"
125                                                         " already specified in to clause.\n",
126                                                         fname, lineno );
127                                                 acl_usage();
128                                         }
129
130                                         a->acl_dn_pat = ch_strdup( "*" );
131                                         continue;
132                                 }
133
134                                 split( argv[i], '=', &left, &right );
135
136                                 if ( strcasecmp( left, "dn" ) == 0 ) {
137                                         if( a->acl_dn_pat != NULL ) {
138                                                 fprintf( stderr,
139                                                         "%s: line %d: dn pattern"
140                                                         " already specified in to clause.\n",
141                                                         fname, lineno );
142                                                 acl_usage();
143                                         }
144
145                                         if ( right == NULL ) {
146                                                 fprintf( stderr,
147         "%s: line %d: missing \"=\" in \"%s\" in to clause\n",
148                                                     fname, lineno, left );
149                                                 acl_usage();
150                                         }
151
152                                         if( *right == '\0' ) {
153                                                 a->acl_dn_pat = ch_strdup("^$");
154
155                                         } else if ( strcmp(right, "*") == 0 
156                                                 || strcmp(right, ".*") == 0 
157                                                 || strcmp(right, ".*$") == 0 
158                                                 || strcmp(right, "^.*") == 0 
159                                                 || strcmp(right, "^.*$$") == 0
160                                                 || strcmp(right, ".*$$") == 0 
161                                                 || strcmp(right, "^.*$$") == 0 )
162                                         {
163                                                 a->acl_dn_pat = ch_strdup( "*" );
164
165                                         } else {
166                                                 a->acl_dn_pat = ch_strdup( right );
167                                         }
168
169                                         continue;
170                                 }
171
172                                 if ( right == NULL || *right == '\0' ) {
173                                         fprintf( stderr,
174         "%s: line %d: missing \"=\" in (or value after) \"%s\" in to clause\n",
175                                             fname, lineno, left );
176                                         acl_usage();
177                                 }
178
179                                 if ( strcasecmp( left, "filter" ) == 0 ) {
180                                         if ( (a->acl_filter = str2filter(
181                                             right )) == NULL ) {
182                                                 fprintf( stderr,
183                                 "%s: line %d: bad filter \"%s\" in to clause\n",
184                                                     fname, lineno, right );
185                                                 acl_usage();
186                                         }
187
188                                 } else if ( strncasecmp( left, "attr", 4 ) == 0 ) {
189                                         char    **alist;
190
191                                         alist = str2charray( right, "," );
192                                         charray_merge( &a->acl_attrs, alist );
193                                         charray_free( alist );
194
195                                 } else {
196                                         fprintf( stderr,
197                                                 "%s: line %d: expecting <what> got \"%s\"\n",
198                                             fname, lineno, left );
199                                         acl_usage();
200                                 }
201                         }
202
203                         if ( a->acl_dn_pat != NULL && strcmp(a->acl_dn_pat, "*") == 0) {
204                                 free( a->acl_dn_pat );
205                                 a->acl_dn_pat = NULL;
206                         }
207                         
208                         if( a->acl_dn_pat != NULL ) {
209                                 int e = regcomp( &a->acl_dn_re, a->acl_dn_pat,
210                                                  REG_EXTENDED | REG_ICASE );
211                                 if ( e ) {
212                                         char buf[512];
213                                         regerror( e, &a->acl_dn_re, buf, sizeof(buf) );
214                                         fprintf( stderr,
215                                 "%s: line %d: regular expression \"%s\" bad because of %s\n",
216                                                  fname, lineno, right, buf );
217                                         acl_usage();
218                                 }
219                         }
220
221                 /* by clause - select who has what access to entries */
222                 } else if ( strcasecmp( argv[i], "by" ) == 0 ) {
223                         if ( a == NULL ) {
224                                 fprintf( stderr,
225                                         "%s: line %d: to clause required before by clause in access line\n",
226                                     fname, lineno );
227                                 acl_usage();
228                         }
229
230                         /*
231                          * by clause consists of <who> and <access>
232                          */
233
234                         b = (Access *) ch_calloc( 1, sizeof(Access) );
235
236                         ACL_INVALIDATE( b->a_mask );
237
238                         if ( ++i == argc ) {
239                                 fprintf( stderr,
240                             "%s: line %d: premature eol: expecting <who>\n",
241                                     fname, lineno );
242                                 acl_usage();
243                         }
244
245                         /* get <who> */
246                         for ( ; i < argc; i++ ) {
247                                 char *pat;
248                                 split( argv[i], '=', &left, &right );
249
250                                 if ( strcasecmp( argv[i], "*" ) == 0 ) {
251                                         pat = ch_strdup( "*" );
252
253                                 } else if ( strcasecmp( argv[i], "anonymous" ) == 0 ) {
254                                         pat = ch_strdup( "anonymous" );
255
256                                 } else if ( strcasecmp( argv[i], "self" ) == 0 ) {
257                                         pat = ch_strdup( "self" );
258
259                                 } else if ( strcasecmp( argv[i], "users" ) == 0 ) {
260                                         pat = ch_strdup( "users" );
261
262                                 } else if ( strcasecmp( left, "dn" ) == 0 ) {
263                                         if( right == NULL ) {
264                                                 /* no '=' */
265                                                 pat = ch_strdup( "users" );
266
267                                         } else if (*right == '\0' ) {
268                                                 /* dn="" */
269                                                 pat = ch_strdup( "anonymous" );
270
271                                         } else if ( strcmp( right, "*" ) == 0 ) {
272                                                 /* dn=* /
273                                                 /* any or users?  any for now */
274                                                 pat = ch_strdup( "users" );
275
276                                         } else if ( strcmp( right, ".+" ) == 0
277                                                 || strcmp( right, "^.+" ) == 0
278                                                 || strcmp( right, ".+$" ) == 0
279                                                 || strcmp( right, "^.+$" ) == 0
280                                                 || strcmp( right, ".+$$" ) == 0
281                                                 || strcmp( right, "^.+$$" ) == 0 )
282                                         {
283                                                 pat = ch_strdup( "users" );
284
285                                         } else if ( strcmp( right, ".*" ) == 0
286                                                 || strcmp( right, "^.*" ) == 0
287                                                 || strcmp( right, ".*$" ) == 0
288                                                 || strcmp( right, "^.*$" ) == 0
289                                                 || strcmp( right, ".*$$" ) == 0
290                                                 || strcmp( right, "^.*$$" ) == 0 )
291                                         {
292                                                 pat = ch_strdup( "*" );
293
294                                         } else {
295                                                 regtest(fname, lineno, right);
296                                                 pat = ch_strdup( right );
297                                         }
298
299                                 } else {
300                                         pat = NULL;
301                                 }
302
303                                 if( pat != NULL ) {
304                                         if( b->a_dn_pat != NULL ) {
305                                                 fprintf( stderr,
306                                                     "%s: line %d: dn pattern already specified.\n",
307                                                     fname, lineno );
308                                                 acl_usage();
309                                         }
310
311                                         b->a_dn_pat = pat;
312                                         continue;
313                                 }
314
315                                 if ( strcasecmp( left, "dnattr" ) == 0 ) {
316                                         if( b->a_dn_pat != NULL ) {
317                                                 fprintf( stderr,
318                                                         "%s: line %d: dnattr already specified.\n",
319                                                         fname, lineno );
320                                                 acl_usage();
321                                         }
322
323 #ifdef SLAPD_SCHEMA_NOT_COMPAT
324                                         b->a_dn_at = at_find( right );
325
326                                         if( b->a_dn_at == NULL ) {
327                                                 fprintf( stderr,
328                                                         "%s: line %d: dnattr attribute type undefined.\n",
329                                                         fname, lineno );
330                                                 acl_usage();
331                                         }
332
333 #ifdef SLAPD_OID_DN_SYNTAX
334                                         if( strcmp( b->a_dn_at->sat_syntax_oid,
335                                                 SLAPD_OID_DN_SYNTAX ) != 0 )
336                                         {
337                                                 fprintf( stderr,
338                                                         "%s: line %d: dnattr attribute type not of DN syntax.\n",
339                                                         fname, lineno );
340                                                 acl_usage();
341                                         }
342 #endif
343 #else
344                                         b->a_dn_at = ch_strdup( right );
345 #endif
346                                         continue;
347                                 }
348
349                                 if ( strncasecmp( left, "group", sizeof("group")-1 ) == 0 ) {
350                                         char *name = NULL;
351                                         char *value = NULL;
352
353                                         if( b->a_group_pat != NULL ) {
354                                                 fprintf( stderr,
355                                                         "%s: line %d: group pattern already specified.\n",
356                                                         fname, lineno );
357                                                 acl_usage();
358                                         }
359
360                                         /* format of string is "group/objectClassValue/groupAttrName" */
361                                         if ((value = strchr(left, '/')) != NULL) {
362                                                 *value++ = '\0';
363                                                 if (*value
364                                                         && (name = strchr(value, '/')) != NULL)
365                                                 {
366                                                         *name++ = '\0';
367                                                 }
368                                         }
369
370                                         regtest(fname, lineno, right);
371                                         b->a_group_pat = ch_strdup( right );
372
373                                         if (value && *value) {
374                                                 b->a_group_oc = ch_strdup(value);
375                                                 *--value = '/';
376                                         } else {
377                                                 b->a_group_oc = ch_strdup("groupOfNames");
378                                         }
379
380                                         if (name && *name) {
381 #ifdef SLAPD_SCHEMA_NOT_COMPAT
382                                                 b->a_group_at = at_find( name );
383 #else
384                                                 b->a_group_at = ch_strdup(name);
385 #endif
386                                                 *--name = '/';
387
388                                         } else {
389 #ifdef SLAPD_SCHEMA_NOT_COMPAT
390                                                 b->a_group_at = at_find("member");
391 #else
392                                                 b->a_group_at = ch_strdup("member");
393 #endif
394                                         }
395
396 #ifdef SLAPD_SCHEMA_NOT_COMPAT
397                                         if( b->a_group_at == NULL ) {
398                                                 fprintf( stderr,
399                                                         "%s: line %d: group attribute type undefined.\n",
400                                                         fname, lineno );
401                                                 acl_usage();
402                                         }
403
404 #ifdef SLAPD_OID_DN_SYNTAX
405                                         if( strcmp( b->a_group_at->sat_syntax_oid,
406                                                 SLAPD_OID_DN_SYNTAX ) != 0 )
407                                         {
408                                                 fprintf( stderr,
409                                                         "%s: line %d: group attribute type not of DN syntax.\n",
410                                                         fname, lineno );
411                                                 acl_usage();
412                                         }
413 #endif /* SLAPD_OID_DN_SYNTAX */
414 #endif /* SLAPD_SCHEMA_NOT_COMPAT */
415                                         continue;
416                                 }
417
418                                 if ( strcasecmp( left, "peername" ) == 0 ) {
419                                         if( b->a_peername_pat != NULL ) {
420                                                 fprintf( stderr,
421                                                         "%s: line %d: peername pattern already specified.\n",
422                                                         fname, lineno );
423                                                 acl_usage();
424                                         }
425
426                                         regtest(fname, lineno, right);
427                                         b->a_peername_pat = ch_strdup( right );
428                                         continue;
429                                 }
430
431                                 if ( strcasecmp( left, "sockname" ) == 0 ) {
432                                         if( b->a_sockname_pat != NULL ) {
433                                                 fprintf( stderr,
434                                                         "%s: line %d: sockname pattern already specified.\n",
435                                                         fname, lineno );
436                                                 acl_usage();
437                                         }
438
439                                         regtest(fname, lineno, right);
440                                         b->a_sockname_pat = ch_strdup( right );
441                                         continue;
442                                 }
443
444                                 if ( strcasecmp( left, "domain" ) == 0 ) {
445                                         if( b->a_domain_pat != NULL ) {
446                                                 fprintf( stderr,
447                                                         "%s: line %d: domain pattern already specified.\n",
448                                                         fname, lineno );
449                                                 acl_usage();
450                                         }
451
452                                         regtest(fname, lineno, right);
453                                         b->a_domain_pat = ch_strdup( right );
454                                         continue;
455                                 }
456
457                                 if ( strcasecmp( left, "sockurl" ) == 0 ) {
458                                         if( b->a_sockurl_pat != NULL ) {
459                                                 fprintf( stderr,
460                                                         "%s: line %d: sockurl pattern already specified.\n",
461                                                         fname, lineno );
462                                                 acl_usage();
463                                         }
464
465                                         regtest(fname, lineno, right);
466                                         b->a_sockurl_pat = ch_strdup( right );
467                                         continue;
468                                 }
469
470 #ifdef SLAPD_ACI_ENABLED
471                                 if ( strcasecmp( left, "aci" ) == 0 ) {
472                                         if( b->a_aci_at != NULL ) {
473                                                 fprintf( stderr,
474                                                         "%s: line %d: aci attribute already specified.\n",
475                                                         fname, lineno );
476                                                 acl_usage();
477                                         }
478
479 #ifdef SLAPD_SCHEMA_NOT_COMPAT
480                                         if ( right != NULL && *right != '\0' ) {
481                                                 b->a_aci_at = at_find( right );
482                                         } else {
483                                                 b->a_aci_at = at_find( SLAPD_ACI_DEFAULT_ATTR );
484                                         }
485
486                                         if( b->a_aci_at == NULL ) {
487                                                 fprintf( stderr,
488                                                         "%s: line %d: aci attribute type undefined.\n",
489                                                         fname, lineno );
490                                                 acl_usage();
491                                         }
492
493                                         if( strcmp( b->a_aci_at->sat_syntax_oid,
494                                                 SLAPD_OID_ACI_SYNTAX ) != 0 )
495                                         {
496                                                 fprintf( stderr,
497                                                         "%s: line %d: aci attribute type not of ACI syntax.\n",
498                                                         fname, lineno );
499                                                 acl_usage();
500                                         }
501 #else
502                                         if ( right != NULL && *right != '\0' ) {
503                                                 b->a_aci_at = ch_strdup( right );
504                                         } else {
505                                                 b->a_aci_at = ch_strdup( SLAPD_ACI_DEFAULT_ATTR );
506                                         }
507 #endif
508                                         continue;
509                                 }
510 #endif /* SLAPD_ACI_ENABLED */
511
512                                 if( right != NULL ) {
513                                         /* unsplit */
514                                         right[-1] = '=';
515                                 }
516                                 break;
517                         }
518
519                         if( i == argc || ( strcasecmp( left, "stop" ) == 0 )) { 
520                                 /* out of arguments or plain stop */
521
522                                 ACL_PRIV_ASSIGN(b->a_mask, ACL_PRIV_ADDITIVE);
523                                 b->a_type = ACL_STOP;
524
525                                 access_append( &a->acl_access, b );
526                                 continue;
527                         }
528
529                         if( strcasecmp( left, "continue" ) == 0 ) {
530                                 /* plain continue */
531
532                                 ACL_PRIV_ASSIGN(b->a_mask, ACL_PRIV_ADDITIVE);
533                                 b->a_type = ACL_CONTINUE;
534
535                                 access_append( &a->acl_access, b );
536                                 continue;
537                         }
538
539                         if( strcasecmp( left, "break" ) == 0 ) {
540                                 /* plain continue */
541
542                                 ACL_PRIV_ASSIGN(b->a_mask, ACL_PRIV_ADDITIVE);
543                                 b->a_type = ACL_BREAK;
544
545                                 access_append( &a->acl_access, b );
546                                 continue;
547                         }
548
549                         if ( strcasecmp( left, "by" ) == 0 ) {
550                                 /* we've gone too far */
551                                 --i;
552                                 ACL_PRIV_ASSIGN(b->a_mask, ACL_PRIV_ADDITIVE);
553                                 b->a_type = ACL_STOP;
554
555                                 access_append( &a->acl_access, b );
556                                 continue;
557                         }
558
559                         /* get <access> */
560                         if( strncasecmp( left, "self", 4 ) == 0 ) {
561                                 b->a_dn_self = 1;
562                                 ACL_PRIV_ASSIGN( b->a_mask, str2accessmask( &left[4] ) );
563
564                         } else {
565                                 ACL_PRIV_ASSIGN( b->a_mask, str2accessmask( left ) );
566                         }
567
568                         if( ACL_IS_INVALID( b->a_mask ) ) {
569                                 fprintf( stderr,
570                                         "%s: line %d: expecting <access> got \"%s\"\n",
571                                         fname, lineno, left );
572                                 acl_usage();
573                         }
574
575                         b->a_type = ACL_STOP;
576
577                         if( ++i == argc ) {
578                                 /* out of arguments or plain stop */
579                                 access_append( &a->acl_access, b );
580                                 continue;
581                         }
582
583                         if( strcasecmp( argv[i], "continue" ) == 0 ) {
584                                 /* plain continue */
585                                 b->a_type = ACL_CONTINUE;
586
587                         } else if( strcasecmp( argv[i], "break" ) == 0 ) {
588                                 /* plain continue */
589                                 b->a_type = ACL_BREAK;
590
591                         } else if ( strcasecmp( argv[i], "stop" ) != 0 ) {
592                                 /* gone to far */
593                                 i--;
594                         }
595
596                         access_append( &a->acl_access, b );
597
598                 } else {
599                         fprintf( stderr,
600                     "%s: line %d: expecting \"to\" or \"by\" got \"%s\"\n",
601                             fname, lineno, argv[i] );
602                         acl_usage();
603                 }
604         }
605
606         /* if we have no real access clause, complain and do nothing */
607         if ( a == NULL ) {
608                         fprintf( stderr,
609                                 "%s: line %d: warning: no access clause(s) specified in access line\n",
610                             fname, lineno );
611
612         } else {
613 #ifdef LDAP_DEBUG
614                 if (ldap_debug & LDAP_DEBUG_ACL)
615                         print_acl(be, a);
616 #endif
617         
618                 if ( a->acl_access == NULL ) {
619                         fprintf( stderr,
620                         "%s: line %d: warning: no by clause(s) specified in access line\n",
621                             fname, lineno );
622                 }
623
624                 if ( be != NULL ) {
625                         acl_append( &be->be_acl, a );
626                 } else {
627                         acl_append( &global_acl, a );
628                 }
629         }
630 }
631
632 char *
633 accessmask2str( slap_access_mask_t mask, char *buf )
634 {
635         int none=1;
636
637         assert( buf != NULL );
638
639         if ( ACL_IS_INVALID( mask ) ) {
640                 return "invalid";
641         }
642
643         buf[0] = '\0';
644
645         if ( ACL_IS_LEVEL( mask ) ) {
646                 if ( ACL_LVL_IS_NONE(mask) ) {
647                         strcat( buf, "none" );
648
649                 } else if ( ACL_LVL_IS_AUTH(mask) ) {
650                         strcat( buf, "auth" );
651
652                 } else if ( ACL_LVL_IS_COMPARE(mask) ) {
653                         strcat( buf, "compare" );
654
655                 } else if ( ACL_LVL_IS_SEARCH(mask) ) {
656                         strcat( buf, "search" );
657
658                 } else if ( ACL_LVL_IS_READ(mask) ) {
659                         strcat( buf, "read" );
660
661                 } else if ( ACL_LVL_IS_WRITE(mask) ) {
662                         strcat( buf, "write" );
663                 } else {
664                         strcat( buf, "unknown" );
665                 }
666                 
667                 strcat(buf, " (");
668         }
669
670         if( ACL_IS_ADDITIVE( mask ) ) {
671                 strcat( buf, "+" );
672
673         } else if( ACL_IS_SUBTRACTIVE( mask ) ) {
674                 strcat( buf, "-" );
675
676         } else {
677                 strcat( buf, "=" );
678         }
679
680         if ( ACL_PRIV_ISSET(mask, ACL_PRIV_WRITE) ) {
681                 none = 0;
682                 strcat( buf, "w" );
683         } 
684
685         if ( ACL_PRIV_ISSET(mask, ACL_PRIV_READ) ) {
686                 none = 0;
687                 strcat( buf, "r" );
688         } 
689
690         if ( ACL_PRIV_ISSET(mask, ACL_PRIV_SEARCH) ) {
691                 none = 0;
692                 strcat( buf, "s" );
693         } 
694
695         if ( ACL_PRIV_ISSET(mask, ACL_PRIV_COMPARE) ) {
696                 none = 0;
697                 strcat( buf, "c" );
698         } 
699
700         if ( ACL_PRIV_ISSET(mask, ACL_PRIV_AUTH) ) {
701                 none = 0;
702                 strcat( buf, "x" );
703         } 
704
705         if ( none && ACL_PRIV_ISSET(mask, ACL_PRIV_NONE) ) {
706                 none = 0;
707                 strcat( buf, "n" );
708         } 
709
710         if ( none ) {
711                 strcat( buf, "0" );
712         }
713
714         if ( ACL_IS_LEVEL( mask ) ) {
715                 strcat(buf, ")");
716         } 
717         return buf;
718 }
719
720 slap_access_mask_t
721 str2accessmask( const char *str )
722 {
723         slap_access_mask_t      mask;
724
725         if( !isalpha(str[0]) ) {
726                 int i;
727
728                 if ( str[0] == '=' ) {
729                         ACL_INIT(mask);
730
731                 } else if( str[0] == '+' ) {
732                         ACL_PRIV_ASSIGN(mask, ACL_PRIV_ADDITIVE);
733
734                 } else if( str[0] == '-' ) {
735                         ACL_PRIV_ASSIGN(mask, ACL_PRIV_SUBSTRACTIVE);
736
737                 } else {
738                         ACL_INVALIDATE(mask);
739                         return mask;
740                 }
741
742                 for( i=1; str[i] != '\0'; i++ ) {
743                         if( TOLOWER(str[i]) == 'w' ) {
744                                 ACL_PRIV_SET(mask, ACL_PRIV_WRITE);
745
746                         } else if( TOLOWER(str[i]) == 'r' ) {
747                                 ACL_PRIV_SET(mask, ACL_PRIV_READ);
748
749                         } else if( TOLOWER(str[i]) == 's' ) {
750                                 ACL_PRIV_SET(mask, ACL_PRIV_SEARCH);
751
752                         } else if( TOLOWER(str[i]) == 'c' ) {
753                                 ACL_PRIV_SET(mask, ACL_PRIV_COMPARE);
754
755                         } else if( TOLOWER(str[i]) == 'x' ) {
756                                 ACL_PRIV_SET(mask, ACL_PRIV_AUTH);
757
758                         } else if( str[i] != '0' ) {
759                                 ACL_INVALIDATE(mask);
760                                 return mask;
761                         }
762                 }
763
764                 return mask;
765         }
766
767         if ( strcasecmp( str, "none" ) == 0 ) {
768                 ACL_LVL_ASSIGN_NONE(mask);
769
770         } else if ( strcasecmp( str, "auth" ) == 0 ) {
771                 ACL_LVL_ASSIGN_AUTH(mask);
772
773         } else if ( strcasecmp( str, "compare" ) == 0 ) {
774                 ACL_LVL_ASSIGN_COMPARE(mask);
775
776         } else if ( strcasecmp( str, "search" ) == 0 ) {
777                 ACL_LVL_ASSIGN_SEARCH(mask);
778
779         } else if ( strcasecmp( str, "read" ) == 0 ) {
780                 ACL_LVL_ASSIGN_READ(mask);
781
782         } else if ( strcasecmp( str, "write" ) == 0 ) {
783                 ACL_LVL_ASSIGN_WRITE(mask);
784
785         } else {
786                 ACL_INVALIDATE( mask );
787         }
788
789         return mask;
790 }
791
792 static void
793 acl_usage( void )
794 {
795         fprintf( stderr, "\n"
796                 "<access clause> ::= access to <what> "
797                                 "[ by <who> <access> <control> ]+ \n"
798                 "<what> ::= * | [dn=<regex>] [filter=<ldapfilter>] [attrs=<attrlist>]\n"
799                 "<attrlist> ::= <attr> | <attr> , <attrlist>\n"
800                 "<attr> ::= <attrname> | entry | children\n"
801                 "<who> ::= [ * | anonymous | users | self | dn=<regex> ]\n"
802                         "\t[dnattr=<attrname>]\n"
803                         "\t[group[/<objectclass>[/<attrname>]]=<regex>]\n"
804                         "\t[peername=<regex>] [sockname=<regex>]\n"
805                         "\t[domain=<regex>] [sockurl=<regex>]\n"
806 #ifdef SLAPD_ACI_ENABLED
807                         "\t[aci=<attrname>]\n"
808 #endif
809                 "<access> ::= [self]{<level>|<priv>}\n"
810                 "<level> ::= none | auth | compare | search | read | write\n"
811                 "<priv> ::= {=|+|-}{w|r|s|c|x}+\n"
812                 "<control> ::= [ stop | continue | break ]\n"
813                 );
814         exit( EXIT_FAILURE );
815 }
816
817 static void
818 split(
819     char        *line,
820     int         splitchar,
821     char        **left,
822     char        **right
823 )
824 {
825         *left = line;
826         if ( (*right = strchr( line, splitchar )) != NULL ) {
827                 *((*right)++) = '\0';
828         }
829 }
830
831 static void
832 access_append( Access **l, Access *a )
833 {
834         for ( ; *l != NULL; l = &(*l)->a_next )
835                 ;       /* NULL */
836
837         *l = a;
838 }
839
840 void
841 acl_append( AccessControl **l, AccessControl *a )
842 {
843         for ( ; *l != NULL; l = &(*l)->acl_next )
844                 ;       /* NULL */
845
846         *l = a;
847 }
848
849 char *
850 access2str( slap_access_t access )
851 {
852         if ( access == ACL_NONE ) {
853                 return "none";
854
855         } else if ( access == ACL_AUTH ) {
856                 return "auth";
857
858         } else if ( access == ACL_COMPARE ) {
859                 return "compare";
860
861         } else if ( access == ACL_SEARCH ) {
862                 return "search";
863
864         } else if ( access == ACL_READ ) {
865                 return "read";
866
867         } else if ( access == ACL_WRITE ) {
868                 return "write";
869         }
870
871         return "unknown";
872 }
873
874 slap_access_t
875 str2access( const char *str )
876 {
877         if ( strcasecmp( str, "none" ) == 0 ) {
878                 return ACL_NONE;
879
880         } else if ( strcasecmp( str, "auth" ) == 0 ) {
881                 return ACL_AUTH;
882
883         } else if ( strcasecmp( str, "compare" ) == 0 ) {
884                 return ACL_COMPARE;
885
886         } else if ( strcasecmp( str, "search" ) == 0 ) {
887                 return ACL_SEARCH;
888
889         } else if ( strcasecmp( str, "read" ) == 0 ) {
890                 return ACL_READ;
891
892         } else if ( strcasecmp( str, "write" ) == 0 ) {
893                 return ACL_WRITE;
894         }
895
896         return( ACL_INVALID_ACCESS );
897 }
898
899 #ifdef LDAP_DEBUG
900
901 static void
902 print_access( Access *b )
903 {
904         char maskbuf[ACCESSMASK_MAXLEN];
905
906         fprintf( stderr, "\tby" );
907
908         if ( b->a_dn_pat != NULL ) {
909                 if( strcmp(b->a_dn_pat, "*") == 0
910                         || strcmp(b->a_dn_pat, "users") == 0 
911                         || strcmp(b->a_dn_pat, "anonymous") == 0 
912                         || strcmp(b->a_dn_pat, "self") == 0 )
913                 {
914                         fprintf( stderr, " %s", b->a_dn_pat );
915
916                 } else {
917                         fprintf( stderr, " dn=%s", b->a_dn_pat );
918                 }
919         }
920
921         if ( b->a_dn_at != NULL ) {
922                 fprintf( stderr, " dnattr=%s", b->a_dn_at );
923         }
924
925         if ( b->a_group_pat != NULL ) {
926                 fprintf( stderr, " group: %s", b->a_group_pat );
927
928                 if ( b->a_group_oc ) {
929                         fprintf( stderr, " objectClass: %s", b->a_group_oc );
930
931                         if ( b->a_group_at ) {
932                                 fprintf( stderr, " attributeType: %s", b->a_group_at );
933                         }
934                 }
935     }
936
937         if ( b->a_peername_pat != NULL ) {
938                 fprintf( stderr, " peername=%s", b->a_peername_pat );
939         }
940
941         if ( b->a_sockname_pat != NULL ) {
942                 fprintf( stderr, " sockname=%s", b->a_sockname_pat );
943         }
944
945         if ( b->a_domain_pat != NULL ) {
946                 fprintf( stderr, " domain=%s", b->a_domain_pat );
947         }
948
949         if ( b->a_sockurl_pat != NULL ) {
950                 fprintf( stderr, " sockurl=%s", b->a_sockurl_pat );
951         }
952
953 #ifdef SLAPD_ACI_ENABLED
954         if ( b->a_aci_at != NULL ) {
955                 fprintf( stderr, " aci=%s", b->a_aci_at );
956         }
957 #endif
958
959         fprintf( stderr, " %s%s",
960                 b->a_dn_self ? "self" : "",
961                 accessmask2str( b->a_mask, maskbuf ) );
962
963         if( b->a_type == ACL_BREAK ) {
964                 fprintf( stderr, " break" );
965
966         } else if( b->a_type == ACL_CONTINUE ) {
967                 fprintf( stderr, " continue" );
968
969         } else if( b->a_type != ACL_STOP ) {
970                 fprintf( stderr, " unknown-control" );
971         }
972
973         fprintf( stderr, "\n" );
974 }
975
976
977 static void
978 print_acl( Backend *be, AccessControl *a )
979 {
980         int             to = 0;
981         Access  *b;
982
983         fprintf( stderr, "%s ACL: access to",
984                 be == NULL ? "Global" : "Backend" );
985
986         if ( a->acl_dn_pat != NULL ) {
987                 to++;
988                 fprintf( stderr, " dn=%s\n",
989                         a->acl_dn_pat );
990         }
991
992         if ( a->acl_filter != NULL ) {
993                 to++;
994                 fprintf( stderr, " filter=" );
995                 filter_print( a->acl_filter );
996                 fprintf( stderr, "\n" );
997         }
998
999         if ( a->acl_attrs != NULL ) {
1000                 int     i, first = 1;
1001                 to++;
1002
1003                 fprintf( stderr, " attrs=" );
1004                 for ( i = 0; a->acl_attrs[i] != NULL; i++ ) {
1005                         if ( ! first ) {
1006                                 fprintf( stderr, "," );
1007                         }
1008                         fprintf( stderr, a->acl_attrs[i] );
1009                         first = 0;
1010                 }
1011                 fprintf(  stderr, "\n" );
1012         }
1013
1014         if( !to ) {
1015                 fprintf( stderr, " *\n" );
1016         }
1017
1018         for ( b = a->acl_access; b != NULL; b = b->a_next ) {
1019                 print_access( b );
1020         }
1021
1022         fprintf( stderr, "\n" );
1023 }
1024
1025 #endif /* LDAP_DEBUG */