JDataStore is a feature of JBuilder Professional and Enterprise, and the Inprise Application Server.
JDataStore provides several built-in security features. This collection of features provides user authentication, user authorization, and encryption for JDataStore databases.
By default JDataStore databases do not require users to be authenticated to access the database. JDataStore authentication support can be enabled by adding at least one user to the SYS/USERS
system table in a JDataStore database. This can be done either programmatically, or by using JDataStore Explorer.
The SYS/USERS
table is read-only if it is accessed by a JDBC query or a StorageDataSet
.
When users are added, their initial password and database rights are supplied.
There are three methods that can be used to administer users. DataStoreRights.ADMINISTRATOR
rights are required to call these methods.
DataStoreConnection.addUser()
method.
DataStoreConnection.removeUser()
method.
DataStoreConnection.changeRights()
method.
DSX: See "Administering Users" for an explanation of administering users using the JDataStore Explorer.
There is aDataStoreConnection.changePassword()
method that can be used to change a password. Any user can change their own password. It requires knowledge of the existing password, but does not require DataStoreRights.ADMINISTRATOR
rights.
DSX: For instructions on changing a password through the JDataStore Explorer, see "Changing a password".
Database rights are supported by specifying the constants in the com.borland.datastore.DataStoreRights
interface. The rights specified by DataStoreRights
include:
STARTUP
- the ability to open a database that is shutdown. The user's password is required to add STARTUP
rights to a user. The DataStoreConnection.changeRights()
method's pass
parameter must not be null, and must match the user's password when calling this method to add STARTUP
rights. STARTUP
rights can also be specified when the user is added.
ADMINISTRATOR
- includes rights to add, remove, and change rights of users, and the ability to encrypt the database. Also includes the four stream rights (WRITE
, CREATE
, DROP
, RENAME
). STARTUP
rights are given to administrators by default when the administrator is added, but STARTUP
rights can be removed from an administrator. WRITE
, CREATE
, DROP
, and RENAME
rights cannot be removed from an administrator. Any attempt to remove these rights from an administrator will be ignored.
WRITE
- the ability to write to file or table streams in the JDataStore.
CREATE
- the ability to create new file or table streams in the JDataStore.
DROP
- the ability to remove file or table streams from the JDataStore.
RENAME
- the ability to rename file or table streams in the JDataStore.
A DataStoreRights.ADMINISTRATOR
user can encrypt an empty database that has a
DataStoreConnection.getVersion()
of DataStore.VERSION_6_0
or greater. The DataStoreConnection.encrypt()
method can be used to encrypt databases.
DataStoreConnection.encrypt()
will remove DataStoreRights.STARTUP
from all users except for the administrator that is adding the encryption. This is because the user's password is required to add STARTUP
rights to a user. To provide STARTUP
rights to a user, call DataStoreConnection.changeRights()
, or drop the user and then add the user back.
Note: A database with existing table or file streams will not be encrypted. If you want to encrypt an existing database, create a new database, call DataStoreConnection.copyUsers()
to copy the existing users to the new database, then go ahead and encrypt the new database. Then call DataStoreConnection.copyStreams()
to copy the contents of the old database into the encrypted database.
For more information on copying streams see "Copying JDataStore Streams".
DSX: See "Encrypting a JDataStore" for information on how to encrypt a JDataStore using the JDataStore Explorer.
In this discussion an opponent is someone who is trying to break the JDataStore security system.
The authentication and authorization support is secure for server side applications where opponents do not have access to
the physical JDataStore files. The SYS/USERS
table stores passwords, user IDs, and rights in encrypted form. The table also
stores the user ID and rights in an unencrypted column, but this is for display purposes only. The encrypted values for user
ID and rights are used for security enforcement.
The stored passwords are encrypted using a strong TwoFish block cypher. A pseudo-random number generator is used to salt the encryption of the password. This makes traditional password dictionary attacks much more difficult. In a dictionary attack, the opponent makes guesses until the password is guessed. This process is easier if the the opponent has personal information about the user, and the user has chosen an obvious password. There is no substitution for a well chosen (obscure) password as a defense against password dictionary attacks. When an incorrect password is entered, the current thread sleeps for 500 milliseconds.
If a JDataStore database is unencrypted, it is important to restrict physical access to the file, for the following reasons:
If it is possible for an opponent to read a JDataStore database file that is not encrypted with a separate file editing utility or program, the opponent might be able to reverse engineer the file format and view its contents.
For environments where a dangerous opponent may gain access to physical copies of a JDataStore, the database and log files should be encrypted, in addition to being password protected.
Warning: The cryptographic techniques that JDataStore uses to encrypt data blocks is state of the art. The TwoFish block cypher used by JDataStore has never been defeated. So this means that if you forget your password for an encrypted JDataStore database, you are really out of luck. The best chance of recovering the data would be to have someone guess the password.
There are measures that can be used to guard against forgetting a password for an encrypted database. It is important to note that there is a master password used internally to encrypt data blocks. Any user that has STARTUP
rights will have the master password encrypted using their password in the SYS/USERS
table. This allows one or more users to open a database that has been shutdown because their password can be used to decrypt a copy of the master password. This feature can be used to create a virgin database that has one secret user in it that has DataStoreRights.ADMINISTRATOR
rights (which includes DataStorerights.STARTUP rights
). If this virgin
database is used whenever a new empty database is needed, you will always have one secret user that can unlock the encryption.
Encrypting a database will affect performance somewhat. Data blocks are encrypted when they are written from the JDataStore cache to the JDataStore database file. Data blocks are decrypted when they are read from the JDataStore database file into the JDataStore cache. So the cost of encryption is only incurred when file I/O is performed.
JDataStore encrypts all but the first 16 bytes of .jds
file data blocks. There is no user data in the first 16 bytes of a data
block. Some blocks are not encrypted. This includes allocation bitmap blocks, the header block, log anchor blocks and
the SYS/USERS
table blocks. Note that the sensitive fields in the SYS/USERS
table are encrypted using the user's
password. Log file blocks are completely encrypted. Log anchor and status log files are not encrypted. The temporary
database used by the query engine is encrypted. Sort files used by large merge sorts are not encrypted, but they are
deleted after the sort completes.
Note that the remote JDBC driver for JDataStore currently uses Java socket classes to communicate with a JDataStore Server. This communication is not secure. Since the local JDBC driver for JDataStore is in-process, it is secure.