1
1
/* acl.c - routines to parse and check acl's */
2
/* $OpenLDAP: pkg/ldap/servers/slapd/acl.c,v 1.303.2.16 2008/05/20 00:08:13 quanah Exp $ */
2
/* $OpenLDAP: pkg/ldap/servers/slapd/acl.c,v 1.303.2.22 2009/01/22 00:00:59 kurt Exp $ */
3
3
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
5
* Copyright 1998-2008 The OpenLDAP Foundation.
5
* Copyright 1998-2009 The OpenLDAP Foundation.
6
6
* All rights reserved.
8
8
* Redistribution and use in source and binary forms, with or without
60
60
Operation *op, Entry *e,
61
61
AttributeDescription *desc,
62
62
struct berval *val,
63
AclRegexMatches *matches,
66
AccessControlState *state );
65
AccessControlState *state,
66
slap_access_t access );
68
68
static int regex_matches(
69
struct berval *pat, char *str, char *buf,
70
int nmatch, regmatch_t *matches);
69
struct berval *pat, char *str,
70
struct berval *dn_matches, struct berval *val_matches,
71
AclRegexMatches *matches);
72
73
typedef struct AclSetCookie {
73
74
SetCookie asc_cookie;
120
#define MATCHES_DNMAXCOUNT(m) \
121
( sizeof ( (m)->dn_data ) / sizeof( *(m)->dn_data ) )
122
#define MATCHES_VALMAXCOUNT(m) \
123
( sizeof ( (m)->val_data ) / sizeof( *(m)->val_data ) )
124
#define MATCHES_MEMSET(m) do { \
125
memset( (m)->dn_data, '\0', sizeof( (m)->dn_data ) ); \
126
memset( (m)->val_data, '\0', sizeof( (m)->val_data ) ); \
127
(m)->dn_count = MATCHES_DNMAXCOUNT( (m) ); \
128
(m)->val_count = MATCHES_VALMAXCOUNT( (m) ); \
129
} while ( 0 /* CONSTCOND */ )
119
132
slap_access_allowed(
201
215
control = ACL_BREAK;
203
if ( state && state->as_vd_ad == desc ) {
219
if ( state->as_vd_ad == desc ) {
204
220
a = state->as_vd_acl;
205
221
count = state->as_vd_acl_count;
222
if ( state->as_fe_done )
225
state->as_vi_acl = NULL;
208
if ( state ) state->as_vi_acl = NULL;
231
state->as_fe_done = 0;
212
233
ACL_PRIV_ASSIGN( mask, *maskp );
213
memset( matches, '\0', sizeof( matches ) );
234
MATCHES_MEMSET( &matches );
215
236
while ( ( a = slap_acl_get( a, &count, op, e, desc, val,
216
MAXREMATCHES, matches, state ) ) != NULL )
237
&matches, state ) ) != NULL )
220
for ( i = 0; i < MAXREMATCHES && matches[i].rm_so > 0; i++ ) {
221
Debug( LDAP_DEBUG_ACL, "=> match[%d]: %d %d ", i,
222
(int)matches[i].rm_so, (int)matches[i].rm_eo );
223
if ( matches[i].rm_so <= matches[0].rm_eo ) {
225
for ( n = matches[i].rm_so; n < matches[i].rm_eo; n++ ) {
226
Debug( LDAP_DEBUG_ACL, "%c", e->e_ndn[n], 0, 0 );
229
Debug( LDAP_DEBUG_ARGS, "\n", 0, 0, 0 );
240
int dnmaxcount = MATCHES_DNMAXCOUNT( &matches );
241
int valmaxcount = MATCHES_VALMAXCOUNT( &matches );
242
regmatch_t *dn_data = matches.dn_data;
243
regmatch_t *val_data = matches.val_data;
246
for ( i = 0; i < dnmaxcount && dn_data[i].rm_eo > 0; i++ ) {
247
char *data = e->e_ndn;
249
Debug( LDAP_DEBUG_ACL, "=> match[dn%d]: %d %d ", i,
250
(int)dn_data[i].rm_so,
251
(int)dn_data[i].rm_eo );
252
if ( dn_data[i].rm_so <= dn_data[0].rm_eo ) {
254
for ( n = dn_data[i].rm_so;
255
n < dn_data[i].rm_eo; n++ ) {
256
Debug( LDAP_DEBUG_ACL, "%c",
260
Debug( LDAP_DEBUG_ACL, "\n", 0, 0, 0 );
264
for ( i = 0; i < valmaxcount && val_data[i].rm_eo > 0; i++ ) {
265
char *data = val->bv_val;
267
Debug( LDAP_DEBUG_ACL, "=> match[val%d]: %d %d ", i,
268
(int)val_data[i].rm_so,
269
(int)val_data[i].rm_eo );
270
if ( val_data[i].rm_so <= val_data[0].rm_eo ) {
272
for ( n = val_data[i].rm_so;
273
n < val_data[i].rm_eo; n++ ) {
274
Debug( LDAP_DEBUG_ACL, "%c",
278
Debug( LDAP_DEBUG_ACL, "\n", 0, 0, 0 );
248
297
control = slap_acl_mask( a, &mask, op,
249
e, desc, val, MAXREMATCHES, matches, count, state );
298
e, desc, val, &matches, count, state, access );
251
300
if ( control != ACL_BREAK ) {
255
memset( matches, '\0', sizeof( matches ) );
304
MATCHES_MEMSET( &matches );
258
307
if ( ACL_IS_INVALID( mask ) ) {
498
548
dnlen = e->e_nname.bv_len;
500
551
for ( ; a != NULL; prev = a, a = a->acl_next ) {
554
if ( a != frontendDB->be_acl && state->as_fe_done )
503
557
if ( a->acl_dn_pat.bv_len || ( a->acl_dn_style != ACL_STYLE_REGEX )) {
504
558
if ( a->acl_dn_style == ACL_STYLE_REGEX ) {
505
559
Debug( LDAP_DEBUG_ACL, "=> dnpat: [%d] %s nsub: %d\n",
506
560
*count, a->acl_dn_pat.bv_val, (int) a->acl_dn_re.re_nsub );
507
if (regexec(&a->acl_dn_re, e->e_ndn, nmatch, matches, 0))
561
if ( regexec ( &a->acl_dn_re,
564
matches->dn_data, 0 ) )
511
570
Debug( LDAP_DEBUG_ACL, "=> dn: [%d] %s\n",
512
571
*count, a->acl_dn_pat.bv_val, 0 );
513
572
patlen = a->acl_dn_pat.bv_len;
731
800
} else if ( bdn->a_style == ACL_STYLE_REGEX ) {
732
801
if ( !ber_bvccmp( &bdn->a_pat, '*' ) ) {
734
regmatch_t tmp_matches[2],
735
*tmp_matchesp = tmp_matches;
802
AclRegexMatches tmp_matches,
803
*tmp_matchesp = &tmp_matches;
739
switch ( a->acl_dn_style ) {
805
regmatch_t *tmp_data;
807
MATCHES_MEMSET( &tmp_matches );
808
tmp_data = &tmp_matches.dn_data[0];
810
if ( a->acl_attrval_style == ACL_STYLE_REGEX )
811
tmp_matchesp = matches;
812
else switch ( a->acl_dn_style ) {
740
813
case ACL_STYLE_REGEX:
741
814
if ( !BER_BVISNULL( &a->acl_dn_pat ) ) {
742
tmp_matchesp = matches;
815
tmp_matchesp = matches;
746
818
/* FALLTHRU: applies also to ACL_STYLE_REGEX when pattern is "*" */
748
820
case ACL_STYLE_BASE:
749
tmp_matches[0].rm_so = 0;
750
tmp_matches[0].rm_eo = e->e_nname.bv_len;
821
tmp_data[0].rm_so = 0;
822
tmp_data[0].rm_eo = e->e_nname.bv_len;
823
tmp_matches.dn_count = 1;
754
826
case ACL_STYLE_ONE:
755
827
case ACL_STYLE_SUBTREE:
756
828
case ACL_STYLE_CHILDREN:
757
tmp_matches[0].rm_so = 0;
758
tmp_matches[0].rm_eo = e->e_nname.bv_len;
759
tmp_matches[1].rm_so = e->e_nname.bv_len - a->acl_dn_pat.bv_len;
760
tmp_matches[1].rm_eo = e->e_nname.bv_len;
829
tmp_data[0].rm_so = 0;
830
tmp_data[0].rm_eo = e->e_nname.bv_len;
831
tmp_data[1].rm_so = e->e_nname.bv_len - a->acl_dn_pat.bv_len;
832
tmp_data[1].rm_eo = e->e_nname.bv_len;
833
tmp_matches.dn_count = 2;
790
862
struct berval bv;
791
863
char buf[ACL_BUF_SIZE];
794
regmatch_t tmp_matches[2],
795
*tmp_matchesp = tmp_matches;
865
AclRegexMatches tmp_matches,
866
*tmp_matchesp = &tmp_matches;
868
regmatch_t *tmp_data;
870
MATCHES_MEMSET( &tmp_matches );
871
tmp_data = &tmp_matches.dn_data[0];
799
873
bv.bv_len = sizeof( buf ) - 1;
802
switch ( a->acl_dn_style ) {
876
/* Expand value regex */
877
if ( a->acl_attrval_style == ACL_STYLE_REGEX )
878
tmp_matchesp = matches;
879
else switch ( a->acl_dn_style ) {
803
880
case ACL_STYLE_REGEX:
804
881
if ( !BER_BVISNULL( &a->acl_dn_pat ) ) {
805
882
tmp_matchesp = matches;
809
885
/* FALLTHRU: applies also to ACL_STYLE_REGEX when pattern is "*" */
811
887
case ACL_STYLE_BASE:
812
tmp_matches[0].rm_so = 0;
813
tmp_matches[0].rm_eo = e->e_nname.bv_len;
888
tmp_data[0].rm_so = 0;
889
tmp_data[0].rm_eo = e->e_nname.bv_len;
890
tmp_matches.dn_count = 1;
817
893
case ACL_STYLE_ONE:
818
894
case ACL_STYLE_SUBTREE:
819
895
case ACL_STYLE_CHILDREN:
820
tmp_matches[0].rm_so = 0;
821
tmp_matches[0].rm_eo = e->e_nname.bv_len;
822
tmp_matches[1].rm_so = e->e_nname.bv_len - a->acl_dn_pat.bv_len;
823
tmp_matches[1].rm_eo = e->e_nname.bv_len;
896
tmp_data[0].rm_so = 0;
897
tmp_data[0].rm_eo = e->e_nname.bv_len;
898
tmp_data[1].rm_so = e->e_nname.bv_len - a->acl_dn_pat.bv_len;
899
tmp_data[1].rm_eo = e->e_nname.bv_len;
900
tmp_matches.dn_count = 2;
1106
1181
* is maintained in a_dn_pat.
1109
if ( acl_mask_dn( op, e, desc, val, a, nmatch, matches,
1184
if ( acl_mask_dn( op, e, val, a, matches,
1110
1185
&b->a_dn, &op->o_ndn ) )
1154
1229
if ( !ber_bvccmp( &b->a_sockurl_pat, '*' ) ) {
1155
1230
if ( b->a_sockurl_style == ACL_STYLE_REGEX) {
1156
if (!regex_matches( &b->a_sockurl_pat, op->o_conn->c_listener_url.bv_val,
1157
e->e_ndn, nmatch, matches ) )
1231
if ( !regex_matches( &b->a_sockurl_pat, op->o_conn->c_listener_url.bv_val,
1232
&e->e_nname, val, matches ) )
1193
1267
b->a_domain_pat.bv_val, 0, 0 );
1194
1268
if ( !ber_bvccmp( &b->a_domain_pat, '*' ) ) {
1195
1269
if ( b->a_domain_style == ACL_STYLE_REGEX) {
1196
if (!regex_matches( &b->a_domain_pat, op->o_conn->c_peer_domain.bv_val,
1197
e->e_ndn, nmatch, matches ) )
1270
if ( !regex_matches( &b->a_domain_pat, op->o_conn->c_peer_domain.bv_val,
1271
&e->e_nname, val, matches ) )
1248
1321
b->a_peername_pat.bv_val, 0, 0 );
1249
1322
if ( !ber_bvccmp( &b->a_peername_pat, '*' ) ) {
1250
1323
if ( b->a_peername_style == ACL_STYLE_REGEX ) {
1251
if (!regex_matches( &b->a_peername_pat, op->o_conn->c_peer_name.bv_val,
1252
e->e_ndn, nmatch, matches ) )
1324
if ( !regex_matches( &b->a_peername_pat, op->o_conn->c_peer_name.bv_val,
1325
&e->e_nname, val, matches ) )
1401
1473
b->a_sockname_pat.bv_val, 0, 0 );
1402
1474
if ( !ber_bvccmp( &b->a_sockname_pat, '*' ) ) {
1403
1475
if ( b->a_sockname_style == ACL_STYLE_REGEX) {
1404
if (!regex_matches( &b->a_sockname_pat, op->o_conn->c_sock_name.bv_val,
1405
e->e_ndn, nmatch, matches ) )
1476
if ( !regex_matches( &b->a_sockname_pat, op->o_conn->c_sock_name.bv_val,
1477
&e->e_nname, val, matches ) )
1477
1548
/* see if asker is listed in dnattr */
1478
1549
if ( b->a_group_style == ACL_STYLE_EXPAND ) {
1479
1550
char buf[ACL_BUF_SIZE];
1481
regmatch_t tmp_matches[2],
1482
*tmp_matchesp = tmp_matches;
1551
AclRegexMatches tmp_matches,
1552
*tmp_matchesp = &tmp_matches;
1553
regmatch_t *tmp_data;
1555
MATCHES_MEMSET( &tmp_matches );
1556
tmp_data = &tmp_matches.dn_data[0];
1484
1558
bv.bv_len = sizeof(buf) - 1;
1485
1559
bv.bv_val = buf;
1489
switch ( a->acl_dn_style ) {
1563
if ( a->acl_attrval_style == ACL_STYLE_REGEX )
1564
tmp_matchesp = matches;
1565
else switch ( a->acl_dn_style ) {
1490
1566
case ACL_STYLE_REGEX:
1491
1567
if ( !BER_BVISNULL( &a->acl_dn_pat ) ) {
1492
1568
tmp_matchesp = matches;
1493
tmp_nmatch = nmatch;
1497
1572
/* FALLTHRU: applies also to ACL_STYLE_REGEX when pattern is "*" */
1498
1573
case ACL_STYLE_BASE:
1499
tmp_matches[0].rm_so = 0;
1500
tmp_matches[0].rm_eo = e->e_nname.bv_len;
1574
tmp_data[0].rm_so = 0;
1575
tmp_data[0].rm_eo = e->e_nname.bv_len;
1576
tmp_matches.dn_count = 1;
1504
1579
case ACL_STYLE_ONE:
1505
1580
case ACL_STYLE_SUBTREE:
1506
1581
case ACL_STYLE_CHILDREN:
1507
tmp_matches[0].rm_so = 0;
1508
tmp_matches[0].rm_eo = e->e_nname.bv_len;
1509
tmp_matches[1].rm_so = e->e_nname.bv_len - a->acl_dn_pat.bv_len;
1510
tmp_matches[1].rm_eo = e->e_nname.bv_len;
1582
tmp_data[0].rm_so = 0;
1583
tmp_data[0].rm_eo = e->e_nname.bv_len;
1585
tmp_data[1].rm_so = e->e_nname.bv_len - a->acl_dn_pat.bv_len;
1586
tmp_data[1].rm_eo = e->e_nname.bv_len;
1587
tmp_matches.dn_count = 2;
1561
1637
b->a_set_pat.bv_val, 0, 0 );
1563
1639
if ( b->a_set_style == ACL_STYLE_EXPAND ) {
1565
regmatch_t tmp_matches[2],
1566
*tmp_matchesp = tmp_matches;
1640
AclRegexMatches tmp_matches,
1641
*tmp_matchesp = &tmp_matches;
1643
regmatch_t *tmp_data;
1645
MATCHES_MEMSET( &tmp_matches );
1646
tmp_data = &tmp_matches.dn_data[0];
1569
1648
bv.bv_len = sizeof( buf ) - 1;
1570
1649
bv.bv_val = buf;
1574
switch ( a->acl_dn_style ) {
1653
if ( a->acl_attrval_style == ACL_STYLE_REGEX )
1654
tmp_matchesp = matches;
1655
else switch ( a->acl_dn_style ) {
1575
1656
case ACL_STYLE_REGEX:
1576
1657
if ( !BER_BVISNULL( &a->acl_dn_pat ) ) {
1577
1658
tmp_matchesp = matches;
1578
tmp_nmatch = nmatch;
1582
1662
/* FALLTHRU: applies also to ACL_STYLE_REGEX when pattern is "*" */
1583
1663
case ACL_STYLE_BASE:
1584
tmp_matches[0].rm_so = 0;
1585
tmp_matches[0].rm_eo = e->e_nname.bv_len;
1664
tmp_data[0].rm_so = 0;
1665
tmp_data[0].rm_eo = e->e_nname.bv_len;
1666
tmp_matches.dn_count = 1;
1589
1669
case ACL_STYLE_ONE:
1590
1670
case ACL_STYLE_SUBTREE:
1591
1671
case ACL_STYLE_CHILDREN:
1592
tmp_matches[0].rm_so = 0;
1593
tmp_matches[0].rm_eo = e->e_nname.bv_len;
1594
tmp_matches[1].rm_so = e->e_nname.bv_len - a->acl_dn_pat.bv_len;
1595
tmp_matches[1].rm_eo = e->e_nname.bv_len;
1672
tmp_data[0].rm_so = 0;
1673
tmp_data[0].rm_eo = e->e_nname.bv_len;
1674
tmp_data[1].rm_so = e->e_nname.bv_len - a->acl_dn_pat.bv_len;
1675
tmp_data[1].rm_eo = e->e_nname.bv_len; tmp_matches.dn_count = 2;
1720
1799
Debug( LDAP_DEBUG_ACL, " <= check a_dynacl: %s\n",
1721
1800
da->da_name, 0, 0 );
1803
* XXXmanu Only DN matches are supplied
1804
* sending attribute values matches require
1723
1807
(void)da->da_mask( da->da_private, op, e, desc,
1724
val, nmatch, matches, &grant, &deny );
1808
val, matches->dn_count, matches->dn_data,
1726
1811
tgrant |= grant;
2420
2509
acl_string_expand(
2421
2510
struct berval *bv,
2422
2511
struct berval *pat,
2425
regmatch_t *matches)
2512
struct berval *dn_matches,
2513
struct berval *val_matches,
2514
AclRegexMatches *matches)
2427
2516
ber_len_t size;
2520
enum { DN_FLAG, VAL_FLAG } tflag;
2433
2523
bv->bv_val[0] = '\0';
2434
2524
bv->bv_len--; /* leave space for lone $ */
2437
2528
for ( dp = bv->bv_val, sp = pat->bv_val; size < bv->bv_len &&
2438
2529
sp < pat->bv_val + pat->bv_len ; sp++ )
2502
2623
bv->bv_len = size;
2504
Debug( LDAP_DEBUG_TRACE, "=> acl_string_expand: pattern: %.*s\n", (int)pat->bv_len, pat->bv_val, 0 );
2505
Debug( LDAP_DEBUG_TRACE, "=> acl_string_expand: expanded: %s\n", bv->bv_val, 0, 0 );
2625
Debug( LDAP_DEBUG_ACL, "=> acl_string_expand: pattern: %.*s\n", (int)pat->bv_len, pat->bv_val, 0 );
2626
Debug( LDAP_DEBUG_ACL, "=> acl_string_expand: expanded: %s\n", bv->bv_val, 0, 0 );
2512
2633
struct berval *pat, /* pattern to expand and match against */
2513
2634
char *str, /* string to match against pattern */
2514
char *buf, /* buffer with $N expansion variables */
2515
int nmatch, /* size of the matches array */
2516
regmatch_t *matches /* offsets in buffer for $N expansion variables */
2635
struct berval *dn_matches, /* buffer with $N expansion variables from DN */
2636
struct berval *val_matches, /* buffer with $N expansion variables from val */
2637
AclRegexMatches *matches /* offsets in buffer for $N expansion variables */
2531
acl_string_expand( &bv, pat, buf, nmatch, matches );
2652
acl_string_expand( &bv, pat, dn_matches, val_matches, matches );
2532
2653
rc = regcomp( &re, newbuf, REG_EXTENDED|REG_ICASE );
2534
2655
char error[ACL_BUF_SIZE];