public abstract class AuthenticationServiceBase extends java.lang.Object implements AuthenticationService, ModuleControl, ModuleSupportable, PropertySetCallback
This is the authentication service base class.
There can be 1 Authentication Service for the whole Derby system and/or 1 authentication per database. In a near future, we intend to allow multiple authentication services per system and/or per database.
It should be extended by the specialized authentication services.
IMPORTANT NOTE:
User passwords are hashed using a message digest algorithm if they're stored in the database. They are not hashed if they were defined at the system level.
The passwords can be hashed using two different schemes:
In order to use the configurable hash authentication scheme, the users have
to set the derby.authentication.builtin.algorithm
property (on
system level or database level) to the name of an algorithm that's available
in one of the security providers registered on the system. If this property
is not set, or if it's set to NULL or an empty string, the SHA-1
authentication scheme is used.
Which scheme to use is decided when a password is about to be stored in the
database. One database may therefore contain passwords stored using
different schemes. In order to determine which scheme to use when comparing
a user's credentials with those stored in the database, the stored password
is prefixed with an identifier that tells which scheme is being used.
Passwords stored using the SHA-1 authentication scheme are prefixed with
PasswordHasher.ID_PATTERN_SHA1_SCHEME
. Passwords that are stored using the
configurable hash authentication scheme are prefixed with
PasswordHasher.ID_PATTERN_CONFIGURABLE_HASH_SCHEME
and suffixed with the name of
the message digest algorithm.
Modifier and Type | Field and Description |
---|---|
protected UserAuthenticator |
authenticationScheme |
static java.lang.String |
AuthenticationTrace
Trace flag to trace authentication operations
|
protected static int |
SECMEC_USRSSBPWD
Userid with Strong password substitute DRDA security mechanism
|
private AccessFactory |
store |
MODULE
Constructor and Description |
---|
AuthenticationServiceBase() |
Modifier and Type | Method and Description |
---|---|
Serviceable |
apply(java.lang.String key,
java.io.Serializable value,
java.util.Dictionary p)
Apply a property change.
|
boolean |
authenticate(java.lang.String databaseName,
java.util.Properties userInfo)
Authenticate a User inside JBMS.T his is an overload method.
|
void |
boot(boolean create,
java.util.Properties properties)
Start this module.
|
private static Context |
getContext(java.lang.String contextID)
Privileged lookup of a Context.
|
private static ContextService |
getContextService()
Privileged lookup of the ContextService.
|
(package private) java.util.Properties |
getDatabaseProperties()
Get all the database properties.
|
java.lang.String |
getDatabaseProperty(java.lang.String key) |
private static DataDictionary |
getDataDictionary()
Find the data dictionary for the current connection.
|
java.lang.String |
getProperty(java.lang.String key)
Returns a property if it was set at the database or
system level.
|
(package private) static java.lang.Object |
getServiceModule(java.lang.Object serviceModule,
java.lang.String factoryInterface)
Privileged module lookup.
|
protected java.lang.String |
getServiceName()
Get the name of the database if we are performing authentication at the database level.
|
private static java.lang.String |
getServiceName(java.lang.Object serviceModule)
Privileged service name lookup.
|
java.lang.String |
getSystemCredentialsDatabaseName()
Get the name of the credentials database used to authenticate system-wide operations.
|
java.lang.String |
getSystemProperty(java.lang.String key) |
protected TransactionController |
getTransaction()
Get a transaction for performing authentication at the database level.
|
protected java.lang.String |
hashPasswordSHA1Scheme(java.lang.String plainTxtUserPassword)
This method hashes a clear user password using a
Single Hash algorithm such as SHA-1 (SHA equivalent)
(it is a 160 bits digest)
The digest is returned as an object string.
|
(package private) java.lang.String |
hashUsingDefaultAlgorithm(java.lang.String user,
java.lang.String password,
java.util.Dictionary props)
Hash a password using the default message digest algorithm for this
system before it's stored in the database.
|
void |
init(boolean dbOnly,
java.util.Dictionary p)
Initialize the properties for this callback.
|
java.io.Serializable |
map(java.lang.String key,
java.io.Serializable value,
java.util.Dictionary p)
Map a proposed new value for a property to an official value.
|
protected java.lang.Long |
parsePasswordLifetime(java.lang.String passwordLifetimeString)
Parse the value of the password lifetime property.
|
protected java.lang.Double |
parsePasswordThreshold(java.lang.String expirationThresholdString)
Parse the value of the password expiration threshold property.
|
protected boolean |
requireAuthentication(java.util.Properties properties) |
protected void |
setAuthenticationService(UserAuthenticator aScheme) |
void |
stop()
Stop the module.
|
protected java.lang.String |
substitutePassword(java.lang.String userName,
java.lang.String password,
java.util.Properties info,
boolean databaseUser)
Strong Password Substitution (USRSSBPWD).
|
private static byte[] |
toHexByte(java.lang.String str)
Convert a string into a byte array in hex format.
|
boolean |
validate(java.lang.String key,
java.io.Serializable value,
java.util.Dictionary p)
Validate a property change.
|
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
canSupport
protected UserAuthenticator authenticationScheme
private AccessFactory store
public static final java.lang.String AuthenticationTrace
protected static final int SECMEC_USRSSBPWD
protected void setAuthenticationService(UserAuthenticator aScheme)
public void boot(boolean create, java.util.Properties properties) throws StandardException
boot
in interface ModuleControl
StandardException
- upon failure to load/boot
the expected authentication service.ModuleControl.boot(boolean, java.util.Properties)
public void stop()
ModuleControl
stop
in interface ModuleControl
ModuleControl.stop()
public boolean authenticate(java.lang.String databaseName, java.util.Properties userInfo) throws java.sql.SQLException
authenticate
in interface AuthenticationService
userInfo
- Connection properties info.
failure.java.sql.SQLException
AuthenticationService.authenticate(java.lang.String, java.util.Properties)
public java.lang.String getSystemCredentialsDatabaseName()
AuthenticationService
Get the name of the credentials database used to authenticate system-wide operations. This returns null for all implementations except NATIVE authentication.
getSystemCredentialsDatabaseName
in interface AuthenticationService
public java.lang.String getProperty(java.lang.String key)
protected TransactionController getTransaction() throws StandardException
Get a transaction for performing authentication at the database level.
StandardException
java.util.Properties getDatabaseProperties() throws StandardException
null
if there is no
access factoryStandardException
protected java.lang.String getServiceName()
Get the name of the database if we are performing authentication at the database level.
public java.lang.String getDatabaseProperty(java.lang.String key)
public java.lang.String getSystemProperty(java.lang.String key)
public void init(boolean dbOnly, java.util.Dictionary p)
PropertySetCallback
Code within an init() method should use the 3 argument PropertyUtil method getPropertyFromSet() to obtain a property's value.
init
in interface PropertySetCallback
dbOnly
- true if only per-database properties are to be looked atp
- the complete set of per-database properties.public boolean validate(java.lang.String key, java.io.Serializable value, java.util.Dictionary p) throws StandardException
PropertySetCallback
validate
in interface PropertySetCallback
key
- Property key for the property being setvalue
- proposed new value for the property being set or null if
the property is being dropped.p
- Property set before the change. SettingProperty may read but
must never change p.StandardException
- Oh well.PropertySetCallback.validate(java.lang.String, java.io.Serializable, java.util.Dictionary)
protected java.lang.Long parsePasswordLifetime(java.lang.String passwordLifetimeString)
protected java.lang.Double parsePasswordThreshold(java.lang.String expirationThresholdString)
public Serviceable apply(java.lang.String key, java.io.Serializable value, java.util.Dictionary p)
PropertySetCallback
apply
in interface PropertySetCallback
key
- Property key for the property being setvalue
- proposed new value for the property being set or null if
the property is being dropped.p
- Property set before the change. SettingProperty may read but
must never change p.PropertySetCallback.validate(java.lang.String, java.io.Serializable, java.util.Dictionary)
public java.io.Serializable map(java.lang.String key, java.io.Serializable value, java.util.Dictionary p) throws StandardException
PropertySetCallback
map
in interface PropertySetCallback
key
- Property key for the property being setvalue
- proposed new value for the property being set or null if
the property is being dropped.p
- Property set before the change. SettingProperty may read but
must never change p.StandardException
- Thrown on error.PropertySetCallback.map(java.lang.String, java.io.Serializable, java.util.Dictionary)
protected final boolean requireAuthentication(java.util.Properties properties)
protected java.lang.String hashPasswordSHA1Scheme(java.lang.String plainTxtUserPassword)
This method hashes a clear user password using a Single Hash algorithm such as SHA-1 (SHA equivalent) (it is a 160 bits digest)
The digest is returned as an object string.
This method is only used by the SHA-1 authentication scheme.
plainTxtUserPassword
- Plain text user passwordnull
if the plaintext password is null
private static byte[] toHexByte(java.lang.String str)
Convert a string into a byte array in hex format.
For each character (b) two bytes are generated, the first byte
represents the high nibble (4 bits) in hexadecimal (b & 0xf0
),
the second byte represents the low nibble (b & 0x0f
).
The character at str.charAt(0)
is represented by the first two
bytes in the returned String.
New code is encouraged to use String.getBytes(String)
or similar
methods instead, since this method does not preserve all bits for
characters whose codepoint exceeds 8 bits. This method is preserved for
compatibility with the SHA-1 authentication scheme.
str
- stringjava.lang.String hashUsingDefaultAlgorithm(java.lang.String user, java.lang.String password, java.util.Dictionary props) throws StandardException
Hash a password using the default message digest algorithm for this system before it's stored in the database.
If the data dictionary supports the configurable hash authentication
scheme, and the property derby.authentication.builtin.algorithm
is a non-empty string, the password will be hashed using the
algorithm specified by that property. Otherwise, we fall back to the new
authentication scheme based on SHA-1. The algorithm used is encoded in
the returned token so that the code that validates a user's credentials
knows which algorithm to use.
user
- the user whose password to hashpassword
- the plain text passwordprops
- database propertiesnull
if password
is null
StandardException
- if the specified algorithm is not supportedprivate static DataDictionary getDataDictionary()
DataDictionary
for the current connectionprotected java.lang.String substitutePassword(java.lang.String userName, java.lang.String password, java.util.Properties info, boolean databaseUser)
PasswordHasher.ID_PATTERN_SHA1_SCHEME
), so in
the case of database passwords stored using that scheme, we can simply
compare the received hash with the stored hash. If the configurable
hash authentication scheme PasswordHasher.ID_PATTERN_CONFIGURABLE_HASH_SCHEME
is used, we have no way to find out if the received hash matches the
stored password, since we cannot decrypt the hashed passwords and
re-apply another hash algorithm. Therefore, strong password substitution
only works if the database-level passwords are stored with the SHA-1
scheme.
NOTE: A lot of this logic could be shared with the DRDA decryption
and client encryption managers - This will be done _once_
code sharing along with its rules are defined between the
Derby engine, client and network code (PENDING).
Substitution algorithm works as follow:
PW_TOKEN = SHA-1(PW, ID)
The password (PW) and user name (ID) can be of any length greater
than or equal to 1 byte.
The client generates a 20-byte password substitute (PW_SUB) as follows:
PW_SUB = SHA-1(PW_TOKEN, RDr, RDs, ID, PWSEQs)
w/ (RDs) as the random client seed and (RDr) as the server one.
See PWDSSB - Strong Password Substitution Security Mechanism
(DRDA Vol.3 - P.650)private static ContextService getContextService()
private static Context getContext(java.lang.String contextID)
private static java.lang.String getServiceName(java.lang.Object serviceModule)
static java.lang.Object getServiceModule(java.lang.Object serviceModule, java.lang.String factoryInterface)
Apache Derby V10.13 Internals - Copyright © 2004,2016 The Apache Software Foundation. All Rights Reserved.