Class AuthenticationServiceBase
- java.lang.Object
-
- org.apache.derby.impl.jdbc.authentication.AuthenticationServiceBase
-
- All Implemented Interfaces:
AuthenticationService
,ModuleControl
,ModuleSupportable
,PropertySetCallback
- Direct Known Subclasses:
BasicAuthenticationServiceImpl
,JNDIAuthenticationService
,NativeAuthenticationServiceImpl
,NoneAuthenticationServiceImpl
,SpecificAuthenticationServiceImpl
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:
- The SHA-1 authentication scheme, which was the only available scheme in Derby 10.5 and earlier. This scheme uses the SHA-1 message digest algorithm.
- The configurable hash authentication scheme, which allows the users to specify which message digest algorithm to use.
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 withPasswordHasher.ID_PATTERN_CONFIGURABLE_HASH_SCHEME
and suffixed with the name of the message digest algorithm.
-
-
Field Summary
Fields Modifier and Type Field Description protected UserAuthenticator
authenticationScheme
static java.lang.String
AuthenticationTrace
Trace flag to trace authentication operationsprotected static int
SECMEC_USRSSBPWD
Userid with Strong password substitute DRDA security mechanismprivate AccessFactory
store
-
Fields inherited from interface org.apache.derby.iapi.jdbc.AuthenticationService
MODULE
-
-
Constructor Summary
Constructors Constructor Description AuthenticationServiceBase()
-
Method Summary
All Methods Static Methods Instance Methods Concrete Methods Modifier and Type Method 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)(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.-
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
-
Methods inherited from interface org.apache.derby.iapi.services.monitor.ModuleSupportable
canSupport
-
-
-
-
Field Detail
-
authenticationScheme
protected UserAuthenticator authenticationScheme
-
store
private AccessFactory store
-
AuthenticationTrace
public static final java.lang.String AuthenticationTrace
Trace flag to trace authentication operations
-
SECMEC_USRSSBPWD
protected static final int SECMEC_USRSSBPWD
Userid with Strong password substitute DRDA security mechanism- See Also:
- Constant Field Values
-
-
Method Detail
-
setAuthenticationService
protected void setAuthenticationService(UserAuthenticator aScheme)
-
boot
public void boot(boolean create, java.util.Properties properties) throws StandardException
Start this module. In this case, nothing needs to be done.- Specified by:
boot
in interfaceModuleControl
- Throws:
StandardException
- upon failure to load/boot the expected authentication service.- See Also:
ModuleControl.boot(boolean, java.util.Properties)
-
stop
public void stop()
Description copied from interface:ModuleControl
Stop the module. The module may be found via a findModule() method until some time after this method returns. Therefore the factory must be prepared to reject requests to it once it has been stopped. In addition other modules may cache a reference to the module and make requests of it after it has been stopped, these requests should be rejected as well.- Specified by:
stop
in interfaceModuleControl
- See Also:
ModuleControl.stop()
-
authenticate
public boolean authenticate(java.lang.String databaseName, java.util.Properties userInfo) throws java.sql.SQLException
Authenticate a User inside JBMS.T his is an overload method. We're passed-in a Properties object containing user credentials information (as well as database name if user needs to be validated for a certain database access).- Specified by:
authenticate
in interfaceAuthenticationService
userInfo
- Connection properties info. failure.- Throws:
java.sql.SQLException
- See Also:
AuthenticationService.authenticate(java.lang.String, java.util.Properties)
-
getSystemCredentialsDatabaseName
public java.lang.String getSystemCredentialsDatabaseName()
Description copied from interface:AuthenticationService
Get the name of the credentials database used to authenticate system-wide operations. This returns null for all implementations except NATIVE authentication.
- Specified by:
getSystemCredentialsDatabaseName
in interfaceAuthenticationService
-
getProperty
public java.lang.String getProperty(java.lang.String key)
Returns a property if it was set at the database or system level. Treated as SERVICE property by default.- Returns:
- a property string value.
-
getTransaction
protected TransactionController getTransaction() throws StandardException
Get a transaction for performing authentication at the database level.
- Throws:
StandardException
-
getDatabaseProperties
java.util.Properties getDatabaseProperties() throws StandardException
Get all the database properties.- Returns:
- the database properties, or
null
if there is no access factory - Throws:
StandardException
-
getServiceName
protected java.lang.String getServiceName()
Get the name of the database if we are performing authentication at the database level.
-
getDatabaseProperty
public java.lang.String getDatabaseProperty(java.lang.String key)
-
getSystemProperty
public java.lang.String getSystemProperty(java.lang.String key)
-
init
public void init(boolean dbOnly, java.util.Dictionary p)
Description copied from interface:PropertySetCallback
Initialize the properties for this callback. Called when addPropertySetNotification() is called with a non-null transaction controller. This allows code to set read its initial property values at boot time.Code within an init() method should use the 3 argument PropertyUtil method getPropertyFromSet() to obtain a property's value.
- Specified by:
init
in interfacePropertySetCallback
- Parameters:
dbOnly
- true if only per-database properties are to be looked atp
- the complete set of per-database properties.
-
validate
public boolean validate(java.lang.String key, java.io.Serializable value, java.util.Dictionary p) throws StandardException
Description copied from interface:PropertySetCallback
Validate a property change.- Specified by:
validate
in interfacePropertySetCallback
- Parameters:
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.- Returns:
- true if this object was interested in this property, false otherwise.
- Throws:
StandardException
- Oh well.- See Also:
PropertySetCallback.validate(java.lang.String, java.io.Serializable, java.util.Dictionary)
-
parsePasswordLifetime
protected java.lang.Long parsePasswordLifetime(java.lang.String passwordLifetimeString)
Parse the value of the password lifetime property. Return null if it is bad.
-
parsePasswordThreshold
protected java.lang.Double parsePasswordThreshold(java.lang.String expirationThresholdString)
Parse the value of the password expiration threshold property. Return null if it is bad.
-
apply
public Serviceable apply(java.lang.String key, java.io.Serializable value, java.util.Dictionary p)
Description copied from interface:PropertySetCallback
Apply a property change. Will only be called after validate has been called and only if validate returned true. If this method is called then the new value is the value to be used, ie. the property is not set in the overriding JVM system set.- Specified by:
apply
in interfacePropertySetCallback
- Parameters:
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.- Returns:
- post commit work for the property change.
- See Also:
PropertySetCallback.validate(java.lang.String, java.io.Serializable, java.util.Dictionary)
-
map
public java.io.Serializable map(java.lang.String key, java.io.Serializable value, java.util.Dictionary p) throws StandardException
Description copied from interface:PropertySetCallback
Map a proposed new value for a property to an official value. Will only be called after apply() has been called.- Specified by:
map
in interfacePropertySetCallback
- Parameters:
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.- Returns:
- new value for the change
- Throws:
StandardException
- Thrown on error.- See Also:
PropertySetCallback.map(java.lang.String, java.io.Serializable, java.util.Dictionary)
-
requireAuthentication
protected final boolean requireAuthentication(java.util.Properties properties)
-
hashPasswordSHA1Scheme
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.
- Parameters:
plainTxtUserPassword
- Plain text user password- Returns:
- hashed user password (digest) as a String object
or
null
if the plaintext password isnull
-
toHexByte
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.- Parameters:
str
- string- Returns:
- the byte[] (with hexadecimal format) form of the string (str)
-
hashUsingDefaultAlgorithm
java.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.- Parameters:
user
- the user whose password to hashpassword
- the plain text passwordprops
- database properties- Returns:
- a digest of the user name and password formatted as a string,
or
null
ifpassword
isnull
- Throws:
StandardException
- if the specified algorithm is not supported
-
getDataDictionary
private static DataDictionary getDataDictionary()
Find the data dictionary for the current connection.- Returns:
- the
DataDictionary
for the current connection
-
substitutePassword
protected java.lang.String substitutePassword(java.lang.String userName, java.lang.String password, java.util.Properties info, boolean databaseUser)
Strong Password Substitution (USRSSBPWD). This method generates a password substitute to authenticate a client which is using a DRDA security mechanism such as SECMEC_USRSSBPWD. Depending how the user is defined in Derby and if BUILTIN is used, the stored password can be in clear-text (system level) or encrypted (hashed - *not decryptable*)) (database level) - If the user has authenticated at the network level via SECMEC_USRSSBPWD, it means we're presented with a password substitute and we need to generate a substitute password coming from the store to compare with the one passed-in. The substitution algorithm used is the same as the one used in the SHA-1 authentication scheme (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 schemePasswordHasher.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)- Returns:
- a substituted password.
-
getContextService
private static ContextService getContextService()
Privileged lookup of the ContextService. Must be private so that user code can't call this entry point.
-
getContext
private static Context getContext(java.lang.String contextID)
Privileged lookup of a Context. Must be private so that user code can't call this entry point.
-
getServiceName
private static java.lang.String getServiceName(java.lang.Object serviceModule)
Privileged service name lookup. Must be private so that user code can't call this entry point.
-
getServiceModule
static java.lang.Object getServiceModule(java.lang.Object serviceModule, java.lang.String factoryInterface)
Privileged module lookup. Must be package protected so that user code can't call this entry point.
-
-