Verifying_credentials are the credentials of the recipient of the
token. They must include the private key of the entity named as the
target in Create_token or the call will fail. The cached incoming
contexts section of the verifying credentials may be modified as a
side effect of this call.
Accepted_credentials will contain additional information about the
token creator. If delegation was requested, these credentials can be
used to make additional calls to Create_token on the creator's
behalf. Whether or not delegation was requested, they can also be
used in the calls which follow to gain additional information about
the token creator.
The deleg_req_flag indicates whether the accepted_credentials include
delegation which can be used by the recipient to act on behalf of the
principal. Mutual_req_flag, replay_det_req_flag, and
sequence_req_flag are passed through from Create_token in support of
the GSSAPI. DASS makes no use of these fields.
The mutual_authentication_token can be returned to the token creator
as proof of receipt. In many protocols, this will be used by a client
to authenticate a server. Only the genuine server would be able to
compute the mutual_authentication_token from the token.
The shared_key and instance_identifier can be used to encrypt or sign
data between the two authenticating parties. See Create_token.
This routine verifies the contents of the authentication token in the
context of the verifying credentials (In particular, the Private Key
of the server is used. Also, the Cached Incoming Contexts and
Incoming Timestamp list is used.) and returns information about it.
The algorithm updates a cache of information. This cache is not
updated if the algorithm exits with an error. The algorithm is as
follows:
a) If there is a Login Ticket, but no Shared Key Ticket or
Delegator then exit with error `Invalid Authenticator'. If
there is a Shared Key Ticket or Delegator, but no Login Ticket
then exit with error `Invalid Authentication Token'.
Look up the Encrypted Shared key in the Cached Incoming Contexts
of the credentials structure. (This cache entry is used during
the execution of this routine. An implementation must ensure that
references to the cache entry can not be affected by other users
modifying the cache. One way is to use a copy of the cache entry,
and update it at exit.) If it is not found then create
a new cache entry as follows:
1) Encrypted Shared Key, from the Authentication Token.
2) Shared Key and Validity Interval, by decrypting the
Encrypted Shared Key using the server private key in
credentials. If the decryption fails then exit with error
`Invalid Authentication Token'.
b) Check that the Validity Interval (in the cache entry) includes
the current time; return `Invalid Authentication Token' if not.
Check the Timestamp is within max-clock-skew of the current
time, return `invalid Authentication Token' if not.
Reconstruct the Authenticator including the Channel Bindings
passed as a parameter.
Check that the reconstructed Authenticator is signed by the
Shared key. If not then exit with error `Invalid
Authentication Token'.
Look up the Authenticator Signature in the Received
Authenticators. If the same Signature is found in the list
then exit with error `Duplicate Authenticator'. Otherwise add
the Signature and timestamp to the list.
If there is a Login Ticket and the Delegation Public key is in
the cache entry, then check that the same key is specified in
the Login Ticket, if not then exit with error `Invalid
Authentication Token'. Place the Delegation Public key in the
cache if it is not already there.
If there is a Login Ticket, the Delegation Public key was not
previously in the cache entry, and there is a Shared Key
Ticket in the Authentication Token, then check that the Shared
Key Ticket is signed by the Delegation Public Key in the Login
Ticket. If not then exit with error `Invalid Authentication
Token'.
If a delegator is present in the message then decrypt the
delegator using the Shared key. If the private key does not
match the Delegation Public key then exit with error
`Invalid Authentication Token' (The prime in the delegator
is used to find the other prime (from the modulus). The division
must not have a remainder. Neither prime may be 1. The two
primes are then used to reconstruct any other information
needed to perform cryptographic operations.).
Build the delegation credentials data structure as follows:
1) Claimant credentials:
(i) Login Ticket from the Authentication token
(ii) Delegation Private key from the decrypted delegator if
the token is delegating.
(iii)Encrypted Shared Key from the Authentication token.
2) There are no verifier credentials.
3) Trusted authorities are copied from the verifying_credentials
passed to this routine (If an implementation is able to
obtain the original Trusted Authorities of the Principal then
it may do so instead of using the server's Trusted
Authorities.).
4) Remote node credentials (Node name, Username, Node Ticket)
5) There are no local node credentials.
6) There are no cached contexts.
c) The returned boolean values are obtained from the
Authenticator.
d) Mutual_authentication_token is computed by encrypting the
timestamp from the Authenticator with the Shared key from the
cache.
e) Instance_identifier is the timestamp from the Authenticator.
This and the Shared key are returned to the caller for further
encryption operations (if these are supported).
3.10.3 Compare Mutual Token
Compare_mutual_token(
--inputs
Generated_token Mutual authentication token,
Received_token Mutual authentication token,
--outputs
equality_flag Boolean)
This routine compares two mutual authentication tokens and tells
whether they match. In the expected use, the first is the token
generated by Create_token at the initiating end and the second is the
token generated by Accept_token at the accepting end and returned to
the initiating end. This routine can be implemented as a byte by
byte comparison of the two parameters.
3.10.4 Get Node Info
get_node_info(
--inputs
accepted_credentials Credentials,
--outputs
nodename Name,
username String)
This routine extracts from accepted credentials the name of the node
from which the authentication token came and the named account on
that node. Because this information is not cryptographically
protected within the token, this information can only be regarded as
a "hint" by the receiving application. It can, however, be verified
using Verify_node_name in a cryptographically secure manner. This
information will only be present if these are accepted credentials
and it the caller of Create_token set the include_node_name and/or
include_username flags.
An actual implementation is not likely to have get_node_info and
verify_node_name as separate calls. They are specified this way
because there are different ways this information might be used. For
most applications, the nodename and username will be included in the
token, and a single function might extract and verify them (it might
in fact be part of accept token). For other applications, the
nodename and username will not be in the token but rather will be
computed from other information passed during connection initiation
so a call would have to take these as inputs. Still other
applications such as ACL evaluators that want to support the renaming
and aliasing capabilities of DASS would defer verifying node
information until they came upon an ACL which allowed access only
from a particular node. They would then verify that the name on the
ACL was an authenticatable alias for the node which created the
token. All of these uses can be defined in terms of calls to
get_node_info and verify_node_name.
3.10.5 Get Principal UID
get_principal_uid(
--inputs
accepted_credentials Credentials,
--outputs
uid UID)
This routine extracts a principal UID from a set of credentials.
As with Get_Node_Info, this interface is not likely to appear in an
actual implementation, but rather will be bundled with other
routines. It is specified this way because there might be a variety
of algorithms by which credentials are evaluated and all of them can
be defined in terms of these primitives.
In DASS, it is possible for a principal to have many aliases. This
can happen either because the principal was given multiple names to
limit the number of CAs that need to be trusted when authenticating
to different servers or because the principal's name has changed and
the old name remains behind as an alias. Accept_token returns the
name by which the principal identified itself when creating its
credentials. A service may know the user by some alias. The normal
way to handle this is for the service to know the principal's UID
(which is constant over name changes) and to compare it with the UID
in the token to identify a likely alias situation. It gets the UID
from the token using this routine. It then confirms the alias by
calling verify_principal_name.
The UID is in a signed portion of accepted credentials, but the
signature may not have been verified at the time this call is issued.
The information returned by this routine must therefore be regarded
as a hint. If a call to Verify_principal_name succeeds, however,
then the caller can securely know that the name given to that routine
and the UID returned by this one are the authenticated source of the
token.
3.10.6 Get Principal Name
get_principal_name(
--inputs
accepted_credentials Credentials,
--outputs
name Name)
This routine extracts a principal name from a set of credentials.
This name is the name most recently associated with the principal. It
may be the name that the principal supplied when the credentials were
created (in which case it may not have been verified yet) or it may
be a different name that has been verified.
As with Get_Node_Info and Get_Principal_UID, this routine is not
likely to appear in an actual implementation, but will be bundled in
some fashion with related procedures. The name returned by this
procedure is not guaranteed to have been cryptographically verified.
Verify_Principal_Name performs that function.
3.10.7 Get Lifetime
get_lifetime(
--inputs
Claimant_credentials Credentials,
--outputs
lifetime Duration)
This routine computes the life remaining in a set of credentials.
Its most common use would be to know to renew credentials before they
expire.
Returns the remaining lifetime of the login ticket in the
credentials. This can either be the done on the node where the
original login took place, or at a server which has been delegated
to. It indicates how much longer these credentials can be used for
further delegations. This routine will return 0 if the login ticket
has passed the end of its life, if there is no login ticket, or if
the credentials do not contain the private key certified by the
ticket (i.e., where they were created by an authentication-without-
delegation operation).
3.10.8 Verify Node Name
Verify_node_name(
--inputs
nodename Name,
username String,
--updated
verifying_credentials Credentials,
accepted_credentials Credentials,
--outputs
Name matches Boolean)
This routine tests whether the originating node of an authentication
token can be authenticated as having the provided name. Like a
principal, a node may have multiple aliases. One of them may be
returned by Get_node_info, but this call allows a suspected alias to
be verified. The verifying credentials supplied with this call must
be the same credentials as were used in the Accept_token call. The
procedure for completing this request is as follows:
a) If there is no Node Ticket in the claimant credentials then
return False.
b) Search the incoming context cache of the verifying credentials
for an entry containing the same encrypted shared key as the
encrypted shared key subfield of the claimant information of
the accepted credentials. In the steps which follow,
references to "the cache" refer to this entry. If none is
found, initialize such an entry as follows:
1) Encrypted shared key from the encrypted shared key subfield
of the claimant information of the accepted credentials.
2) The shared key and validity interval are determined by
decrypting the encrypted shared key using the RSA private
key in the verifier information of the server credentials.
If this procedure is called after a call to Accept_token
using the same server credentials (as is required for
correct use), the shared key and validity interval must
correctly decrypt. If called in some other context, the
results are undefined. The validity interval is not
checked.
3) Initialize all other entries in the cache to missing.
c) If there is a "local username on client node" in the cache and
it does not match the username supplied as a parameter, return
False.
d) If there is a "name of client node" in the cache and it
matches the nodename supplied as a parameter:
1) Set the "Full name of the node" subfield of the remote node
authentication field of the accepted credentials to be the
nodename supplied as a parameter.
2) Set the "Local Username on the node" subfield of the remote
node authentication field of the accepted credentials to be
the username supplied as a parameter.
3) return True.
e) Call the Get_Pub_Keys subroutine with the server_credentials,
the nodename supplied as a parameter, and Try_Hard=False.
f) If "Public Key of Client Node" is missing from the cache,
check all of the Public keys returned to see if one verifies
the node ticket. If one does, set the "Public Key of Client
Node" and "UID of Client Node" fields in the cache to be the
PK/UID pair that verified the ticket and set the "Local
Username on Client node" field to be the username supplied as
a parameter..
g) If any of the Public Key/UID pairs match the "Public Key of
Client Node" and "UID of Client Node" fields in the cache,
then:
1) Set the "name of client node" in the cache equal to the
nodename supplied as a parameter.
2) Set the "Full name of the node" subfield of the remote node
authentication field of the accepted credentials to be the
nodename supplied as a parameter.
3) Set the "Local Username on the node" subfield of the remote
node authentication field of the accepted credentials to be
the username supplied as a parameter.
4) Return True.
h) If none of them match, call Get_Pub_Keys again with
Try_Hard=True and repeat steps 6 & 7. If Step 7 fails a
second time, return False.
3.10.9 Verify Principal Name
Verify_principal_name(
--inputs
principal_name Name,
--updated
verifier_credentials Credentials,
claimant_credentials Credentials,
--outputs
Name matches Boolean)
This routine tests (in the context of the verifier credentials)
whether the claimant credentials are authenticatable as being those
of the named principal. This procedure is called with a set of
accepted credentials to authenticate their source, or with a set of
credentials produced by network_login to authenticate the creator of
those credentials. If the claimant credentials were created by
Accept_token, then the verifier credentials supplied in this call
must be the same as those used in that call. The procedure for
completing this request is as follows:
a) If there is no Login Ticket in the claimant credentials, then
return False.
b) If the current time is not within the validity interval of the
Login Ticket, then return False.
c) If there is an Encrypted Shared Key present in the Claimant
information field of the claimant credentials, then find or
create a matching cache entry in the Cached Incoming Contexts
of the verifier credentials. In the description which
follows, references to "the cache" refer to this entry. If
the cache entry must be created, its contents is set to be as
follows:
1) Encrypted shared key from the encrypted shared key subfield
of the claimant information of the accepted credentials.
2) The shared key and validity interval are determined by
decrypting the encrypted shared key using the RSA private
key in the verifier information of the server credentials.
If this procedure is called after a call to Accept_token
using the same server credentials (as is required for
correct use), the shared key and validity interval must
correctly decrypt. If called in some other context, the
results are undefined. The validity interval is not
checked.
3) Initialize all other entries in the cache to missing.
d) If there is a cache entry and if the "Public Key of Client
Principal" field is present and if the "UID of Client
Principal" field is present and matches the UID in the Login
Ticket, then:
1) Set the Public Key of the principal field in the Claimant
information to be the Public Key of Client Principal.
2) If the "Full name of the principal" field is missing from
the claimant information of the claimant credentials, then
set it to the "Name of Client Principal" field from the
cache.
e) If there is a cache entry and if the "Name of Client
Principal" field is present and if it matches the principal
name supplied to this routine and if the UID in the cache
matches the UID in the Login Ticket, return True.
f) Call the Get_Pub_Keys subroutine with the name and verifier
credentials supplied to this routine and Try_Hard=FALSE.
Ignore any keys retrieved where the corresponding UID does not
match the UID in the claimant credentials.
g) If the Public Key of the principal is missing from the
claimant information of the claimant credentials, then attempt
to verify the signature on the login ticket with each public
key returned by Get_Pub_Keys. If verification succeeds:
1) Set the Public Key of the principal in the claimant
information of the claimant credentials to be the Public Key
that verified the ticket.
2) If the Full name of the principal in the claimant
information of the claimant credentials is missing, set it
to the name supplied to this routine.
3) If there is a cache entry, set the Name of Client Principal
to be the name supplied to this routine, the UID of Client
Principal to be the UID from the Login Ticket, and the
Public Key of Client Principal to be the Public Key that
verified the ticket.
4) Return True.
h) If the Public Key of the principal is present in the claimant
information of the claimant credentials, then see if it
matches any of the public keys returned by Get_Pub_Keys. If
one of them matches:
1) If the Full name of the principal in the claimant
information of the claimant credentials is missing, set it
to the name supplied to this routine.
2) If there is a cache entry, set the Name of Client Principal
to be the name supplied to this routine, the UID of Client
Principal to be the UID from the Login Ticket, and the
Public Key of Client Principal to be the Public Key that
verified the ticket.
3) Return True.
i) If steps 7 & 8 fail, retry the call to Get_Pub_Keys with
Try_Hard=TRUE, and retry steps 7 & 8. If they fail again,
return false.
3.10.10 Get Pub Keys
Get_Pub_Keys(
--inputs
TA_credentials Credentials
Try_Hard Boolean,
Target Name Name,
--outputs
Pub_keys Set of Public key/UID pairs
This common subroutine is used in the execution of Create_Token,
Verify_Principal_Name, and Verify_Node_Name. Given the name of a
principal, it retrieves a set of public key/UID pairs which
authenticate that principal (normally only one pair). It does this
by retrieving from the naming service a series of certificates,
verifying the signatures on those certificates, and verifying that
the sequence of certificates constitute a valid "treewalk".
The credentials structure passed into this procedure represent a
starting point for the treewalk. Included in these credentials will
be the public key, UID, and name of an authority that is trusted to
authenticate all remote principals (directly or indirectly).
The "Try_Hard" bit is a specification anomaly resulting from the fact
that caches maintained by this routine are not transparent to the
calling routines. It tells this procedure to bypass caches when
doing all name service lookups because the information in caches is
believed to be stale. In general, a routine will call Get_Pub_Keys
with Try_Hard set false and try to use the keys returned. If use of
those keys fails, the calling routine may call this routine again
with Try_Hard set true in hopes of getting additional keys.
Routinely calling this routine with Try_Hard set true is likely to
have adverse performance implications but would not affect the
correctness or the security of the operation.
The name supplied is the full X.500 name of the principal for whom
public keys are needed as part of some authentication process.
This procedure securely learns the public keys and UIDs of foreign
principals by constructing a valid chain of certificates between its
trusted TA and the certificate naming the foreign principal. In the
simplest case, where the TA has signed a certificate for the foreign
principal, the chain consists of a single certificate. Otherwise,
the chain must consist of a series of certificates where the first is
signed by the TA, the last is a certificate for the foreign
principal, and the subject of each principal in the chain is the
issuer of the next. What follows is first a definition of what
constitutes a valid chain of certificates followed by a model
algorithm which constructs all of (and only) the valid chains which
exist between the TA and the target name.
In order to limit the implications of the compromise of a single CA,
and also to limit the complexity of the search of the certificate
space, there are restrictions on what constitutes a valid chain of
certificates from the TA to the Name provided. The only CAs whose
compromise should be able to compromise an authentication are those
controlling directories that are ancestors of one of the two names
and that are not above a common ancestor. Therefore, only
certificates signed by those CAs will be considered valid in a
certificate chain. Normally, the CA for a directory is expected to
certify a public key and UID for the CA of each child directory and
one parent directory. A CA may also certify another CA for some
remote part of the naming hierarchy, and such certificates are
necessary if there are no CAs assigned to directories high in the
naming hierarchy.
A certificate chain is considered valid if it meets the following
criteria:
a) It must consist of zero or more parent certificates, followed
by zero or one cross certificates, followed by zero or more
child certificates.
b) The number of parent certificates may not exceed the number of
levels in the naming hierarchy between the TA name and the
name of the least common ancestor in the naming hierarchy
between the TA name and the target name.
c) Each parent certificate must be stored in the naming service
under the entry of its issuer.
d) The subject of the cross certificate (if any) must be an
ancestor of the target name but must be a longer name than the
least common ancestor of the TA name and the target name.
e) The cross certificate (if any) must have been stored in the
naming service under the entry of its issuer or there must
have been an indication in the naming service that
certificates signed by this issuer may be stored with their
subjects.
f) The issuer of each parent certificate does not have stored
with it in the naming service a cross certificate with the
same issuer whose subject is an ancestor of the target name.
g) Each child certificate must be stored in the naming service
under the entry of its subject.
h) The subject of each child certificate does not have associated
with it in the naming service a cross certificate with the
same subject whose issuer is the same as the issuer of any of
the parent certificates or the cross certificate of the chain.
i) The subject of each certificate must be the issuer of the
certificate that follows in the chain. The equality test can
be met by either of two methods:
1) The public key of the subject in the earlier certificate
verifies the signature of the later and the subject UID in
the earlier certificate is equal to the issuer UID in the
later; or
2) The public key of the subject in the earlier certificate
verifies the signature of the later, the earlier lacks a
subject UID and/or the later lacks an issuer UID and the
name of the subject in the earlier certificate is equal to
the name of the issuer in the later.
j) The Public Key of the TA verifies the signature of the first
certificate.
k) The UID of the TA equals the UID of the issuer of the first
certificate or the UID is missing on one or both places and
the name of the TA equals the name of the issuer of the first
certificate.
l) All of the certificates are valid X.509 encodings and the
current time is within all of their validity intervals.
If a chain is valid, the name which it authenticates can be
constructed as follows:
a) If the chain contains a cross certificate, the name
authenticated can be constructed by taking the subject name
from the cross certificate and appending to it a relative name
for each child certificate which follows. The relative name
is the extension by which the subject name in the child
certificate extends the issuer name.
b) If the chain does not contain a cross certificate, the name
authenticated can be constructed by taking the TA name,
truncating from it the last n name components where n is the
number of parent certificates in the chain, and appending to
the result a relative name for each child certificate. The
relative name is the extension by which the subject name in
the child certificate extends the issuer name.
In the common case, the authenticated name will be the subject
name in the last certificate. The authenticated name is
constructed by the rules above to deal with namespace
reorganization. If a branch of the namespace is renamed (due to,
for example, a corporate acquisition or reorganization), only the
certificates around the break point need to be regenerated.
Certificates below the break will continue to contain the old
names (until renewed), but the algorithms above assure the
principals in that branch will be able to authenticate as their
new names. Further, if the certificates at the branch point are
maintained for both the old and new names for an interim period,
principals in the moved branch will be able to authenticate as
either their old or new names for that interim period without
having duplicate certificates.
A final complication that the algorithm must deal with is the
location of cross certificates. If a key is compromised or for
some other reason it is important to revoke a certificate ahead
of its expiration, it is removed from the naming service. This
algorithm will only use certificates that it has recently
retrieved from the naming service, so revocation is as effective
as the mechanisms that prevent impersonation of the naming
service. There are plans to eventually use DASS mechanisms to
secure access to the naming service; until they are in place,
name service impersonation is a theoretical threat to the
security of revocation. Opinions differ as to whether it is a
practical threat. Child certificates are always stored with the
subject and will not be found unless stored in the name server of
the subject. Parent certificates are always stored with the
issuer and will not be found unless stored in the name server of
the issuer. For best security, cross certificates should be
stored with the issuer because the name server for the subject
may not be adequately trustworthy to perform revocation. There
are performance and availability penalties, however, in doing so.
The architecture and the algorithm therefore support storing
cross certificates with either the issuer or the subject. There
must be some sort of flag in the name service associated with the
issuer saying whether cross certificates from that issuer are
permitted to be stored in the subject's name service entry, and
if that flag is set such certificates will be found and used.
In order to make revocation effective, DASS must assure that
naming service caches do not become arbitrarily stale (the
allowed age of a cache entry is included in the sum of times with
together make up the revocation time). If DASS uses a naming
service such as DNS that does not time out cache entries, it must
bypass cache on all calls and (to achieve reasonable performance)
maintain its own naming service cache. It may be advantageous to
maintain a cache in any case so the that the fact that the
certificates have been verified can be cached as well as the fact
that they are current.
3.10.10.1 Basic Algorithm
For ease of exposition, this first description will ignore the
operation of any caches. Permissible modifications to take
advantage of caches and enhance performance will be covered in
the next section. This path will be followed if the Try_Hard bit
is set True on the call.
Rather than trying construct all possible chains between the TA
and the name to be authenticated (in the event of multiple
certificates per principal, there could be exponentially many
valid chains), this algorithm computes a set of PK/UID/Name
triples that are valid for each principal on the path between the
TA and the name to be authenticated. By doing so, it minimizes
the processing of redundant information.
a) Determining path and initialization
Several state variables are manipulated during the tree walk.
These are called:
1) Current-directory-name
This is the name indicating the current place in the tree
walk. Initially, this is the name of the TA.
2) Least-Common-Ancestor-Name
This is the portion of the names which is common to both the
CA and the Target. This is computed at initialization and
does not change during the treewalk.
3) Trusted-Key-Set
For each name which is an ancestor of either the TA or the
Target but not of the Least-Common-Ancestor, a list of
PK/UID/Name triples. This is initialized to a single triple
from the TA information in the supplied credentials.
4) Search-when-descending
This is a list of PK/UID/Name triples of issuers that will
be trusted when descending the tree. This set is initially
empty.
5) Saved-RDNs
This is a sequence of Relative Distinguished Names (RDNs)
stripped off the right of the target name to form
Least-common-ancestor-name. This "stack" is initially empty
and is populated during Step 3.
b) Ascending the "TA side" of the tree
While Current-directory-name is not identical to
Common-point-Name the algorithm moves up the tree. At each
step it does the following operations.
1) Find all cross certificates stored in the naming service
under Current-directory-name in which the subject is an
ancestor of the principal to be authenticated or an
indication that cross certificates from this issuer are
stored in the subject entry. If there is an indication that
such certificates are stored in the subject entry, copy all
triples in Trusted-Key-Set for Current-directory-name into
the "Search-when-descending" list. If any such certificates
are found, filter them to include only those which meet the
following criteria:
(i) For some triple in the Trusted-Key-Set corresponding to
the Current-directory-name, the public key in the triple
verifies the signature on the certificate and either the
UID in the triple matches the issuer UID in the
certificate or the UID in the triple and/or the
certificate is missing and the name in the triple matches
the issuer name in the certificate.
(ii) No certificates were found signed by this issuer in which
the subject name is longer than the subject name in this
certificate (i.e., if there are cross certificates to two
different ancestors, accept only those which lead to the
closest ancestor).
(iii)The current time is within the validity interval of the
certificate.
2) If any cross certificates were found (whether or not they
were all eliminated as part of the filtering process), set
Current-directory-name to the longest name that was found in
any certificate and construct a set of PK/UID/Name triples
for that name from the certificates which pass the filter
and place them in the Trusted Key Set associated with their
subject. Exit the ascending tree loop at this point and
proceed directly to step 3. Note that this means that if
there are cross certificates to an ancestor of the target
but they are all rejected (for example if they have
expired), the treewalk will not construct a chain through
the least common ancestor and will ultimately fail unless a
crosslink from a lower ancestor is found stored with its
subject. This is a security feature.
3) If no cross certificates are found, find all the parent
directory certificates for the directory whose name is in
the Current-directory-name. Filter these to find only those
which meet the following criteria:
(i) The current time is within the validity interval.
(ii) For some triple corresponding to the
Current-directory-name, the public key in the triple
verifies the signature on the certificate and either the
UID in the triple matches the issuer UID in the
certificate or the UID in the triple and/or the
certificate is missing and the name in the triple matches
the issuer name in the certificate.
4) Construct PK/UID/Name triples from the remaining
certificates for the directory whose name is constructed by
stripping the rightmost simple name from the
Current-directory-name and place them in the Trusted-Key-Set.
5) Strip the rightmost simple name of the
Current-directory-name.
6) Repeat from step (a) (testing to see if
current-directory-name is the same as Common-point-Name).
c) Searching the "target side" of the tree for a crosslink:
1) Initialization: set Current-directory-name to the name
supplied as input to this procedure.
2) Retrieve from the naming service all cross certificates
associated with Current-directory-name. Filter to only
those that meet the following criteria:
(i) The current time is within their validity interval.
(ii) The subject name is equal to Current-directory-name.
(iii)For some PK/UID/Name triple in the
"Search-when-descending" list compiled while ascending
the tree, the Public Key verifies the signature on the
certificate and either the UID matches the issuer UID in
the certificate or a UID is missing from the triple
and/or the certificate and the Name in the triple matches
the issuer name in the certificate.
(iv) There are no certificates found meeting criteria (ii) and
(iii) matching a PK/UID/Name triple in the
Search-when-descending list whose subject is a directory
lower in the naming hierarchy.
3) If any qualifying certificates are found, construct
PK/UID/Name triples for each of them; these should replace
rather than supplement any triples already in the
Trusted-key-set for that directory.
4) If after steps (b) and (c), there are no PK/UID/Name triples
corresponding to Current-directory-name in Trusted-Key-Set,
shorten Current-directory-name by one RDN (pushing it onto
the Saved-RDNs stack) and repeat this process until
Current-directory-name is equal to
Least-common-ancestor-name or there is at least one triple
in Trusted-key-set corresponding to Current-directory-name.
d) Descending the tree
While the list Saved-RDNs is not Empty the algorithm moves
down the tree. At each step it does the following operations.
1) Remove the first RDN from Saved-RDNs and append it to the
Current-directory-name.
2) Find all the child directory certificates for the directory
whose name is in the current-directory-name.
3) Filter these certificates to find only those which meet the
following criteria:
(i) The current time is within the validity interval.
(ii) For some PK/UID/Name triple in the Current-key-set for
the parent directory, the Public Key verifies the
signature on the certificate and either the UID matches
the issuer UID of the certificate or the UID is missing
from the triple and/or the certificate and the Name in
the triple matches the issuer name in the certificate.
(iii)The issuer name in the certificate is a prefix of the
subject name and the difference between the two names is
the final RDN of Current-directory-name.
4) Take the key, UID, and name from each remaining certificate
and form a new triple corresponding to
Current-directory-name in Trusted-Key-Set. If this set is
empty then the algorithm exits with the
'Incomplete-chain-of-trustworthy-CAs' error condition.
5) repeat from step (a), appending a new simple name to
Current-directory-name.
e) Find public keys:
If there are no triples in the Trusted-Key-Set for the named
principal, then the algorithm exits with the `Target-has-no-keys-w
error condition. Otherwise, the Public Key and UID are
extracted from each pair, duplicates are eliminated, and this
set is returned as the Pub_keys.
3.10.10.2 Allowed Variations - Caching
Some use of caches can be implemented without affecting the semantics
of the Get_Pub_Keys routine. For example, a crypto-cache could
remember the public key that verified a signature in the past and
could avoid the verification operation if the same key was used to
verify the same data structure again. In some cases, however, it is
impossible (or at least inconvenient) for a cache implementation to
be completely transparent.
In particular, for good performance it is important that certificates
not be re-retrieved from the naming service on every authentication.
This must be balanced against the need to have changes to the
contents of the naming service be reflected in DASS calls on a timely
basis. There are two cases of interest: changes which cause an
authentication which previously would have succeeded to fail and
changes which cause an authentication which previously would have
failed to succeed. These two cases are subject to different time
constraints.
In general, changes that cause authentication to succeed must be
reflected quite quickly - on the order of minutes. If a user
attempts an operation, it fails, the user tracks down a system
manager and causes the appropriate updates to take place, and the
user retries the operation, it is unacceptable for the operation to
continue to fail for an extended period because of stale caches.
Changes that cause authentication to fail must be reflected reliably
within a bounded period of time for security reasons. If a user
leaves the company, it must be possible to revoke his ability to
authenticate within a relatively short period of time - say hours.
These constraints mean that a naming service cache which contains
arbitrarily old information is unacceptable. To meet the second
constraint, naming service cache entries must be timed out within a
reasonable period of time unless in implementation verifies that the
certificate is still present (a crypto-cache which lasted longer
would be legal; rather than deleting a name service cache entry, in
implementation might instead verify that the entry was still present
in the naming service. This would avoid repeating the cryptographic
"verify").
In order to assure that information cached for even a few hours not
deny authentication for that extended period, it must be possible to
bypass caches when the result would otherwise be a failure. Since
the performance of authentication failures is not a serious concern,
it is acceptable to expect that before an operation fails a retry
will be made to the naming service to see if there are any new
relevant certificates (or in certain obscure conditions, to see if
any relevant certificates have been deleted).
If on a call to Get_Pub_Keys, the Try_Hard bit is True, then this
procedure must return results based on the contents of the naming
service no more than five minutes previous (this would normally be
accomplished by ignoring name service caches and making all
operations directly to the naming service). If the Try_Hard bit is
False, this procedure may return results based on the contents of the
naming service any time in the previous few hours, in the sense that
it may ignore any certificate added in the previous few hours and may
use any certificate deleted in the previous few hours. Procedures
which call this routine with Try_Hard set to false must be prepared
to call it again with Try_Hard True if their operation fails possibly
from this result.
The exact timer values for "five minutes" and "a few hours" are
expected to be implementation constants.
In the envisioned implementation, the entire "ascending treewalk" is
retrieved, verified, and its digested contents cached when a
principal first establishes credentials. A mechanism should be
provided to refresh this information periodically for principals
whose sessions might be long lived, but it would probably be
acceptable in the unlikely event of a user's ancestor's keys changing
to require that the user log out and log back in. This is consistent
with the observed behavior of existing security mechanisms.
The descending treewalk, on the other hand, is expected to be
maintained as a more conventional cache, where entries are kept in a
fixed amount of memory with a "least recently used" replacement
policy and a watchdog timer that assures that stale information is
not kept indefinitely. A call to Get_Pub_Keys with Try_Hard set
false would first check that cache for relevant certificates and only
if none were found there would it go out to the naming service. If
there were newer certificates in the naming service, they might not
be found and an authentication might therefore fail.
When Try_Hard is false, an implementation may assume that
certificates not in the cache do not exist so long as that assumption
does not cause an authentication to falsely succeed. In that case,
it may only make that assumption if the certificates have been
verified to not exist within the revocation time (a few hours).
3.11 DASSlessness Determination Functions
In order to provide better interoperability with alternative
authentication mechanisms and to provide backward compatibility with
older (insecure) authentication mechanisms, it is sometimes important
to be able to determine in a secure way what the appropriate
authentication mechanism is for a particular named principal. For
some applications, this will be done by a local mechanism, where
either the person creating access control information must know and
specify the mechanism for each principal or a system administrator on
the node must maintain a database mapping names to mechanisms. Three
applications come to mind where scaleability makes such mechanisms
implausible:
a) To transparently secure proxy-based applications (like rlogin)
in an environment where some hosts have been upgraded to
support DASS and some have not, a node must be willing to
accept connections authenticated only by their network
addresses but only if they can be assured that such nodes do
not have DASS installed. Access to a resource becomes secure
without administrative action when all nodes authorized to
access it have been upgraded.
In this scenario, the server node must be able to determine
whether the client node is DASSless in a secure fashion.
b) Similarly, in a mixed environment where some servers are
running DASS and some are not, it may be desirable for clients
to authenticate servers if they can but it would be
unacceptable for a client to stop being able to access a
DASSless server once DASS is installed on the client. In such
a situation where server authentication is desirable but not
essential, the client would like to determine in a secure
fashion whether the server can accept DASS authentication.
c) In a DASS/Kerberos interoperability scenario, a server may
decide that Kerberos authentication is "good enough" for
principals that do not have DASS credentials without
introducing trust in on-line authorities when DASS credentials
are available. In parallel with case 1, we want it to be true
that when the last principal with authority to access an
object is upgraded to DASS, we automatically cease to trust
PasswdEtc servers without administrative action on the part of
the object owner. For this purpose, the authenticator must
learn in a secure fashion that the principal is incapable of
DASS authentication.
Reliably determining DASSlessness is optional for implementations of
DASS and for applications. No other capabilities of DASS rely on
this one.
The interface to the DASSlessness inquiry function is specified as a
call independent of all others. This capability must be exposed to
the calling application so that a server that receives a request and
no token can ask whether the named principal should be believed
without a token. It might improve performance and usability if in
real interfaces DASSlessness were returned in addition to a bad
status on the function that creates a token if the token is targeted
toward a server incapable or processing it. An application could
then decide whether to make the request without a token (and give up
server authentication) or to abort the request.
3.11.1 Query DASSlessness
Query_DASSlessness(
--inputs
verifying_credentials Credentials,
principal_name Name,
--outputs
alternate_authentication Set of OIDs)
This function uses the verifying credentials to search for an
alternative authentication mechanism certificate for the named
principal or for any CA on the path between the verifying credentials
and the named principal. Such a certificate is identical to an DASS
X.509 certificate except that it lists a different algorithm
identifier for the public key of the subject than that expected by
DASS.
This function is implemented identically to Get_Pub_Keys except:
a) If in any set of certificates found, no valid DASS certificate
is found and one or more certificates are found that would
otherwise be valid except for an invalid subject public key
OID, the OID from that certificate or certificates is returned
and the algorithm terminates.
b) On initial execution, Try_Hard=False. If the first execution
fails to retrieve any valid PK/UID pairs but also fails to
find any invalid OID certificates, repeat the execution with
Try_Hard=True.
c) If the either execution finds PK/UID pairs or if neither finds
and invalid OID certificates, fail by returning a null set.
4. Certificate and message formats
4.1 ASN.1 encoding
Some definitions are taken from X.501 and X.509.
Dass DEFINITIONS ::=
BEGIN
--CCITT Definitions:
joint-iso-ccitt OBJECT IDENTIFIER ::= {2}
ds OBJECT IDENTIFIER ::= {joint-iso-ccitt 5}
algorithm OBJECT IDENTIFIER ::= {ds 8}
encryptionAlgorithm OBJECT IDENTIFIER ::= {algorithm 1}
hashAlgorithm OBJECT IDENTIFIER ::= {algorithm 2}
signatureAlgorithm OBJECT IDENTIFIER ::= {algorithm 3}
rsa OBJECT IDENTIFIER ::= {encryptionAlgorithm 1}
iso OBJECT IDENTIFIER ::= {1}
identified-organization OBJECT IDENTIFIER ::= {iso 3}
ecma OBJECT IDENTIFIER ::= {identified-organization 12}
member-company OBJECT IDENTIFIER ::= {ecma 2}
digital OBJECT IDENTIFIER ::= {member-company 1011}
--1989 OSI Implementors Workshop "Stable" Agreements
oiw OBJECT IDENTIFIER ::= {identified-organization 14}
dssig OBJECT IDENTIFIER ::= {oiw 7}