From: Howard Chu Date: Sat, 15 Dec 2007 19:07:41 +0000 (+0000) Subject: Support DB encryption X-Git-Tag: OPENLDAP_REL_ENG_2_4_9~20^2~298 X-Git-Url: https://git.sur5r.net/?a=commitdiff_plain;h=ddd90958a151f56684fcea954ab9b43e8809d597;p=openldap Support DB encryption --- diff --git a/servers/slapd/back-bdb/back-bdb.h b/servers/slapd/back-bdb/back-bdb.h index e3a9a2caad..90c119c3e4 100644 --- a/servers/slapd/back-bdb/back-bdb.h +++ b/servers/slapd/back-bdb/back-bdb.h @@ -235,6 +235,8 @@ struct bdb_info { alock_info_t bi_alock_info; char *bi_db_config_path; BerVarray bi_db_config; + char *bi_db_crypt_file; + struct berval bi_db_crypt_key; bdb_monitor_t bi_monitor; #ifdef BDB_MONITOR_IDX diff --git a/servers/slapd/back-bdb/config.c b/servers/slapd/back-bdb/config.c index 32291d7d05..eda23ebd4e 100644 --- a/servers/slapd/back-bdb/config.c +++ b/servers/slapd/back-bdb/config.c @@ -42,6 +42,8 @@ static ConfigDriver bdb_cf_gen; enum { BDB_CHKPT = 1, BDB_CONFIG, + BDB_CRYPTFILE, + BDB_CRYPTKEY, BDB_DIRECTORY, BDB_NOSYNC, BDB_DIRTYR, @@ -70,6 +72,14 @@ static ConfigTable bdbcfg[] = { bdb_cf_gen, "( OLcfgDbAt:1.2 NAME 'olcDbCheckpoint' " "DESC 'Database checkpoint interval in kbytes and minutes' " "SYNTAX OMsDirectoryString SINGLE-VALUE )",NULL, NULL }, + { "cryptfile", "file", 2, 2, 0, ARG_STRING|ARG_MAGIC|BDB_CRYPTFILE, + bdb_cf_gen, "( OLcfgDbAt:1.13 NAME 'olcDbCryptFile' " + "DESC 'Pathname of file containing the DB encryption key' " + "SYNTAX OMsDirectoryString SINGLE-VALUE )",NULL, NULL }, + { "cryptkey", "key", 2, 2, 0, ARG_BERVAL|ARG_MAGIC|BDB_CRYPTKEY, + bdb_cf_gen, "( OLcfgDbAt:1.14 NAME 'olcDbCryptKey' " + "DESC 'DB encryption key' " + "SYNTAX OMsOctetString SINGLE-VALUE )",NULL, NULL }, { "dbconfig", "DB_CONFIG setting", 1, 0, 0, ARG_MAGIC|BDB_CONFIG, bdb_cf_gen, "( OLcfgDbAt:1.3 NAME 'olcDbConfig' " "DESC 'BerkeleyDB DB_CONFIG configuration directives' " @@ -143,6 +153,7 @@ static ConfigOCs bdbocs[] = { "SUP olcDatabaseConfig " "MUST olcDbDirectory " "MAY ( olcDbCacheSize $ olcDbCheckpoint $ olcDbConfig $ " + "olcDbCryptFile $ olcDbCryptKey $ " "olcDbNoSync $ olcDbDirtyRead $ olcDbIDLcacheSize $ " "olcDbIndex $ olcDbLinearIndex $ olcDbLockDetect $ " "olcDbMode $ olcDbSearchStack $ olcDbShmKey $ " @@ -364,6 +375,25 @@ bdb_cf_gen( ConfigArgs *c ) } break; + case BDB_CRYPTFILE: + if ( bdb->bi_db_crypt_file ) { + c->value_string = ch_strdup( bdb->bi_db_crypt_file ); + } else { + rc = 1; + } + break; + + /* If a crypt file has been set, its contents are copied here. + * But we don't want the key to be incorporated here. + */ + case BDB_CRYPTKEY: + if ( !bdb->bi_db_crypt_file && !BER_BVISNULL( &bdb->bi_db_crypt_key )) { + value_add_one( &c->rvalue_vals, &bdb->bi_db_crypt_key ); + } else { + rc = 1; + } + break; + case BDB_DIRECTORY: if ( bdb->bi_dbenv_home ) { c->value_string = ch_strdup( bdb->bi_dbenv_home ); @@ -472,6 +502,21 @@ bdb_cf_gen( ConfigArgs *c ) bdb->bi_flags |= BDB_UPD_CONFIG; c->cleanup = bdb_cf_cleanup; break; + /* Doesn't really make sense to change these on the fly; + * the entire DB must be dumped and reloaded + */ + case BDB_CRYPTFILE: + if ( bdb->bi_db_crypt_file ) { + ch_free( bdb->bi_db_crypt_file ); + bdb->bi_db_crypt_file = NULL; + } + /* FALLTHRU */ + case BDB_CRYPTKEY: + if ( !BER_BVISNULL( &bdb->bi_db_crypt_key )) { + ch_free( bdb->bi_db_crypt_key.bv_val ); + BER_BVZERO( &bdb->bi_db_crypt_key ); + } + break; case BDB_DIRECTORY: bdb->bi_flags |= BDB_RE_OPEN; bdb->bi_flags ^= BDB_HAS_CONFIG; @@ -616,6 +661,22 @@ bdb_cf_gen( ConfigArgs *c ) } break; + case BDB_CRYPTFILE: + rc = lutil_get_filed_password( c->value_string, &bdb->bi_db_crypt_key ); + if ( rc == 0 ) { + bdb->bi_db_crypt_file = c->value_string; + } + break; + + /* Cannot set key if file was already set */ + case BDB_CRYPTKEY: + if ( bdb->bi_db_crypt_file ) { + rc = 1; + } else { + bdb->bi_db_crypt_key = c->value_bv; + } + break; + case BDB_DIRECTORY: { FILE *f; char *ptr, *testpath; diff --git a/servers/slapd/back-bdb/dbcache.c b/servers/slapd/back-bdb/dbcache.c index ba005476f2..ec24666c65 100644 --- a/servers/slapd/back-bdb/dbcache.c +++ b/servers/slapd/back-bdb/dbcache.c @@ -104,9 +104,23 @@ bdb_db_cache( "bdb_db_cache: db_create(%s) failed: %s (%d)\n", bdb->bi_dbenv_home, db_strerror(rc), rc ); ldap_pvt_thread_mutex_unlock( &bdb->bi_database_mutex ); + ch_free( db ); return rc; } + if( !BER_BVISNULL( &bdb->bi_db_crypt_key )) { + rc = db->bdi_db->set_flags( db->bdi_db, DB_ENCRYPT ); + if ( rc ) { + Debug( LDAP_DEBUG_ANY, + "bdb_db_cache: db set_flags(DB_ENCRYPT)(%s) failed: %s (%d)\n", + bdb->bi_dbenv_home, db_strerror(rc), rc ); + ldap_pvt_thread_mutex_unlock( &bdb->bi_database_mutex ); + db->bdi_db->close( db->bdi_db, 0 ); + ch_free( db ); + return rc; + } + } + rc = db->bdi_db->set_pagesize( db->bdi_db, BDB_PAGESIZE ); #ifdef BDB_INDEX_USE_HASH rc = db->bdi_db->set_h_hash( db->bdi_db, bdb_db_hash ); diff --git a/servers/slapd/back-bdb/init.c b/servers/slapd/back-bdb/init.c index 552540112f..3b4d42672c 100644 --- a/servers/slapd/back-bdb/init.c +++ b/servers/slapd/back-bdb/init.c @@ -279,6 +279,18 @@ shm_retry: bdb->bi_dbenv->set_lk_detect( bdb->bi_dbenv, bdb->bi_lock_detect ); + if ( !BER_BVISNULL( &bdb->bi_db_crypt_key )) { + rc = bdb->bi_dbenv->set_encrypt( bdb->bi_dbenv, bdb->bi_db_crypt_key.bv_val, + DB_ENCRYPT_AES ); + if ( rc ) { + Debug( LDAP_DEBUG_ANY, + LDAP_XSTRING(bdb_db_open) ": database \"%s\": " + "dbenv set_encrypt failed: %s (%d).\n", + be->be_suffix[0].bv_val, db_strerror(rc), rc ); + goto fail; + } + } + /* One long-lived TXN per thread, two TXNs per write op */ bdb->bi_dbenv->set_tx_max( bdb->bi_dbenv, connection_pool_max * 3 ); @@ -390,6 +402,20 @@ shm_retry: goto fail; } + if( !BER_BVISNULL( &bdb->bi_db_crypt_key )) { + rc = db->bdi_db->set_flags( db->bdi_db, DB_ENCRYPT ); + if ( rc ) { + snprintf(cr->msg, sizeof(cr->msg), + "database \"%s\": db set_flags(DB_ENCRYPT)(%s) failed: %s (%d).", + be->be_suffix[0].bv_val, + bdb->bi_dbenv_home, db_strerror(rc), rc ); + Debug( LDAP_DEBUG_ANY, + LDAP_XSTRING(bdb_db_open) ": %s\n", + cr->msg, 0, 0 ); + goto fail; + } + } + if( i == BDB_ID2ENTRY ) { if ( slapMode & SLAP_TOOL_MODE ) db->bdi_db->mpf->set_priority( db->bdi_db->mpf,