Commit 933908f7 authored by Kurt Zeilenga's avatar Kurt Zeilenga
Browse files

ACL CHANGES:

  by <who> <access> changed to by <who>+ <access> (joined with AND)
  added peername=<regex> sockname=<regex> url=<regex>
  removed addr=<regex> (use peername instead).
replace dn_upcase with str2upper and str2lower.  Use where needed.
parent 17eb2027
......@@ -315,7 +315,7 @@ void *getRegParam( char *svc, char *value )
return (void*)NULL;
}
void LogSlapdStartedEvent( char *svc, int slap_debug, char *configfile, short port, int udp )
void LogSlapdStartedEvent( char *svc, int slap_debug, char *configfile, char *urls )
{
char *Inserts[5];
WORD i = 0, j;
......@@ -326,12 +326,11 @@ void LogSlapdStartedEvent( char *svc, int slap_debug, char *configfile, short po
Inserts[i] = (char *)malloc( 20 );
itoa( slap_debug, Inserts[i++], 10 );
Inserts[i++] = ldap_pvt_strdup( configfile );
Inserts[i] = (char *)malloc( 20 );
itoa( port, Inserts[i++], 10 );
Inserts[i++] = ldap_pvt_strdup( udp ? "udp" : "tcp" );
Inserts[i++] = ldap_pvt_strdup( urls );
Inserts[i++] = ldap_pvt_strdup( is_NT_Service ? "svc" : "cmd" );
ReportEvent( hEventLog, EVENTLOG_INFORMATION_TYPE, 0, MSG_SLAPD_STARTED, NULL, i, 0, Inserts, NULL );
ReportEvent( hEventLog, EVENTLOG_INFORMATION_TYPE, 0,
MSG_SLAPD_STARTED, NULL, i, 0, Inserts, NULL );
for ( j = 0; j < i; j++ )
ldap_memfree( Inserts[j] );
......@@ -345,7 +344,8 @@ void LogSlapdStoppedEvent( char *svc )
HANDLE hEventLog;
hEventLog = RegisterEventSource( NULL, svc );
ReportEvent( hEventLog, EVENTLOG_INFORMATION_TYPE, 0, MSG_SLAPD_STOPPED, NULL, 0, 0, NULL, NULL );
ReportEvent( hEventLog, EVENTLOG_INFORMATION_TYPE, 0,
MSG_SLAPD_STOPPED, NULL, 0, 0, NULL, NULL );
DeregisterEventSource( hEventLog );
}
......
......@@ -15,7 +15,7 @@ Severity=Informational
SymbolicName=MSG_SLAPD_STARTED
Facility=Application
Language=English
OpenLDAP SLAPD service started. debuglevel=%1, conffile=%2, port=%3, ip=%4, mode=%5
OpenLDAP SLAPD service started. debuglevel=%1, conffile=%2, urls=%3, mode=%4
.
......
......@@ -123,15 +123,17 @@ acl_get_applicable(
/* check for a backend-specific acl that matches the entry */
for ( i = 1, a = be->be_acl; a != NULL; a = a->acl_next, i++ ) {
if (a->acl_dnpat != NULL) {
if (a->acl_dn_pat != NULL) {
Debug( LDAP_DEBUG_TRACE, "=> dnpat: [%d] %s nsub: %d\n",
i, a->acl_dnpat, (int) a->acl_dnre.re_nsub);
i, a->acl_dn_pat, (int) a->acl_dn_re.re_nsub);
if (regexec(&a->acl_dnre, edn, nmatch, matches, 0))
if (regexec(&a->acl_dn_re, edn, nmatch, matches, 0)) {
continue;
else
} else {
Debug( LDAP_DEBUG_TRACE, "=> acl_get:[%d] backend ACL match\n",
i, 0, 0);
}
}
if ( a->acl_filter != NULL ) {
......@@ -154,12 +156,13 @@ acl_get_applicable(
/* check for a global acl that matches the entry */
for ( i = 1, a = global_acl; a != NULL; a = a->acl_next, i++ ) {
if (a->acl_dnpat != NULL) {
Debug( LDAP_DEBUG_TRACE, "=> dnpat: [%d] %s nsub: %d\n",
i, a->acl_dnpat, (int) a->acl_dnre.re_nsub);
if (a->acl_dn_pat != NULL) {
Debug( LDAP_DEBUG_TRACE, "=> dn pat: [%d] %s nsub: %d\n",
i, a->acl_dn_pat, (int) a->acl_dn_re.re_nsub);
if (regexec(&a->acl_dnre, edn, nmatch, matches, 0)) {
if (regexec(&a->acl_dn_re, edn, nmatch, matches, 0)) {
continue;
} else {
Debug( LDAP_DEBUG_TRACE, "=> acl_get: [%d] global ACL match\n",
i, 0, 0);
......@@ -213,8 +216,6 @@ acl_access_allowed(
{
int i;
Access *b;
Attribute *at;
struct berval bv;
int default_access;
Debug( LDAP_DEBUG_ACL,
......@@ -243,83 +244,97 @@ acl_access_allowed(
return( default_access >= access );
}
if ( op->o_ndn != NULL ) {
bv.bv_val = op->o_ndn;
bv.bv_len = strlen( bv.bv_val );
}
for ( i = 1, b = a->acl_access; b != NULL; b = b->a_next, i++ ) {
if ( b->a_dnpat != NULL ) {
Debug( LDAP_DEBUG_TRACE, "<= check a_dnpat: %s\n",
b->a_dnpat, 0, 0);
/* AND <who> clauses */
if ( b->a_dn_pat != NULL ) {
Debug( LDAP_DEBUG_TRACE, "<= check a_dn_pat: %s\n",
b->a_dn_pat, 0, 0);
/*
* if access applies to the entry itself, and the
* user is bound as somebody in the same namespace as
* the entry, OR the given dn matches the dn pattern
*/
if ( strcasecmp( b->a_dnpat, "anonymous" ) == 0 &&
(op->o_ndn == NULL || *(op->o_ndn) == '\0' ) )
if ( strcasecmp( b->a_dn_pat, "anonymous" ) == 0 ) {
if (op->o_ndn != NULL && op->o_ndn[0] != '\0' ) {
continue;
}
} else if ( strcasecmp( b->a_dn_pat, "self" ) == 0 ) {
if( op->o_ndn == NULL || op->o_ndn[0] == '\0' ) {
continue;
}
if ( e->e_dn == NULL || strcmp( edn, op->o_ndn ) != 0 ) {
continue;
}
} else if ( strcmp( b->a_dn_pat, ".*" ) != 0 &&
!regex_matches( b->a_dn_pat, op->o_ndn, edn, matches ) )
{
Debug( LDAP_DEBUG_ACL,
"<= acl_access_allowed: matched by clause #%d access %s\n",
i, ACL_GRANT(b->a_access, access)
? "granted" : "denied", 0 );
continue;
}
}
return ACL_GRANT(b->a_access, access );
if ( b->a_url_pat != NULL ) {
Debug( LDAP_DEBUG_ARGS, "<= check a_url_pat: %s\n",
b->a_url_pat, 0, 0 );
} else if ( strcasecmp( b->a_dnpat, "self" ) == 0 &&
op->o_ndn != NULL && *(op->o_ndn) && e->e_dn != NULL )
if ( strcmp( b->a_url_pat, ".*" ) != 0 &&
!regex_matches( b->a_url_pat, conn->c_listener_url,
edn, matches ) )
{
if ( strcmp( edn, op->o_ndn ) == 0 ) {
Debug( LDAP_DEBUG_ACL,
"<= acl_access_allowed: matched by clause #%d access %s\n",
i, ACL_GRANT(b->a_access, access)
? "granted" : "denied", 0 );
continue;
}
}
return ACL_GRANT(b->a_access, access );
}
} else {
if ( regex_matches( b->a_dnpat, op->o_ndn, edn, matches ) ) {
Debug( LDAP_DEBUG_ACL,
"<= acl_access_allowed: matched by clause #%d access %s\n",
i, ACL_GRANT(b->a_access, access)
? "granted" : "denied", 0 );
if ( b->a_domain_pat != NULL ) {
Debug( LDAP_DEBUG_ARGS, "<= check a_domain_pat: %s\n",
b->a_domain_pat, 0, 0 );
return ACL_GRANT(b->a_access, access );
}
if ( strcmp( b->a_domain_pat, ".*" ) != 0 &&
!regex_matches( b->a_domain_pat, conn->c_peer_domain,
edn, matches ) )
{
continue;
}
}
if ( b->a_addrpat != NULL ) {
if ( regex_matches( b->a_addrpat, conn->c_client_addr,
if ( b->a_peername_pat != NULL ) {
Debug( LDAP_DEBUG_ARGS, "<= check a_peername_path: %s\n",
b->a_peername_pat, 0, 0 );
if ( strcmp( b->a_peername_pat, ".*" ) != 0 &&
!regex_matches( b->a_peername_pat, conn->c_peer_name,
edn, matches ) )
{
Debug( LDAP_DEBUG_ACL,
"<= acl_access_allowed: matched by clause #%d access %s\n",
i, ACL_GRANT(b->a_access, access)
? "granted" : "denied", 0 );
return ACL_GRANT(b->a_access, access );
continue;
}
}
if ( b->a_domainpat != NULL ) {
Debug( LDAP_DEBUG_ARGS, "<= check a_domainpath: %s\n",
b->a_domainpat, 0, 0 );
if ( regex_matches( b->a_domainpat, conn->c_client_name,
edn, matches ) )
{
Debug( LDAP_DEBUG_ACL,
"<= acl_access_allowed: matched by clause #%d access %s\n",
i, ACL_GRANT(b->a_access, access)
? "granted" : "denied", 0 );
return ACL_GRANT(b->a_access, access );
if ( b->a_sockname_pat != NULL ) {
Debug( LDAP_DEBUG_ARGS, "<= check a_sockname_path: %s\n",
b->a_sockname_pat, 0, 0 );
if ( strcmp( b->a_sockname_pat, ".*" ) != 0 &&
!regex_matches( b->a_sockname_pat, conn->c_sock_name,
edn, matches ) )
{
continue;
}
}
if ( b->a_dnattr != NULL && op->o_ndn != NULL ) {
Debug( LDAP_DEBUG_ARGS, "<= check a_dnattr: %s\n",
b->a_dnattr, 0, 0);
/* see if asker is listed in dnattr */
if ( (at = attr_find( e->e_attrs, b->a_dnattr )) != NULL &&
if ( b->a_dn_at != NULL && op->o_ndn != NULL ) {
Attribute *at;
struct berval bv;
Debug( LDAP_DEBUG_ARGS, "<= check a_dn_at: %s\n",
b->a_dn_at, 0, 0);
bv.bv_val = op->o_ndn;
bv.bv_len = strlen( bv.bv_val );
/* see if asker is listed in dnattr */
if ( (at = attr_find( e->e_attrs, b->a_dn_at )) != NULL &&
value_find( at->a_vals, &bv, at->a_syntax, 3 ) == 0 )
{
if ( ACL_IS_SELF(b->a_access) &&
......@@ -328,30 +343,15 @@ acl_access_allowed(
continue;
}
Debug( LDAP_DEBUG_ACL,
"<= acl_acces_allowed: matched by clause #%d access %s\n",
i, ACL_GRANT(b->a_access, access)
? "granted" : "denied", 0 );
return ACL_GRANT(b->a_access, access );
}
/* asker not listed in dnattr - check for self access */
if ( ! ACL_IS_SELF(b->a_access) || val == NULL ||
} else if ( ! ACL_IS_SELF(b->a_access) || val == NULL ||
value_cmp( &bv, val, at->a_syntax, 2 ) != 0 )
{
continue;
}
Debug( LDAP_DEBUG_ACL,
"<= acl_access_allowed: matched by clause #%d (self) access %s\n",
i, ACL_GRANT(b->a_access, access)
? "granted" : "denied", 0 );
return ACL_GRANT(b->a_access, access );
}
if ( b->a_group != NULL && op->o_ndn != NULL ) {
if ( b->a_group_pat != NULL && op->o_ndn != NULL ) {
char buf[1024];
/* b->a_group is an unexpanded entry name, expanded it should be an
......@@ -359,18 +359,23 @@ acl_access_allowed(
* the values in the attribute group
*/
/* see if asker is listed in dnattr */
string_expand(buf, sizeof(buf), b->a_group, edn, matches);
string_expand(buf, sizeof(buf), b->a_group_pat, edn, matches);
(void) dn_normalize_case(buf);
if (backend_group(be, e, buf, op->o_ndn,
b->a_group_oc, b->a_group_at) == 0)
b->a_group_oc, b->a_group_at) != 0)
{
Debug( LDAP_DEBUG_ACL,
"<= acl_access_allowed: matched by clause #%d (group) access granted\n",
i, 0, 0 );
return ACL_GRANT(b->a_access, access );
continue;
}
}
Debug( LDAP_DEBUG_ACL,
"<= acl_access_allowed: matched by clause #%d access %s\n",
i,
ACL_GRANT(b->a_access, access) ? "granted" : "denied",
0 );
return ACL_GRANT(b->a_access, access );
}
Debug( LDAP_DEBUG_ACL,
......
......@@ -109,18 +109,7 @@ parse_acl(
}
if ( strcasecmp( argv[i], "*" ) == 0 ) {
int e;
if ((e = regcomp( &a->acl_dnre, ".*",
REG_EXTENDED|REG_ICASE)))
{
char buf[512];
regerror(e, &a->acl_dnre, buf, sizeof(buf));
fprintf( stderr,
"%s: line %d: regular expression \"%s\" bad because of %s\n",
fname, lineno, right, buf );
acl_usage();
}
a->acl_dnpat = ch_strdup( ".*" );
a->acl_dn_pat = ch_strdup( ".*" );
continue;
}
......@@ -140,27 +129,30 @@ parse_acl(
fname, lineno, right );
acl_usage();
}
} else if ( strcasecmp( left, "dn" ) == 0 ) {
int e;
if ((e = regcomp(&a->acl_dnre, right,
if ((e = regcomp(&a->acl_dn_re, right,
REG_EXTENDED|REG_ICASE))) {
char buf[512];
regerror(e, &a->acl_dnre, buf, sizeof(buf));
regerror(e, &a->acl_dn_re, buf, sizeof(buf));
fprintf( stderr,
"%s: line %d: regular expression \"%s\" bad because of %s\n",
fname, lineno, right, buf );
acl_usage();
} else {
a->acl_dnpat = dn_upcase(ch_strdup( right ));
a->acl_dn_pat = ch_strdup( right );
}
} else if ( strncasecmp( left, "attr", 4 )
== 0 ) {
} else if ( strncasecmp( left, "attr", 4 ) == 0 ) {
char **alist;
alist = str2charray( right, "," );
charray_merge( &a->acl_attrs, alist );
charray_free( alist );
} else {
fprintf( stderr,
"%s: line %d: expecting <what> got \"%s\"\n",
......@@ -191,87 +183,148 @@ parse_acl(
}
/* get <who> */
split( argv[i], '=', &left, &right );
if ( strcasecmp( argv[i], "*" ) == 0 ) {
b->a_dnpat = ch_strdup( ".*" );
} else if ( strcasecmp( argv[i], "anonymous" ) == 0 ) {
b->a_dnpat = ch_strdup( "anonymous" );
} else if ( strcasecmp( argv[i], "self" ) == 0 ) {
b->a_dnpat = ch_strdup( "self" );
} else if ( strcasecmp( left, "dn" ) == 0 ) {
regtest(fname, lineno, right);
b->a_dnpat = dn_upcase( ch_strdup( right ) );
} else if ( strcasecmp( left, "dnattr" ) == 0 ) {
b->a_dnattr = ch_strdup( right );
} else if ( strncasecmp( left, "group", sizeof("group")-1 ) == 0 ) {
char *name = NULL;
char *value = NULL;
/* format of string is "group/objectClassValue/groupAttrName" */
if ((value = strchr(left, '/')) != NULL) {
*value++ = '\0';
if (value && *value
&& (name = strchr(value, '/')) != NULL)
{
*name++ = '\0';
for ( ; i < argc; i++ ) {
char* pat;
split( argv[i], '=', &left, &right );
if ( strcasecmp( argv[i], "*" ) == 0 ) {
pat = ch_strdup( ".*" );
} else if ( strcasecmp( argv[i], "anonymous" ) == 0 ) {
pat = ch_strdup( "anonymous" );
} else if ( strcasecmp( argv[i], "self" ) == 0 ) {
pat = ch_strdup( "self" );
} else if ( strcasecmp( left, "dn" ) == 0 ) {
regtest(fname, lineno, right);
pat = ch_strdup( right );
}
if( pat != NULL ) {
if( b->a_dn_pat != NULL ) {
fprintf( stderr,
"%s: line %d: dn pattern already specified.\n",
fname, lineno );
acl_usage();
}
b->a_dn_pat = pat;
continue;
}
if ( strcasecmp( left, "dnattr" ) == 0 ) {
if( b->a_dn_pat != NULL ) {
fprintf( stderr,
"%s: line %d: dnaddr already specified.\n",
fname, lineno );
acl_usage();
}
b->a_dn_at = ch_strdup( right );
continue;
}
regtest(fname, lineno, right);
b->a_group = dn_upcase(ch_strdup( right ));
if ( strncasecmp( left, "group", sizeof("group")-1 ) == 0 ) {
char *name = NULL;
char *value = NULL;
if (value && *value) {
b->a_group_oc = ch_strdup(value);
*--value = '/';
} else {
b->a_group_oc = ch_strdup("groupOfNames");
if( b->a_group_pat != NULL ) {
fprintf( stderr,
"%s: line %d: group pattern already specified.\n",
fname, lineno );
acl_usage();
}
/* format of string is "group/objectClassValue/groupAttrName" */
if ((value = strchr(left, '/')) != NULL) {
*value++ = '\0';
if (value && *value
&& (name = strchr(value, '/')) != NULL)
{
*name++ = '\0';
}
}
if (name && *name) {
b->a_group_at = ch_strdup(name);
*--name = '/';
regtest(fname, lineno, right);
b->a_group_pat = ch_strdup( right );
if (value && *value) {
b->a_group_oc = ch_strdup(value);
*--value = '/';
} else {
b->a_group_at = ch_strdup("member");
b->a_group_oc = ch_strdup("groupOfNames");
if (name && *name) {
b->a_group_at = ch_strdup(name);
*--name = '/';
} else {
b->a_group_at = ch_strdup("member");
}
}
continue;
}
} else if ( strcasecmp( left, "domain" ) == 0 ) {
char *s;
regtest(fname, lineno, right);
b->a_domainpat = ch_strdup( right );
if ( strcasecmp( left, "peername" ) == 0 ) {
if( b->a_peername_pat != NULL ) {
fprintf( stderr,
"%s: line %d: peername pattern already specified.\n",
fname, lineno );
acl_usage();
}
/* normalize the domain */
for ( s = b->a_domainpat; *s; s++ ) {
*s = TOLOWER( (unsigned char) *s );
regtest(fname, lineno, right);
b->a_peername_pat = ch_strdup( right );
continue;
}
} else if ( strcasecmp( left, "addr" ) == 0 ) {
regtest(fname, lineno, right);
b->a_addrpat = ch_strdup( right );
} else {
fprintf( stderr,
"%s: line %d: expecting <who> got \"%s\"\n",
fname, lineno, left );
acl_usage();
}
if ( ++i == argc ) {
fprintf( stderr,
"%s: line %d: premature eol: expecting <access>\n",
fname, lineno );
acl_usage();
}
if ( strcasecmp( left, "sockname" ) == 0 ) {
if( b->a_sockname_pat != NULL ) {
fprintf( stderr,
"%s: line %d: sockname pattern already specified.\n",
fname, lineno );
acl_usage();
}
/* get <access> */
split( argv[i], '=', &left, &right );
if ( ACL_IS_INVALID(ACL_SET(b->a_access,str2access( left ))) ) {
fprintf( stderr,
"%s: line %d: expecting <access> got \"%s\"\n",
fname, lineno, left );
acl_usage();
}
access_append( &a->acl_access, b );
regtest(fname, lineno, right);
b->a_sockname_pat = ch_strdup( right );
continue;
}
if ( strcasecmp( left, "domain" ) == 0 ) {
if( b->a_domain_pat != NULL ) {
fprintf( stderr,
"%s: line %d: domain pattern already specified.\n",
fname, lineno );
acl_usage();
}
regtest(fname, lineno, right);
b->a_domain_pat = ch_strdup( right );
continue;
}
if ( strcasecmp( left, "url" ) == 0 ) {
if( b->a_url_pat != NULL ) {
fprintf( stderr,
"%s: line %d: url pattern already specified.\n",
fname, lineno );
acl_usage();
}
regtest(fname, lineno, right);
b->a_url_pat = ch_strdup( right );
continue;
}
/* get <access> */
if ( ACL_IS_INVALID(ACL_SET(b->a_access, str2access( left ))) ) {
fprintf( stderr,
"%s: line %d: expecting <access> got \"%s\"\n",
fname, lineno, left );
acl_usage();
}
access_append( &a->acl_access, b );
break;
}
} else {
fprintf( stderr,
"%s: line %d: expecting \"to\" or \"by\" got \"%s\"\n",
......@@ -377,9 +430,10 @@ acl_usage( void )
"<what> ::= * | [dn=<regex>] [filter=<ldapfilter>] [attrs=<attrlist>]\n"
"<attrlist> ::= <attr> | <attr> , <attrlist>\n"
"<attr> ::= <attrname> | entry | children\n"
"<who> ::= * | anonymous | self | dn=<regex> | addr=<regex>\n"
"\t| domain=<regex> | dnattr=<dnattrname>\n"
"\t| group[/<objectclass>[/<attrname>]]=<regex>\n"
"<who> ::= * | anonymous | self | dn=<regex>\n"
"\t| dnattr=<attrname> | group[/<objectclass>[/<attrname>]]=<regex>\n"
"\t| peername=<regex> | sockname=<regex>\n"
"\t| domain=<regex> | sockurl=<regex>\n"
"<access> ::= [self]{none|auth|compare|search|read|write}\n"
);
exit( 1 );
......@@ -424,29 +478,49 @@ print_access( Access *b )
{
fprintf( stderr, "\tby" );
if ( b->a_dnpat != NULL ) {
if( strcmp(b->a_dnpat, "anonymous") == 0 ) {
if ( b->a_dn_pat != NULL ) {
if( strcmp(b->a_dn_pat, "anonymous") == 0 ) {