public abstract class SecurityProvider
extends jespa.security.Properties
A SecurityProvider is also a HashMap of properties that are used to:
The life-cycle of a SecurityProvider depends on what it is used for. Some examples of SecurityProvider life-cycles are:
this.put("channelBindings", channelBindingsBytesFromTicket);
.
The HttpSecurutyService will retrieve and check this value and accept or reject the client based on the various bindings.cert.* settings.Modifier and Type | Field and Description |
---|---|
protected java.lang.String |
identity
The identity of the currently authenticated user such as
through acceptSecContext.
|
protected boolean |
isComplete
Indicates that an authentication using initSecContext
or acceptSecContext has been completed.
|
Constructor and Description |
---|
SecurityProvider(java.util.Map properties)
Construct a new SecurityProvider with a copy of the supplied properties.
|
SecurityProvider(java.util.Map properties,
java.lang.String[] pnames)
Construct a SecurityProvider with only the properties named in the pnames parameter.
|
Modifier and Type | Method and Description |
---|---|
byte[] |
acceptSecContext(byte[] token,
int off,
int len)
Accept authentication with another peer by exchanging tokens.
|
void |
authenticate(java.lang.Object credential)
Validates the supplied credential with this provider's authority.
|
void |
dispose()
Destroy any sensitive cryptographic material used by this SecurityProvider.
|
java.lang.Object |
exportState()
Returns an Object representing the current state of this
SecurityProvider.
|
Account |
getAccount(java.lang.String acctname,
java.lang.String[] attrs)
Retrieve an Account object representing the named account and populate it (an Account is also a Map) with the attributes listed in the attrs array.
|
Domain |
getDomain(java.lang.String dname,
java.lang.String[] attrs)
Retrieve a Domain object representing the named domain and populate it (a Domain is also a Map) with the attributes listed in the attrs array.
|
boolean |
getFlag(java.lang.String name)
Retrieve the named security flag as a boolean.
|
java.lang.String |
getIdentity()
Retrieve the account name of the currently authenticated user or
null if no applicable authentication has occured.
|
java.lang.String |
getName() |
java.lang.Object |
getProperty(java.lang.String name,
java.lang.Object def)
Retrieve a property by name or return the supplied default value if the
property is not set.
|
void |
importState(java.lang.Object state)
Initializes a SecurityProvider with the state Object returned in a previous call
to
exportState() . |
byte[] |
initSecContext(byte[] token,
int off,
int len)
Initiate authentication with another peer by exchanging tokens.
|
boolean |
isComplete()
Used with
initSecContext(byte[], int, int) or acceptSecContext(byte[], int, int) to determine
if more tokens need to be exchanged. |
void |
setFlag(java.lang.String name,
boolean value)
Sets the value of the named flag.
|
void |
setProperty(java.lang.String name,
java.lang.Object obj)
Set a property such as a SecurityProvider specific option.
|
void |
unwrap(ByteBuffer incoming)
Process an input buffer provided by a peer using another instance
of this SecurityProvider's
wrap(jespa.io.ByteBuffer) method or an equivalent
routine. |
void |
wrap(ByteBuffer outgoing)
Process an output buffer to apply some form of security such as message
signing or encryption.
|
decodeObject, encodeObject, getEncryptedProperty, getFilteredProperties, getFilteredProperties, getProperty, getPropertyAsBoolean, getPropertyAsLong, setEncryptedProperty
clear, clone, compute, computeIfAbsent, computeIfPresent, containsKey, containsValue, entrySet, forEach, get, getOrDefault, isEmpty, keySet, merge, put, putAll, putIfAbsent, remove, remove, replace, replace, replaceAll, size, values
protected java.lang.String identity
protected boolean isComplete
public SecurityProvider(java.util.Map properties)
properties
- a Map of initial options specific to this SecurityProviderpublic SecurityProvider(java.util.Map properties, java.lang.String[] pnames) throws SecurityProviderException
properties
- the properties from which the named properties will be copied.pnames
- an array of property names to be populated in this SecurityProviderSecurityProviderException
public java.lang.String getName() throws SecurityProviderException
SecurityProviderException
public void setProperty(java.lang.String name, java.lang.Object obj) throws SecurityProviderException
setProperty
in class jespa.security.Properties
name
- the name of the property to set.obj
- the value of the property to set (which may be null).SecurityProviderException
- if the property or it's value are invalid
or cannot be set.public java.lang.Object getProperty(java.lang.String name, java.lang.Object def) throws SecurityProviderException
getProperty
in class jespa.security.Properties
name
- the name of the property to retrieve.def
- the default value to return of the named property is not set.SecurityProviderException
- if the name is invalid or it's value cannot
be retrieved.public boolean getFlag(java.lang.String name) throws SecurityProviderException
The following table lists suggested names for common security flags:
Name | Description |
---|---|
integrity | The wrap and unwrap methods support integrity checking to ensure that data has not been modified. |
confidentiality | The wrap and unwrap methods support encryption. |
sequenceDetection | The wrap and unwrap methods use sequence numbers to ensure messages are not received out-of-sequence. |
replayDetection | |
mutualAuthentication | |
delegation | |
transferable | |
protocolReady |
Security flags may also be retrieved and set as properties using the flag name prefixed with "flags.". For example, the code fragment provider.getFlag("confidentiality")
refers to the same property as provider.getProperty("flags.confidentiality")
but getFlag returns the result as a boolean.
name
- the name of the flag value to retrieve.SecurityProviderException
public void setFlag(java.lang.String name, boolean value) throws SecurityProviderException
Security flags may also be supplied as properties or set using other property methods by simply prefixing the flag names with "flags.". For example, the property name for integrity checking is "flags.integrity".
name
- the name of the flag to set.value
- the new value of the flag.SecurityProviderException
public Domain getDomain(java.lang.String dname, java.lang.String[] attrs) throws SecurityProviderException
If the dname parameter is null, a default Domain will be retrieved. If the attrs parameter is null, a default set of attributes will be assumed.
The behavior of this method is highly dependant on the specific SecurityProvider implementation being used. See the specific SecurityProvider documentation for details.
dname
- the name of the domain to retrieveattrs
- the list of attribute names to populate in the Domain object returnedSecurityProviderException
- if the named domain could not be found or if a catostrophic error occurs.public Account getAccount(java.lang.String acctname, java.lang.String[] attrs) throws SecurityProviderException
If the acctname parameter is null, this method will return a default Account or null if this SecurityProvider has not been sufficiently initialized (such as by performing authentication).
If the attrs parameter is the special constant Account.ALL_ATTRS, this indicates that "all attributes" should be returned although the interpretation of this value depends greatly on the SecurityProvider (such as with the case of constructed attributes in Active Directory which can only be retrieved by explicitly requesting them by name).
If the attrs parameter is null, a default set of attributes will be retrieved.
This default set may be determined only by what is convenient or efficent for the SecurityProvider implementation.
With the exception of the attribute used to uniquely identify the account, the specific set of attributes returned if the attrs parameter is null is not defined unless stated otherwise in the API documentation of the SecurityProvider being used.
Generally an attrs parameter of null should only be used when the caller has no interest in attributes or their values such as when checking for the existance of an account, deleting an account or checking group membership with Account.isMemberOf(java.lang.String)
.
If the acctname and attrs parameters are both null, a cached Account object may be returned.
Account.update(java.lang.String[])
operations to ensure that the Account object has current data. If data is not current, unexpected update behavior can result.
Account.isMemberOf(java.lang.String)
. Otherwise, if cached group membership data is not utilized, the performance of isMemberOf may be poor.
The behavior of this method depends greatly on the specific SecurityProvider implementation being used.
acctname
- the name of the account to retrieve or null to indicate that a default account should be retrievedattrs
- the names of the account attributes to retrieve or null to indicate that a default set of attriubutes should be retrieved or the special constant Account.ALL_ATTRS to indicate that "all attributes" should be retrieved.SecurityProviderException
- if the named account could not be found or if a catostrophic error occurs.public java.lang.String getIdentity() throws SecurityProviderException
SecurityProviderException
- if an error occurs trying to retrieve
the identity value.public java.lang.Object exportState() throws SecurityProviderException
importState(java.lang.Object)
into a different instance of the same type of
SecurityProvider initialized with the same properties. The result
should be a transfer of all state such that the new SecurityProvider
instance should behave like the original within limits defined by the
SecurityProvider type.
Transference of state between SecurityProvider instances may be used for a number of reasons including but not limited to:
Exported SecurityProvider state may be limited in how it can be transferred. The reason may be to protect the integrity of the SecurityProvider data such as not writing potentially sensitive cryptographic material to an unprotected disk file. Or the reason may be a technical limitation such as the fact that the state may only be valid if the new SecurityProvider instance has access to a resource in the current VM like a database connection or network socket. If such a limitation is reached, an exception should be thrown from importState.
Once the state of a SecurityProvider has been exported, performing further operations may be invalid or may invalidate the exported state.
The return value should be a type that can easily be serialized such as a byte[] array or a java.io.Serializable object that can be used efficiently with I/O streams.
SecurityProviderException
- if the state could not or cannot be
exported.public void importState(java.lang.Object state) throws SecurityProviderException
exportState()
. Before the state is imported, this SecurityProvider must
be initialized with the same properties as the original SecurityProvider.state
- an Object (or byte[] array) that represets the state
to be imported.SecurityProviderException
- if the state could not be imported such as
because the state being imported has been transferred beyond it's acceptable
boundries.public byte[] initSecContext(byte[] token, int off, int len) throws SecurityProviderException
acceptSecContext(byte[], int, int)
or an equivalent routine
that accepts tokens of the same type. Tokens communicated back to
this peer should be again passed to this method using the same SecurityProvider
object (or one initialized using importState(java.lang.Object)
). This exchange of tokens
continues until isComplete
returns true at
which point authentication is complete from the prespective of the peer using this
SecurityProvider. Note that any non-null final
token may still need to be sent to the other peer to satisfy it's
authentication context.
If the initial call to this method has no token (which is almost always
true), an empty byte array (new byte[0]
) should be supplied.
token
- the buffer containing the authentication token supplied by the other peer
or an empty byte array if no token has been supplied (which is almost always true
with the initial call to this method).off
- the offset within token to the relevant data.len
- the length of the token within token at offset off.SecurityProviderException
- if the authentication operation failed. Where
possible, the exception code should be
SecurityProviderException.STATUS_ACCOUNT_NOT_FOUND
if the other peer could not find the account for the identity being authenticated or
SecurityProviderException.STATUS_INVALID_CREDENTIALS
if the other peer indicated that the supplied credential was cryptographically incorrect.
If the peer only indicated that the authentication failed in general and does not
distinguish between the two cases, STATUS_INVALID_CREDENTIALS should be
favored.public byte[] acceptSecContext(byte[] token, int off, int len) throws SecurityProviderException
initSecContext(byte[], int, int)
or an equivalent
routine that accepts tokens of the same type. Tokens supplied by the other
peer should be again passed to this method using the same SecurityProvider
object (or one initialized using importState(java.lang.Object)
). This
exchange of tokens continues until isComplete
returns
true at which point authentication from the prespective
of the peer using this SecurityProvider is complete although any
non-null final token may still need to be communicated back
to the initiator to satisfy it's authentication context.
Note that it may be nessary to use the
exportState()
/importState(java.lang.Object)
methods to initialize
a SecurityProvider if, during the token exchange, a SecurityProvider
object cannot persist between invocations of this method. For example,
Java application servers frequently do not allow arbitrary objects
to perist between HTTP requests. If the token exchange requires more
than one request / response it would not be possible to maintain a
single SecurityProvider instance. This issue is remedied by temporarily
exporting the state with exportState where it can safely
and efficiently be stored as an HTTP session variable. That state can
then be restored into a new SecurityProvider with each subsequent HTTP
request thereby allowing stateful authentication to proceed over the
otherwise stateless HTTP protocol.
token
- the buffer containing the authentication token supplied by
the other peer.off
- the offset within token to the relevant data.len
- the length of the token within token at offset off.SecurityProviderException
- if a catostrophic error occured in processing. Note
that unlike initSecContext, this method should not throw an exception
to indicate that authentication has failed. Most errors will be encoded into a
final token so as to communicate the failure to the initiator.public boolean isComplete()
initSecContext(byte[], int, int)
or acceptSecContext(byte[], int, int)
to determine
if more tokens need to be exchanged.public void wrap(ByteBuffer outgoing) throws SecurityProviderException
unwrap(jespa.io.ByteBuffer)
method of another instance of this SecurityProvider
or an equivalent routine.
Precisely what this method does depends on the SecurityProvider and it's properties which may be negotiated during another operation such as authentication between peers.
The wrap and unwrap methods are most commonly
used to add security to network protocol messages. In this case it is
first necessary to authenticate the peers using initSecContext(byte[], int, int)
and acceptSecContext(byte[], int, int)
to negotiate and initialize any security
flags, message digests and crytographic materials that may be used
for processing.
This method uses a ByteBuffer instead of byte[] arrays because it wraps data in-place without copying data and because the method cascades directly with other routines that use ByteBuffer. To emulate similar methods that operate on simple byte[] arrays, code like the following would be used:
ByteBuffer bb = new ByteBuffer(); bb.encodeBytes(outgoing, offset, len); bb.setIndex(0); provider.wrap(bb); byte[] wrapped = bb.toByteArray();
outgoing
- the buffer to be processed.SecurityProviderException
- if a failure occurs processing the data.public void unwrap(ByteBuffer incoming) throws SecurityProviderException
wrap(jespa.io.ByteBuffer)
method or an equivalent
routine.
This method uses a ByteBuffer instead of byte[] arrays because it unwraps data in-place without copying data and because the method cascades directly with other routines that use ByteBuffer. To emulate similar methods that operate on simple byte[] arrays, code like the following would be used:
ByteBuffer bb = new ByteBuffer(); bb.encodeBytes(incoming, offset, len); bb.setIndex(0); provider.unwrap(bb); byte[] unwrapped = bb.toByteArray();
incoming
- the buffer to be processed.SecurityProviderException
- if a failure occurs processing the data.public void authenticate(java.lang.Object credential) throws SecurityProviderException
A SecurityProvider authority could be an LDAP database, a simple in-memory list of accounts, or a stub for the local host security authority such as nsswitch on UNIX or the LSA on Microsoft Windows.
credential
- a credential to be validated. Providers should support the generic
PasswordCredential
class.SecurityProviderException
- if the validation fails. The exception code should be
SecurityProviderException.STATUS_ACCOUNT_NOT_FOUND
if the credential identity was not found by the provider authority or
SecurityProviderException.STATUS_INVALID_CREDENTIALS
if the credential was cryptographically incorrect.
If the authority only indicated that the authentication failed in general and does not
distinguish between the two cases, STATUS_INVALID_CREDENTIALS should be
favored.public void dispose() throws SecurityProviderException
SecurityProviderException