draft-ietf-kitten-2478bis-02.txt | draft-ietf-kitten-2478bis-03.txt | |||
---|---|---|---|---|
NETWORK WORKING GROUP L. Zhu | NETWORK WORKING GROUP L. Zhu | |||
Internet-Draft P. Leach | Internet-Draft P. Leach | |||
Obsoletes: 2478 (if approved) K. Jaganathan | Obsoletes: 2478 (if approved) K. Jaganathan | |||
Expires: June 1, 2005 Microsoft Corporation | Expires: June 14, 2005 Microsoft Corporation | |||
W. Ingersoll | W. Ingersoll | |||
Sun Microsystems | Sun Microsystems | |||
December 1, 2004 | December 14, 2004 | |||
The Simple and Protected GSS-API Negotiation Mechanism | The Simple and Protected GSS-API Negotiation Mechanism | |||
draft-ietf-kitten-2478bis-02 | draft-ietf-kitten-2478bis-03 | |||
Status of this Memo | Status of this Memo | |||
This document is an Internet-Draft and is subject to all provisions | This document is an Internet-Draft and is subject to all provisions | |||
of section 3 of RFC 3667. By submitting this Internet-Draft, each | of section 3 of RFC 3667. By submitting this Internet-Draft, each | |||
author represents that any applicable patent or other IPR claims of | author represents that any applicable patent or other IPR claims of | |||
which he or she is aware have been or will be disclosed, and any of | which he or she is aware have been or will be disclosed, and any of | |||
which he or she become aware will be disclosed, in accordance with | which he or she become aware will be disclosed, in accordance with | |||
RFC 3668. | RFC 3668. | |||
skipping to change at page 1, line 38 | skipping to change at page 1, line 39 | |||
and may be updated, replaced, or obsoleted by other documents at any | and may be updated, replaced, or obsoleted by other documents at any | |||
time. It is inappropriate to use Internet-Drafts as reference | time. It is inappropriate to use Internet-Drafts as reference | |||
material or to cite them other than as "work in progress." | material or to cite them other than as "work in progress." | |||
The list of current Internet-Drafts can be accessed at | The list of current Internet-Drafts can be accessed at | |||
http://www.ietf.org/ietf/1id-abstracts.txt. | http://www.ietf.org/ietf/1id-abstracts.txt. | |||
The list of Internet-Draft Shadow Directories can be accessed at | The list of Internet-Draft Shadow Directories can be accessed at | |||
http://www.ietf.org/shadow.html. | http://www.ietf.org/shadow.html. | |||
This Internet-Draft will expire on June 1, 2005. | This Internet-Draft will expire on June 14, 2005. | |||
Copyright Notice | Copyright Notice | |||
Copyright (C) The Internet Society (2004). | Copyright (C) The Internet Society (2004). | |||
Abstract | Abstract | |||
This document specifies a negotiation mechanism for the Generic | This document specifies a negotiation mechanism for the Generic | |||
Security Service Application Program Interface (GSS-API) which is | Security Service Application Program Interface (GSS-API) which is | |||
described in RFC 2743. | described in RFC 2743. | |||
GSS-API peers can use this negotiation mechanism to choose from a | GSS-API peers can use this negotiation mechanism to choose from a | |||
common set of security mechanisms. | common set of security mechanisms. | |||
If per-message integrity services are available on the established | ||||
mechanism context, then the negotiation is protected against an | ||||
attacker forcing the selection of a mechanism not desired by the | ||||
peers. | ||||
This mechanism replaces RFC 2478 in order to fix defects in that | ||||
specification and to describe how to interoperate with | ||||
implementations of that specification commonly deployed on the | ||||
Internet. | ||||
Table of Contents | Table of Contents | |||
1. Introduction . . . . . . . . . . . . . . . . . . . . . . . . . 3 | 1. Introduction . . . . . . . . . . . . . . . . . . . . . . . . . 3 | |||
2. Conventions Used in This Document . . . . . . . . . . . . . . 5 | 2. Conventions Used in This Document . . . . . . . . . . . . . . 5 | |||
3. Negotiation Protocol . . . . . . . . . . . . . . . . . . . . . 6 | 3. Negotiation Protocol . . . . . . . . . . . . . . . . . . . . . 6 | |||
3.1 Negotiation Description . . . . . . . . . . . . . . . . . 6 | 3.1 Negotiation Description . . . . . . . . . . . . . . . . . 6 | |||
3.2 Negotiation Procedure . . . . . . . . . . . . . . . . . . 7 | 3.2 Negotiation Procedure . . . . . . . . . . . . . . . . . . 7 | |||
4. Token Definitions . . . . . . . . . . . . . . . . . . . . . . 9 | 4. Token Definitions . . . . . . . . . . . . . . . . . . . . . . 10 | |||
4.1 Mechanism Types . . . . . . . . . . . . . . . . . . . . . 9 | 4.1 Mechanism Types . . . . . . . . . . . . . . . . . . . . . 10 | |||
4.2 Negotiation Tokens . . . . . . . . . . . . . . . . . . . . 9 | 4.2 Negotiation Tokens . . . . . . . . . . . . . . . . . . . . 10 | |||
4.2.1 negTokenInit . . . . . . . . . . . . . . . . . . . . . 10 | 4.2.1 negTokenInit . . . . . . . . . . . . . . . . . . . . . 11 | |||
4.2.2 negTokenResp . . . . . . . . . . . . . . . . . . . . . 11 | 4.2.2 negTokenResp . . . . . . . . . . . . . . . . . . . . . 12 | |||
5. Processing of mechListMIC . . . . . . . . . . . . . . . . . . 13 | 5. Processing of mechListMIC . . . . . . . . . . . . . . . . . . 14 | |||
6. Extensibility . . . . . . . . . . . . . . . . . . . . . . . . 16 | 6. Extensibility . . . . . . . . . . . . . . . . . . . . . . . . 17 | |||
7. Security Considerations . . . . . . . . . . . . . . . . . . . 17 | 7. Security Considerations . . . . . . . . . . . . . . . . . . . 18 | |||
8. IANA Considerations . . . . . . . . . . . . . . . . . . . . . 18 | 8. IANA Considerations . . . . . . . . . . . . . . . . . . . . . 19 | |||
9. Acknowledgments . . . . . . . . . . . . . . . . . . . . . . . 19 | 9. Acknowledgments . . . . . . . . . . . . . . . . . . . . . . . 20 | |||
10. Normative References . . . . . . . . . . . . . . . . . . . . 19 | 10. References . . . . . . . . . . . . . . . . . . . . . . . . . 21 | |||
Authors' Addresses . . . . . . . . . . . . . . . . . . . . . . 19 | 10.1 Normative References . . . . . . . . . . . . . . . . . . . . 21 | |||
A. GSS-API Negotiation Support API . . . . . . . . . . . . . . . 21 | 10.2 Informative References . . . . . . . . . . . . . . . . . . . 21 | |||
A.1 GSS_Set_neg_mechs call . . . . . . . . . . . . . . . . . . 21 | Authors' Addresses . . . . . . . . . . . . . . . . . . . . . . 21 | |||
A.2 GSS_Get_neg_mechs call . . . . . . . . . . . . . . . . . . 21 | A. GSS-API Negotiation Support API . . . . . . . . . . . . . . . 23 | |||
B. Changes since RFC2478 . . . . . . . . . . . . . . . . . . . . 23 | A.1 GSS_Set_neg_mechs call . . . . . . . . . . . . . . . . . . 23 | |||
Intellectual Property and Copyright Statements . . . . . . . . 25 | A.2 GSS_Get_neg_mechs call . . . . . . . . . . . . . . . . . . 23 | |||
B. Changes since RFC2478 . . . . . . . . . . . . . . . . . . . . 25 | ||||
C. mechListMIC Computation Example . . . . . . . . . . . . . . . 27 | ||||
Intellectual Property and Copyright Statements . . . . . . . . 28 | ||||
1. Introduction | 1. Introduction | |||
The GSS-API [RFC2743] provides a generic interface which can be | The GSS-API [RFC2743] provides a generic interface which can be | |||
layered atop different security mechanisms such that if communicating | layered atop different security mechanisms such that if communicating | |||
peers acquire GSS-API credentials for the same security mechanism, | peers acquire GSS-API credentials for the same security mechanism, | |||
then a security context may be established between them (subject to | then a security context may be established between them (subject to | |||
policy). However, GSS-API does not prescribe the method by which | policy). However, GSS-API does not prescribe the method by which | |||
GSS-API peers can establish whether they have a common security | GSS-API peers can establish whether they have a common security | |||
mechanism. | mechanism. | |||
The Simple and Protected GSS-API Negotiation (SPNEGO) mechanism | The Simple and Protected GSS-API Negotiation (SPNEGO) mechanism | |||
defined here is a pseudo security mechanism, represented by the | defined here is a pseudo security mechanism, represented by the | |||
Object Identifier iso.org.dod.internet.security.mechanism.snego | Object Identifier iso.org.dod.internet.security.mechanism.snego | |||
(1.3.6.1.5.5.2), which enables GSS-API peers to determine in-band | (1.3.6.1.5.5.2), which enables GSS-API peers to determine in-band | |||
whether their credentials share common GSS-API security mechanism(s), | whether their credentials support a common set of one or more GSS-API | |||
and if so, to invoke normal security context establishment for a | security mechanisms, and if so, to invoke the normal security context | |||
selected common security mechanism. This is most useful for | establishment for a selected common security mechanism. This is most | |||
applications which are based on GSS-API implementations and share | useful for applications which depend on GSS-API implementations and | |||
multiple mechanisms between the peers. | share multiple mechanisms between the peers. | |||
The SPNEGO mechanism negotiation is based on the following | The SPNEGO mechanism negotiation is based on the following model: the | |||
negotiation model: the initiator proposes a list of security | initiator proposes a list of security mechanism(s), in decreasing | |||
mechanism(s), in decreasing preference order (favorite choice first), | preference order (favorite choice first), the acceptor (also known as | |||
the acceptor (also known as the target) either accepts the | the target) either accepts the initiator's preferred security | |||
initiator's preferred security mechanism (the first in the list), or | mechanism (the first in the list), or chooses one that is available | |||
chooses one that is available from the offered list, or rejects the | from the offered list, or rejects the proposed value(s). The target | |||
proposed value(s). The target then informs the initiator of its | then informs the initiator of its choice. | |||
choice. | ||||
Once a common security mechanism is chosen, mechanism-specific | Once a common security mechanism is chosen, mechanism-specific | |||
options MAY be negotiated as part of the selected mechanism's context | options MAY be negotiated as part of the selected mechanism's context | |||
establishment. These negotiations (if any) are internal to the | establishment. These negotiations (if any) are internal to the | |||
mechanism and opaque to the SPNEGO protocol. As such they are | mechanism and opaque to the SPNEGO protocol. As such they are | |||
outside the scope of this document. | outside the scope of this document. | |||
If per-message integrity services are available on the established | If per-message integrity services are available on the established | |||
mechanism security context, then the peers can exchange MIC tokens to | mechanism security context, then the negotiation is protected to | |||
ensure that the mechanism list was not tampered with. This MIC token | ensure that the mechanism list has not been modified. In cases where | |||
exchange is OPTIONAL if the selected mechanism is the most preferred | an attacker could have materially influenced the negotiation, peers | |||
choice of both peers (see Section 5). | exchange message integrity code (MIC) tokens to confirm the mechanism | |||
list has not been modified. If no action of an attacker could have | ||||
materially modified the outcome of the negotiation, the exchange of | ||||
MIC tokens is optional (see Section 5). Allowing MIC tokens to be | ||||
optional in this case provides interoperability with existing | ||||
implementations while still protecting the negotiation. This | ||||
interoperability comes at the cost of increased complexity. | ||||
In order to avoid an extra round trip, the first security token of | In order to avoid an extra round trip, the first context | |||
the initiator's preferred mechanism SHOULD be embedded in the initial | establishment token of the initiator's preferred mechanism SHOULD be | |||
negotiation message (as defined in Section 4.2). This mechanism | embedded in the initial negotiation message (as defined in Section | |||
token is referred to as the optimistic mechanism token in this | 4.2). (This mechanism token is referred to as the optimistic | |||
document. If the selected mechanism matches the initiator's | mechanism token in this document.) In addition, using the optimistic | |||
preferred mechanism, no additional round trips need be incurred by | mechanism token allows the initiator to recover from non-fatal errors | |||
using this protocol. In addition, using the optimistic mechanism | encountered trying to produce the first mechanism token before a | |||
token allows the initiator to recover from non-fatal errors while | mechanism can be selected. Implementations MAY omit the optimistic | |||
producing the first mechanism token before a mechanism can be | mechanism token in cases where the likelihood of the initiator's | |||
selected. Implementations MAY omit the optimistic mechanism token to | preferred mechanism not being selected by the acceptor is significant | |||
avoid the cost of generating it in cases where the initiator's | given the cost of generating it. | |||
preferred mechanism is not selected by the acceptor. | ||||
SPNEGO relies the concepts developed in the GSS-API specification | SPNEGO relies on the concepts developed in the GSS-API specification | |||
[RFC2743]. The negotiation data is encapsulated in context-level | [RFC2743]. The negotiation data is encapsulated in context-level | |||
tokens. Therefore, callers of the GSS-API do not need to be aware of | tokens. Therefore, callers of the GSS-API do not need to be aware of | |||
the existence of the negotiation tokens but only of the new | the existence of the negotiation tokens but only of the new | |||
pseudo-security mechanism. A failure in the negotiation phase causes | pseudo-security mechanism. A failure in the negotiation phase causes | |||
a major status code to be returned: GSS_S_BAD_MECH. | a major status code to be returned: GSS_S_BAD_MECH. | |||
2. Conventions Used in This Document | 2. Conventions Used in This Document | |||
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", | The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", | |||
"SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this | "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this | |||
skipping to change at page 6, line 21 | skipping to change at page 6, line 21 | |||
When the established mechanism context supports per-message integrity | When the established mechanism context supports per-message integrity | |||
services, SPNEGO guarantees that the selected mechanism is mutually | services, SPNEGO guarantees that the selected mechanism is mutually | |||
preferred. | preferred. | |||
This section describes the negotiation process of this protocol. | This section describes the negotiation process of this protocol. | |||
3.1 Negotiation Description | 3.1 Negotiation Description | |||
The first negotiation token sent by the initiator contains an ordered | The first negotiation token sent by the initiator contains an ordered | |||
list of mechanisms (in decreasing preference order, favorite | list of mechanisms in decreasing preference order (favorite mechanism | |||
mechanism first), and optionally the initial mechanism token for the | first), and optionally the initial mechanism token for the preferred | |||
preferred mechanism of the initiator (i.e., the first in the list). | mechanism of the initiator (i.e., the first in the list). (Note that | |||
The list of security mechanisms available for negotiation is based on | the list MUST NOT contain mechanisms for which the client does not | |||
the credentials being used. | have appropriate credentials.) | |||
The target then processes the token from the initiator. This will | The target then processes the token from the initiator. This will | |||
result in one of four possible states (as defined in Section 4.2.2): | result in one of four possible states (as defined in Section 4.2.2) | |||
accept_completed, accept_incomplete, reject, or request_mic. A | being returned in the reply message: accept_completed, | |||
reject state will terminate the negotiation; an accept_completed | accept_incomplete, reject, or request_mic. A reject state will | |||
state indicates that not only was the initiator-selected mechanism | terminate the negotiation; an accept_completed state indicates that | |||
acceptable to the target, but also that the initial mechanism token | not only was the initiator-selected mechanism acceptable to the | |||
was sufficient to complete the authentication; an accept_incomplete | target, but also that the optimistic mechanism token was sufficient | |||
state indicates that further message exchange is needed but the MIC | to complete the authentication; an accept_incomplete state indicates | |||
token exchange as described in Section 5 is OPTIONAL; a request_mic | that further message exchange is needed but the MIC token exchange as | |||
state (this state can only be present in the first reply message from | described in Section 5 is OPTIONAL; a request_mic state (this state | |||
the target) indicates the MIC token exchange is REQUIRED if | can only be present in the first reply message from the target) | |||
per-message integrity services are available. | indicates the MIC token exchange is REQUIRED if per-message integrity | |||
services are available. | ||||
Unless the preference order is specified by the application (see | Unless the preference order is specified by the application (see | |||
Appendix A), the policy by which the target chooses a mechanism is an | Appendix A), the policy by which the target chooses a mechanism is an | |||
implementation-specific local matter. In the absence of an | implementation-specific local matter. In the absence of an | |||
application specified preference order or other policy, the target | application specified preference order or other policy, the target | |||
SHALL choose the first mechanism in the initiator proposed list for | SHALL choose the first mechanism in the initiator proposed list for | |||
which it has valid credentials. | which it has valid credentials. | |||
In case of a successful negotiation, the security mechanism in the | In case of a successful negotiation, the security mechanism in the | |||
first reply message represents the value suitable for the target, | first reply message represents the value suitable for the target, | |||
picked up from the list offered by the initiator. A context level | chosen from the list offered by the initiator. | |||
token for a reject state is OPTIONAL. | ||||
Once a mechanism has been selected, the tokens specific to the | In case of an unsuccessful negotiation, the reject state is returned | |||
selected mechanism are carried within the negotiation tokens. | and it is OPTIONAL to emit a context level negotiation token. | |||
Lastly, MIC tokens MAY be exchanged to ensure the authenticity of the | Once a mechanism has been selected, context establishment tokens | |||
specific to the selected mechanism are carried within the negotiation | ||||
tokens. | ||||
Lastly, MIC tokens may be exchanged to ensure the authenticity of the | ||||
mechanism list received by the target. | mechanism list received by the target. | |||
To avoid conflicts with the use of MIC tokens by SPNEGO, | To avoid conflicts with the use of MIC tokens by SPNEGO, | |||
partially-established contexts are not used for per-message calls: | partially-established contexts MUST NOT be used for per-message | |||
the prot_ready_state [RFC2743] will be false even if the underlying | calls. To guarantee this, the prot_ready_state [RFC2743] MUST be set | |||
mechanism would return true natively. | to false on return from GSS_Init_sec_context() and | |||
GSS_Accept_sec_context() even if the underlying mechanism returned | ||||
true. | ||||
3.2 Negotiation Procedure | 3.2 Negotiation Procedure | |||
The basic form of the procedure assumes that per-message integrity | The basic form of the procedure assumes that per-message integrity | |||
services are available on the established mechanism context, and it | services are available on the established mechanism context, and it | |||
is summarized as follows: | is summarized as follows: | |||
(a) The GSS-API initiator invokes GSS_Init_sec_context() as normal, | (a) The GSS-API initiator invokes GSS_Init_sec_context() as normal, | |||
but requests that SPNEGO be used. SPNEGO can either be explicity | but requests that SPNEGO be used. SPNEGO can either be explicity | |||
requested or accepted as the default mechanism. | requested or accepted as the default mechanism. | |||
skipping to change at page 7, line 40 | skipping to change at page 7, line 46 | |||
(c) The GSS-API initiator application sends the token to the target | (c) The GSS-API initiator application sends the token to the target | |||
application. The GSS-API target application deposits the token by | application. The GSS-API target application deposits the token by | |||
invoking GSS_Accept_sec_context(). The acceptor will do one of | invoking GSS_Accept_sec_context(). The acceptor will do one of | |||
the following: | the following: | |||
(I) If none of the proposed mechanisms are acceptable, the | (I) If none of the proposed mechanisms are acceptable, the | |||
negotiation SHALL be terminated. GSS_Accept_sec_context | negotiation SHALL be terminated. GSS_Accept_sec_context | |||
indicates GSS_S_BAD_MECH. The acceptor MAY output a | indicates GSS_S_BAD_MECH. The acceptor MAY output a | |||
negotiation token containing a reject state. | negotiation token containing a reject state. | |||
(II) If either the initiator's preferred mechanism is not accepted | (II) If either the initiator's preferred mechanism is not | |||
by the target or this mechanism is accepted but it is not the | accepted by the target or this mechanism is accepted but it | |||
acceptor's most preferred mechanism (see Section 3.1 and | is not the acceptor's most preferred mechanism (i.e., the | |||
Section 5), GSS_Accept_sec_context() indicates | MIC token exchange as described in Section 5 is required), | |||
GSS_S_CONTINUE_NEEDED. The acceptor MUST output a negotiation | GSS_Accept_sec_context() indicates GSS_S_CONTINUE_NEEDED. | |||
token containing a request_mic state. | ||||
(III) Otherwise, GSS_Accept_sec_conext() indicates GSS_S_COMPLETE | The acceptor MUST output a negotiation token containing a | |||
or GSS_S_CONTINUE_NEEDED depending on if at least one | request_mic state. | |||
additional negotiation token from the initiator is needed to | ||||
establish this context. The acceptor outputs a negotiation | (III) Otherwise if at least one additional negotiation token | |||
token containing an accept_complete or accept_incomplete state, | from the initiator is needed to establish this context, | |||
respectively. | GSS_Accept_sec_context() indicates GSS_S_CONTINUE_NEEDED and | |||
outputs a negotiation token containing an accept_incomplete | ||||
state. | ||||
(IV) Otherwise no additional negotiation token from the | ||||
initiator is needed to establish this context, | ||||
GSS_Accept_sec_context() indicates GSS_S_COMPLETE and | ||||
outputs a negotiation token containing an accept_complete | ||||
state. | ||||
If the initiator's preferred mechanism is accepted, and an | If the initiator's preferred mechanism is accepted, and an | |||
optimistic mechanism token was included, this mechanism token MUST | optimistic mechanism token was included, this mechanism token MUST | |||
be deposited to the selected mechanism by invoking | be deposited to the selected mechanism by invoking | |||
GSS_Accept_sec_context() and if a response mechanism token is | GSS_Accept_sec_context() and if a response mechanism token is | |||
emitted, it MUST be included in the response negotiation token. | emitted, it MUST be included in the response negotiation token. | |||
Otherwise, the target will not emit a response mechanism token in | Otherwise, the target will not emit a response mechanism token in | |||
the first reply. | the first reply. | |||
(d) The GSS-API target application returns the negotiation token to | (d) The GSS-API target application returns the negotiation token to | |||
skipping to change at page 11, line 14 | skipping to change at page 12, line 14 | |||
mechlistMIC | mechlistMIC | |||
This field, if present, contains a MIC token for the mechanism | This field, if present, contains a MIC token for the mechanism | |||
list in the initial negotiation message. This MIC token is | list in the initial negotiation message. This MIC token is | |||
computed according to Section 5. | computed according to Section 5. | |||
4.2.2 negTokenResp | 4.2.2 negTokenResp | |||
NegTokenResp ::= SEQUENCE { | NegTokenResp ::= SEQUENCE { | |||
negResult [0] ENUMERATED { | negState [0] ENUMERATED { | |||
accept_completed (0), | accept_completed (0), | |||
accept_incomplete (1), | accept_incomplete (1), | |||
reject (2), | reject (2), | |||
request_mic (3) | request_mic (3) | |||
} OPTIONAL, | } OPTIONAL, | |||
-- REQUIRED in the first reply from the target | -- REQUIRED in the first reply from the target | |||
supportedMech [1] MechType OPTIONAL, | supportedMech [1] MechType OPTIONAL, | |||
-- present only in the first reply from the target | -- present only in the first reply from the target | |||
responseToken [2] OCTET STRING OPTIONAL, | responseToken [2] OCTET STRING OPTIONAL, | |||
mechListMIC [3] OCTET STRING OPTIONAL, | mechListMIC [3] OCTET STRING OPTIONAL, | |||
... | ... | |||
} | } | |||
This is the syntax for all subsequent negotiation messages. | This is the syntax for all subsequent negotiation messages. | |||
negResult | negState | |||
This field, if present, contains the state of the negotiation. | This field, if present, contains the state of the negotiation. | |||
This can be: | This can be: | |||
accept_completed | accept_completed | |||
No further negotiation message from the peer is expected, | No further negotiation message from the peer is expected, | |||
and the security context is established for the sender. | and the security context is established for the sender. | |||
accept_incomplete | accept_incomplete | |||
skipping to change at page 13, line 10 | skipping to change at page 14, line 10 | |||
This field, if present, contains a MIC token for the mechanism | This field, if present, contains a MIC token for the mechanism | |||
list in the initial negotiation message. This MIC token is | list in the initial negotiation message. This MIC token is | |||
computed according to Section 5. | computed according to Section 5. | |||
5. Processing of mechListMIC | 5. Processing of mechListMIC | |||
If the mechanism selected by the negotiation does not support | If the mechanism selected by the negotiation does not support | |||
integrity protection, then no mechlistMIC token is used. | integrity protection, then no mechlistMIC token is used. | |||
Otherwise if the accepted mechanism is the most preferred mechanism | Otherwise, if the accepted mechanism is the most preferred mechanism | |||
of both the initiator and the acceptor, then the MIC token exchange, | of both the initiator and the acceptor, then the MIC token exchange, | |||
as described later in this section, is OPTIONAL. A mechanism is the | as described later in this section, is OPTIONAL. A mechanism is the | |||
acceptor's most preferred mechanism if there is no other mechanism | acceptor's most preferred mechanism if there is no other mechanism | |||
which would have been preferred over the accepted mechanism if it had | which, had it been present in the mechanism list, the acceptor would | |||
been present in the received mechanism list. | have preferred over the accepted mechanism. | |||
In all other cases, MIC tokens MUST be exchanged after the mechanism | In all other cases, MIC tokens MUST be exchanged after the mechanism | |||
context is fully established. | context is fully established. | |||
It is assumed that per-message integrity services are available on | a) The mechlistMIC token (or simply the MIC token) is computed over | |||
the established mechanism context in the following procedure for | the mechanism list in the initial negotiation message by invoking | |||
processing MIC tokens of the initiator's mechanism list. | GSS_GetMIC() as follows: the input context_handle is the | |||
established mechanism context, the input qop_req is 0, and the | ||||
a) The mechlistMIC token (or simply the MIC token) is computed by | input message is the DER encoding of the value of type | |||
invoking GSS_GetMIC(): the input context_handle is the established | MechTypeList which is contained in the "mechTypes" field of the | |||
mechanism context, the input qop_req is 0, and the input message | NegTokenInit. The input message is NOT the DER encoding of the | |||
is the mechTypes field in the initial negotiation message (only | type "[0] MechTypeList". | |||
the DER encoding of the type MechTypeList is included). | ||||
b) If the selected mechanism uses an even number of mechanism tokens | b) If the selected mechanism exchanges an even number of mechanism | |||
(namely the acceptor sends the last mechanism token), the acceptor | tokens (i.e., the acceptor sends the last mechanism token), the | |||
does the following when emitting the negotiation message | acceptor does the following when emitting the negotiation message | |||
containing the last mechanism token: if the MIC token exchange is | containing the last mechanism token: if the MIC token exchange is | |||
not required, GSS_Accept_sec_context() either indicates | optional, GSS_Accept_sec_context() either indicates GSS_S_COMPLETE | |||
GSS_S_COMPLETE and does not include a mechlistMIC token, or | and does not include a mechlistMIC token, or indicates | |||
indicates GSS_S_CONTINUE_NEEDED and includes a mechlistMIC token | GSS_S_CONTINUE_NEEDED and includes a mechlistMIC token and an | |||
and an accept_incomplete state; if the MIC token exchange is | accept_incomplete state; if the MIC token exchange is required, | |||
required, GSS_Accept_sec_context() indicates | GSS_Accept_sec_context() indicates GSS_S_CONTINUE_NEEDED, and | |||
GSS_S_CONTINUE_NEEDED, and includes a mechlistMIC token. | includes a mechlistMIC token. Acceptors that wish to be | |||
Acceptors that wish to be compatible with legacy Windows SPNEGO | compatible with legacy Windows SPNEGO implementations as described | |||
implementations as described in Appendix B shall not generate a | in Appendix B should not generate a mechlistMIC token when the MIC | |||
mechlistMIC token when the MIC token exchange is not required. | token exchange is not required. The initiator then processes the | |||
The initiator then processes the last mechanism token, and does | last mechanism token, and does one of the following: | |||
one of the following: | ||||
(I) If a mechlistMIC token was included, and is correctly | (I) If a mechlistMIC token was included, and is correctly | |||
verified, GSS_Init_sec_context() indicates GSS_S_COMPLETE. The | verified, GSS_Init_sec_context() indicates GSS_S_COMPLETE. The | |||
output negotiation message contains a mechlistMIC token, and an | output negotiation message contains a mechlistMIC token, and an | |||
accept_complete state. The acceptor MUST then verify this | accept_complete state. The acceptor MUST then verify this | |||
mechlistMIC token. | mechlistMIC token. | |||
(II) If a mechlistMIC token was included but is incorrect, the | (II) If a mechlistMIC token was included but is incorrect, the | |||
negotiation SHALL be terminated. GSS_Accept_sec_context() | negotiation SHALL be terminated. GSS_Init_sec_context() | |||
indicates GSS_S_DEFECTIVE_TOKEN. | indicates GSS_S_DEFECTIVE_TOKEN. | |||
(III) If no mechlistMIC token was included, and the MIC token | (III) If no mechlistMIC token was included, and the MIC token | |||
exchange is not required, GSS_Init_sec_context() indicates | exchange is not required, GSS_Init_sec_context() indicates | |||
GSS_S_COMPLETE with no output token. | GSS_S_COMPLETE with no output token. | |||
(IV) If no mechlistMIC token was included, but the MIC token | (IV) If no mechlistMIC token was included, but the MIC token | |||
exchange is required, the negotiation SHALL be terminated. | exchange is required, the negotiation SHALL be terminated. | |||
GSS_Accept_sec_context() indicates GSS_S_DEFECTIVE_TOKEN. | GSS_Accept_sec_context() indicates GSS_S_DEFECTIVE_TOKEN. | |||
c) In the case that the chosen mechanism uses an odd number of | c) In the case that the chosen mechanism exchanges an odd number of | |||
mechanism tokens (namely the initiator sends the last mechanism | mechanism tokens (i.e., the initiator sends the last mechanism | |||
token), the initiator does the following when emitting the | token), the initiator does the following when emitting the | |||
negotiation message containing the last mechanism token: if the | negotiation message containing the last mechanism token: if the | |||
negResult state was request_mic in the first reply from the | negState was request_mic in the first reply from the target, a | |||
target, a mechlistMIC token MUST be included, otherwise the | mechlistMIC token MUST be included, otherwise the mechlistMIC | |||
mechlistMIC token is OPTIONAL. In the case that the optimistic | token is OPTIONAL. (Note that the MIC token exchange is required | |||
mechanism token is the only mechanism token for the initiator's | if a mechanism other than the initiator's first choice is chosen.) | |||
preferred mechanism, the mechlistMIC token is OPTIONAL. | In the case that the optimistic mechanism token is the only | |||
GSS_Init_sec_context() indicates GSS_S_CONTINUE_NEEDED. | mechanism token for the initiator's preferred mechanism, the | |||
Initiators that wish to be compatible with legacy Windows SPNEGO | mechlistMIC token is OPTIONAL. Whether or not the mechlistMIC | |||
implementations as described in Appendix B shall not generate a | token is included, GSS_Init_sec_context() indicates | |||
mechlistMIC token when the MIC token exchange is not required. | GSS_S_CONTINUE_NEEDED. Initiators that wish to be compatible with | |||
The acceptor then processes the last mechanism token and does one | legacy Windows SPNEGO implementations as described in Appendix B | |||
of the following: | should not generate a mechlistMIC token when the MIC token | |||
exchange is not required. The acceptor then processes the last | ||||
mechanism token and does one of the following: | ||||
(I) If a mechlistMIC token was included and is correctly verified, | (I) If a mechlistMIC token was included and is correctly verified, | |||
GSS_Accept_sec_context() indicates GSS_S_COMPLETE. The output | GSS_Accept_sec_context() indicates GSS_S_COMPLETE. The output | |||
negotiation message contains a mechlistMIC token and an | negotiation message contains a mechlistMIC token and an | |||
accept_complete state. The initiator MUST then verify this | accept_complete state. The initiator MUST then verify this | |||
mechlistMIC token. | mechlistMIC token. | |||
(II) If a mechlistMIC token was included but is incorrect, the | (II) If a mechlistMIC token was included but is incorrect, the | |||
negotiation SHALL be terminated. GSS_Accept_sec_context() | negotiation SHALL be terminated. GSS_Accept_sec_context() | |||
indicates GSS_S_DEFECTIVE_TOKEN. | indicates GSS_S_DEFECTIVE_TOKEN. | |||
skipping to change at page 16, line 12 | skipping to change at page 17, line 12 | |||
MIC tokens is required), the negotiation SHALL be terminated. | MIC tokens is required), the negotiation SHALL be terminated. | |||
GSS_Accept_sec_context() indicates GSS_S_DEFECTIVE_TOKEN. | GSS_Accept_sec_context() indicates GSS_S_DEFECTIVE_TOKEN. | |||
6. Extensibility | 6. Extensibility | |||
Two mechanisms are provided for extensibility. First, the ASN.1 | Two mechanisms are provided for extensibility. First, the ASN.1 | |||
structures in this specification MAY be expanded by IETF standards | structures in this specification MAY be expanded by IETF standards | |||
action. Implementations receiving unknown fields MUST ignore these | action. Implementations receiving unknown fields MUST ignore these | |||
fields. | fields. | |||
Secondly, OIDs corresponding to a desired mechanism attribute may be | Secondly, OIDs corresponding to a desired mechanism attribute (i.e., | |||
included in the set of preferred mechanisms by an initiator. The | mechanism variants) may be included in the set of preferred | |||
acceptor can choose to honor this request by preferring mechanisms | mechanisms by an initiator. The acceptor can choose to honor this | |||
that have the included attributes. Future work within the Kitten | request by preferring mechanisms that have the included attributes. | |||
working group is expected to standardize common attributes that | Future work within the Kitten working group is expected to | |||
SPNEGO mechanisms may wish to support. At this time it is sufficient | standardize common attributes that SPNEGO mechanisms may wish to | |||
to say that initiators MAY include OIDs that do not correspond to | support. At this time it is sufficient to say that initiators MAY | |||
mechanisms but instead correspond to desired mechanism attributes in | include OIDs that do not correspond to mechanisms but instead | |||
their requests. Such OIDs MAY influence the acceptor's choice of | correspond to desired mechanism attributes in their requests. Such | |||
mechanism. As discussed in Section 5, if there are mechanisms that | OIDs MAY influence the acceptor's choice of mechanism. As discussed | |||
if present in the initiator's list of mechanisms might be preferred | in Section 5, if there are mechanisms that if present in the | |||
by the acceptor to the initiator's preferred mechanism, the acceptor | initiator's list of mechanisms might be preferred by the acceptor to | |||
MUST demand the MIC token exchange. As a consequence, acceptors MUST | the initiator's preferred mechanism, the acceptor MUST demand the MIC | |||
demand the MIC token exchange if they support negotiation of | token exchange. As a consequence, acceptors MUST demand the MIC | |||
attributes not available in the initiator's preferred mechanism | token exchange if they support negotiation of attributes not | |||
regardless of whether the initiator actually requested these | available in the initiator's preferred mechanism regardless of | |||
attributes. | whether the initiator actually requested these attributes. | |||
7. Security Considerations | 7. Security Considerations | |||
In order to produce the MIC token for the mechanism list, the | In order to produce the MIC token for the mechanism list, the | |||
mechanism must provide integrity protection. When the selected | mechanism must provide integrity protection. When the selected | |||
mechanism does not support integrity protection, the negotiation is | mechanism does not support integrity protection, the negotiation is | |||
vulnerable: an active attacker can force it to use a security | vulnerable: an active attacker can force it to use a security | |||
mechanism that is not mutually preferred but is acceptable to the | mechanism that is not mutually preferred but is acceptable to the | |||
target. | target. | |||
This protocol provides the following guarantees when per-message | This protocol provides the following guarantees when per-message | |||
integrity services are available on the established mechanism context | integrity services are available on the established mechanism context | |||
and the mechanism list was altered by an adversary such that a | and the mechanism list was altered by an adversary such that a | |||
mechanism which is not mutually preferred could be selected: | mechanism which is not mutually preferred could be selected: | |||
o if the last mechanism token is sent by the initiator, both peers | a) If the last mechanism token is sent by the initiator, both peers | |||
shall fail; | shall fail; | |||
o if the last mechanism token is sent by the acceptor, the acceptor | b) If the last mechanism token is sent by the acceptor, the acceptor | |||
shall not complete and the initiator at worst shall complete with | shall not complete and the initiator at worst shall complete with | |||
its preferred mechanism being selected. | its preferred mechanism being selected. | |||
The negotiation may not be terminated if an alteration was made but | The negotiation may not be terminated if an alteration was made but | |||
it had no material impact. | it had no material impact. | |||
The protection of the negotiation depends on the strength of the | The protection of the negotiation depends on the strength of the | |||
integrity protection. In particular, the strength of SPNEGO is no | integrity protection. In particular, the strength of SPNEGO is no | |||
stronger than the integrity protection of the weakest mechanism | stronger than the integrity protection of the weakest mechanism | |||
acceptable to GSS-API peers. | acceptable to GSS-API peers. | |||
skipping to change at page 19, line 18 | skipping to change at page 21, line 5 | |||
Jeff Altman, Tom Yu, Cristian Ilac and Martin Rex for their comments | Jeff Altman, Tom Yu, Cristian Ilac and Martin Rex for their comments | |||
and suggestions during development of this document. | and suggestions during development of this document. | |||
Luke Howard provided a prototype of this protocol in Heimdal and | Luke Howard provided a prototype of this protocol in Heimdal and | |||
resolved several issues in the initial draft. | resolved several issues in the initial draft. | |||
Eric Baize and Denis Pinkas wrote the original SPNEGO specification | Eric Baize and Denis Pinkas wrote the original SPNEGO specification | |||
[RFC2478] of which some of the text has been retained in this | [RFC2478] of which some of the text has been retained in this | |||
document. | document. | |||
10 Normative References | 10. References | |||
10.1 Normative References | ||||
[RFC2119] Bradner, S., "Key words for use in RFCs to Indicate | [RFC2119] Bradner, S., "Key words for use in RFCs to Indicate | |||
Requirement Levels", BCP 14, RFC 2119, March 1997. | Requirement Levels", BCP 14, RFC 2119, March 1997. | |||
[RFC2478] Baize, E. and D. Pinkas, "The Simple and Protected GSS-API | ||||
Negotiation Mechanism", RFC 2478, December 1998. | ||||
[RFC2743] Linn, J., "Generic Security Service Application Program | [RFC2743] Linn, J., "Generic Security Service Application Program | |||
Interface Version 2, Update 1", RFC 2743, January 2000. | Interface Version 2, Update 1", RFC 2743, January 2000. | |||
[X690] ASN.1 encoding rules: Specification of Basic Encoding | [X690] ASN.1 encoding rules: Specification of Basic Encoding | |||
Rules (BER), Canonical Encoding Rules (CER) and | Rules (BER), Canonical Encoding Rules (CER) and | |||
Distinguished Encoding Rules (DER), ITU-T Recommendation | Distinguished Encoding Rules (DER), ITU-T Recommendation | |||
X.690 (1997) | ISO/IEC International Standard 8825-1:1998. | X.690 (1997) | ISO/IEC International Standard 8825-1:1998. | |||
10.2 Informative References | ||||
[RFC2478] Baize, E. and D. Pinkas, "The Simple and Protected GSS-API | ||||
Negotiation Mechanism", RFC 2478, December 1998. | ||||
Authors' Addresses | Authors' Addresses | |||
Larry Zhu | Larry Zhu | |||
Microsoft Corporation | Microsoft Corporation | |||
One Microsoft Way | One Microsoft Way | |||
Redmond, WA 98052 | Redmond, WA 98052 | |||
US | US | |||
EMail: lzhu@microsoft.com | EMail: lzhu@microsoft.com | |||
skipping to change at page 21, line 13 | skipping to change at page 23, line 13 | |||
EMail: wyllys.ingersoll@sun.com | EMail: wyllys.ingersoll@sun.com | |||
Appendix A. GSS-API Negotiation Support API | Appendix A. GSS-API Negotiation Support API | |||
In order to provide to a GSS-API caller (either the initiator or the | In order to provide to a GSS-API caller (either the initiator or the | |||
target or both) the ability to choose among the set of supported | target or both) the ability to choose among the set of supported | |||
mechanisms a reduced set of mechanisms for negotiation, two | mechanisms a reduced set of mechanisms for negotiation, two | |||
additional APIs are defined: | additional APIs are defined: | |||
o GSS_Get_neg_mechs() indicates the set of security mechanisms | o GSS_Get_neg_mechs() indicates the set of security mechanisms | |||
available on the local system to the caller for negotiation, based | available on the local system to the caller for negotiation, for | |||
on the credentials being used. | which appropriate credentials are available. | |||
o GSS_Set_neg_mechs() specifies the set of security mechanisms to be | o GSS_Set_neg_mechs() specifies the set of security mechanisms to be | |||
used on the local system by the caller for negotiation, for the | used on the local system by the caller for negotiation, for the | |||
given credentials. | given credentials. | |||
A.1 GSS_Set_neg_mechs call | A.1 GSS_Set_neg_mechs call | |||
Inputs: | Inputs: | |||
o cred_handle CREDENTIAL HANDLE, -- NULL specifies default | o cred_handle CREDENTIAL HANDLE, -- NULL specifies default | |||
-- credentials | -- credentials | |||
skipping to change at page 23, line 12 | skipping to change at page 25, line 12 | |||
no input parameter, the returned set is not necessarily available for | no input parameter, the returned set is not necessarily available for | |||
all credentials. | all credentials. | |||
Appendix B. Changes since RFC2478 | Appendix B. Changes since RFC2478 | |||
SPNEGO implementations in Windows 2000/Windows XP/Windows Server | SPNEGO implementations in Windows 2000/Windows XP/Windows Server | |||
2003 have the following behavior: no mechlistMIC is produced and | 2003 have the following behavior: no mechlistMIC is produced and | |||
mechlistMIC is not processed if one is provided; if the initiator | mechlistMIC is not processed if one is provided; if the initiator | |||
sends the last mechanism token, the acceptor will send back a | sends the last mechanism token, the acceptor will send back a | |||
negotiation token with an accept_complete state and no mechlistMIC | negotiation token with an accept_complete state and no mechlistMIC | |||
token. In addition, the OID (1.2.840.48018.1.2.2) can be used to | token. In addition, an incorrect OID (1.2.840.48018.1.2.2) can be | |||
identify the GSS-API Kerberos Version 5 mechanism. | used to identify the GSS-API Kerberos Version 5 mechanism. | |||
The following changes have been made to be compatible with these | The following changes have been made to be compatible with these | |||
legacy implementations. | legacy implementations. | |||
* NegTokenTarg is changed to negTokenResp and it is the message | * NegTokenTarg is changed to negTokenResp and it is the message | |||
format for all subsequent negotiation tokens. | format for all subsequent negotiation tokens. | |||
* NegTokenInit is the message for the initial negotiation message | * NegTokenInit is the message for the initial negotiation message | |||
and that message only. | and that message only. | |||
* mechTypes in negTokenInit is not optional. | * mechTypes in negTokenInit is not optional. | |||
* Two MIC tokens are exchanged, one in each direction. | ||||
* If the selected mechanism is also the most preferred mechanism | * If the selected mechanism is also the most preferred mechanism | |||
for both peers, it is safe to omit the MIC tokens. | for both peers, it is safe to omit the MIC tokens. | |||
If at least one of the two peers implements the pseudo mechanism | If at least one of the two peers implements the updated pseudo | |||
in this document, the negotiation is protected. | mechanism in this document, the negotiation is protected. | |||
The following changes are to address the problems in RFC 2478. | The following changes are to address the problems in RFC 2478. | |||
* reqFlags is not protected therefore it should not impact the | * reqFlags is not protected therefore it should not impact the | |||
negotiation. | negotiation. | |||
* DER encoding is required. | * DER encoding is required. | |||
* GSS_GetMIC() input is clarified. | * GSS_GetMIC() input is clarified. | |||
* Per-message integrity services are requested for the negotiated | * Per-message integrity services are requested for the negotiated | |||
mechanism. | mechanism. | |||
* Two MIC tokens are exchanged, one in each direction. | ||||
An implementation that conforms to this specification will not | An implementation that conforms to this specification will not | |||
interoperate with a strict 2748 implementation. Even if the new | interoperate with a strict 2748 implementation. Even if the new | |||
implementation always sends a mechlistMIC token, it will still fail | implementation always sends a mechlistMIC token, it will still fail | |||
to interoperate. If it is a server, it will fail because it requests | to interoperate. If it is a server, it will fail because it requests | |||
a mechlistMIC token using an option that older implementations simply | a mechlistMIC token using an option that older implementations simply | |||
do not support. Clients will tend to fail as well. | do not support. Clients will tend to fail as well. | |||
As an alternative to the approach chosen in this specification, we | As an alternative to the approach chosen in this specification, we | |||
could have documented a correct behavior that is fully backward | could have documented a correct behavior that is fully backward | |||
compatible with RFC 2478 and included an appendix on how to | compatible with RFC 2478 and included an appendix on how to | |||
interoperate with existing incorrect implementations of RFC 2478. | interoperate with existing incorrect implementations of RFC 2478. | |||
As a practical matter, the SPNEGO implementers within the IETF have | As a practical matter, the SPNEGO implementers within the IETF have | |||
valued interoperability with the Microsoft implementations. We were | valued interoperability with the Microsoft implementations. We were | |||
unable to choose to maintain reasonable security guarantees, maintain | unable to choose to maintain reasonable security guarantees, maintain | |||
interoperability with the Microsoft implementations and maintain | interoperability with the Microsoft implementations and maintain | |||
interoperability with correct implementations of RFC 2478. The | interoperability with correct implementations of RFC 2478. The | |||
working group was not aware of any RFC 2478 implementations. Even if | working group was not aware of any RFC 2478 implementations deployed | |||
there are RFC 2478 implementations, it is unlikely that they will | on the Internet. Even if there are such implementations, it is | |||
interoperate because of a critical flaw in the description of the | unlikely that they will interoperate because of a critical flaw in | |||
encoding of the mechanism list in RFC 2478. | the description of the encoding of the mechanism list in RFC 2478. | |||
With the approach taken in this specification, we get security | With the approach taken in this specification, security is ensured | |||
between new implementations all the time while maintaining | between new implementations all the time while maintaining | |||
interoperability with the implementations we have within the IETF | interoperability with the implementations deployed within the IETF | |||
community. The working group believes that this justifies breaking | community. The working group believes that this justifies breaking | |||
compatibility with a correct implementation of RFC 2478. | compatibility with a correct implementation of RFC 2478. | |||
Appendix C. mechListMIC Computation Example | ||||
The following is an example to illustrate how the mechListMIC field | ||||
would be computed. | ||||
The initial part of the DER encoding of NegTokenInit is constructed | ||||
as follows (the "nn" are length encodings, possibly longer than one | ||||
octet): | ||||
30 -- identifier octet for constructed SEQUENCE (NegTokenInit) | ||||
nn -- length | ||||
-- contents octets of the SEQUENCE begin with | ||||
-- DER encoding of "[0] MechTypeList": | ||||
A0 -- identifier octet for constructed [0] | ||||
nn -- length | ||||
-- contents of the constructed [0] are DER encoding | ||||
-- of MechTypeList (which is a SEQUENCE): | ||||
30 -- identifier octet for constructed SEQUENCE | ||||
nn -- length | ||||
-- contents octets of the SEQUENCE begin with | ||||
-- DER encoding of OBJECT IDENTIFIER: | ||||
06 -- identifier octet for primitive OBJECT IDENTIFIER | ||||
09 -- length | ||||
2A 86 48 86 F7 12 01 02 02 -- Kerberos V5 | ||||
-- {1 2 840 113554 1 2 2} | ||||
If a mechlistMIC needs to be generated (according to the rules in | ||||
Section 5), it is computed by using the DER encoding of the type | ||||
MechTypeList data from the initiator's NegTokenInit token as input to | ||||
the GSS_GetMIC() function. In this case, the MIC would be computed | ||||
over the following octets: | ||||
DER encoding of MechTypeList: | ||||
30 nn 06 09 2A 86 48 86 F7 12 01 02 02 ... | ||||
Note that the identifier octet and lengh octet(s) for constructed [0] | ||||
(A0 nn) are not included in the MIC computation. | ||||
Intellectual Property Statement | Intellectual Property Statement | |||
The IETF takes no position regarding the validity or scope of any | The IETF takes no position regarding the validity or scope of any | |||
Intellectual Property Rights or other rights that might be claimed to | Intellectual Property Rights or other rights that might be claimed to | |||
pertain to the implementation or use of the technology described in | pertain to the implementation or use of the technology described in | |||
this document or the extent to which any license under such rights | this document or the extent to which any license under such rights | |||
might or might not be available; nor does it represent that it has | might or might not be available; nor does it represent that it has | |||
made any independent effort to identify any such rights. Information | made any independent effort to identify any such rights. Information | |||
on the procedures with respect to rights in RFC documents can be | on the procedures with respect to rights in RFC documents can be | |||
End of changes. | ||||
This html diff was produced by rfcdiff 1.23, available from http://www.levkowetz.com/ietf/tools/rfcdiff/ |