Commit 03c64541 authored by Pierangelo Masarati's avatar Pierangelo Masarati
Browse files

add granular op restriction

parent 9284fbf8
......@@ -1273,6 +1273,34 @@ for more information. The specified file should be located
in a directory with limited read/write/execute access as the replication
logs may contain sensitive information.
.TP
.B restrict <oplist>
Specify a whitespace separated list of operations that are restricted.
If defined inside a database specification, restrictions apply only
to that database, otherwise they are global.
Operations can be any of
.BR add ,
.BR bind ,
.BR compare ,
.BR delete ,
.BR extended[=<OID>] ,
.BR modify ,
.BR rename ,
.BR search ,
or the special pseudo-operations
.B read
and
.BR write ,
which respectively summarize read and write operations.
The use of
.I restrict write
is equivalent to
.I readonly on
(see above).
The
.B extended
keyword allows to indicate the OID of the specific operation
to be restricted.
.TP
.B rootdn <dn>
Specify the distinguished name that is not subject to access control
or administrative limit restrictions for operations on this database.
......
......@@ -940,6 +940,7 @@ backend_check_restrictions(
slap_mask_t restrictops;
slap_mask_t requires;
slap_mask_t opflag;
slap_mask_t exopflag;
slap_ssf_set_t *ssf;
int updateop = 0;
int starttls = 0;
......@@ -989,14 +990,23 @@ backend_check_restrictions(
if( bvmatch( opdata, &slap_EXOP_START_TLS ) ) {
session++;
starttls++;
exopflag = SLAP_RESTRICT_EXOP_START_TLS;
break;
}
if( bvmatch( opdata, &slap_EXOP_WHOAMI ) ) {
exopflag = SLAP_RESTRICT_EXOP_WHOAMI;
break;
}
if ( bvmatch( opdata, &slap_EXOP_CANCEL ) ) {
exopflag = SLAP_RESTRICT_EXOP_CANCEL;
break;
}
if ( bvmatch( opdata, &slap_EXOP_MODIFY_PASSWD ) ) {
exopflag = SLAP_RESTRICT_EXOP_MODIFY_PASSWD;
updateop++;
break;
}
......@@ -1179,9 +1189,12 @@ backend_check_restrictions(
}
if( restrictops & opflag ) {
if( restrictops == SLAP_RESTRICT_OP_READS ) {
if( ( restrictops & opflag )
|| ( exopflag && ( restrictops & exopflag ) ) ) {
if( ( restrictops & SLAP_RESTRICT_OP_MASK) == SLAP_RESTRICT_OP_READS ) {
rs->sr_text = "read operations restricted";
} else if ( restrictops & exopflag ) {
rs->sr_text = "extended operation restricted";
} else {
rs->sr_text = "operation restricted";
}
......
......@@ -1304,6 +1304,114 @@ read_config( const char *fname, int depth )
}
}
/* restricts specific operations */
} else if ( strcasecmp( cargv[0], "restrict" ) == 0 ) {
slap_mask_t restrict = 0;
struct restrictable_exops_t {
char *name;
int flag;
} restrictable_exops[] = {
{ LDAP_EXOP_START_TLS, SLAP_RESTRICT_EXOP_START_TLS },
{ LDAP_EXOP_MODIFY_PASSWD, SLAP_RESTRICT_EXOP_MODIFY_PASSWD },
{ LDAP_EXOP_X_WHO_AM_I, SLAP_RESTRICT_EXOP_WHOAMI },
{ LDAP_EXOP_X_CANCEL, SLAP_RESTRICT_EXOP_CANCEL },
{ NULL, 0 }
};
int i;
if ( cargc < 2 ) {
#ifdef NEW_LOGGING
LDAP_LOG( CONFIG, CRIT,
"%s: line %d: missing <op_list> in \"restrict <op_list>\" "
"line.\n", fname, lineno ,0 );
#else
Debug( LDAP_DEBUG_ANY,
"%s: line %d: missing <op_list> in \"restrict <op_list>\" "
"line.\n", fname, lineno, 0 );
#endif
return( 1 );
}
for ( i = 1; i < cargc; i++ ) {
if ( strcasecmp( cargv[ i ], "read" ) == 0 ) {
restrict |= SLAP_RESTRICT_OP_READS;
} else if ( strcasecmp( cargv[ i ], "write" ) == 0 ) {
restrict |= SLAP_RESTRICT_OP_WRITES;
} else if ( strcasecmp( cargv[ i ], "add" ) == 0 ) {
restrict |= SLAP_RESTRICT_OP_ADD;
} else if ( strcasecmp( cargv[ i ], "bind" ) == 0 ) {
restrict |= SLAP_RESTRICT_OP_BIND;
} else if ( strcasecmp( cargv[ i ], "compare" ) == 0 ) {
restrict |= SLAP_RESTRICT_OP_COMPARE;
} else if ( strcasecmp( cargv[ i ], "delete" ) == 0 ) {
restrict |= SLAP_RESTRICT_OP_DELETE;
} else if ( strncasecmp( cargv[ i ], "extended",
STRLENOF( "extended" ) ) == 0 ) {
char *e = cargv[ i ] + STRLENOF( "extended" );
restrict |= SLAP_RESTRICT_OP_EXTENDED;
if ( e[0] == '=' ) {
int j;
e++;
for ( j = 0; restrictable_exops[ j ].name; j++ ) {
if ( strcmp( e, restrictable_exops[ j ].name ) == 0 ) {
restrict |= restrictable_exops[ j ].flag;
break;
}
}
if ( restrictable_exops[ j ].name == NULL ) {
goto restrict_unknown;
}
} else if ( e[0] == '\0' ) {
restrict = SLAP_RESTRICT_EXOP_MASK;
} else {
goto restrict_unknown;
}
} else if ( strcasecmp( cargv[ i ], "modify" ) == 0 ) {
restrict |= SLAP_RESTRICT_OP_MODIFY;
} else if ( strcasecmp( cargv[ i ], "rename" ) == 0
|| strcasecmp( cargv[ i ], "modrdn" ) == 0 ) {
restrict |= SLAP_RESTRICT_OP_RENAME;
} else if ( strcasecmp( cargv[ i ], "search" ) == 0 ) {
restrict |= SLAP_RESTRICT_OP_SEARCH;
} else {
restrict_unknown:;
#ifdef NEW_LOGGING
LDAP_LOG( CONFIG, CRIT, "%s: line %d: "
"unknown operation %s in \"allow <features>\" line.\n",
fname, lineno, cargv[i] );
#else
Debug( LDAP_DEBUG_ANY, "%s: line %d: "
"unknown operation %s in \"allow <features>\" line\n",
fname, lineno, cargv[i] );
#endif
return 1;
}
}
if ( be == NULL ) {
global_restrictops |= restrict;
} else {
be->be_restrictops |= restrict;
}
/* allow these features */
} else if ( strcasecmp( cargv[0], "allows" ) == 0 ||
......@@ -1357,7 +1465,7 @@ read_config( const char *fname, int depth )
#ifdef NEW_LOGGING
LDAP_LOG( CONFIG, CRIT, "%s: line %d: "
"unknown feature %s in \"allow <features>\" line.\n",
fname, lineno, cargv[1] );
fname, lineno, cargv[i] );
#else
Debug( LDAP_DEBUG_ANY, "%s: line %d: "
"unknown feature %s in \"allow <features>\" line\n",
......
......@@ -1490,6 +1490,13 @@ struct slap_backend_db {
#define SLAP_RESTRICT_OP_MODIFY 0x0020U
#define SLAP_RESTRICT_OP_RENAME 0x0040U
#define SLAP_RESTRICT_OP_SEARCH 0x0080U
#define SLAP_RESTRICT_OP_MASK 0x00FFU
#define SLAP_RESTRICT_EXOP_START_TLS 0x0100U
#define SLAP_RESTRICT_EXOP_MODIFY_PASSWD 0x0200U
#define SLAP_RESTRICT_EXOP_WHOAMI 0x0400U
#define SLAP_RESTRICT_EXOP_CANCEL 0x0800U
#define SLAP_RESTRICT_EXOP_MASK 0xFF00U
#define SLAP_RESTRICT_OP_READS \
( SLAP_RESTRICT_OP_COMPARE \
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment