From 2b2cc9c5e4016d144ce08767d6d5b3649a3df799 Mon Sep 17 00:00:00 2001 From: Anupam Jain Date: Thu, 27 Jun 2013 11:32:15 -0700 Subject: [PATCH] Ticket 47384 - Plugin library path validation Description: Added the validations to check plugin library path before performing add or modify operations --- ldap/servers/slapd/dse.c | 161 ++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 160 insertions(+), 1 deletion(-) diff --git a/ldap/servers/slapd/dse.c b/ldap/servers/slapd/dse.c index ab7448c..b80f2fc 100644 --- a/ldap/servers/slapd/dse.c +++ b/ldap/servers/slapd/dse.c @@ -253,7 +253,7 @@ dse_callback_new(int operation, int flags, const Slapi_DN *base, int scope, cons static void dse_callback_delete(struct dse_callback **pp) -{ +{ if (pp!=NULL) { slapi_sdn_free(&((*pp)->base)); slapi_ch_free((void**)&((*pp)->filter)); @@ -1847,6 +1847,89 @@ dse_modify(Slapi_PBlock *pb) /* JCM There should only be one exit point from thi goto done; } + /* check for invalid nsslapd-pluginPath */ + + if ( slapi_entry_attr_hasvalue( ec, SLAPI_ATTR_OBJECTCLASS, "nsslapdPlugin" ) ) { + Slapi_Mods *smods = NULL; + Slapi_Mod *smod = NULL, *next_mod = NULL; + smods = slapi_mods_new(); + next_mod = slapi_mod_new(); + slapi_mods_init_byref( smods, mods ); + smod = slapi_mods_get_first_smod( smods, next_mod ); + + while ( smod ) { + char *type = ( char* )slapi_mod_get_type( smod ); + int op = ( (slapi_mod_get_operation( smod ) ) & ~LDAP_MOD_BVALUES ); + if (( strcasecmp( type, ATTR_PLUGIN_PATH ) == 0 ) && (( op == 0 ) || ( op == 2 ))) { + struct berval *bv = slapi_mod_get_first_value( smod ); + while ( bv ) { + char *entry_val = slapi_ch_smprintf( "%s", bv ->bv_val ); + int entry_val_len = strlen( entry_val ); + int plugindir_len = strlen( PLUGINDIR ); + char *resolved_path = NULL; + + /* check for absolute path */ + if ( entry_val[0] == '/' ) { + resolved_path = slapi_ch_malloc( entry_val_len ); + char file_extn[4]; + int i = 0; + for ( i=0; i<4; i++ ) + file_extn[i] = entry_val[ entry_val_len-( 3-i ) ]; + if ( strcmp( file_extn, ".so" ) == 0 ) { + char *res = realpath( entry_val, resolved_path ); + if ( res ) { + if ( strncmp( PLUGINDIR, resolved_path, plugindir_len ) != 0 ) + returncode = LDAP_PARAM_ERROR; + } + else + returncode = LDAP_PARAM_ERROR; + } + else + returncode = LDAP_PARAM_ERROR; + } + else { + char file_extn[4]; + char *resolved_entry = NULL; + int i = 0; + for ( i=0; i<4; i++ ) + file_extn[i] = entry_val[ entry_val_len - ( 3-i ) ]; + if ( strcmp( file_extn, ".so" ) == 0 ) + resolved_entry = slapi_ch_smprintf( "%s%s%s", PLUGINDIR, "/", entry_val ); + else + resolved_entry = slapi_ch_smprintf( "%s%s%s%s", PLUGINDIR, "/", entry_val, ".so" ); + + resolved_path = slapi_ch_malloc( strlen( resolved_entry ) + 1 ); + char *res = realpath( resolved_entry, resolved_path ); + + if ( res ) { + if ( strncmp( PLUGINDIR, resolved_path, plugindir_len ) != 0 ) + returncode = LDAP_PARAM_ERROR; + } + else + returncode = LDAP_PARAM_ERROR; + slapi_ch_free_string( &resolved_entry ); + } + + slapi_ch_free( (void **) &resolved_path ); + slapi_ch_free_string( &entry_val ); + if( returncode == LDAP_PARAM_ERROR ) { + PL_strncpyz( returntext, "Invalid Plugin Path", sizeof( returntext )); + goto done; + } + bv = slapi_mod_get_next_value( smod ); + } + } + smod = slapi_mods_get_next_smod( smods, next_mod ); + } + slapi_mod_free( &next_mod ); + slapi_mods_free( &smods ); + } + + + + + + /* Save away a copy of the entry, before modifications */ slapi_pblock_set( pb, SLAPI_ENTRY_PRE_OP, slapi_entry_dup( ec )); /* JCM - When does this get free'd? */ /* richm - it is freed in modify.c */ @@ -2168,6 +2251,82 @@ dse_add(Slapi_PBlock *pb) /* JCM There should only be one exit point from this f goto done; } + /* check for invalid nsslapd-pluginPath */ + + if ( slapi_entry_attr_hasvalue( e, SLAPI_ATTR_OBJECTCLASS, "nsslapdPlugin" ) ) { + + char **vals = slapi_entry_attr_get_charray ( e, ATTR_PLUGIN_PATH ); + int j = 0; + for ( j=0; vals && vals[j]; j++ ) { + char *entry_val = slapi_ch_smprintf( "%s", vals[j] ); + int entry_val_len = strlen( entry_val ); + int plugindir_len = strlen( PLUGINDIR ); + char *resolved_path = NULL; + + /* check for absolute path */ + if ( entry_val[0] == '/' ) { + resolved_path = slapi_ch_malloc( entry_val_len ); + char file_extn[4]; + int i = 0; + for ( i=0; i<4; i++ ) + file_extn[i] = entry_val[ entry_val_len-( 3-i ) ]; + if ( strcmp( file_extn, ".so" ) == 0 ) { + char *res = realpath( entry_val, resolved_path ); + if ( res ) { + if ( strncmp( PLUGINDIR, resolved_path, plugindir_len ) != 0 ) { + returncode = LDAP_PARAM_ERROR; + e = NULL; + } + } + else { + returncode = LDAP_PARAM_ERROR; + e = NULL; + } + } + else { + returncode = LDAP_PARAM_ERROR; + e = NULL; + } + } + else { + char file_extn[4]; + char *resolved_entry = NULL; + int i = 0; + for ( i=0; i<4; i++ ) + file_extn[i] = entry_val[ entry_val_len - ( 3-i ) ]; + if ( strcmp( file_extn, ".so" ) == 0 ) + resolved_entry = slapi_ch_smprintf( "%s%s%s", PLUGINDIR, "/", entry_val ); + else + resolved_entry = slapi_ch_smprintf( "%s%s%s%s", PLUGINDIR, "/", entry_val, ".so" ); + + resolved_path = slapi_ch_malloc( strlen( resolved_entry ) + 1 ); + char *res = realpath( resolved_entry, resolved_path ); + + if ( res ) { + if ( strncmp( PLUGINDIR, resolved_path, plugindir_len ) != 0 ) { + returncode = LDAP_PARAM_ERROR; + e = NULL; + } + } + else { + returncode = LDAP_PARAM_ERROR; + e = NULL; + } + slapi_ch_free_string( &resolved_entry ); + } + + slapi_ch_free( (void **) &resolved_path ); + slapi_ch_free_string( &entry_val ); + if( returncode == LDAP_PARAM_ERROR ) { + PL_strncpyz( returntext, "Invalid Plugin Path", sizeof( returntext )); + goto done; + } + } + slapi_ch_array_free ( vals ); + } + + + if(dse_call_callback(pdse, pb, SLAPI_OPERATION_ADD, DSE_FLAG_PREOP, e, NULL, &returncode, returntext)!=SLAPI_DSE_CALLBACK_OK) { if (!returncode) { -- 1.8.1.4