From 03c64541d4efbe43ec848f18749262bc853ac45c Mon Sep 17 00:00:00 2001 From: Pierangelo Masarati Date: Sat, 1 May 2004 17:53:37 +0000 Subject: [PATCH] add granular op restriction --- doc/man/man5/slapd.conf.5 | 28 ++++++++++ servers/slapd/backend.c | 17 +++++- servers/slapd/config.c | 110 +++++++++++++++++++++++++++++++++++++- servers/slapd/slap.h | 7 +++ 4 files changed, 159 insertions(+), 3 deletions(-) diff --git a/doc/man/man5/slapd.conf.5 b/doc/man/man5/slapd.conf.5 index f3356344e0..961bba83b6 100644 --- a/doc/man/man5/slapd.conf.5 +++ b/doc/man/man5/slapd.conf.5 @@ -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 +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[=] , +.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 Specify the distinguished name that is not subject to access control or administrative limit restrictions for operations on this database. diff --git a/servers/slapd/backend.c b/servers/slapd/backend.c index b8f4b17d00..b99ecdc1e2 100644 --- a/servers/slapd/backend.c +++ b/servers/slapd/backend.c @@ -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"; } diff --git a/servers/slapd/config.c b/servers/slapd/config.c index b2e147ade8..c0ca57b330 100644 --- a/servers/slapd/config.c +++ b/servers/slapd/config.c @@ -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 in \"restrict \" " + "line.\n", fname, lineno ,0 ); +#else + Debug( LDAP_DEBUG_ANY, + "%s: line %d: missing in \"restrict \" " + "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 \" line.\n", + fname, lineno, cargv[i] ); +#else + Debug( LDAP_DEBUG_ANY, "%s: line %d: " + "unknown operation %s in \"allow \" 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 \" line.\n", - fname, lineno, cargv[1] ); + fname, lineno, cargv[i] ); #else Debug( LDAP_DEBUG_ANY, "%s: line %d: " "unknown feature %s in \"allow \" line\n", diff --git a/servers/slapd/slap.h b/servers/slapd/slap.h index e01c80dbec..1c0bf3175c 100644 --- a/servers/slapd/slap.h +++ b/servers/slapd/slap.h @@ -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 \ -- 2.39.5