merge support for FAST in as-req codepath
This commit is contained in:
17
README.fast
Normal file
17
README.fast
Normal file
@@ -0,0 +1,17 @@
|
||||
|
||||
-- in order of preference
|
||||
|
||||
- client: support KRB5_PADATA_ENCRYPTED_CHALLENGE in lib/krb5/init_creds_pw.c
|
||||
- client: don't support ENC-TS in FAST
|
||||
|
||||
- client: plugin support for fast plugins
|
||||
|
||||
- kdc: plugin support for fast plugins
|
||||
partly done with "struct kdc_patypes"
|
||||
|
||||
- kcm: support FAST armor ticket
|
||||
-- using PK-INIT anonymous
|
||||
-- using host key
|
||||
|
||||
- client: tgs-req fast support
|
||||
- kdc: tgs-req fast support
|
899
doc/standardisation/rfc6112.txt
Normal file
899
doc/standardisation/rfc6112.txt
Normal file
@@ -0,0 +1,899 @@
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Internet Engineering Task Force (IETF) L. Zhu
|
||||
Request for Comments: 6112 P. Leach
|
||||
Updates: 4120, 4121, 4556 Microsoft Corporation
|
||||
Category: Standards Track S. Hartman
|
||||
ISSN: 2070-1721 Painless Security
|
||||
April 2011
|
||||
|
||||
|
||||
Anonymity Support for Kerberos
|
||||
|
||||
Abstract
|
||||
|
||||
This document defines extensions to the Kerberos protocol to allow a
|
||||
Kerberos client to securely communicate with a Kerberos application
|
||||
service without revealing its identity, or without revealing more
|
||||
than its Kerberos realm. It also defines extensions that allow a
|
||||
Kerberos client to obtain anonymous credentials without revealing its
|
||||
identity to the Kerberos Key Distribution Center (KDC). This
|
||||
document updates RFCs 4120, 4121, and 4556.
|
||||
|
||||
Status of This Memo
|
||||
|
||||
This is an Internet Standards Track document.
|
||||
|
||||
This document is a product of the Internet Engineering Task Force
|
||||
(IETF). It represents the consensus of the IETF community. It has
|
||||
received public review and has been approved for publication by the
|
||||
Internet Engineering Steering Group (IESG). Further information on
|
||||
Internet Standards is available in Section 2 of RFC 5741.
|
||||
|
||||
Information about the current status of this document, any errata,
|
||||
and how to provide feedback on it may be obtained at
|
||||
http://www.rfc-editor.org/info/rfc6112.
|
||||
|
||||
Copyright Notice
|
||||
|
||||
Copyright (c) 2011 IETF Trust and the persons identified as the
|
||||
document authors. All rights reserved.
|
||||
|
||||
This document is subject to BCP 78 and the IETF Trust's Legal
|
||||
Provisions Relating to IETF Documents
|
||||
(http://trustee.ietf.org/license-info) in effect on the date of
|
||||
publication of this document. Please review these documents
|
||||
carefully, as they describe your rights and restrictions with respect
|
||||
to this document. Code Components extracted from this document must
|
||||
include Simplified BSD License text as described in Section 4.e of
|
||||
the Trust Legal Provisions and are provided without warranty as
|
||||
described in the Simplified BSD License.
|
||||
|
||||
|
||||
|
||||
Zhu, et al. Standards Track [Page 1]
|
||||
|
||||
RFC 6112 Kerberos Anonymity Support April 2011
|
||||
|
||||
|
||||
This document may contain material from IETF Documents or IETF
|
||||
Contributions published or made publicly available before November
|
||||
10, 2008. The person(s) controlling the copyright in some of this
|
||||
material may not have granted the IETF Trust the right to allow
|
||||
modifications of such material outside the IETF Standards Process.
|
||||
Without obtaining an adequate license from the person(s) controlling
|
||||
the copyright in such materials, this document may not be modified
|
||||
outside the IETF Standards Process, and derivative works of it may
|
||||
not be created outside the IETF Standards Process, except to format
|
||||
it for publication as an RFC or to translate it into languages other
|
||||
than English.
|
||||
|
||||
Table of Contents
|
||||
|
||||
1. Introduction . . . . . . . . . . . . . . . . . . . . . . . . . 3
|
||||
2. Conventions Used in This Document . . . . . . . . . . . . . . 3
|
||||
3. Definitions . . . . . . . . . . . . . . . . . . . . . . . . . 3
|
||||
4. Protocol Description . . . . . . . . . . . . . . . . . . . . . 5
|
||||
4.1. Anonymity Support in AS Exchange . . . . . . . . . . . . . 5
|
||||
4.1.1. Anonymous PKINIT . . . . . . . . . . . . . . . . . . . 6
|
||||
4.2. Anonymity Support in TGS Exchange . . . . . . . . . . . . 7
|
||||
4.3. Subsequent Exchanges and Protocol Actions Common to AS
|
||||
and TGS for Anonymity Support . . . . . . . . . . . . . . 9
|
||||
5. Interoperability Requirements . . . . . . . . . . . . . . . . 10
|
||||
6. GSS-API Implementation Notes . . . . . . . . . . . . . . . . . 10
|
||||
7. PKINIT Client Contribution to the Ticket Session Key . . . . . 11
|
||||
7.1. Combining Two Protocol Keys . . . . . . . . . . . . . . . 12
|
||||
8. Security Considerations . . . . . . . . . . . . . . . . . . . 13
|
||||
9. Acknowledgements . . . . . . . . . . . . . . . . . . . . . . . 14
|
||||
10. IANA Considerations . . . . . . . . . . . . . . . . . . . . . 15
|
||||
11. References . . . . . . . . . . . . . . . . . . . . . . . . . . 15
|
||||
11.1. Normative References . . . . . . . . . . . . . . . . . . . 15
|
||||
11.2. Informative References . . . . . . . . . . . . . . . . . . 16
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Zhu, et al. Standards Track [Page 2]
|
||||
|
||||
RFC 6112 Kerberos Anonymity Support April 2011
|
||||
|
||||
|
||||
1. Introduction
|
||||
|
||||
In certain situations, the Kerberos [RFC4120] client may wish to
|
||||
authenticate a server and/or protect communications without revealing
|
||||
the client's own identity. For example, consider an application that
|
||||
provides read access to a research database and that permits queries
|
||||
by arbitrary requesters. A client of such a service might wish to
|
||||
authenticate the service, to establish trust in the information
|
||||
received from it, but might not wish to disclose the client's
|
||||
identity to the service for privacy reasons.
|
||||
|
||||
Extensions to Kerberos are specified in this document by which a
|
||||
client can authenticate the Key Distribution Center (KDC) and request
|
||||
an anonymous ticket. The client can use the anonymous ticket to
|
||||
authenticate the server and protect subsequent client-server
|
||||
communications.
|
||||
|
||||
By using the extensions defined in this specification, the client can
|
||||
request an anonymous ticket where the client may reveal the client's
|
||||
identity to the client's own KDC, or the client can hide the client's
|
||||
identity completely by using anonymous Public Key Cryptography for
|
||||
Initial Authentication in Kerberos (PKINIT) as defined in
|
||||
Section 4.1. Using the returned anonymous ticket, the client remains
|
||||
anonymous in subsequent Kerberos exchanges thereafter to KDCs on the
|
||||
cross-realm authentication path and to the server with which it
|
||||
communicates.
|
||||
|
||||
In this specification, the client realm in the anonymous ticket is
|
||||
the anonymous realm name when anonymous PKINIT is used to obtain the
|
||||
ticket. The client realm is the client's real realm name if the
|
||||
client is authenticated using the client's long-term keys. Note that
|
||||
the membership of a realm can imply a member of the community
|
||||
represented by the realm.
|
||||
|
||||
The interaction with Generic Security Service Application Program
|
||||
Interface (GSS-API) is described after the protocol description.
|
||||
|
||||
2. Conventions Used in This Document
|
||||
|
||||
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
|
||||
"SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this
|
||||
document are to be interpreted as described in [RFC2119].
|
||||
|
||||
3. Definitions
|
||||
|
||||
The anonymous Kerberos realm name is defined as a well-known realm
|
||||
name based on [RFC6111], and the value of this well-known realm name
|
||||
is the literal "WELLKNOWN:ANONYMOUS".
|
||||
|
||||
|
||||
|
||||
Zhu, et al. Standards Track [Page 3]
|
||||
|
||||
RFC 6112 Kerberos Anonymity Support April 2011
|
||||
|
||||
|
||||
The anonymous Kerberos principal name is defined as a well-known
|
||||
Kerberos principal name based on [RFC6111]. The value of the name-
|
||||
type field is KRB_NT_WELLKNOWN [RFC6111], and the value of the name-
|
||||
string field is a sequence of two KerberosString components:
|
||||
"WELLKNOWN", "ANONYMOUS".
|
||||
|
||||
The anonymous ticket flag is defined as bit 16 (with the first bit
|
||||
being bit 0) in the TicketFlags:
|
||||
|
||||
TicketFlags ::= KerberosFlags
|
||||
-- anonymous(16)
|
||||
-- TicketFlags and KerberosFlags are defined in [RFC4120]
|
||||
|
||||
This is a new ticket flag that is used to indicate that a ticket is
|
||||
an anonymous one.
|
||||
|
||||
An anonymous ticket is a ticket that has all of the following
|
||||
properties:
|
||||
|
||||
o The cname field contains the anonymous Kerberos principal name.
|
||||
|
||||
o The crealm field contains the client's realm name or the anonymous
|
||||
realm name.
|
||||
|
||||
o The anonymous ticket contains no information that can reveal the
|
||||
client's identity. However, the ticket may contain the client
|
||||
realm, intermediate realms on the client's authentication path,
|
||||
and authorization data that may provide information related to the
|
||||
client's identity. For example, an anonymous principal that is
|
||||
identifiable only within a particular group of users can be
|
||||
implemented using authorization data and such authorization data,
|
||||
if included in the anonymous ticket, would disclose the client's
|
||||
membership of that group.
|
||||
|
||||
o The anonymous ticket flag is set.
|
||||
|
||||
The anonymous KDC option is defined as bit 16 (with the first bit
|
||||
being bit 0) in the KDCOptions:
|
||||
|
||||
KDCOptions ::= KerberosFlags
|
||||
-- anonymous(16)
|
||||
-- KDCOptions and KerberosFlags are defined in [RFC4120]
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Zhu, et al. Standards Track [Page 4]
|
||||
|
||||
RFC 6112 Kerberos Anonymity Support April 2011
|
||||
|
||||
|
||||
As described in Section 4, the anonymous KDC option is set to request
|
||||
an anonymous ticket in an Authentication Service (AS) request or a
|
||||
Ticket Granting Service (TGS) request.
|
||||
|
||||
4. Protocol Description
|
||||
|
||||
In order to request an anonymous ticket, the client sets the
|
||||
anonymous KDC option in an AS request or a TGS request.
|
||||
|
||||
The rest of this section is organized as follows: it first describes
|
||||
protocol actions specific to AS exchanges, then it describes those of
|
||||
TGS exchanges. These are then followed by the description of
|
||||
protocol actions common to both AS and TGS and those in subsequent
|
||||
exchanges.
|
||||
|
||||
4.1. Anonymity Support in AS Exchange
|
||||
|
||||
The client requests an anonymous ticket by setting the anonymous KDC
|
||||
option in an AS exchange.
|
||||
|
||||
The Kerberos client can use the client's long-term keys, the client's
|
||||
X.509 certificates [RFC4556], or any other pre-authentication data,
|
||||
to authenticate to the KDC and requests an anonymous ticket in an AS
|
||||
exchange where the client's identity is known to the KDC.
|
||||
|
||||
If the client in the AS request is anonymous, the anonymous KDC
|
||||
option MUST be set in the request. Otherwise, the KDC MUST return a
|
||||
KRB-ERROR message with the code KDC_ERR_BADOPTION.
|
||||
|
||||
If the client is anonymous and the KDC does not have a key to encrypt
|
||||
the reply (this can happen when, for example, the KDC does not
|
||||
support PKINIT [RFC4556]), the KDC MUST return an error message with
|
||||
the code KDC_ERR_NULL_KEY [RFC4120].
|
||||
|
||||
When policy allows, the KDC issues an anonymous ticket. If the
|
||||
client name in the request is the anonymous principal, the client
|
||||
realm (crealm) in the reply is the anonymous realm, otherwise, the
|
||||
client realm is the realm of the AS. According to [RFC4120], the
|
||||
client name and the client realm in the EncTicketPart of the reply
|
||||
MUST match with the corresponding client name and the client realm of
|
||||
the KDC reply; the client MUST use the client name and the client
|
||||
realm returned in the KDC-REP in subsequent message exchanges when
|
||||
using the obtained anonymous ticket.
|
||||
|
||||
Care MUST be taken by the KDC not to reveal the client's identity in
|
||||
the authorization data of the returned ticket when populating the
|
||||
authorization data in a returned anonymous ticket.
|
||||
|
||||
|
||||
|
||||
|
||||
Zhu, et al. Standards Track [Page 5]
|
||||
|
||||
RFC 6112 Kerberos Anonymity Support April 2011
|
||||
|
||||
|
||||
The AD-INITIAL-VERIFIED-CAS authorization data, as defined in
|
||||
[RFC4556], contains the issuer name of the client certificate. This
|
||||
authorization is not applicable and MUST NOT be present in the
|
||||
returned anonymous ticket when anonymous PKINIT is used. When the
|
||||
client is authenticated (i.e., anonymous PKINIT is not used), if it
|
||||
is undesirable to disclose such information about the client's
|
||||
identity, the AD-INITIAL-VERIFIED-CAS authorization data SHOULD be
|
||||
removed from the returned anonymous ticket.
|
||||
|
||||
The client can use the client keys to mutually authenticate with the
|
||||
KDC and request an anonymous Ticket Granting Ticket (TGT) in the AS
|
||||
request. In that case, the reply key is selected as normal,
|
||||
according to Section 3.1.3 of [RFC4120].
|
||||
|
||||
4.1.1. Anonymous PKINIT
|
||||
|
||||
This sub-section defines anonymous PKINIT.
|
||||
|
||||
As described earlier in this section, the client can request an
|
||||
anonymous ticket by authenticating to the KDC using the client's
|
||||
identity; alternatively, without revealing the client's identity to
|
||||
the KDC, the Kerberos client can request an anonymous ticket as
|
||||
follows: the client sets the client name as the anonymous principal
|
||||
in the AS exchange and provides PA_PK_AS_REQ pre-authentication data
|
||||
[RFC4556] where the signerInfos field of the SignedData [RFC5652] of
|
||||
the PA_PK_AS_REQ is empty, and the certificates field is absent.
|
||||
Because the anonymous client does not have an associated asymmetric
|
||||
key pair, the client MUST choose the Diffie-Hellman key agreement
|
||||
method by filling in the Diffie-Hellman domain parameters in the
|
||||
clientPublicValue [RFC4556]. This use of the anonymous client name
|
||||
in conjunction with PKINIT is referred to as anonymous PKINIT. If
|
||||
anonymous PKINIT is used, the realm name in the returned anonymous
|
||||
ticket MUST be the anonymous realm.
|
||||
|
||||
Upon receiving the anonymous PKINIT request from the client, the KDC
|
||||
processes the request, according to Section 3.1.2 of [RFC4120]. The
|
||||
KDC skips the checks for the client's signature and the client's
|
||||
public key (such as the verification of the binding between the
|
||||
client's public key and the client name), but performs otherwise
|
||||
applicable checks, and proceeds as normal, according to [RFC4556].
|
||||
For example, the AS MUST check if the client's Diffie-Hellman domain
|
||||
parameters are acceptable. The Diffie-Hellman key agreement method
|
||||
MUST be used and the reply key is derived according to Section
|
||||
3.2.3.1 of [RFC4556]. If the clientPublicValue is not present in the
|
||||
request, the KDC MUST return a KRB-ERROR with the code
|
||||
KDC_ERR_PUBLIC_KEY_ENCRYPTION_NOT_SUPPORTED [RFC4556]. If all goes
|
||||
well, an anonymous ticket is generated, according to Section 3.1.3 of
|
||||
[RFC4120], and PA_PK_AS_REP [RFC4556] pre-authentication data is
|
||||
|
||||
|
||||
|
||||
Zhu, et al. Standards Track [Page 6]
|
||||
|
||||
RFC 6112 Kerberos Anonymity Support April 2011
|
||||
|
||||
|
||||
included in the KDC reply, according to [RFC4556]. If the KDC does
|
||||
not have an asymmetric key pair, it MAY reply anonymously or reject
|
||||
the authentication attempt. If the KDC replies anonymously, the
|
||||
signerInfos field of the SignedData [RFC5652] of PA_PK_AS_REP in the
|
||||
reply is empty, and the certificates field is absent. The server
|
||||
name in the anonymous KDC reply contains the name of the TGS.
|
||||
|
||||
Upon receipt of the KDC reply that contains an anonymous ticket and
|
||||
PA_PK_AS_REP [RFC4556] pre-authentication data, the client can then
|
||||
authenticate the KDC based on the KDC's signature in the
|
||||
PA_PK_AS_REP. If the KDC's signature is missing in the KDC reply
|
||||
(the reply is anonymous), the client MUST reject the returned ticket
|
||||
if it cannot authenticate the KDC otherwise.
|
||||
|
||||
A KDC that supports anonymous PKINIT MUST indicate the support of
|
||||
PKINIT, according to Section 3.4 of [RFC4556]. In addition, such a
|
||||
KDC MUST indicate support for anonymous PKINIT by including a padata
|
||||
element of padata-type PA_PKINIT_KX and empty padata-value when
|
||||
including PA-PK-AS-REQ in an error reply.
|
||||
|
||||
When included in a KDC error, PA_PKINIT_KX indicates support for
|
||||
anonymous PKINIT. As discussed in Section 7, when included in an AS-
|
||||
REP, PA_PKINIT_KX proves that the KDC and client both contributed to
|
||||
the session key for any use of Diffie-Hellman key agreement with
|
||||
PKINIT.
|
||||
|
||||
Note that in order to obtain an anonymous ticket with the anonymous
|
||||
realm name, the client MUST set the client name as the anonymous
|
||||
principal in the request when requesting an anonymous ticket in an AS
|
||||
exchange. Anonymity PKINIT is the only way via which an anonymous
|
||||
ticket with the anonymous realm as the client realm can be generated
|
||||
in this specification.
|
||||
|
||||
4.2. Anonymity Support in TGS Exchange
|
||||
|
||||
The client requests an anonymous ticket by setting the anonymous KDC
|
||||
option in a TGS exchange, and in that request the client can use a
|
||||
normal Ticket Granting Ticket (TGT) with the client's identity, or an
|
||||
anonymous TGT, or an anonymous cross-realm TGT. If the client uses a
|
||||
normal TGT, the client's identity is known to the TGS.
|
||||
|
||||
Note that the client can completely hide the client's identity in an
|
||||
AS exchange using anonymous PKINIT, as described in the previous
|
||||
section.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Zhu, et al. Standards Track [Page 7]
|
||||
|
||||
RFC 6112 Kerberos Anonymity Support April 2011
|
||||
|
||||
|
||||
If the ticket in the PA-TGS-REQ of the TGS request is an anonymous
|
||||
one, the anonymous KDC option MUST be set in the request. Otherwise,
|
||||
the KDC MUST return a KRB-ERROR message with the code
|
||||
KDC_ERR_BADOPTION.
|
||||
|
||||
When policy allows, the KDC issues an anonymous ticket. If the
|
||||
ticket in the TGS request is an anonymous one, the client name and
|
||||
the client realm are copied from that ticket; otherwise, the ticket
|
||||
in the TGS request is a normal ticket, the returned anonymous ticket
|
||||
contains the client name as the anonymous principal and the client
|
||||
realm as the true realm of the client. In all cases, according to
|
||||
[RFC4120] the client name and the client realm in the EncTicketPart
|
||||
of the reply MUST match with the corresponding client name and the
|
||||
client realm of the anonymous ticket in the reply; the client MUST
|
||||
use the client name and the client realm returned in the KDC-REP in
|
||||
subsequent message exchanges when using the obtained anonymous
|
||||
ticket.
|
||||
|
||||
Care MUST be taken by the TGS not to reveal the client's identity in
|
||||
the authorization data of the returned ticket. When propagating
|
||||
authorization data in the ticket or in the enc-authorization-data
|
||||
field of the request, the TGS MUST ensure that the client
|
||||
confidentiality is not violated in the returned anonymous ticket.
|
||||
The TGS MUST process the authorization data recursively, according to
|
||||
Section 5.2.6 of [RFC4120], beyond the container levels such that all
|
||||
embedded authorization elements are interpreted. The TGS SHOULD NOT
|
||||
populate identity-based authorization data into an anonymous ticket
|
||||
in that such authorization data typically reveals the client's
|
||||
identity. The specification of a new authorization data type MUST
|
||||
specify the processing rules of the authorization data when an
|
||||
anonymous ticket is returned. If there is no processing rule defined
|
||||
for an authorization data element or the authorization data element
|
||||
is unknown, the TGS MUST process it when an anonymous ticket is
|
||||
returned as follows:
|
||||
|
||||
o If the authorization data element may reveal the client's
|
||||
identity, it MUST be removed unless otherwise specified.
|
||||
|
||||
o If the authorization data element, that could reveal the client's
|
||||
identity, is intended to restrict the use of the ticket or limit
|
||||
the rights otherwise conveyed in the ticket, it cannot be removed
|
||||
in order to hide the client's identity. In this case, the
|
||||
authentication attempt MUST be rejected, and the TGS MUST return
|
||||
an error message with the code KDC_ERR_POLICY. Note this is
|
||||
applicable to both critical and optional authorization data.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Zhu, et al. Standards Track [Page 8]
|
||||
|
||||
RFC 6112 Kerberos Anonymity Support April 2011
|
||||
|
||||
|
||||
o If the authorization data element is unknown, the TGS MAY remove
|
||||
it, or transfer it into the returned anonymous ticket, or reject
|
||||
the authentication attempt, based on local policy for that
|
||||
authorization data type unless otherwise specified. If there is
|
||||
no policy defined for a given unknown authorization data type, the
|
||||
authentication MUST be rejected. The error code is KDC_ERR_POLICY
|
||||
when the authentication is rejected.
|
||||
|
||||
The AD-INITIAL-VERIFIED-CAS authorization data, as defined in
|
||||
[RFC4556], contains the issuer name of the client certificate. If it
|
||||
is undesirable to disclose such information about the client's
|
||||
identity, the AD-INITIAL-VERIFIED-CAS authorization data SHOULD be
|
||||
removed from an anonymous ticket.
|
||||
|
||||
The TGS encodes the name of the previous realm into the transited
|
||||
field, according to Section 3.3.3.2 of [RFC4120]. Based on local
|
||||
policy, the TGS MAY omit the previous realm, if the cross realm TGT
|
||||
is an anonymous one, in order to hide the authentication path of the
|
||||
client. The unordered set of realms in the transited field, if
|
||||
present, can reveal which realm may potentially be the realm of the
|
||||
client or the realm that issued the anonymous TGT. The anonymous
|
||||
Kerberos realm name MUST NOT be present in the transited field of a
|
||||
ticket. The true name of the realm that issued the anonymous ticket
|
||||
MAY be present in the transited field of a ticket.
|
||||
|
||||
4.3. Subsequent Exchanges and Protocol Actions Common to AS and TGS for
|
||||
Anonymity Support
|
||||
|
||||
In both AS and TGS exchanges, the realm field in the KDC request is
|
||||
always the realm of the target KDC, not the anonymous realm when the
|
||||
client requests an anonymous ticket.
|
||||
|
||||
Absent other information, the KDC MUST NOT include any identifier in
|
||||
the returned anonymous ticket that could reveal the client's identity
|
||||
to the server.
|
||||
|
||||
Unless anonymous PKINIT is used, if a client requires anonymous
|
||||
communication, then the client MUST check to make sure that the
|
||||
ticket in the reply is actually anonymous by checking the presence of
|
||||
the anonymous ticket flag in the flags field of the EncKDCRepPart.
|
||||
This is because KDCs ignore unknown KDC options. A KDC that does not
|
||||
understand the anonymous KDC option will not return an error, but
|
||||
will instead return a normal ticket.
|
||||
|
||||
The subsequent client and server communications then proceed as
|
||||
described in [RFC4120].
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Zhu, et al. Standards Track [Page 9]
|
||||
|
||||
RFC 6112 Kerberos Anonymity Support April 2011
|
||||
|
||||
|
||||
Note that the anonymous principal name and realm are only applicable
|
||||
to the client in Kerberos messages, the server cannot be anonymous in
|
||||
any Kerberos message per this specification.
|
||||
|
||||
A server accepting an anonymous service ticket may assume that
|
||||
subsequent requests using the same ticket originate from the same
|
||||
client. Requests with different tickets are likely to originate from
|
||||
different clients.
|
||||
|
||||
Upon receipt of an anonymous ticket, the transited policy check is
|
||||
performed in the same way as that of a normal ticket if the client's
|
||||
realm is not the anonymous realm; if the client realm is the
|
||||
anonymous realm, absent other information any realm in the
|
||||
authentication path is allowed by the cross-realm policy check.
|
||||
|
||||
5. Interoperability Requirements
|
||||
|
||||
Conforming implementations MUST support the anonymous principal with
|
||||
a non-anonymous realm, and they MAY support the anonymous principal
|
||||
with the anonymous realm using anonymous PKINIT.
|
||||
|
||||
6. GSS-API Implementation Notes
|
||||
|
||||
GSS-API defines the name_type GSS_C_NT_ANONYMOUS [RFC2743] to
|
||||
represent the anonymous identity. In addition, Section 2.1.1 of
|
||||
[RFC1964] defines the single string representation of a Kerberos
|
||||
principal name with the name_type GSS_KRB5_NT_PRINCIPAL_NAME. The
|
||||
anonymous principal with the anonymous realm corresponds to the GSS-
|
||||
API anonymous principal. A principal with the anonymous principal
|
||||
name and a non-anonymous realm is an authenticated principal; hence,
|
||||
such a principal does not correspond to the anonymous principal in
|
||||
GSS-API with the GSS_C_NT_ANONYMOUS name type. The [RFC1964] name
|
||||
syntax for GSS_KRB5_NT_PRINCIPAL_NAME MUST be used for importing the
|
||||
anonymous principal name with a non-anonymous realm name and for
|
||||
displaying and exporting these names. In addition, this syntax must
|
||||
be used along with the name type GSS_C_NT_ANONYMOUS for displaying
|
||||
and exporting the anonymous principal with the anonymous realm.
|
||||
|
||||
At the GSS-API [RFC2743] level, an initiator/client requests the use
|
||||
of an anonymous principal with the anonymous realm by asserting the
|
||||
"anonymous" flag when calling GSS_Init_Sec_Context(). The GSS-API
|
||||
implementation MAY provide implementation-specific means for
|
||||
requesting the use of an anonymous principal with a non-anonymous
|
||||
realm.
|
||||
|
||||
GSS-API does not know or define "anonymous credentials", so the
|
||||
(printable) name of the anonymous principal will rarely be used by or
|
||||
relevant for the initiator/client. The printable name is relevant
|
||||
|
||||
|
||||
|
||||
Zhu, et al. Standards Track [Page 10]
|
||||
|
||||
RFC 6112 Kerberos Anonymity Support April 2011
|
||||
|
||||
|
||||
for the acceptor/server when performing an authorization decision
|
||||
based on the initiator name that is returned from the acceptor side
|
||||
upon the successful security context establishment.
|
||||
|
||||
A GSS-API initiator MUST carefully check the resulting context
|
||||
attributes from the initial call to GSS_Init_Sec_Context() when
|
||||
requesting anonymity, because (as in the GSS-API tradition and for
|
||||
backwards compatibility) anonymity is just another optional context
|
||||
attribute. It could be that the mechanism doesn't recognize the
|
||||
attribute at all or that anonymity is not available for some other
|
||||
reasons -- and in that case the initiator MUST NOT send the initial
|
||||
security context token to the acceptor, because it will likely reveal
|
||||
the initiators identity to the acceptor, something that can rarely be
|
||||
"un-done".
|
||||
|
||||
Portable initiators are RECOMMENDED to use default credentials
|
||||
whenever possible, and request anonymity only through the input
|
||||
anon_req_flag [RFC2743] to GSS_Init_Sec_Context().
|
||||
|
||||
7. PKINIT Client Contribution to the Ticket Session Key
|
||||
|
||||
The definition in this section was motivated by protocol analysis of
|
||||
anonymous PKINIT (defined in this document) in building tunneling
|
||||
channels [RFC6113] and subsequent channel bindings. In order to
|
||||
enable applications of anonymous PKINIT to form channels, all
|
||||
implementations of anonymous PKINIT need to meet the requirements of
|
||||
this section. There is otherwise no connection to the rest of this
|
||||
document.
|
||||
|
||||
PKINIT is useful for constructing tunneling channels. To ensure that
|
||||
an attacker cannot create a channel with a given name, it is
|
||||
desirable that neither the KDC nor the client unilaterally determine
|
||||
the ticket session key. To achieve that end, a KDC conforming to
|
||||
this definition MUST encrypt a randomly generated key, called the KDC
|
||||
contribution key, in the PA_PKINIT_KX padata (defined next in this
|
||||
section). The KDC contribution key is then combined with the reply
|
||||
key to form the ticket session key of the returned ticket. These two
|
||||
keys are then combined using the KRB-FX-CF2 operation defined in
|
||||
Section 7.1, where K1 is the KDC contribution key, K2 is the reply
|
||||
key, the input pepper1 is American Standard Code for Information
|
||||
Interchange (ASCII) [ASAX34] string "PKINIT", and the input pepper2
|
||||
is ASCII string "KeyExchange".
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Zhu, et al. Standards Track [Page 11]
|
||||
|
||||
RFC 6112 Kerberos Anonymity Support April 2011
|
||||
|
||||
|
||||
PA_PKINIT_KX 147
|
||||
-- padata for PKINIT that contains an encrypted
|
||||
-- KDC contribution key.
|
||||
|
||||
PA-PKINIT-KX ::= EncryptedData -- EncryptionKey
|
||||
-- Contains an encrypted key randomly
|
||||
-- generated by the KDC (known as the KDC contribution key).
|
||||
-- Both EncryptedData and EncryptionKey are defined in [RFC4120]
|
||||
|
||||
The PA_PKINIT_KX padata MUST be included in the KDC reply when
|
||||
anonymous PKINIT is used; it SHOULD be included if PKINIT is used
|
||||
with the Diffie-Hellman key exchange but the client is not anonymous;
|
||||
it MUST NOT be included otherwise (e.g., when PKINIT is used with the
|
||||
public key encryption as the key exchange).
|
||||
|
||||
The padata-value field of the PA-PKINIT-KX type padata contains the
|
||||
DER [X.680] [X.690] encoding of the Abstract Syntax Notation One
|
||||
(ASN.1) type PA-PKINIT-KX. The PA-PKINIT-KX structure is an
|
||||
EncryptedData. The cleartext data being encrypted is the DER-encoded
|
||||
KDC contribution key randomly generated by the KDC. The encryption
|
||||
key is the reply key and the key usage number is
|
||||
KEY_USAGE_PA_PKINIT_KX (44).
|
||||
|
||||
The client then decrypts the KDC contribution key and verifies the
|
||||
ticket session key in the returned ticket is the combined key of the
|
||||
KDC contribution key and the reply key as described above. A
|
||||
conforming client MUST reject anonymous PKINIT authentication if the
|
||||
PA_PKINIT_KX padata is not present in the KDC reply or if the ticket
|
||||
session key of the returned ticket is not the combined key of the KDC
|
||||
contribution key and the reply key when PA-PKINIT-KX is present in
|
||||
the KDC reply.
|
||||
|
||||
7.1. Combining Two Protocol Keys
|
||||
|
||||
KRB-FX-CF2() combines two protocol keys based on the pseudo-random()
|
||||
function defined in [RFC3961].
|
||||
|
||||
Given two input keys, K1 and K2, where K1 and K2 can be of two
|
||||
different enctypes, the output key of KRB-FX-CF2(), K3, is derived as
|
||||
follows:
|
||||
|
||||
KRB-FX-CF2(protocol key, protocol key, octet string,
|
||||
octet string) -> (protocol key)
|
||||
|
||||
PRF+(K1, pepper1) -> octet-string-1
|
||||
PRF+(K2, pepper2) -> octet-string-2
|
||||
KRB-FX-CF2(K1, K2, pepper1, pepper2) ->
|
||||
random-to-key(octet-string-1 ^ octet-string-2)
|
||||
|
||||
|
||||
|
||||
Zhu, et al. Standards Track [Page 12]
|
||||
|
||||
RFC 6112 Kerberos Anonymity Support April 2011
|
||||
|
||||
|
||||
Where ^ denotes the exclusive-OR operation. PRF+() is defined as
|
||||
follows:
|
||||
|
||||
PRF+(protocol key, octet string) -> (octet string)
|
||||
|
||||
PRF+(key, shared-info) -> pseudo-random( key, 1 || shared-info ) ||
|
||||
pseudo-random( key, 2 || shared-info ) ||
|
||||
pseudo-random( key, 3 || shared-info ) || ...
|
||||
|
||||
Here the counter value 1, 2, 3, and so on are encoded as a one-octet
|
||||
integer. The pseudo-random() operation is specified by the enctype
|
||||
of the protocol key. PRF+() uses the counter to generate enough bits
|
||||
as needed by the random-to-key() [RFC3961] function for the
|
||||
encryption type specified for the resulting key; unneeded bits are
|
||||
removed from the tail.
|
||||
|
||||
8. Security Considerations
|
||||
|
||||
Since KDCs ignore unknown options, a client requiring anonymous
|
||||
communication needs to make sure that the returned ticket is actually
|
||||
anonymous. This is because a KDC that does not understand the
|
||||
anonymous option would not return an anonymous ticket.
|
||||
|
||||
By using the mechanism defined in this specification, the client does
|
||||
not reveal the client's identity to the server but the client
|
||||
identity may be revealed to the KDC of the server principal (when the
|
||||
server principal is in a different realm than that of the client),
|
||||
and any KDC on the cross-realm authentication path. The Kerberos
|
||||
client MUST verify the ticket being used is indeed anonymous before
|
||||
communicating with the server, otherwise, the client's identity may
|
||||
be revealed unintentionally.
|
||||
|
||||
In cases where specific server principals must not have access to the
|
||||
client's identity (for example, an anonymous poll service), the KDC
|
||||
can define server-principal-specific policy that ensures any normal
|
||||
service ticket can NEVER be issued to any of these server principals.
|
||||
|
||||
If the KDC that issued an anonymous ticket were to maintain records
|
||||
of the association of identities to an anonymous ticket, then someone
|
||||
obtaining such records could breach the anonymity. Additionally, the
|
||||
implementations of most (for now all) KDC's respond to requests at
|
||||
the time that they are received. Traffic analysis on the connection
|
||||
to the KDC will allow an attacker to match client identities to
|
||||
anonymous tickets issued. Because there are plaintext parts of the
|
||||
tickets that are exposed on the wire, such matching by a third-party
|
||||
observer is relatively straightforward. A service that is
|
||||
authenticated by the anonymous principals may be able to infer the
|
||||
|
||||
|
||||
|
||||
|
||||
Zhu, et al. Standards Track [Page 13]
|
||||
|
||||
RFC 6112 Kerberos Anonymity Support April 2011
|
||||
|
||||
|
||||
identity of the client by examining and linking quasi-static protocol
|
||||
information such as the IP address from which a request is received,
|
||||
or by linking multiple uses of the same anonymous ticket.
|
||||
|
||||
Two mechanisms, the FAST facility with the hide-client-names option
|
||||
in [RFC6113] and the Kerberos5 starttls option [STARTTLS], protect
|
||||
the client identity so that an attacker would never be able to
|
||||
observe the client identity sent to the KDC. Transport or network
|
||||
layer security between the client and the server will help prevent
|
||||
tracking of a particular ticket to link a ticket to a user. In
|
||||
addition, clients can limit how often a ticket is reused to minimize
|
||||
ticket linking.
|
||||
|
||||
The client's real identity is not revealed when the client is
|
||||
authenticated as the anonymous principal. Application servers MAY
|
||||
reject the authentication in order to, for example, prevent
|
||||
information disclosure or as part of Denial of Service (DoS)
|
||||
prevention. Application servers MUST avoid accepting anonymous
|
||||
credentials in situations where they must record the client's
|
||||
identity; for example, when there must be an audit trail.
|
||||
|
||||
9. Acknowledgements
|
||||
|
||||
JK Jaganathan helped editing early revisions of this document.
|
||||
|
||||
Clifford Neuman contributed the core notions of this document.
|
||||
|
||||
Ken Raeburn reviewed the document and provided suggestions for
|
||||
improvements.
|
||||
|
||||
Martin Rex wrote the text for GSS-API considerations.
|
||||
|
||||
Nicolas Williams reviewed the GSS-API considerations section and
|
||||
suggested ideas for improvements.
|
||||
|
||||
Sam Hartman and Nicolas Williams were great champions of this work.
|
||||
|
||||
Miguel Garcia and Phillip Hallam-Baker reviewed the document and
|
||||
provided helpful suggestions.
|
||||
|
||||
In addition, the following individuals made significant
|
||||
contributions: Jeffrey Altman, Tom Yu, Chaskiel M Grundman, Love
|
||||
Hornquist Astrand, Jeffrey Hutzelman, and Olga Kornievskaia.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Zhu, et al. Standards Track [Page 14]
|
||||
|
||||
RFC 6112 Kerberos Anonymity Support April 2011
|
||||
|
||||
|
||||
10. IANA Considerations
|
||||
|
||||
This document defines a new 'anonymous' Kerberos well-known name and
|
||||
a new 'anonymous' Kerberos well-known realm based on [RFC6111]. IANA
|
||||
has added these two values to the Kerberos naming registries that are
|
||||
created in [RFC6111].
|
||||
|
||||
11. References
|
||||
|
||||
11.1. Normative References
|
||||
|
||||
[ASAX34] American Standards Institute, "American Standard Code for
|
||||
Information Interchange", ASA X3.4-1963, June 1963.
|
||||
|
||||
[RFC1964] Linn, J., "The Kerberos Version 5 GSS-API Mechanism",
|
||||
RFC 1964, June 1996.
|
||||
|
||||
[RFC2119] Bradner, S., "Key words for use in RFCs to Indicate
|
||||
Requirement Levels", BCP 14, RFC 2119, March 1997.
|
||||
|
||||
[RFC2743] Linn, J., "Generic Security Service Application Program
|
||||
Interface Version 2, Update 1", RFC 2743, January 2000.
|
||||
|
||||
[RFC3961] Raeburn, K., "Encryption and Checksum Specifications for
|
||||
Kerberos 5", RFC 3961, February 2005.
|
||||
|
||||
[RFC4120] Neuman, C., Yu, T., Hartman, S., and K. Raeburn, "The
|
||||
Kerberos Network Authentication Service (V5)", RFC 4120,
|
||||
July 2005.
|
||||
|
||||
[RFC4556] Zhu, L. and B. Tung, "Public Key Cryptography for Initial
|
||||
Authentication in Kerberos (PKINIT)", RFC 4556,
|
||||
June 2006.
|
||||
|
||||
[RFC5652] Housley, R., "Cryptographic Message Syntax (CMS)",
|
||||
STD 70, RFC 5652, September 2009.
|
||||
|
||||
[RFC6111] Zhu, L., "Additional Kerberos Naming Constraints",
|
||||
RFC 6111, April 2011.
|
||||
|
||||
[X.680] "Abstract Syntax Notation One (ASN.1): Specification of
|
||||
Basic Notation", ITU-T Recommendation X.680: ISO/IEC
|
||||
International Standard 8824-1:1998, 1997.
|
||||
|
||||
[X.690] "ASN.1 encoding rules: Specification of Basic Encoding
|
||||
Rules (BER), Canonical Encoding Rules (CER) and
|
||||
Distinguished Encoding Rules (DER)", ITU-T Recommendation
|
||||
X.690 ISO/IEC International Standard 8825-1:1998, 1997.
|
||||
|
||||
|
||||
|
||||
Zhu, et al. Standards Track [Page 15]
|
||||
|
||||
RFC 6112 Kerberos Anonymity Support April 2011
|
||||
|
||||
|
||||
11.2. Informative References
|
||||
|
||||
[RFC6113] Hartman, S. and L. Zhu, "A Generalized Framework for
|
||||
Kerberos Pre-Authentication", RFC 6113, April 2011.
|
||||
|
||||
[STARTTLS] Josefsson, S., "Using Kerberos V5 over the Transport
|
||||
Layer Security (TLS) protocol", Work in Progress,
|
||||
August 2010.
|
||||
|
||||
Authors' Addresses
|
||||
|
||||
Larry Zhu
|
||||
Microsoft Corporation
|
||||
One Microsoft Way
|
||||
Redmond, WA 98052
|
||||
US
|
||||
|
||||
EMail: larry.zhu@microsoft.com
|
||||
|
||||
|
||||
Paul Leach
|
||||
Microsoft Corporation
|
||||
One Microsoft Way
|
||||
Redmond, WA 98052
|
||||
US
|
||||
|
||||
EMail: paulle@microsoft.com
|
||||
|
||||
|
||||
Sam Hartman
|
||||
Painless Security
|
||||
|
||||
EMail: hartmans-ietf@mit.edu
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Zhu, et al. Standards Track [Page 16]
|
||||
|
2691
doc/standardisation/rfc6113.txt
Normal file
2691
doc/standardisation/rfc6113.txt
Normal file
File diff suppressed because it is too large
Load Diff
@@ -232,6 +232,15 @@ init(struct init_options *opt, int argc, char **argv)
|
||||
krb5_free_principal(context, princ);
|
||||
|
||||
|
||||
/* Create `WELLKNONW/org.h5l.fast-cookie@WELLKNOWN:ORG.H5L' for FAST cookie */
|
||||
krb5_make_principal(context, &princ, KRB5_WELLKNOWN_ORG_H5L_REALM,
|
||||
KRB5_WELLKNOWN_NAME, "org.h5l.fast-cookie", NULL);
|
||||
create_random_entry(princ, 60*60, 60*60,
|
||||
KRB5_KDB_REQUIRES_PRE_AUTH|
|
||||
KRB5_KDB_DISALLOW_TGT_BASED|
|
||||
KRB5_KDB_DISALLOW_ALL_TIX);
|
||||
krb5_free_principal(context, princ);
|
||||
|
||||
/* Create `default' */
|
||||
{
|
||||
kadm5_principal_ent_rec ent;
|
||||
|
@@ -37,6 +37,7 @@ libkdc_la_SOURCES = \
|
||||
default_config.c \
|
||||
set_dbinfo.c \
|
||||
digest.c \
|
||||
fast.c \
|
||||
kdc_locl.h \
|
||||
kerberos5.c \
|
||||
krb5tgs.c \
|
||||
|
@@ -44,6 +44,8 @@
|
||||
typedef struct pk_client_params pk_client_params;
|
||||
struct DigestREQ;
|
||||
struct Kx509Request;
|
||||
typedef struct kdc_request_desc *kdc_request_t;
|
||||
|
||||
#include <kdc-private.h>
|
||||
|
||||
krb5_kdc_configuration *config;
|
||||
|
557
kdc/fast.c
Normal file
557
kdc/fast.c
Normal file
@@ -0,0 +1,557 @@
|
||||
/*
|
||||
* Copyright (c) 1997-2011 Kungliga Tekniska Högskolan
|
||||
* (Royal Institute of Technology, Stockholm, Sweden).
|
||||
* All rights reserved.
|
||||
*
|
||||
* Portions Copyright (c) 2010 - 2011 Apple Inc. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the Institute nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "kdc_locl.h"
|
||||
|
||||
static krb5_error_code
|
||||
get_fastuser_crypto(kdc_request_t r, krb5_enctype enctype, krb5_crypto *crypto)
|
||||
{
|
||||
krb5_principal fast_princ;
|
||||
hdb_entry_ex *fast_user = NULL;
|
||||
Key *cookie_key = NULL;
|
||||
krb5_error_code ret;
|
||||
|
||||
*crypto = NULL;
|
||||
|
||||
ret = krb5_make_principal(r->context, &fast_princ,
|
||||
KRB5_WELLKNOWN_ORG_H5L_REALM,
|
||||
KRB5_WELLKNOWN_NAME, "org.h5l.fast-cookie", NULL);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
ret = _kdc_db_fetch(r->context, r->config, fast_princ,
|
||||
HDB_F_GET_CLIENT, NULL, NULL, &fast_user);
|
||||
krb5_free_principal(r->context, fast_princ);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
if (enctype == KRB5_ENCTYPE_NULL)
|
||||
ret = _kdc_get_preferred_key(r->context, r->config, fast_user,
|
||||
"fast-cookie", &enctype, &cookie_key);
|
||||
else
|
||||
ret = hdb_enctype2key(r->context, &fast_user->entry,
|
||||
enctype, &cookie_key);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
ret = krb5_crypto_init(r->context, &cookie_key->key, 0, crypto);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
out:
|
||||
if (fast_user)
|
||||
_kdc_free_ent(r->context, fast_user);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static krb5_error_code
|
||||
fast_parse_cookie(kdc_request_t r, const PA_DATA *pa)
|
||||
{
|
||||
krb5_crypto crypto = NULL;
|
||||
krb5_error_code ret;
|
||||
KDCFastCookie data;
|
||||
krb5_data d1;
|
||||
size_t len;
|
||||
|
||||
ret = decode_KDCFastCookie(pa->padata_value.data,
|
||||
pa->padata_value.length,
|
||||
&data, &len);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (len != pa->padata_value.length || strcmp("H5L1", data.version) != 0) {
|
||||
free_KDCFastCookie(&data);
|
||||
return KRB5KDC_ERR_POLICY;
|
||||
}
|
||||
|
||||
ret = get_fastuser_crypto(r, data.cookie.etype, &crypto);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
ret = krb5_decrypt_EncryptedData(r->context, crypto,
|
||||
KRB5_KU_H5L_COOKIE,
|
||||
&data.cookie, &d1);
|
||||
krb5_crypto_destroy(r->context, crypto);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
ret = decode_KDCFastState(d1.data, d1.length, &r->fast, &len);
|
||||
krb5_data_free(&d1);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
if (r->fast.expiration < kdc_time) {
|
||||
kdc_log(r->context, r->config, 0, "fast cookie expired");
|
||||
ret = KRB5KDC_ERR_POLICY;
|
||||
goto out;
|
||||
}
|
||||
|
||||
out:
|
||||
free_KDCFastCookie(&data);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static krb5_error_code
|
||||
fast_add_cookie(kdc_request_t r, METHOD_DATA *method_data)
|
||||
{
|
||||
krb5_crypto crypto = NULL;
|
||||
KDCFastCookie shell;
|
||||
krb5_error_code ret;
|
||||
krb5_data data;
|
||||
size_t size;
|
||||
|
||||
memset(&shell, 0, sizeof(shell));
|
||||
|
||||
r->fast.expiration = kdc_time + FAST_EXPIRATION_TIME;
|
||||
|
||||
ASN1_MALLOC_ENCODE(KDCFastState, data.data, data.length,
|
||||
&r->fast, &size, ret);
|
||||
if (ret)
|
||||
return ret;
|
||||
heim_assert(size == data.length, "internal asn1 encoder error");
|
||||
|
||||
ret = get_fastuser_crypto(r, KRB5_ENCTYPE_NULL, &crypto);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
ret = krb5_encrypt_EncryptedData(r->context, crypto,
|
||||
KRB5_KU_H5L_COOKIE,
|
||||
data.data, data.length, 0,
|
||||
&shell.cookie);
|
||||
krb5_crypto_destroy(r->context, crypto);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
free(data.data);
|
||||
|
||||
shell.version = "H5L1";
|
||||
|
||||
ASN1_MALLOC_ENCODE(KDCFastCookie, data.data, data.length,
|
||||
&shell, &size, ret);
|
||||
free_EncryptedData(&shell.cookie);
|
||||
if (ret)
|
||||
goto out;
|
||||
heim_assert(size == data.length, "internal asn1 encoder error");
|
||||
|
||||
ret = krb5_padata_add(r->context, method_data,
|
||||
KRB5_PADATA_FX_COOKIE,
|
||||
data.data, data.length);
|
||||
out:
|
||||
if (ret)
|
||||
free(data.data);
|
||||
return ret;
|
||||
}
|
||||
|
||||
krb5_error_code
|
||||
_kdc_fast_mk_response(krb5_context context,
|
||||
krb5_crypto armor_crypto,
|
||||
METHOD_DATA *pa_data,
|
||||
krb5_keyblock *strengthen_key,
|
||||
KrbFastFinished *finished,
|
||||
krb5uint32 nonce,
|
||||
krb5_data *data)
|
||||
{
|
||||
PA_FX_FAST_REPLY fxfastrep;
|
||||
KrbFastResponse fastrep;
|
||||
krb5_error_code ret;
|
||||
krb5_data buf;
|
||||
size_t size;
|
||||
|
||||
memset(&fxfastrep, 0, sizeof(fxfastrep));
|
||||
memset(&fastrep, 0, sizeof(fastrep));
|
||||
krb5_data_zero(data);
|
||||
|
||||
if (pa_data) {
|
||||
fastrep.padata.val = pa_data->val;
|
||||
fastrep.padata.len = pa_data->len;
|
||||
}
|
||||
fastrep.strengthen_key = strengthen_key;
|
||||
fastrep.finished = finished;
|
||||
fastrep.nonce = nonce;
|
||||
|
||||
ASN1_MALLOC_ENCODE(KrbFastResponse, buf.data, buf.length,
|
||||
&fastrep, &size, ret);
|
||||
if (ret)
|
||||
return ret;
|
||||
if (buf.length != size)
|
||||
krb5_abortx(context, "internal asn.1 error");
|
||||
|
||||
fxfastrep.element = choice_PA_FX_FAST_REPLY_armored_data;
|
||||
|
||||
ret = krb5_encrypt_EncryptedData(context,
|
||||
armor_crypto,
|
||||
KRB5_KU_FAST_REP,
|
||||
buf.data,
|
||||
buf.length,
|
||||
0,
|
||||
&fxfastrep.u.armored_data.enc_fast_rep);
|
||||
krb5_data_free(&buf);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ASN1_MALLOC_ENCODE(PA_FX_FAST_REPLY, data->data, data->length,
|
||||
&fxfastrep, &size, ret);
|
||||
free_PA_FX_FAST_REPLY(&fxfastrep);
|
||||
if (ret)
|
||||
return ret;
|
||||
if (data->length != size)
|
||||
krb5_abortx(context, "internal asn.1 error");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
krb5_error_code
|
||||
_kdc_fast_mk_error(krb5_context context,
|
||||
kdc_request_t r,
|
||||
METHOD_DATA *error_method,
|
||||
krb5_crypto armor_crypto,
|
||||
const KDC_REQ_BODY *req_body,
|
||||
krb5_error_code outer_error,
|
||||
const char *e_text,
|
||||
krb5_principal error_client,
|
||||
krb5_principal error_server,
|
||||
time_t *csec, int *cusec,
|
||||
krb5_data *error_msg)
|
||||
{
|
||||
krb5_error_code ret;
|
||||
krb5_data e_data;
|
||||
size_t size;
|
||||
|
||||
krb5_data_zero(&e_data);
|
||||
|
||||
if (armor_crypto) {
|
||||
PA_FX_FAST_REPLY fxfastrep;
|
||||
KrbFastResponse fastrep;
|
||||
|
||||
memset(&fxfastrep, 0, sizeof(fxfastrep));
|
||||
memset(&fastrep, 0, sizeof(fastrep));
|
||||
|
||||
/* first add the KRB-ERROR to the fast errors */
|
||||
|
||||
ret = krb5_mk_error(context,
|
||||
outer_error,
|
||||
e_text,
|
||||
NULL,
|
||||
error_client,
|
||||
error_server,
|
||||
NULL,
|
||||
NULL,
|
||||
&e_data);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = krb5_padata_add(context, error_method,
|
||||
KRB5_PADATA_FX_ERROR,
|
||||
e_data.data, e_data.length);
|
||||
if (ret) {
|
||||
krb5_data_free(&e_data);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (/* hide_principal */ 0) {
|
||||
error_client = NULL;
|
||||
error_server = NULL;
|
||||
e_text = NULL;
|
||||
}
|
||||
|
||||
if (r)
|
||||
ret = fast_add_cookie(r, error_method);
|
||||
else
|
||||
ret = krb5_padata_add(context, error_method,
|
||||
KRB5_PADATA_FX_COOKIE,
|
||||
NULL, 0);
|
||||
if (ret) {
|
||||
kdc_log(r->context, r->config, 0, "failed to add fast cookie with: %d", ret);
|
||||
free_METHOD_DATA(error_method);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = _kdc_fast_mk_response(context, armor_crypto,
|
||||
error_method, NULL, NULL,
|
||||
req_body->nonce, &e_data);
|
||||
free_METHOD_DATA(error_method);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = krb5_padata_add(context, error_method,
|
||||
KRB5_PADATA_FX_FAST,
|
||||
e_data.data, e_data.length);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (error_method && error_method->len) {
|
||||
ASN1_MALLOC_ENCODE(METHOD_DATA, e_data.data, e_data.length,
|
||||
error_method, &size, ret);
|
||||
if (ret)
|
||||
return ret;
|
||||
if (e_data.length != size)
|
||||
krb5_abortx(context, "internal asn.1 error");
|
||||
}
|
||||
|
||||
ret = krb5_mk_error(context,
|
||||
outer_error,
|
||||
e_text,
|
||||
(e_data.length ? &e_data : NULL),
|
||||
error_client,
|
||||
error_server,
|
||||
csec,
|
||||
cusec,
|
||||
error_msg);
|
||||
krb5_data_free(&e_data);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
krb5_error_code
|
||||
_kdc_fast_unwrap_request(kdc_request_t r)
|
||||
{
|
||||
krb5_principal armor_server = NULL;
|
||||
hdb_entry_ex *armor_user = NULL;
|
||||
PA_FX_FAST_REQUEST fxreq;
|
||||
krb5_auth_context ac = NULL;
|
||||
krb5_ticket *ticket = NULL;
|
||||
krb5_flags ap_req_options;
|
||||
Key *armor_key = NULL;
|
||||
krb5_keyblock armorkey;
|
||||
krb5_error_code ret;
|
||||
krb5_ap_req ap_req;
|
||||
unsigned char *buf;
|
||||
KrbFastReq fastreq;
|
||||
size_t len, size;
|
||||
krb5_data data;
|
||||
const PA_DATA *pa;
|
||||
int i = 0;
|
||||
|
||||
/*
|
||||
* First look for FX_COOKIE and and process it
|
||||
*/
|
||||
pa = _kdc_find_padata(&r->req, &i, KRB5_PADATA_FX_COOKIE);
|
||||
if (pa) {
|
||||
ret = fast_parse_cookie(r, pa);
|
||||
if (ret)
|
||||
goto out;
|
||||
}
|
||||
|
||||
i = 0;
|
||||
pa = _kdc_find_padata(&r->req, &i, KRB5_PADATA_FX_FAST);
|
||||
if (pa == NULL)
|
||||
return 0;
|
||||
|
||||
ret = decode_PA_FX_FAST_REQUEST(pa->padata_value.data,
|
||||
pa->padata_value.length,
|
||||
&fxreq,
|
||||
&len);
|
||||
if (ret)
|
||||
goto out;
|
||||
if (len != pa->padata_value.length) {
|
||||
ret = KRB5KDC_ERR_PREAUTH_FAILED;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (fxreq.element != choice_PA_FX_FAST_REQUEST_armored_data) {
|
||||
kdc_log(r->context, r->config, 0,
|
||||
"AS-REQ FAST contain unknown type: %d", (int)fxreq.element);
|
||||
ret = KRB5KDC_ERR_PREAUTH_FAILED;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* pull out armor key */
|
||||
if (fxreq.u.armored_data.armor == NULL) {
|
||||
kdc_log(r->context, r->config, 0,
|
||||
"AS-REQ armor missing");
|
||||
ret = KRB5KDC_ERR_PREAUTH_FAILED;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (fxreq.u.armored_data.armor->armor_type != 1) {
|
||||
kdc_log(r->context, r->config, 0,
|
||||
"AS-REQ armor type not ap-req");
|
||||
ret = KRB5KDC_ERR_PREAUTH_FAILED;
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = krb5_decode_ap_req(r->context,
|
||||
&fxreq.u.armored_data.armor->armor_value,
|
||||
&ap_req);
|
||||
if(ret) {
|
||||
kdc_log(r->context, r->config, 0, "AP-REQ decode failed");
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Save that principal that was in the request */
|
||||
ret = _krb5_principalname2krb5_principal(r->context,
|
||||
&armor_server,
|
||||
ap_req.ticket.sname,
|
||||
ap_req.ticket.realm);
|
||||
if (ret) {
|
||||
free_AP_REQ(&ap_req);
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = _kdc_db_fetch(r->context, r->config, armor_server,
|
||||
HDB_F_GET_SERVER, NULL, NULL, &armor_user);
|
||||
if(ret == HDB_ERR_NOT_FOUND_HERE) {
|
||||
kdc_log(r->context, r->config, 5,
|
||||
"armor key does not have secrets at this KDC, "
|
||||
"need to proxy");
|
||||
goto out;
|
||||
} else if (ret) {
|
||||
free_AP_REQ(&ap_req);
|
||||
ret = KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN;
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = hdb_enctype2key(r->context, &armor_user->entry,
|
||||
ap_req.ticket.enc_part.etype,
|
||||
&armor_key);
|
||||
if (ret) {
|
||||
free_AP_REQ(&ap_req);
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = krb5_verify_ap_req2(r->context, &ac,
|
||||
&ap_req,
|
||||
armor_server,
|
||||
&armor_key->key,
|
||||
0,
|
||||
&ap_req_options,
|
||||
&ticket,
|
||||
KRB5_KU_AP_REQ_AUTH);
|
||||
free_AP_REQ(&ap_req);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
if (ac->remote_subkey == NULL) {
|
||||
krb5_auth_con_free(r->context, ac);
|
||||
kdc_log(r->context, r->config, 0,
|
||||
"FAST AP-REQ remote subkey missing");
|
||||
ret = KRB5KDC_ERR_PREAUTH_FAILED;
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = _krb5_fast_armor_key(r->context,
|
||||
ac->remote_subkey,
|
||||
&ticket->ticket.key,
|
||||
&armorkey,
|
||||
&r->armor_crypto);
|
||||
krb5_auth_con_free(r->context, ac);
|
||||
krb5_free_ticket(r->context, ticket);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
krb5_free_keyblock_contents(r->context, &armorkey);
|
||||
|
||||
/* verify req-checksum of the outer body */
|
||||
|
||||
ASN1_MALLOC_ENCODE(KDC_REQ_BODY, buf, len, &r->req.req_body, &size, ret);
|
||||
if (ret)
|
||||
goto out;
|
||||
if (size != len) {
|
||||
ret = KRB5KDC_ERR_PREAUTH_FAILED;
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = krb5_verify_checksum(r->context, r->armor_crypto,
|
||||
KRB5_KU_FAST_REQ_CHKSUM,
|
||||
buf, len,
|
||||
&fxreq.u.armored_data.req_checksum);
|
||||
free(buf);
|
||||
if (ret) {
|
||||
kdc_log(r->context, r->config, 0,
|
||||
"FAST request have a bad checksum");
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = krb5_decrypt_EncryptedData(r->context, r->armor_crypto,
|
||||
KRB5_KU_FAST_ENC,
|
||||
&fxreq.u.armored_data.enc_fast_req,
|
||||
&data);
|
||||
if (ret) {
|
||||
kdc_log(r->context, r->config, 0,
|
||||
"Failed to decrypt FAST request");
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = decode_KrbFastReq(data.data, data.length, &fastreq, &size);
|
||||
if (ret) {
|
||||
krb5_data_free(&data);
|
||||
goto out;
|
||||
}
|
||||
if (data.length != size) {
|
||||
krb5_data_free(&data);
|
||||
ret = KRB5KDC_ERR_PREAUTH_FAILED;
|
||||
goto out;
|
||||
}
|
||||
krb5_data_free(&data);
|
||||
|
||||
free_KDC_REQ_BODY(&r->req.req_body);
|
||||
ret = copy_KDC_REQ_BODY(&fastreq.req_body, &r->req.req_body);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
/* check for unsupported mandatory options */
|
||||
if (FastOptions2int(fastreq.fast_options) & 0xfffc) {
|
||||
kdc_log(r->context, r->config, 0,
|
||||
"FAST unsupported mandatory option set");
|
||||
ret = KRB5KDC_ERR_PREAUTH_FAILED;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* KDC MUST ignore outer pa data preauth-14 - 6.5.5 */
|
||||
if (r->req.padata)
|
||||
free_METHOD_DATA(r->req.padata);
|
||||
else
|
||||
ALLOC(r->req.padata);
|
||||
|
||||
ret = copy_METHOD_DATA(&fastreq.padata, r->req.padata);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
free_KrbFastReq(&fastreq);
|
||||
free_PA_FX_FAST_REQUEST(&fxreq);
|
||||
|
||||
out:
|
||||
if (armor_server)
|
||||
krb5_free_principal(r->context, armor_server);
|
||||
if(armor_user)
|
||||
_kdc_free_ent(r->context, armor_user);
|
||||
|
||||
return ret;
|
||||
}
|
@@ -106,6 +106,8 @@
|
||||
#include <kdc.h>
|
||||
#include <windc_plugin.h>
|
||||
|
||||
#include <heimbase.h>
|
||||
|
||||
#undef ALLOC
|
||||
#define ALLOC(X) ((X) = calloc(1, sizeof(*(X))))
|
||||
#undef ALLOC_SEQ
|
||||
|
@@ -43,8 +43,53 @@
|
||||
typedef struct pk_client_params pk_client_params;
|
||||
struct DigestREQ;
|
||||
struct Kx509Request;
|
||||
typedef struct kdc_request_desc *kdc_request_t;
|
||||
|
||||
#include <kdc-private.h>
|
||||
|
||||
#define FAST_EXPIRATION_TIME (3 * 60)
|
||||
|
||||
struct kdc_request_desc {
|
||||
krb5_context context;
|
||||
krb5_kdc_configuration *config;
|
||||
|
||||
/* */
|
||||
|
||||
krb5_data request;
|
||||
KDC_REQ req;
|
||||
METHOD_DATA *padata;
|
||||
|
||||
/* out */
|
||||
|
||||
METHOD_DATA outpadata;
|
||||
|
||||
KDC_REP rep;
|
||||
EncTicketPart et;
|
||||
EncKDCRepPart ek;
|
||||
|
||||
/* PA methods can affect both the reply key and the session key (pkinit) */
|
||||
krb5_enctype sessionetype;
|
||||
krb5_keyblock reply_key;
|
||||
krb5_keyblock session_key;
|
||||
|
||||
const char *e_text;
|
||||
|
||||
/* state */
|
||||
krb5_principal client_princ;
|
||||
char *client_name;
|
||||
hdb_entry_ex *client;
|
||||
HDB *clientdb;
|
||||
|
||||
krb5_principal server_princ;
|
||||
char *server_name;
|
||||
hdb_entry_ex *server;
|
||||
|
||||
krb5_crypto armor_crypto;
|
||||
|
||||
KDCFastState fast;
|
||||
};
|
||||
|
||||
|
||||
extern sig_atomic_t exit_flag;
|
||||
extern size_t max_request_udp;
|
||||
extern size_t max_request_tcp;
|
||||
|
1455
kdc/kerberos5.c
1455
kdc/kerberos5.c
File diff suppressed because it is too large
Load Diff
@@ -987,7 +987,7 @@ tgs_make_reply(krb5_context context,
|
||||
CAST session key. Should the DES3 etype be added to the
|
||||
etype list, even if we don't want a session key with
|
||||
DES3? */
|
||||
ret = _kdc_encode_reply(context, config,
|
||||
ret = _kdc_encode_reply(context, config, NULL, 0
|
||||
&rep, &et, &ek, serverkey->keytype,
|
||||
kvno,
|
||||
serverkey, 0, replykey, rk_is_subkey,
|
||||
@@ -2362,6 +2362,14 @@ _kdc_tgs_rep(krb5_context context,
|
||||
goto out;
|
||||
}
|
||||
|
||||
{
|
||||
int i = 0;
|
||||
const PA_DATA *pa = _kdc_find_padata(req, &i, KRB5_PADATA_FX_FAST);
|
||||
if (pa)
|
||||
kdc_log(context, config, 10, "Got TGS FAST request");
|
||||
}
|
||||
|
||||
|
||||
ret = tgs_build_reply(context,
|
||||
config,
|
||||
req,
|
||||
@@ -2392,17 +2400,22 @@ _kdc_tgs_rep(krb5_context context,
|
||||
out:
|
||||
if (replykey)
|
||||
krb5_free_keyblock(context, replykey);
|
||||
|
||||
if(ret && ret != HDB_ERR_NOT_FOUND_HERE && data->data == NULL){
|
||||
krb5_mk_error(context,
|
||||
ret,
|
||||
/* XXX add fast wrapping on the error */
|
||||
METHOD_DATA error_method = { 0, NULL };
|
||||
|
||||
|
||||
kdc_log(context, config, 10, "tgs-req: sending error: %d to client", ret);
|
||||
ret = _kdc_fast_mk_error(context, NULL,
|
||||
&error_method,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
csec,
|
||||
cusec,
|
||||
ret, NULL,
|
||||
NULL, NULL,
|
||||
csec, cusec,
|
||||
data);
|
||||
ret = 0;
|
||||
free_METHOD_DATA(&error_method);
|
||||
}
|
||||
free(csec);
|
||||
free(cusec);
|
||||
|
@@ -1237,7 +1237,7 @@ _kdc_pk_mk_pa_reply(krb5_context context,
|
||||
krb5_enctype sessionetype,
|
||||
const KDC_REQ *req,
|
||||
const krb5_data *req_buffer,
|
||||
krb5_keyblock **reply_key,
|
||||
krb5_keyblock *reply_key,
|
||||
krb5_keyblock *sessionkey,
|
||||
METHOD_DATA *md)
|
||||
{
|
||||
@@ -1563,7 +1563,7 @@ out:
|
||||
hx509_cert_free(kdc_cert);
|
||||
|
||||
if (ret == 0)
|
||||
*reply_key = &cp->reply_key;
|
||||
ret = krb5_copy_keyblock_contents(context, &cp->reply_key, reply_key);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@@ -57,19 +57,25 @@ kdc_as_req(krb5_context context,
|
||||
int datagram_reply,
|
||||
int *claim)
|
||||
{
|
||||
struct kdc_request_desc r;
|
||||
krb5_error_code ret;
|
||||
KDC_REQ req;
|
||||
size_t len;
|
||||
|
||||
ret = decode_AS_REQ(req_buffer->data, req_buffer->length, &req, &len);
|
||||
memset(&r, 0, sizeof(r));
|
||||
|
||||
ret = decode_AS_REQ(req_buffer->data, req_buffer->length, &r.req, &len);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
r.context = context;
|
||||
r.config = config;
|
||||
r.request.data = req_buffer->data;
|
||||
r.request.length = req_buffer->length;
|
||||
|
||||
*claim = 1;
|
||||
|
||||
ret = _kdc_as_rep(context, config, &req, req_buffer,
|
||||
reply, from, addr, datagram_reply);
|
||||
free_AS_REQ(&req);
|
||||
ret = _kdc_as_rep(&r, reply, from, addr, datagram_reply);
|
||||
free_AS_REQ(&r.req);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@@ -111,7 +111,7 @@ _kdc_check_access(krb5_context context,
|
||||
hdb_entry_ex *client_ex, const char *client_name,
|
||||
hdb_entry_ex *server_ex, const char *server_name,
|
||||
KDC_REQ *req,
|
||||
krb5_data *e_data)
|
||||
METHOD_DATA *method_data)
|
||||
{
|
||||
if (windcft == NULL)
|
||||
return kdc_check_flags(context, config,
|
||||
@@ -123,5 +123,5 @@ _kdc_check_access(krb5_context context,
|
||||
context, config,
|
||||
client_ex, client_name,
|
||||
server_ex, server_name,
|
||||
req, e_data);
|
||||
req, method_data);
|
||||
}
|
||||
|
@@ -70,7 +70,7 @@ typedef krb5_error_code
|
||||
krb5_kdc_configuration *config,
|
||||
hdb_entry_ex *, const char *,
|
||||
hdb_entry_ex *, const char *,
|
||||
KDC_REQ *, krb5_data *);
|
||||
KDC_REQ *, METHOD_DATA *);
|
||||
|
||||
|
||||
#define KRB5_WINDC_PLUGIN_MINOR 6
|
||||
|
@@ -74,6 +74,7 @@ int pk_use_enckey = 0;
|
||||
static int canonicalize_flag = 0;
|
||||
static int enterprise_flag = 0;
|
||||
static int ok_as_delegate_flag = 0;
|
||||
static char *fast_armor_cache_string = NULL;
|
||||
static int use_referrals_flag = 0;
|
||||
static int windows_flag = 0;
|
||||
#ifndef NO_NTLM
|
||||
@@ -187,6 +188,9 @@ static struct getargs args[] = {
|
||||
{ "ok-as-delegate", 0, arg_flag, &ok_as_delegate_flag,
|
||||
NP_("honor ok-as-delegate on tickets", ""), NULL },
|
||||
|
||||
{ "fast-armor-cache", 0, arg_string, &fast_armor_cache_string,
|
||||
NP_("use this credential cache as FAST armor cache", ""), "cache" },
|
||||
|
||||
{ "use-referrals", 0, arg_flag, &use_referrals_flag,
|
||||
NP_("only use referrals, no dns canalisation", ""), NULL },
|
||||
|
||||
@@ -360,6 +364,8 @@ get_new_tickets(krb5_context context,
|
||||
const char *renewstr = NULL;
|
||||
krb5_enctype *enctype = NULL;
|
||||
krb5_ccache tempccache;
|
||||
krb5_keytab kt = NULL;
|
||||
krb5_init_creds_context ctx;
|
||||
#ifndef NO_NTLM
|
||||
struct ntlm_buf ntlmkey;
|
||||
memset(&ntlmkey, 0, sizeof(ntlmkey));
|
||||
@@ -498,32 +504,43 @@ get_new_tickets(krb5_context context,
|
||||
etype_str.num_strings);
|
||||
}
|
||||
|
||||
ret = krb5_init_creds_init(context, principal, krb5_prompter_posix, NULL, start_time, opt, &ctx);
|
||||
if (ret)
|
||||
krb5_err(context, 1, ret, "krb5_init_creds_init");
|
||||
|
||||
if (server_str) {
|
||||
ret = krb5_init_creds_set_service(context, ctx, server_str);
|
||||
if (ret)
|
||||
krb5_err(context, 1, ret, "krb5_init_creds_set_service");
|
||||
}
|
||||
|
||||
if (fast_armor_cache_string) {
|
||||
krb5_ccache fastid;
|
||||
|
||||
ret = krb5_cc_resolve(context, fast_armor_cache_string, &fastid);
|
||||
if (ret)
|
||||
krb5_err(context, 1, ret, "krb5_cc_resolve(FAST cache)");
|
||||
|
||||
ret = krb5_init_creds_set_fast_ccache(context, ctx, fastid);
|
||||
if (ret)
|
||||
krb5_err(context, 1, ret, "krb5_init_creds_set_fast_ccache");
|
||||
}
|
||||
|
||||
if(use_keytab || keytab_str) {
|
||||
krb5_keytab kt;
|
||||
|
||||
if(keytab_str)
|
||||
ret = krb5_kt_resolve(context, keytab_str, &kt);
|
||||
else
|
||||
ret = krb5_kt_default(context, &kt);
|
||||
if (ret)
|
||||
krb5_err(context, 1, ret, "resolving keytab");
|
||||
ret = krb5_get_init_creds_keytab (context,
|
||||
&cred,
|
||||
principal,
|
||||
kt,
|
||||
start_time,
|
||||
server_str,
|
||||
opt);
|
||||
krb5_kt_close(context, kt);
|
||||
|
||||
ret = krb5_init_creds_set_keytab(context, ctx, kt);
|
||||
if (ret)
|
||||
krb5_err(context, 1, ret, "krb5_init_creds_set_keytab");
|
||||
|
||||
} else if (pk_user_id || ent_user_id || anonymous_flag) {
|
||||
ret = krb5_get_init_creds_password (context,
|
||||
&cred,
|
||||
principal,
|
||||
passwd,
|
||||
krb5_prompter_posix,
|
||||
NULL,
|
||||
start_time,
|
||||
server_str,
|
||||
opt);
|
||||
|
||||
} else if (!interactive) {
|
||||
krb5_warnx(context, "Not interactive, failed to get initial ticket");
|
||||
krb5_get_init_creds_opt_free(context, opt);
|
||||
@@ -539,23 +556,20 @@ get_new_tickets(krb5_context context,
|
||||
|
||||
if (UI_UTIL_read_pw_string(passwd, sizeof(passwd)-1, prompt, 0)){
|
||||
memset(passwd, 0, sizeof(passwd));
|
||||
exit(1);
|
||||
errx(1, "failed to read password");
|
||||
}
|
||||
free (prompt);
|
||||
}
|
||||
|
||||
|
||||
ret = krb5_get_init_creds_password (context,
|
||||
&cred,
|
||||
principal,
|
||||
passwd,
|
||||
krb5_prompter_posix,
|
||||
NULL,
|
||||
start_time,
|
||||
server_str,
|
||||
opt);
|
||||
if (passwd[0]) {
|
||||
ret = krb5_init_creds_set_password(context, ctx, passwd);
|
||||
if (ret)
|
||||
krb5_err(context, 1, ret, "krb5_init_creds_set_password");
|
||||
}
|
||||
krb5_get_init_creds_opt_free(context, opt);
|
||||
}
|
||||
|
||||
ret = krb5_init_creds_get(context, ctx);
|
||||
|
||||
#ifndef NO_NTLM
|
||||
if (ntlm_domain && passwd[0])
|
||||
heim_ntlm_nt_key(passwd, &ntlmkey);
|
||||
@@ -579,6 +593,8 @@ get_new_tickets(krb5_context context,
|
||||
krb5_err(context, 1, ret, "krb5_get_init_creds");
|
||||
}
|
||||
|
||||
krb5_process_last_request(context, opt, ctx);
|
||||
|
||||
if(ticket_life != 0) {
|
||||
if(abs(cred.times.endtime - cred.times.starttime - ticket_life) > 30) {
|
||||
char life[64];
|
||||
@@ -603,15 +619,11 @@ get_new_tickets(krb5_context context,
|
||||
if (ret)
|
||||
krb5_err (context, 1, ret, "krb5_cc_new_unique");
|
||||
|
||||
ret = krb5_cc_initialize (context, tempccache, cred.client);
|
||||
ret = krb5_init_creds_store(context, ctx, tempccache);
|
||||
if (ret)
|
||||
krb5_err (context, 1, ret, "krb5_cc_initialize");
|
||||
krb5_err(context, 1, ret, "krb5_init_creds_store");
|
||||
|
||||
ret = krb5_cc_store_cred (context, tempccache, &cred);
|
||||
if (ret)
|
||||
krb5_err (context, 1, ret, "krb5_cc_store_cred");
|
||||
|
||||
krb5_free_cred_contents (context, &cred);
|
||||
krb5_init_creds_free(context, ctx);
|
||||
|
||||
ret = krb5_cc_move(context, tempccache, ccache);
|
||||
if (ret)
|
||||
@@ -640,7 +652,10 @@ get_new_tickets(krb5_context context,
|
||||
krb5_cc_set_config(context, ccache, NULL, "realm-config", &data);
|
||||
}
|
||||
|
||||
krb5_get_init_creds_opt_free(context, opt);
|
||||
|
||||
if (kt)
|
||||
krb5_kt_close(context, kt);
|
||||
if (enctype)
|
||||
free(enctype);
|
||||
|
||||
|
@@ -888,7 +888,7 @@ define_type (int level, const char *name, const char *basename, Type *t, int typ
|
||||
fprintf(headerfile, "heim_octet_string _save;\n");
|
||||
}
|
||||
space(level + 1);
|
||||
fprintf (headerfile, "enum {\n");
|
||||
fprintf (headerfile, "enum %s_enum {\n", newbasename);
|
||||
m = have_ellipsis(t);
|
||||
if (m) {
|
||||
space(level + 2);
|
||||
|
@@ -63,6 +63,8 @@ EXPORTS
|
||||
PA-ServerReferralData,
|
||||
PA-SvrReferralData,
|
||||
PADATA-TYPE,
|
||||
PA-FX-FAST-REQUEST,
|
||||
PA-FX-FAST-REPLY,
|
||||
Principal,
|
||||
PrincipalName,
|
||||
Principals,
|
||||
@@ -72,7 +74,13 @@ EXPORTS
|
||||
Ticket,
|
||||
TicketFlags,
|
||||
TransitedEncoding,
|
||||
TypedData
|
||||
TypedData,
|
||||
KrbFastResponse,
|
||||
KrbFastFinished,
|
||||
KrbFastReq,
|
||||
KrbFastArmor,
|
||||
KDCFastState,
|
||||
KDCFastCookie
|
||||
;
|
||||
|
||||
NAME-TYPE ::= INTEGER {
|
||||
@@ -771,12 +779,12 @@ PA-ServerReferralData ::= SEQUENCE {
|
||||
FastOptions ::= BIT STRING {
|
||||
reserved(0),
|
||||
hide-client-names(1),
|
||||
kdc-follow--referrals(16)
|
||||
kdc-follow-referrals(16)
|
||||
}
|
||||
|
||||
KrbFastReq ::= SEQUENCE {
|
||||
fast-options [0] FastOptions,
|
||||
padata [1] SEQUENCE OF PA-DATA,
|
||||
padata [1] METHOD-DATA,
|
||||
req-body [2] KDC-REQ-BODY,
|
||||
...
|
||||
}
|
||||
@@ -803,15 +811,15 @@ KrbFastFinished ::= SEQUENCE {
|
||||
usec [1] krb5int32,
|
||||
crealm [2] Realm,
|
||||
cname [3] PrincipalName,
|
||||
checksum [4] Checksum,
|
||||
ticket-checksum [5] Checksum,
|
||||
ticket-checksum [4] Checksum,
|
||||
...
|
||||
}
|
||||
|
||||
KrbFastResponse ::= SEQUENCE {
|
||||
padata [0] SEQUENCE OF PA-DATA,
|
||||
rep-key [1] EncryptionKey OPTIONAL,
|
||||
padata [0] METHOD-DATA,
|
||||
strengthen-key [1] EncryptionKey OPTIONAL,
|
||||
finished [2] KrbFastFinished OPTIONAL,
|
||||
nonce [3] krb5uint32,
|
||||
...
|
||||
}
|
||||
|
||||
@@ -825,6 +833,26 @@ PA-FX-FAST-REPLY ::= CHOICE {
|
||||
...
|
||||
}
|
||||
|
||||
KDCFastFlags ::= BIT STRING {
|
||||
use_reply_key(0),
|
||||
reply_key_used(1),
|
||||
reply_key_replaced(2),
|
||||
kdc_verfied(3)
|
||||
}
|
||||
|
||||
-- KDCFastState is stored in FX_COOKIE
|
||||
KDCFastState ::= SEQUENCE {
|
||||
flags [0] KDCFastFlags,
|
||||
expiration [1] GeneralizedTime,
|
||||
fast-state [2] METHOD-DATA,
|
||||
expected-pa-types [3] SEQUENCE OF PADATA-TYPE OPTIONAL
|
||||
}
|
||||
|
||||
KDCFastCookie ::= SEQUENCE {
|
||||
version [0] UTF8String,
|
||||
cookie [1] EncryptedData
|
||||
}
|
||||
|
||||
END
|
||||
|
||||
-- etags -r '/\([A-Za-z][-A-Za-z0-9]*\).*::=/\1/' k5.asn1
|
||||
|
@@ -147,6 +147,7 @@ dist_libkrb5_la_SOURCES = \
|
||||
error_string.c \
|
||||
expand_hostname.c \
|
||||
expand_path.c \
|
||||
fast.c \
|
||||
fcache.c \
|
||||
free.c \
|
||||
free_host_realm.c \
|
||||
|
@@ -64,7 +64,7 @@ struct _krb5_checksum_type _krb5_checksum_none = {
|
||||
"none",
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
F_DISABLED,
|
||||
NONE_checksum,
|
||||
NULL
|
||||
};
|
||||
|
95
lib/krb5/fast.c
Normal file
95
lib/krb5/fast.c
Normal file
@@ -0,0 +1,95 @@
|
||||
/*
|
||||
* Copyright (c) 2011 Kungliga Tekniska Högskolan
|
||||
* (Royal Institute of Technology, Stockholm, Sweden).
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the Institute nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "krb5_locl.h"
|
||||
|
||||
|
||||
krb5_error_code
|
||||
_krb5_fast_cf2(krb5_context context,
|
||||
krb5_keyblock *key1,
|
||||
const char *pepper1,
|
||||
krb5_keyblock *key2,
|
||||
const char *pepper2,
|
||||
krb5_keyblock *armorkey,
|
||||
krb5_crypto *armor_crypto)
|
||||
{
|
||||
krb5_crypto crypto1, crypto2;
|
||||
krb5_data pa1, pa2;
|
||||
krb5_error_code ret;
|
||||
|
||||
ret = krb5_crypto_init(context, key1, 0, &crypto1);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = krb5_crypto_init(context, key2, 0, &crypto2);
|
||||
if (ret) {
|
||||
krb5_crypto_destroy(context, crypto1);
|
||||
return ret;
|
||||
}
|
||||
|
||||
pa1.data = rk_UNCONST(pepper1);
|
||||
pa1.length = strlen(pepper1);
|
||||
pa2.data = rk_UNCONST(pepper2);
|
||||
pa2.length = strlen(pepper2);
|
||||
|
||||
ret = krb5_crypto_fx_cf2(context, crypto1, crypto2, &pa1, &pa2,
|
||||
key1->keytype, armorkey);
|
||||
krb5_crypto_destroy(context, crypto1);
|
||||
krb5_crypto_destroy(context, crypto2);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (armor_crypto) {
|
||||
ret = krb5_crypto_init(context, armorkey, 0, armor_crypto);
|
||||
if (ret)
|
||||
krb5_free_keyblock_contents(context, armorkey);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
krb5_error_code
|
||||
_krb5_fast_armor_key(krb5_context context,
|
||||
krb5_keyblock *subkey,
|
||||
krb5_keyblock *sessionkey,
|
||||
krb5_keyblock *armorkey,
|
||||
krb5_crypto *armor_crypto)
|
||||
{
|
||||
return _krb5_fast_cf2(context,
|
||||
subkey,
|
||||
"subkeyarmor",
|
||||
sessionkey,
|
||||
"ticketarmor",
|
||||
armorkey,
|
||||
armor_crypto);
|
||||
}
|
@@ -544,6 +544,7 @@ get_cred_kdc(krb5_context context,
|
||||
&krbtgt->addresses,
|
||||
nonce,
|
||||
eflags,
|
||||
NULL,
|
||||
decrypt_tkt_with_subkey,
|
||||
subkey);
|
||||
out2:
|
||||
|
@@ -510,6 +510,7 @@ krb5_get_in_cred(krb5_context context,
|
||||
NULL,
|
||||
nonce,
|
||||
flags,
|
||||
NULL,
|
||||
decrypt_proc,
|
||||
decryptarg);
|
||||
}
|
||||
|
@@ -76,7 +76,20 @@ typedef struct krb5_get_init_creds_ctx {
|
||||
void *prompter_data;
|
||||
|
||||
struct pa_info_data *ppaid;
|
||||
|
||||
struct fast_state {
|
||||
enum PA_FX_FAST_REQUEST_enum type;
|
||||
unsigned int flags;
|
||||
#define KRB5_FAST_REPLY_KEY_USE_TO_ENCRYPT_THE_REPLY 1
|
||||
#define KRB5_FAST_REPLY_KEY_USE_IN_TRANSACTION 2
|
||||
#define KRB5_FAST_KDC_REPLY_KEY_REPLACED 4
|
||||
#define KRB5_FAST_REPLY_REPLY_VERIFED 8
|
||||
#define KRB5_FAST_STRONG 16
|
||||
#define KRB5_FAST_EXPECTED 32
|
||||
krb5_keyblock *reply_key;
|
||||
krb5_ccache armor_ccache;
|
||||
krb5_crypto armor_crypto;
|
||||
krb5_keyblock armor_key;
|
||||
} fast_state;
|
||||
} krb5_get_init_creds_ctx;
|
||||
|
||||
|
||||
@@ -140,6 +153,15 @@ free_init_creds_ctx(krb5_context context, krb5_init_creds_context ctx)
|
||||
memset(ctx->password, 0, strlen(ctx->password));
|
||||
free(ctx->password);
|
||||
}
|
||||
/*
|
||||
* FAST state
|
||||
*/
|
||||
if (ctx->fast_state.armor_ccache)
|
||||
krb5_cc_close(context, ctx->fast_state.armor_ccache);
|
||||
if (ctx->fast_state.armor_crypto)
|
||||
krb5_crypto_destroy(context, ctx->fast_state.armor_crypto);
|
||||
krb5_free_keyblock_contents(context, &ctx->fast_state.armor_key);
|
||||
|
||||
krb5_data_free(&ctx->req_buffer);
|
||||
krb5_free_cred_contents(context, &ctx->cred);
|
||||
free_METHOD_DATA(&ctx->md);
|
||||
@@ -251,8 +273,8 @@ report_expiration (krb5_context context,
|
||||
* @param ctx The krb5_init_creds_context check for expiration.
|
||||
*/
|
||||
|
||||
static krb5_error_code
|
||||
process_last_request(krb5_context context,
|
||||
krb5_error_code
|
||||
krb5_process_last_request(krb5_context context,
|
||||
krb5_get_init_creds_opt *options,
|
||||
krb5_init_creds_context ctx)
|
||||
{
|
||||
@@ -1237,6 +1259,10 @@ process_pa_data_to_md(krb5_context context,
|
||||
|
||||
pa_data_add_pac_request(context, ctx, *out_md);
|
||||
|
||||
ret = krb5_padata_add(context, *out_md, KRB5_PADATA_REQ_ENC_PA_REP, NULL, 0);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if ((*out_md)->len == 0) {
|
||||
free(*out_md);
|
||||
*out_md = NULL;
|
||||
@@ -1618,6 +1644,352 @@ krb5_init_creds_set_keyblock(krb5_context context,
|
||||
return 0;
|
||||
}
|
||||
|
||||
KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
|
||||
krb5_init_creds_set_fast_ccache(krb5_context context,
|
||||
krb5_init_creds_context ctx,
|
||||
krb5_ccache fast_ccache)
|
||||
{
|
||||
ctx->fast_state.armor_ccache = fast_ccache;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* FAST
|
||||
*/
|
||||
|
||||
static krb5_error_code
|
||||
check_fast(krb5_context context, struct fast_state *state)
|
||||
{
|
||||
if (state->flags & KRB5_FAST_EXPECTED) {
|
||||
krb5_set_error_message(context, KRB5KRB_AP_ERR_MODIFIED,
|
||||
"Expected FAST, but no FAST "
|
||||
"was in the response from the KDC");
|
||||
return KRB5KRB_AP_ERR_MODIFIED;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static krb5_error_code
|
||||
fast_unwrap_as_rep(krb5_context context, int32_t nonce,
|
||||
krb5_data *chksumdata,
|
||||
struct fast_state *state, AS_REP *rep)
|
||||
{
|
||||
PA_FX_FAST_REPLY fxfastrep;
|
||||
KrbFastResponse fastrep;
|
||||
krb5_error_code ret;
|
||||
PA_DATA *pa = NULL;
|
||||
int idx = 0;
|
||||
|
||||
if (state->armor_crypto == NULL || rep->padata == NULL)
|
||||
return check_fast(context, state);
|
||||
|
||||
/* find PA_FX_FAST_REPLY */
|
||||
|
||||
pa = krb5_find_padata(rep->padata->val, rep->padata->len,
|
||||
KRB5_PADATA_FX_FAST, &idx);
|
||||
if (pa == NULL)
|
||||
return check_fast(context, state);
|
||||
|
||||
memset(&fxfastrep, 0, sizeof(fxfastrep));
|
||||
memset(&fastrep, 0, sizeof(fastrep));
|
||||
|
||||
ret = decode_PA_FX_FAST_REPLY(pa->padata_value.data, pa->padata_value.length, &fxfastrep, NULL);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (fxfastrep.element == choice_PA_FX_FAST_REPLY_armored_data) {
|
||||
krb5_data data;
|
||||
ret = krb5_decrypt_EncryptedData(context,
|
||||
state->armor_crypto,
|
||||
KRB5_KU_FAST_REP,
|
||||
&fxfastrep.u.armored_data.enc_fast_rep,
|
||||
&data);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
ret = decode_KrbFastResponse(data.data, data.length, &fastrep, NULL);
|
||||
krb5_data_free(&data);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
} else {
|
||||
ret = KRB5KDC_ERR_PREAUTH_FAILED;
|
||||
goto out;
|
||||
}
|
||||
|
||||
free_METHOD_DATA(rep->padata);
|
||||
ret = copy_METHOD_DATA(&fastrep.padata, rep->padata);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
if (fastrep.strengthen_key) {
|
||||
krb5_keyblock result;
|
||||
|
||||
ret = _krb5_fast_cf2(context,
|
||||
fastrep.strengthen_key,
|
||||
"strengthenkey",
|
||||
state->reply_key,
|
||||
"replykey",
|
||||
&result,
|
||||
NULL);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
krb5_free_keyblock_contents(context, state->reply_key);
|
||||
*state->reply_key = result;
|
||||
}
|
||||
|
||||
if (nonce != fastrep.nonce) {
|
||||
ret = KRB5KDC_ERR_PREAUTH_FAILED;
|
||||
goto out;
|
||||
}
|
||||
if (fastrep.finished) {
|
||||
PrincipalName cname;
|
||||
krb5_realm crealm = NULL;
|
||||
|
||||
if (chksumdata == NULL) {
|
||||
ret = KRB5KDC_ERR_PREAUTH_FAILED;
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = krb5_verify_checksum(context, state->armor_crypto,
|
||||
KRB5_KU_FAST_FINISHED,
|
||||
chksumdata->data, chksumdata->length,
|
||||
&fastrep.finished->ticket_checksum);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
/* update */
|
||||
ret = copy_Realm(&fastrep.finished->crealm, &crealm);
|
||||
if (ret)
|
||||
goto out;
|
||||
free_Realm(&rep->crealm);
|
||||
rep->crealm = crealm;
|
||||
|
||||
ret = copy_PrincipalName(&fastrep.finished->cname, &cname);
|
||||
if (ret)
|
||||
goto out;
|
||||
free_PrincipalName(&rep->cname);
|
||||
rep->cname = cname;
|
||||
|
||||
#if 0 /* store authenticated checksum as kdc-offset */
|
||||
fastrep->finished.timestamp;
|
||||
fastrep->finished.usec = 0;
|
||||
#endif
|
||||
|
||||
} else if (chksumdata) {
|
||||
/* expected fastrep.finish but didn't get it */
|
||||
ret = KRB5KDC_ERR_PREAUTH_FAILED;
|
||||
}
|
||||
|
||||
out:
|
||||
free_PA_FX_FAST_REPLY(&fxfastrep);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static krb5_error_code
|
||||
fast_unwrap_error(krb5_context context, struct fast_state *state, KRB_ERROR *error)
|
||||
{
|
||||
if (state->armor_crypto == NULL)
|
||||
return check_fast(context, state);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static krb5_error_code
|
||||
make_fast_ap_fxarmor(krb5_context context,
|
||||
struct fast_state *state,
|
||||
KrbFastArmor **armor)
|
||||
{
|
||||
KrbFastArmor *fxarmor = NULL;
|
||||
krb5_auth_context auth_context = NULL;
|
||||
krb5_creds cred, *credp = NULL;
|
||||
krb5_error_code ret;
|
||||
|
||||
ALLOC(fxarmor, 1);
|
||||
if (fxarmor == NULL) {
|
||||
ret = ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
fxarmor->armor_type = 1;
|
||||
|
||||
memset(&cred, 0, sizeof(cred));
|
||||
|
||||
ret = krb5_auth_con_init (context, &auth_context);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
ret = krb5_cc_get_principal(context, state->armor_ccache, &cred.client);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
ret = krb5_make_principal(context, &cred.server,
|
||||
cred.client->realm,
|
||||
KRB5_TGS_NAME,
|
||||
cred.client->realm,
|
||||
NULL);
|
||||
if (ret) {
|
||||
krb5_free_principal(context, cred.client);
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = krb5_get_credentials(context, 0, state->armor_ccache, &cred, &credp);
|
||||
krb5_free_principal(context, cred.server);
|
||||
krb5_free_principal(context, cred.client);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
ret = krb5_mk_req_extended(context,
|
||||
&auth_context,
|
||||
AP_OPTS_USE_SUBKEY,
|
||||
NULL,
|
||||
credp,
|
||||
&fxarmor->armor_value);
|
||||
krb5_free_creds(context, credp);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
if (state->armor_crypto)
|
||||
krb5_crypto_destroy(context, state->armor_crypto);
|
||||
krb5_free_keyblock_contents(context, &state->armor_key);
|
||||
|
||||
ret = _krb5_fast_armor_key(context,
|
||||
auth_context->local_subkey,
|
||||
auth_context->keyblock,
|
||||
&state->armor_key,
|
||||
&state->armor_crypto);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
*armor = fxarmor;
|
||||
fxarmor = NULL;
|
||||
out:
|
||||
if (fxarmor)
|
||||
free_KrbFastArmor(fxarmor);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static krb5_error_code
|
||||
fast_wrap_req(krb5_context context, struct fast_state *state, KDC_REQ *req)
|
||||
{
|
||||
KrbFastArmor *fxarmor = NULL;
|
||||
PA_FX_FAST_REQUEST fxreq;
|
||||
krb5_error_code ret;
|
||||
KrbFastReq fastreq;
|
||||
krb5_data data;
|
||||
size_t size;
|
||||
|
||||
memset(&fxreq, 0, sizeof(fxreq));
|
||||
memset(&fastreq, 0, sizeof(fastreq));
|
||||
krb5_data_zero(&data);
|
||||
|
||||
if (state->armor_crypto == NULL) {
|
||||
if (state->armor_ccache) {
|
||||
/*
|
||||
* Instead of keeping state in FX_COOKIE in the KDC, we
|
||||
* rebuild a new armor key for every request, because this
|
||||
* is what the MIT KDC expect and RFC6113 is vage about
|
||||
* what the behavior should be.
|
||||
*/
|
||||
state->type = choice_PA_FX_FAST_REQUEST_armored_data;
|
||||
} else {
|
||||
return check_fast(context, state);
|
||||
}
|
||||
}
|
||||
|
||||
state->flags |= KRB5_FAST_EXPECTED;
|
||||
|
||||
fastreq.fast_options.hide_client_names = 1;
|
||||
|
||||
ret = copy_KDC_REQ_BODY(&req->req_body, &fastreq.req_body);
|
||||
free_KDC_REQ_BODY(&req->req_body);
|
||||
|
||||
req->req_body.realm = strdup(KRB5_ANON_REALM);
|
||||
ALLOC(req->req_body.cname, 1);
|
||||
req->req_body.cname->name_type = KRB5_NT_PRINCIPAL;
|
||||
ALLOC(req->req_body.cname->name_string.val, 2);
|
||||
req->req_body.cname->name_string.len = 2;
|
||||
req->req_body.cname->name_string.val[0] = strdup(KRB5_WELLKNOWN_NAME);
|
||||
req->req_body.cname->name_string.val[1] = strdup(KRB5_ANON_NAME);
|
||||
|
||||
if (req->padata) {
|
||||
ret = copy_METHOD_DATA(req->padata, &fastreq.padata);
|
||||
free_METHOD_DATA(req->padata);
|
||||
} else {
|
||||
ALLOC(req->padata, 1);
|
||||
}
|
||||
|
||||
|
||||
ASN1_MALLOC_ENCODE(KrbFastReq, data.data, data.length, &fastreq, &size, ret);
|
||||
if (ret)
|
||||
goto out;
|
||||
heim_assert(data.length == size, "ASN.1 internal error");
|
||||
|
||||
fxreq.element = state->type;
|
||||
|
||||
if (state->type == choice_PA_FX_FAST_REQUEST_armored_data) {
|
||||
size_t len;
|
||||
void *buf;
|
||||
|
||||
ret = make_fast_ap_fxarmor(context, state, &fxreq.u.armored_data.armor);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
heim_assert(state->armor_crypto != NULL, "FAST armor key missing when FAST started");
|
||||
|
||||
ASN1_MALLOC_ENCODE(KDC_REQ_BODY, buf, len, &req->req_body, &size, ret);
|
||||
if (ret)
|
||||
goto out;
|
||||
heim_assert(len == size, "ASN.1 internal error");
|
||||
|
||||
ret = krb5_create_checksum(context, state->armor_crypto,
|
||||
KRB5_KU_FAST_REQ_CHKSUM, 0,
|
||||
buf, len,
|
||||
&fxreq.u.armored_data.req_checksum);
|
||||
free(buf);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
ret = krb5_encrypt_EncryptedData(context, state->armor_crypto,
|
||||
KRB5_KU_FAST_ENC,
|
||||
data.data,
|
||||
data.length,
|
||||
0,
|
||||
&fxreq.u.armored_data.enc_fast_req);
|
||||
krb5_data_free(&data);
|
||||
|
||||
} else {
|
||||
krb5_data_free(&data);
|
||||
heim_assert(false, "unknown FAST type, internal error");
|
||||
}
|
||||
|
||||
ASN1_MALLOC_ENCODE(PA_FX_FAST_REQUEST, data.data, data.length, &fxreq, &size, ret);
|
||||
if (ret)
|
||||
goto out;
|
||||
heim_assert(data.length == size, "ASN.1 internal error");
|
||||
|
||||
|
||||
ret = krb5_padata_add(context, req->padata, KRB5_PADATA_FX_FAST, data.data, data.length);
|
||||
if (ret)
|
||||
goto out;
|
||||
krb5_data_zero(&data);
|
||||
|
||||
out:
|
||||
free_PA_FX_FAST_REQUEST(&fxreq);
|
||||
if (fxarmor) {
|
||||
free_KrbFastArmor(fxarmor);
|
||||
free(fxarmor);
|
||||
}
|
||||
krb5_data_free(&data);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* The core loop if krb5_get_init_creds() function family. Create the
|
||||
* packets and have the caller send them off to the KDC.
|
||||
@@ -1650,6 +2022,7 @@ krb5_init_creds_step(krb5_context context,
|
||||
krb5_error_code ret;
|
||||
size_t len = 0;
|
||||
size_t size;
|
||||
AS_REQ req2;
|
||||
|
||||
krb5_data_zero(out);
|
||||
|
||||
@@ -1684,8 +2057,27 @@ krb5_init_creds_step(krb5_context context,
|
||||
|
||||
ret = decode_AS_REP(in->data, in->length, &rep.kdc_rep, &size);
|
||||
if (ret == 0) {
|
||||
krb5_keyblock *key = NULL;
|
||||
unsigned eflags = EXTRACT_TICKET_AS_REQ | EXTRACT_TICKET_TIMESYNC;
|
||||
krb5_data data;
|
||||
|
||||
/*
|
||||
* Unwrap AS-REP
|
||||
*/
|
||||
ASN1_MALLOC_ENCODE(Ticket, data.data, data.length,
|
||||
&rep.kdc_rep.ticket, &size, ret);
|
||||
if (ret)
|
||||
goto out;
|
||||
heim_assert(data.length == size, "ASN.1 internal error");
|
||||
|
||||
ret = fast_unwrap_as_rep(context, ctx->nonce, &data,
|
||||
&ctx->fast_state, &rep.kdc_rep);
|
||||
krb5_data_free(&data);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
/*
|
||||
* Now check and extract the ticket
|
||||
*/
|
||||
|
||||
if (ctx->flags.canonicalize) {
|
||||
eflags |= EXTRACT_TICKET_ALLOW_SERVER_MISMATCH;
|
||||
@@ -1695,7 +2087,8 @@ krb5_init_creds_step(krb5_context context,
|
||||
eflags |= EXTRACT_TICKET_ALLOW_CNAME_MISMATCH;
|
||||
|
||||
ret = process_pa_data_to_key(context, ctx, &ctx->cred,
|
||||
&ctx->as_req, &rep.kdc_rep, hostinfo, &key);
|
||||
&ctx->as_req, &rep.kdc_rep,
|
||||
hostinfo, &ctx->fast_state.reply_key);
|
||||
if (ret) {
|
||||
free_AS_REP(&rep.kdc_rep);
|
||||
goto out;
|
||||
@@ -1706,21 +2099,22 @@ krb5_init_creds_step(krb5_context context,
|
||||
ret = _krb5_extract_ticket(context,
|
||||
&rep,
|
||||
&ctx->cred,
|
||||
key,
|
||||
ctx->fast_state.reply_key,
|
||||
NULL,
|
||||
KRB5_KU_AS_REP_ENC_PART,
|
||||
NULL,
|
||||
ctx->nonce,
|
||||
eflags,
|
||||
&ctx->req_buffer,
|
||||
NULL,
|
||||
NULL);
|
||||
krb5_free_keyblock(context, key);
|
||||
|
||||
*flags = 0;
|
||||
|
||||
if (ret == 0)
|
||||
ret = copy_EncKDCRepPart(&rep.enc_part, &ctx->enc_part);
|
||||
|
||||
krb5_free_keyblock(context, ctx->fast_state.reply_key);
|
||||
ctx->fast_state.reply_key = NULL;
|
||||
*flags = 0;
|
||||
|
||||
free_AS_REP(&rep.kdc_rep);
|
||||
free_EncASRepPart(&rep.enc_part);
|
||||
|
||||
@@ -1741,6 +2135,17 @@ krb5_init_creds_step(krb5_context context,
|
||||
goto out;
|
||||
}
|
||||
|
||||
/*
|
||||
* Unwrap KRB-ERROR
|
||||
*/
|
||||
ret = fast_unwrap_error(context, &ctx->fast_state, &ctx->error);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
/*
|
||||
*
|
||||
*/
|
||||
|
||||
ret = krb5_error_from_rd_error(context, &ctx->error, &ctx->cred);
|
||||
|
||||
_krb5_debug(context, 5, "krb5_get_init_creds: KRB-ERROR %d", ret);
|
||||
@@ -1821,11 +2226,23 @@ krb5_init_creds_step(krb5_context context,
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
/*
|
||||
* Wrap with FAST
|
||||
*/
|
||||
copy_AS_REQ(&ctx->as_req, &req2);
|
||||
|
||||
ret = fast_wrap_req(context, &ctx->fast_state, &req2);
|
||||
if (ret) {
|
||||
free_AS_REQ(&req2);
|
||||
goto out;
|
||||
}
|
||||
|
||||
krb5_data_free(&ctx->req_buffer);
|
||||
|
||||
ASN1_MALLOC_ENCODE(AS_REQ,
|
||||
ctx->req_buffer.data, ctx->req_buffer.length,
|
||||
&ctx->as_req, &len, ret);
|
||||
&req2, &len, ret);
|
||||
free_AS_REQ(&req2);
|
||||
if (ret)
|
||||
goto out;
|
||||
if(len != ctx->req_buffer.length)
|
||||
@@ -1882,6 +2299,43 @@ krb5_init_creds_get_error(krb5_context context,
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @ingroup krb5_credential
|
||||
*/
|
||||
|
||||
krb5_error_code
|
||||
krb5_init_creds_store(krb5_context context,
|
||||
krb5_init_creds_context ctx,
|
||||
krb5_ccache id)
|
||||
{
|
||||
krb5_error_code ret;
|
||||
|
||||
if (ctx->cred.client == NULL) {
|
||||
ret = KRB5KDC_ERR_PREAUTH_REQUIRED;
|
||||
krb5_set_error_message(context, ret, "init creds not completed yet");
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = krb5_cc_initialize(context, id, ctx->cred.client);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = krb5_cc_store_cred(context, id, &ctx->cred);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (ctx->cred.flags.b.enc_pa_rep) {
|
||||
krb5_data data = { 3, rk_UNCONST("yes") };
|
||||
ret = krb5_cc_set_config(context, id, ctx->cred.server,
|
||||
"fast_avail", &data);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Free the krb5_init_creds_context allocated by krb5_init_creds_init().
|
||||
*
|
||||
@@ -2016,7 +2470,7 @@ krb5_get_init_creds_password(krb5_context context,
|
||||
ret = krb5_init_creds_get(context, ctx);
|
||||
|
||||
if (ret == 0)
|
||||
process_last_request(context, options, ctx);
|
||||
krb5_process_last_request(context, options, ctx);
|
||||
|
||||
|
||||
if (ret == KRB5KDC_ERR_KEY_EXPIRED && chpw == 0) {
|
||||
@@ -2091,7 +2545,7 @@ krb5_get_init_creds_keyblock(krb5_context context,
|
||||
ret = krb5_init_creds_get(context, ctx);
|
||||
|
||||
if (ret == 0)
|
||||
process_last_request(context, options, ctx);
|
||||
krb5_process_last_request(context, options, ctx);
|
||||
|
||||
out:
|
||||
if (ret == 0)
|
||||
@@ -2137,7 +2591,7 @@ krb5_get_init_creds_keytab(krb5_context context,
|
||||
|
||||
ret = krb5_init_creds_get(context, ctx);
|
||||
if (ret == 0)
|
||||
process_last_request(context, options, ctx);
|
||||
krb5_process_last_request(context, options, ctx);
|
||||
|
||||
out:
|
||||
if (ret == 0)
|
||||
|
@@ -274,14 +274,28 @@ typedef enum krb5_key_usage {
|
||||
/* Encryption type of the kdc session contribution in pk-init */
|
||||
KRB5_KU_AS_REQ = 56,
|
||||
/* Checksum of over the AS-REQ send by the KDC in PA-REQ-ENC-PA-REP */
|
||||
KRB5_KU_FAST_REQ_CHKSUM = 50,
|
||||
/* FAST armor checksum */
|
||||
KRB5_KU_FAST_ENC = 51,
|
||||
/* FAST armor encryption */
|
||||
KRB5_KU_FAST_REP = 52,
|
||||
/* FAST armor reply */
|
||||
KRB5_KU_FAST_FINISHED = 53,
|
||||
/* FAST finished checksum */
|
||||
KRB5_KU_ENC_CHALLENGE_CLIENT = 54,
|
||||
/* fast challange from client */
|
||||
KRB5_KU_ENC_CHALLENGE_KDC = 55,
|
||||
/* fast challange from kdc */
|
||||
KRB5_KU_DIGEST_ENCRYPT = -18,
|
||||
/* Encryption key usage used in the digest encryption field */
|
||||
KRB5_KU_DIGEST_OPAQUE = -19,
|
||||
/* Checksum key usage used in the digest opaque field */
|
||||
KRB5_KU_KRB5SIGNEDPATH = -21,
|
||||
/* Checksum key usage on KRB5SignedPath */
|
||||
KRB5_KU_CANONICALIZED_NAMES = -23
|
||||
KRB5_KU_CANONICALIZED_NAMES = -23,
|
||||
/* Checksum key usage on PA-CANONICALIZED */
|
||||
KRB5_KU_H5L_COOKIE = -25
|
||||
/* encrypted foo */
|
||||
} krb5_key_usage;
|
||||
|
||||
typedef krb5_key_usage krb5_keyusage;
|
||||
@@ -671,6 +685,8 @@ typedef EncAPRepPart krb5_ap_rep_enc_part;
|
||||
#define KRB5_TGS_NAME ("krbtgt")
|
||||
#define KRB5_WELLKNOWN_NAME ("WELLKNOWN")
|
||||
#define KRB5_ANON_NAME ("ANONYMOUS")
|
||||
#define KRB5_ANON_REALM ("WELLKNOWN:ANONYMOUS")
|
||||
#define KRB5_WELLKNOWN_ORG_H5L_REALM ("WELLKNOWN:ORG.H5L")
|
||||
#define KRB5_DIGEST_NAME ("digest")
|
||||
|
||||
typedef enum {
|
||||
|
@@ -592,7 +592,9 @@ check_client_referral(krb5_context context,
|
||||
return 0;
|
||||
|
||||
noreferral:
|
||||
if (krb5_principal_compare(context, requested, mapped) == FALSE) {
|
||||
if (krb5_principal_compare(context, requested, mapped) == FALSE &&
|
||||
!rep->enc_part.flags.enc_pa_rep)
|
||||
{
|
||||
krb5_set_error_message(context, KRB5KRB_AP_ERR_MODIFIED,
|
||||
N_("Not same client principal returned "
|
||||
"as requested", ""));
|
||||
@@ -656,6 +658,7 @@ _krb5_extract_ticket(krb5_context context,
|
||||
krb5_addresses *addrs,
|
||||
unsigned nonce,
|
||||
unsigned flags,
|
||||
krb5_data *request,
|
||||
krb5_decrypt_proc decrypt_proc,
|
||||
krb5_const_pointer decryptarg)
|
||||
{
|
||||
@@ -674,6 +677,48 @@ _krb5_extract_ticket(krb5_context context,
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
if (rep->enc_part.flags.enc_pa_rep && request) {
|
||||
krb5_crypto crypto = NULL;
|
||||
Checksum cksum;
|
||||
PA_DATA *pa = NULL;
|
||||
int idx = 0;
|
||||
|
||||
_krb5_debug(context, 5, "processing enc-ap-rep");
|
||||
|
||||
if (rep->enc_part.encrypted_pa_data == NULL ||
|
||||
(pa = krb5_find_padata(rep->enc_part.encrypted_pa_data->val,
|
||||
rep->enc_part.encrypted_pa_data->len,
|
||||
KRB5_PADATA_REQ_ENC_PA_REP,
|
||||
&idx)) == NULL)
|
||||
{
|
||||
_krb5_debug(context, 5, "KRB5_PADATA_REQ_ENC_PA_REP missing");
|
||||
ret = KRB5KRB_AP_ERR_MODIFIED;
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = krb5_crypto_init(context, key, 0, &crypto);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
ret = decode_Checksum(pa->padata_value.data,
|
||||
pa->padata_value.length,
|
||||
&cksum, NULL);
|
||||
if (ret) {
|
||||
krb5_crypto_destroy(context, crypto);
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = krb5_verify_checksum(context, crypto,
|
||||
KRB5_KU_AS_REQ,
|
||||
request->data, request->length,
|
||||
&cksum);
|
||||
krb5_crypto_destroy(context, crypto);
|
||||
free_Checksum(&cksum);
|
||||
_krb5_debug(context, 5, "enc-ap-rep: %svalid", (ret == 0) ? "" : "in");
|
||||
if (ret)
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* save session key */
|
||||
|
||||
creds->session.keyvalue.length = 0;
|
||||
|
@@ -766,11 +766,25 @@ HEIMDAL_KRB5_2.0 {
|
||||
# kinit helper
|
||||
krb5_get_init_creds_opt_set_pkinit_user_certs;
|
||||
krb5_pk_enterprise_cert;
|
||||
krb5_process_last_request;
|
||||
krb5_init_creds_init;
|
||||
krb5_init_creds_set_service;
|
||||
krb5_init_creds_set_fast_ccache;
|
||||
krb5_init_creds_set_keytab;
|
||||
krb5_init_creds_get;
|
||||
krb5_init_creds_set_password;
|
||||
krb5_init_creds_store;
|
||||
krb5_init_creds_free;
|
||||
|
||||
# testing
|
||||
_krb5_aes_cts_encrypt;
|
||||
_krb5_n_fold;
|
||||
_krb5_expand_default_cc_name;
|
||||
|
||||
# FAST
|
||||
_krb5_fast_cf2;
|
||||
_krb5_fast_armor_key;
|
||||
|
||||
local:
|
||||
*;
|
||||
};
|
||||
|
@@ -18,6 +18,7 @@ SCRIPT_TESTS = \
|
||||
check-delegation \
|
||||
check-des \
|
||||
check-digest \
|
||||
check-fast \
|
||||
check-kadmin \
|
||||
check-hdb-mitdb \
|
||||
check-kdc \
|
||||
@@ -78,6 +79,11 @@ check-hdb-mitdb: check-hdb-mitdb.in Makefile krb5-hdb-mitdb.conf
|
||||
chmod +x check-hdb-mitdb.tmp
|
||||
mv check-hdb-mitdb.tmp check-hdb-mitdb
|
||||
|
||||
check-fast: check-fast.in Makefile
|
||||
$(do_subst) < $(srcdir)/check-fast.in > check-fast.tmp
|
||||
chmod +x check-fast.tmp
|
||||
mv check-fast.tmp check-fast
|
||||
|
||||
check-kdc: check-kdc.in Makefile
|
||||
$(do_subst) < $(srcdir)/check-kdc.in > check-kdc.tmp
|
||||
chmod +x check-kdc.tmp
|
||||
|
183
tests/kdc/check-fast.in
Normal file
183
tests/kdc/check-fast.in
Normal file
@@ -0,0 +1,183 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# Copyright (c) 2006 - 2011 Kungliga Tekniska Högskolan
|
||||
# (Royal Institute of Technology, Stockholm, Sweden).
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
#
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
#
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
#
|
||||
# 3. Neither the name of the Institute nor the names of its contributors
|
||||
# may be used to endorse or promote products derived from this software
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
|
||||
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
# ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
|
||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
# SUCH DAMAGE.
|
||||
|
||||
top_builddir="@top_builddir@"
|
||||
env_setup="@env_setup@"
|
||||
objdir="@objdir@"
|
||||
|
||||
. ${env_setup}
|
||||
|
||||
KRB5_CONFIG="${1-${objdir}/krb5.conf}"
|
||||
export KRB5_CONFIG
|
||||
|
||||
testfailed="echo test failed; cat messages.log; exit 1"
|
||||
|
||||
# If there is no useful db support compile in, disable test
|
||||
#${have_db} || exit 77
|
||||
|
||||
R=TEST.H5L.SE
|
||||
|
||||
port=@port@
|
||||
|
||||
kadmin="${kadmin} -l -r $R"
|
||||
kdc="${kdc} --addresses=localhost -P $port"
|
||||
|
||||
server=host/datan.test.h5l.se
|
||||
cache="FILE:${objdir}/cache.krb5"
|
||||
acache="FILE:${objdir}/acache.krb5"
|
||||
|
||||
kinit="${kinit} -c $cache ${afs_no_afslog}"
|
||||
akinit="${kinit} -c $acache ${afs_no_afslog}"
|
||||
klist="${klist} -c $cache"
|
||||
aklist="${klist} -c $acache"
|
||||
kgetcred="${kgetcred} -c $cache"
|
||||
kdestroy="${kdestroy} -c $cache ${afs_no_unlog}"
|
||||
|
||||
rm -f ${keytabfile}
|
||||
rm -f current-db*
|
||||
rm -f out-*
|
||||
rm -f mkey.file*
|
||||
|
||||
> messages.log
|
||||
|
||||
echo Creating database
|
||||
${kadmin} \
|
||||
init \
|
||||
--realm-max-ticket-life=1day \
|
||||
--realm-max-renewable-life=1month \
|
||||
${R} || exit 1
|
||||
|
||||
${kadmin} add -p foo --use-defaults foo@${R} || exit 1
|
||||
${kadmin} add -p foo --use-defaults ${server}@${R} || exit 1
|
||||
|
||||
echo "Doing database check"
|
||||
${kadmin} check ${R} || exit 1
|
||||
|
||||
echo foo > ${objdir}/foopassword
|
||||
|
||||
echo Starting kdc
|
||||
env MallocStackLogging=1 MallocStackLoggingNoCompact=1 MallocErrorAbort=1 MallocLogFile=${objdir}/malloc-log \
|
||||
${kdc} &
|
||||
kdcpid=$!
|
||||
|
||||
sh ${wait_kdc}
|
||||
if [ "$?" != 0 ] ; then
|
||||
kill -9 ${kdcpid}
|
||||
exit 1
|
||||
fi
|
||||
|
||||
trap "kill -9 ${kdcpid}; echo signal killing kdc; exit 1;" EXIT
|
||||
|
||||
ec=0
|
||||
|
||||
#
|
||||
# Check armor ticket
|
||||
#
|
||||
|
||||
echo "Getting client initial tickets"; > messages.log
|
||||
${kinit} --password-file=${objdir}/foopassword foo@$R || \
|
||||
{ ec=1 ; eval "${testfailed}"; }
|
||||
echo "Checking for FAST avail"
|
||||
${klist} --hidden | grep fast_avail > /dev/null || { exit 1; }
|
||||
echo "Getting tickets"; > messages.log
|
||||
${kgetcred} ${server}@${R} || { ec=1 ; eval "${testfailed}"; }
|
||||
echo "Listing tickets"; > messages.log
|
||||
${klist} > /dev/null || { ec=1 ; eval "${testfailed}"; }
|
||||
${kdestroy}
|
||||
|
||||
echo "Acquire host ticket to be used as an ARMOR ticket"
|
||||
${akinit} --password-file=${objdir}/foopassword ${server}@${R} >/dev/null|| { exit 1; }
|
||||
echo "Checking for FAST avail (in the FAST armor cache)"
|
||||
${aklist} --hidden | grep fast_avail > /dev/null || { exit 1; }
|
||||
|
||||
#
|
||||
# Client tests
|
||||
#
|
||||
|
||||
echo "Getting client initial tickets with FAST armor ticket"
|
||||
${kinit} --fast-armor-cache=${acache} \
|
||||
--password-file=${objdir}/foopassword foo@$R || \
|
||||
{ ec=1 ; eval "${testfailed}"; }
|
||||
|
||||
echo "Checking for FAST avail (in the FAST acquired cache)"
|
||||
${klist} --hidden | grep fast_avail > /dev/null || { exit 1; }
|
||||
|
||||
echo "Getting service ticket"
|
||||
${kgetcred} ${server}@${R} || { exit 1; }
|
||||
${kdestroy}
|
||||
|
||||
#
|
||||
# Use MIT client tools
|
||||
#
|
||||
|
||||
mit=/usr/local/mitkerberos/bin
|
||||
|
||||
if [ -f ${mit}/kinit ] ; then
|
||||
echo "Running MIT FAST tests"
|
||||
|
||||
kinitpty=${objdir}/foopassword.rkpty
|
||||
cat > ${kinitpty} <<EOF
|
||||
expect Password
|
||||
password foo\n
|
||||
EOF
|
||||
|
||||
echo "Acquire host ticket"
|
||||
${rkpty} ${kinitpty} ${mit}/kinit -c ${acache} ${server}@${R} >/dev/null|| { exit 1; }
|
||||
(${aklist} | grep ${server} > /dev/null ) || { exit 1; }
|
||||
|
||||
echo "Checking for FAST avail"
|
||||
${aklist} --hidden | grep fast_avail > /dev/null || { exit 1; }
|
||||
|
||||
echo "Using plain to get a initial ticket"
|
||||
${rkpty} ${kinitpty} ${mit}/kinit -c ${cache} foo@${R} >/dev/null|| { exit 1; }
|
||||
(${klist} | grep foo > /dev/null ) || { exit 1; }
|
||||
|
||||
echo "Using FAST to get a initial ticket"
|
||||
${rkpty} ${kinitpty} ${mit}/kinit -c ${cache} -T ${acache} foo@${R} >/dev/null || { exit 1; }
|
||||
(${klist} | grep foo > /dev/null ) || { exit 1; }
|
||||
|
||||
echo "Checking for FAST avail"
|
||||
${klist} --hidden | grep fast_avail > /dev/null || { exit 1; }
|
||||
|
||||
echo "Getting service ticket"
|
||||
${mit}/kvno -c ${cache} ${server}@${R} || { exit 1; }
|
||||
|
||||
fi
|
||||
|
||||
|
||||
echo "killing kdc (${kdcpid})"
|
||||
sh ${leaks_kill} kdc $kdcpid || exit 1
|
||||
|
||||
trap "" EXIT
|
||||
|
||||
exit $ec
|
@@ -1,554 +0,0 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# Copyright (c) 2006 - 2007 Kungliga Tekniska Högskolan
|
||||
# (Royal Institute of Technology, Stockholm, Sweden).
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
#
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
#
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
#
|
||||
# 3. Neither the name of the Institute nor the names of its contributors
|
||||
# may be used to endorse or promote products derived from this software
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
|
||||
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
# ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
|
||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
# SUCH DAMAGE.
|
||||
|
||||
top_builddir="@top_builddir@"
|
||||
env_setup="@env_setup@"
|
||||
objdir="@objdir@"
|
||||
|
||||
. ${env_setup}
|
||||
|
||||
KRB5_CONFIG="${1-${objdir}/krb5.conf}"
|
||||
export KRB5_CONFIG
|
||||
|
||||
testfailed="echo test failed; cat messages.log; exit 1"
|
||||
|
||||
# If there is no useful db support compile in, disable test
|
||||
${have_db} || exit 77
|
||||
|
||||
R=TEST.H5L.SE
|
||||
R2=TEST2.H5L.SE
|
||||
R3=TEST-HTTP.H5L.SE
|
||||
|
||||
port=@port@
|
||||
|
||||
kadmin="${kadmin} -l -r $R"
|
||||
kdc="${kdc} --addresses=localhost -P $port"
|
||||
|
||||
server=host/datan.test.h5l.se
|
||||
server2=host/computer.example.com
|
||||
serverip=host/10.11.12.13
|
||||
serveripname=host/ip.test.h5l.org
|
||||
serveripname2=host/10.11.12.14
|
||||
alias1=host/datan.example.com
|
||||
alias2=host/datan
|
||||
aliaskeytab=host/datan
|
||||
cache="FILE:${objdir}/cache.krb5"
|
||||
ocache="FILE:${objdir}/ocache.krb5"
|
||||
o2cache="FILE:${objdir}/o2cache.krb5"
|
||||
icache="FILE:${objdir}/icache.krb5"
|
||||
keytabfile=${objdir}/server.keytab
|
||||
keytab="FILE:${keytabfile}"
|
||||
ps="proxy-service@${R}"
|
||||
aesenctype="aes256-cts-hmac-sha1-96"
|
||||
|
||||
kinit="${kinit} -c $cache ${afs_no_afslog}"
|
||||
klist="${klist} -c $cache"
|
||||
kgetcred="${kgetcred} -c $cache"
|
||||
kgetcred_imp="${kgetcred} -c $cache --out-cache=${ocache}"
|
||||
kdestroy="${kdestroy} -c $cache ${afs_no_unlog}"
|
||||
kimpersonate="${kimpersonate} -k ${keytab} --ccache=${ocache}"
|
||||
|
||||
rm -f ${keytabfile}
|
||||
rm -f current-db*
|
||||
rm -f out-*
|
||||
rm -f mkey.file*
|
||||
|
||||
> messages.log
|
||||
|
||||
echo Creating database
|
||||
${kadmin} \
|
||||
init \
|
||||
--realm-max-ticket-life=1day \
|
||||
--realm-max-renewable-life=1month \
|
||||
${R} || exit 1
|
||||
|
||||
${kadmin} \
|
||||
init \
|
||||
--realm-max-ticket-life=1day \
|
||||
--realm-max-renewable-life=1month \
|
||||
${R2} || exit 1
|
||||
|
||||
${kadmin} \
|
||||
init \
|
||||
--realm-max-ticket-life=1day \
|
||||
--realm-max-renewable-life=1month \
|
||||
${R3} || exit 1
|
||||
|
||||
${kadmin} cpw -r krbtgt/${R}@${R} || exit 1
|
||||
${kadmin} cpw -r krbtgt/${R}@${R} || exit 1
|
||||
${kadmin} cpw -r krbtgt/${R}@${R} || exit 1
|
||||
${kadmin} cpw -r krbtgt/${R}@${R} || exit 1
|
||||
|
||||
${kadmin} add -p foo --use-defaults foo@${R} || exit 1
|
||||
${kadmin} add -p bar --use-defaults bar@${R} || exit 1
|
||||
${kadmin} add -p foo --use-defaults remove@${R} || exit 1
|
||||
${kadmin} add -p kaka --use-defaults ${server}@${R} || exit 1
|
||||
${kadmin} add -p kaka --use-defaults ${server}-des3@${R} || exit 1
|
||||
${kadmin} add -p kaka --use-defaults kt-des3@${R} || exit 1
|
||||
${kadmin} add -p foo --use-defaults ${ps} || exit 1
|
||||
${kadmin} modify --attributes=+trusted-for-delegation ${ps} || exit 1
|
||||
${kadmin} modify --constrained-delegation=${server} ${ps} || exit 1
|
||||
${kadmin} ext -k ${keytab} ${server}@${R} || exit 1
|
||||
${kadmin} ext -k ${keytab} ${ps} || exit 1
|
||||
|
||||
${kadmin} add -p kaka --use-defaults ${server2}@${R2} || exit 1
|
||||
${kadmin} ext -k ${keytab} ${server2}@${R2} || exit 1
|
||||
${kadmin} add -p kaka --use-defaults ${serverip}@${R} || exit 1
|
||||
${kadmin} ext -k ${keytab} ${serverip}@${R} || exit 1
|
||||
${kadmin} add -p kaka --use-defaults ${serveripname}@${R} || exit 1
|
||||
${kadmin} ext -k ${keytab} ${serveripname}@${R} || exit 1
|
||||
${kadmin} modify --alias=${serveripname2}@${R} ${serveripname}@${R}
|
||||
${kadmin} add -p foo --use-defaults remove2@${R2} || exit 1
|
||||
|
||||
${kadmin} add -p kaka --use-defaults ${alias1}@${R} || exit 1
|
||||
${kadmin} ext -k ${keytab} ${alias1}@${R} || exit 1
|
||||
${kadmin} modify --alias=${alias2}@${R} ${alias1}@${R}
|
||||
|
||||
${kadmin} add -p cross1 --use-defaults krbtgt/${R2}@${R} || exit 1
|
||||
${kadmin} add -p cross2 --use-defaults krbtgt/${R}@${R2} || exit 1
|
||||
|
||||
${kadmin} add -p foo --use-defaults pw-expire@${R} || exit 1
|
||||
${kadmin} modify --pw-expiration-time=+1day pw-expire@${R} || exit 1
|
||||
|
||||
${kadmin} add -p foo --use-defaults foo@${R3} || exit 1
|
||||
|
||||
echo "Check parser"
|
||||
${kadmin} add -p foo --use-defaults -- -p || exit 1
|
||||
${kadmin} delete -- -p || exit 1
|
||||
|
||||
echo "Doing database check"
|
||||
${kadmin} check ${R} || exit 1
|
||||
${kadmin} check ${R2} || exit 1
|
||||
|
||||
echo "Extracting enctypes"
|
||||
${ktutil} -k ${keytab} list > tempfile || exit 1
|
||||
${EGREP} -v '^FILE:' tempfile | ${EGREP} -v '^Vno' | ${EGREP} -v '^$' | \
|
||||
awk '$1 !~ /1/ { exit 1 }' || exit 1
|
||||
|
||||
${kadmin} get foo@${R} > tempfile || exit 1
|
||||
enctypes=`grep Keytypes: tempfile | sed 's/(pw-salt)//g' | sed 's/,//g' | sed 's/Keytypes://' | sed 's/\[[0-9]*\]//g'`
|
||||
|
||||
enctype_sans_aes=`echo $enctypes | sed 's/aes[^ ]*//g'`
|
||||
enctype_sans_des3=`echo $enctypes | sed 's/des3-cbc-sha1//g'`
|
||||
|
||||
echo "deleting all but des enctypes on kt-des3 in keytab"
|
||||
${kadmin} ext -k ${keytab} kt-des3@${R} || exit 1
|
||||
for a in ${enctype_sans_des3} ; do
|
||||
${ktutil} -k ${keytab} remove -p kt-des3@${R} -e $a
|
||||
done
|
||||
|
||||
echo foo > ${objdir}/foopassword
|
||||
|
||||
echo Starting kdc
|
||||
env MallocStackLogging=1 MallocStackLoggingNoCompact=1 MallocErrorAbort=1 MallocLogFile=${objdir}/malloc-log \
|
||||
${kdc} &
|
||||
kdcpid=$!
|
||||
|
||||
sh ${wait_kdc}
|
||||
if [ "$?" != 0 ] ; then
|
||||
kill -9 ${kdcpid}
|
||||
exit 1
|
||||
fi
|
||||
|
||||
trap "kill -9 ${kdcpid}; echo signal killing kdc; exit 1;" EXIT
|
||||
|
||||
ec=0
|
||||
|
||||
echo "Getting client initial tickets"; > messages.log
|
||||
${kinit} --password-file=${objdir}/foopassword foo@$R || \
|
||||
{ ec=1 ; eval "${testfailed}"; }
|
||||
echo "Doing krbtgt key rollover"; > messages.log
|
||||
${kadmin} cpw -r --keepold krbtgt/${R}@${R} || exit 1
|
||||
echo "Getting tickets"; > messages.log
|
||||
${kgetcred} ${server}@${R} || { ec=1 ; eval "${testfailed}"; }
|
||||
echo "Listing tickets"; > messages.log
|
||||
${klist} > /dev/null || { ec=1 ; eval "${testfailed}"; }
|
||||
${test_ap_req} ${server}@${R} ${keytab} ${cache} || \
|
||||
{ ec=1 ; eval "${testfailed}"; }
|
||||
${kdestroy}
|
||||
|
||||
echo "Getting client initial tickets (http transport)"; > messages.log
|
||||
${kinit} --password-file=${objdir}/foopassword foo@${R3} || \
|
||||
{ ec=1 ; eval "${testfailed}"; }
|
||||
${kdestroy}
|
||||
|
||||
echo "Specific enctype"; > messages.log
|
||||
${kinit} --password-file=${objdir}/foopassword \
|
||||
-e ${aesenctype} -e ${aesenctype} \
|
||||
foo@$R || \
|
||||
{ ec=1 ; eval "${testfailed}"; }
|
||||
|
||||
for a in $enctypes; do
|
||||
echo "Getting client initial tickets ($a)"; > messages.log
|
||||
${kinit} --enctype=$a --password-file=${objdir}/foopassword foo@$R || { ec=1 ; eval "${testfailed}"; }
|
||||
echo "Getting tickets"; > messages.log
|
||||
${kgetcred} ${server}@${R} || { ec=1 ; eval "${testfailed}"; }
|
||||
${test_ap_req} ${server}@${R} ${keytab} ${cache} || { ec=1 ; eval "${testfailed}"; }
|
||||
${kdestroy}
|
||||
done
|
||||
|
||||
|
||||
echo "Getting client initial tickets"; > messages.log
|
||||
${kinit} --password-file=${objdir}/foopassword foo@$R || \
|
||||
{ ec=1 ; eval "${testfailed}"; }
|
||||
for a in $enctypes; do
|
||||
echo "Getting tickets ($a)"; > messages.log
|
||||
${kgetcred} -e $a ${server}@${R} || { ec=1 ; eval "${testfailed}"; }
|
||||
${test_ap_req} ${server}@${R} ${keytab} ${cache} || \
|
||||
{ ec=1 ; eval "${testfailed}"; }
|
||||
${kdestroy} --credential=${server}@${R}
|
||||
done
|
||||
${kdestroy}
|
||||
|
||||
echo "Getting client initial tickets for cross realm case"; > messages.log
|
||||
${kinit} --password-file=${objdir}/foopassword foo@$R || { ec=1 ; eval "${testfailed}"; }
|
||||
for a in $enctypes; do
|
||||
echo "Getting cross realm tickets ($a)"; > messages.log
|
||||
${kgetcred} -e $a ${server2}@${R2} || { ec=1 ; eval "${testfailed}"; }
|
||||
echo " checking we we got back right ticket"
|
||||
${klist} | grep ${server2}@ > /dev/null || { ec=1 ; eval "${testfailed}"; }
|
||||
echo " checking if ticket is useful"
|
||||
${test_ap_req} ${server2}@${R2} ${keytab} ${cache} || \
|
||||
{ ec=1 ; eval "${testfailed}"; }
|
||||
${kdestroy} --credential=${server2}@${R2}
|
||||
done
|
||||
${kdestroy}
|
||||
|
||||
echo "try all permutations"; > messages.log
|
||||
for a in $enctypes; do
|
||||
echo "Getting client initial tickets ($a)"; > messages.log
|
||||
${kinit} --enctype=$a --password-file=${objdir}/foopassword foo@$R || \
|
||||
{ ec=1 ; eval "${testfailed}"; }
|
||||
for b in $enctypes; do
|
||||
echo "Getting tickets ($a -> $b)"; > messages.log
|
||||
${kgetcred} -e $b ${server}@${R} || \
|
||||
{ ec=1 ; eval "${testfailed}"; }
|
||||
${test_ap_req} ${server}@${R} ${keytab} ${cache} || \
|
||||
{ ec=1 ; eval "${testfailed}"; }
|
||||
${kdestroy} --credential=${server}@${R}
|
||||
done
|
||||
${kdestroy}
|
||||
done
|
||||
|
||||
echo "Getting client initial tickets ip based name"; > messages.log
|
||||
${kinit} --password-file=${objdir}/foopassword foo@$R || { ec=1 ; eval "${testfailed}"; }
|
||||
echo "Getting ip based name tickets"; > messages.log
|
||||
${kgetcred} ${serverip}@${R} || { ec=1 ; eval "${testfailed}"; }
|
||||
echo " checking we we got back right ticket"
|
||||
${klist} | grep ${serverip}@ > /dev/null || { ec=1 ; eval "${testfailed}"; }
|
||||
echo " checking if ticket is useful"
|
||||
${test_ap_req} ${serverip}@${R} ${keytab} ${cache} || \
|
||||
{ ec=1 ; eval "${testfailed}"; }
|
||||
${kdestroy}
|
||||
|
||||
echo "Getting client initial tickets ip based name (alias)"; > messages.log
|
||||
${kinit} --password-file=${objdir}/foopassword foo@$R || { ec=1 ; eval "${testfailed}"; }
|
||||
for a in ${serveripname} ${serveripname2} ; do
|
||||
echo "Getting ip based name tickets (alias) $a"; > messages.log
|
||||
${kgetcred} ${a}@${R} || { ec=1 ; eval "${testfailed}"; }
|
||||
echo " checking we we got back right ticket"
|
||||
${klist} | grep ${a}@ > /dev/null || { ec=1 ; eval "${testfailed}"; }
|
||||
echo " checking if ticket is useful"
|
||||
${test_ap_req} --server-any ${a}@${R} ${keytab} ${cache} || \
|
||||
{ ec=1 ; eval "${testfailed}"; }
|
||||
done
|
||||
${kdestroy}
|
||||
|
||||
echo "Getting server initial tickets"; > messages.log
|
||||
${kinit} --keytab=${keytab} ${server}@$R || { ec=1 ; eval "${testfailed}"; }
|
||||
echo "Listing tickets"; > messages.log
|
||||
${klist} | grep "Principal: ${server}" > /dev/null || \
|
||||
{ ec=1 ; eval "${testfailed}"; }
|
||||
${kdestroy}
|
||||
|
||||
echo "Getting key for key that are a subset in keytab compared to kdb"
|
||||
${kinit} --keytab=${keytab} kt-des3@${R}
|
||||
${klist} | grep "Principal: kt-des3" > /dev/null || \
|
||||
{ ec=1 ; eval "${testfailed}"; }
|
||||
${kdestroy}
|
||||
|
||||
echo "initial tickets for deleted user test case"; > messages.log
|
||||
${kinit} --password-file=${objdir}/foopassword remove@$R || \
|
||||
{ ec=1 ; eval "${testfailed}"; }
|
||||
${kadmin} delete remove@${R} || { ec=1 ; eval "${testfailed}"; }
|
||||
echo "try getting ticket with deleted user"; > messages.log
|
||||
${kgetcred} ${server}@${R} 2> /dev/null && { ec=1 ; eval "${testfailed}"; }
|
||||
${kdestroy}
|
||||
|
||||
echo "cross realm case (deleted user)"; > messages.log
|
||||
${kinit} --password-file=${objdir}/foopassword remove2@$R2 || \
|
||||
{ ec=1 ; eval "${testfailed}"; }
|
||||
${kgetcred} krbtgt/${R}@${R2} 2> /dev/null || \
|
||||
{ ec=1 ; eval "${testfailed}"; }
|
||||
${kadmin} delete remove2@${R2} || exit 1
|
||||
${kgetcred} ${server}@${R} 2> /dev/null || \
|
||||
{ ec=1 ; eval "${testfailed}"; }
|
||||
${kdestroy}
|
||||
|
||||
echo "rename user"; > messages.log
|
||||
${kadmin} add -p foo --use-defaults rename@${R} || exit 1
|
||||
${kinit} --password-file=${objdir}/foopassword rename@${R} || \
|
||||
{ ec=1 ; eval "${testfailed}"; }
|
||||
${kadmin} rename rename@${R} rename2@${R} || exit 1
|
||||
${kinit} --password-file=${objdir}/foopassword rename2@${R} || \
|
||||
{ ec=1 ; eval "${testfailed}"; }
|
||||
${kdestroy}
|
||||
${kadmin} delete rename2@${R} || exit 1
|
||||
|
||||
echo "rename user to another realm"; > messages.log
|
||||
${kadmin} add -p foo --use-defaults rename@${R} || exit 1
|
||||
${kinit} --password-file=${objdir}/foopassword rename@${R} || \
|
||||
{ ec=1 ; eval "${testfailed}"; }
|
||||
${kadmin} rename rename@${R} rename@${R2} || exit 1
|
||||
${kinit} --password-file=${objdir}/foopassword rename@${R2} || \
|
||||
{ ec=1 ; eval "${testfailed}"; }
|
||||
${kdestroy}
|
||||
${kadmin} delete rename@${R2} || exit 1
|
||||
|
||||
echo deleting all but aes enctypes on krbtgt
|
||||
${kadmin} del_enctype krbtgt/${R}@${R} ${enctype_sans_aes} || exit 1
|
||||
|
||||
echo deleting all but des enctypes on server-des3
|
||||
${kadmin} del_enctype ${server}-des3@${R} ${enctype_sans_des3} || exit 1
|
||||
${kadmin} ext -k ${keytab} ${server}-des3@${R} || exit 1
|
||||
|
||||
echo "try all permutations (only aes)"; > messages.log
|
||||
for a in $enctypes; do
|
||||
echo "Getting client initial tickets ($a)"; > messages.log
|
||||
${kinit} --enctype=$a --password-file=${objdir}/foopassword foo@${R} ||\
|
||||
{ ec=1 ; eval "${testfailed}"; }
|
||||
for b in $enctypes; do
|
||||
echo "Getting tickets ($a -> $b)"; > messages.log
|
||||
${kgetcred} -e $b ${server}@${R} || \
|
||||
{ ec=1 ; eval "${testfailed}"; }
|
||||
${test_ap_req} ${server}@${R} ${keytab} ${cache} || \
|
||||
{ ec=1 ; eval "${testfailed}"; }
|
||||
|
||||
echo "Getting tickets ($a -> $b) (server des3 only)"; > messages.log
|
||||
${kgetcred} ${server}-des3@${R} || \
|
||||
{ ec=1 ; eval "${testfailed}"; }
|
||||
${test_ap_req} ${server}-des3@${R} ${keytab} ${cache} || \
|
||||
{ ec=1 ; eval "${testfailed}"; }
|
||||
|
||||
${kdestroy} --credential=${server}@${R}
|
||||
${kdestroy} --credential=${server}-des3@${R}
|
||||
done
|
||||
${kdestroy}
|
||||
done
|
||||
|
||||
echo deleting all enctypes on krbtgt
|
||||
${kadmin} del_enctype krbtgt/${R}@${R} aes256-cts-hmac-sha1-96 || \
|
||||
{ ec=1 ; eval "${testfailed}"; }
|
||||
echo "try initial ticket w/o and keys on krbtgt"
|
||||
${kinit} --password-file=${objdir}/foopassword foo@${R} 2>/dev/null && \
|
||||
{ ec=1 ; eval "${testfailed}"; }
|
||||
echo "adding random aes key"
|
||||
${kadmin} add_enctype -r krbtgt/${R}@${R} aes256-cts-hmac-sha1-96 || \
|
||||
{ ec=1 ; eval "${testfailed}"; }
|
||||
echo "try initial ticket with random aes key on krbtgt"
|
||||
${kinit} --password-file=${objdir}/foopassword foo@${R} || \
|
||||
{ ec=1 ; eval "${testfailed}"; }
|
||||
${kdestroy}
|
||||
|
||||
rsa=yes
|
||||
ecdsa=yes
|
||||
pkinit=no
|
||||
if ${hxtool} info | grep 'rsa: hx509 null RSA' > /dev/null ; then
|
||||
rsa=no
|
||||
fi
|
||||
if ${hxtool} info | grep 'rand: not available' > /dev/null ; then
|
||||
rsa=no
|
||||
fi
|
||||
if ${kinit} --help 2>&1 | grep "CA certificates" > /dev/null; then
|
||||
pkinit=yes
|
||||
fi
|
||||
|
||||
if ${hxtool} info | grep 'ecdsa: hcrypto null' > /dev/null ; then
|
||||
ecdsa=no
|
||||
fi
|
||||
|
||||
|
||||
# If we support pkinit and have RSA, lets try that
|
||||
if test "$pkinit" = yes -a "$rsa" = yes ; then
|
||||
|
||||
echo "try anonymous pkinit"; > messages.log
|
||||
${kinit} --anonymous ${R} || \
|
||||
{ ec=1 ; eval "${testfailed}"; }
|
||||
${kgetcred} ${server}@${R} || { ec=1 ; eval "${testfailed}"; }
|
||||
${kdestroy}
|
||||
|
||||
for type in "" "--pk-use-enckey"; do
|
||||
echo "Trying pk-init (principal in certificate) $type"; > messages.log
|
||||
${kinit} $type -C FILE:${hx509_data}/pkinit.crt,${hx509_data}/pkinit.key bar@${R} || \
|
||||
{ ec=1 ; eval "${testfailed}"; }
|
||||
${kgetcred} ${server}@${R} || { ec=1 ; eval "${testfailed}"; }
|
||||
${kdestroy}
|
||||
|
||||
echo "Trying pk-init (principal in pki-mapping) $type"; > messages.log
|
||||
${kinit} $type -C FILE:${hx509_data}/pkinit.crt,${hx509_data}/pkinit.key foo@${R} || \
|
||||
{ ec=1 ; eval "${testfailed}"; }
|
||||
${kgetcred} ${server}@${R} || { ec=1 ; eval "${testfailed}"; }
|
||||
${kdestroy}
|
||||
|
||||
echo "Trying pk-init (password protected key) $type"; > messages.log
|
||||
${kinit} $type -C FILE:${hx509_data}/pkinit.crt,${hx509_data}/pkinit-pw.key --password-file=${objdir}/foopassword foo@${R} || \
|
||||
{ ec=1 ; eval "${testfailed}"; }
|
||||
${kgetcred} ${server}@${R} || \
|
||||
{ ec=1 ; eval "${testfailed}"; }
|
||||
${kdestroy}
|
||||
|
||||
echo "Trying pk-init (proxy cert) $type"; > messages.log
|
||||
${kinit} $type -C FILE:${hx509_data}/pkinit-proxy-chain.crt,${hx509_data}/pkinit-proxy.key foo@${R} || \
|
||||
{ ec=1 ; eval "${testfailed}"; }
|
||||
${kgetcred} ${server}@${R} || { ec=1 ; eval "${testfailed}"; }
|
||||
${kdestroy}
|
||||
|
||||
done
|
||||
|
||||
if test "$ecdsa" = yes > /dev/null ; then
|
||||
echo "Trying pk-init (ec certificate)"
|
||||
> messages.log
|
||||
${kinit} -C FILE:${hx509_data}/pkinit-ec.crt,${hx509_data}/pkinit-ec.key bar@${R} || \
|
||||
{ ec=1 ; eval "${testfailed}"; }
|
||||
${kgetcred} ${server}@${R} || { ec=1 ; eval "${testfailed}"; }
|
||||
${kdestroy}
|
||||
grep 'PK-INIT using ecdh' messages.log > /dev/null || \
|
||||
{ ec=1 ; eval "${testfailed}"; }
|
||||
fi
|
||||
|
||||
else
|
||||
echo "no pkinit (pkinit: $pkinit, rsa: $rsa)"; > messages.log
|
||||
fi
|
||||
|
||||
echo "tickets for impersonate test case"; > messages.log
|
||||
${kinit} --forwardable --password-file=${objdir}/foopassword ${ps} || \
|
||||
{ ec=1 ; eval "${testfailed}"; }
|
||||
${kgetcred_imp} --impersonate=bar@${R} ${ps} || \
|
||||
{ ec=1 ; eval "${testfailed}"; }
|
||||
${test_ap_req} ${ps} ${keytab} ${ocache} || \
|
||||
{ ec=1 ; eval "${testfailed}"; }
|
||||
echo " negative check"
|
||||
${kgetcred_imp} --impersonate=bar@${R} foo@${R} 2>/dev/null && \
|
||||
{ ec=1 ; eval "${testfailed}"; }
|
||||
|
||||
echo "test constrained delegation"; > messages.log
|
||||
${kgetcred_imp} --forward --impersonate=bar@${R} ${ps} || \
|
||||
{ ec=1 ; eval "${testfailed}"; }
|
||||
${kgetcred} \
|
||||
--out-cache=${o2cache} \
|
||||
--delegation-credential-cache=${ocache} \
|
||||
${server}@${R} || \
|
||||
{ ec=1 ; eval "${testfailed}"; }
|
||||
echo " try using the credential"
|
||||
${test_ap_req} ${server}@${R} ${keytab} ${o2cache} || \
|
||||
{ ec=1 ; eval "${testfailed}"; }
|
||||
echo " negative check"
|
||||
${kgetcred} \
|
||||
--out-cache=${o2cache} \
|
||||
--delegation-credential-cache=${ocache} \
|
||||
bar@${R} 2>/dev/null && \
|
||||
{ ec=1 ; eval "${testfailed}"; }
|
||||
|
||||
echo "test constrained delegation impersonation (non forward)"; > messages.log
|
||||
rm -f ocache.krb5
|
||||
${kimpersonate} -s ${ps} -c bar@${R} -t ${aesenctype} || \
|
||||
{ ec=1 ; eval "${testfailed}"; }
|
||||
${kgetcred} --out-cache=${o2cache} --delegation-credential-cache=${ocache} ${server}@${R} > /dev/null 2>/dev/null && \
|
||||
{ ec=1 ; eval "${testfailed}"; }
|
||||
|
||||
echo "test constrained delegation impersonation (missing KRB5SignedPath)"; > messages.log
|
||||
rm -f ocache.krb5
|
||||
${kimpersonate} -s ${ps} -c bar@${R} -t ${aesenctype} -f forwardable || \
|
||||
{ ec=1 ; eval "${testfailed}"; }
|
||||
${kgetcred} --out-cache=${o2cache} --delegation-credential-cache=${ocache} ${server}@${R} > /dev/null 2>/dev/null && \
|
||||
{ ec=1 ; eval "${testfailed}"; }
|
||||
|
||||
${kdestroy}
|
||||
|
||||
echo "check renewing" > messages.log
|
||||
${kinit} --renewable --password-file=${objdir}/foopassword foo@$R || \
|
||||
{ ec=1 ; eval "${testfailed}"; }
|
||||
echo "kinit -R"
|
||||
${kinit} -R || \
|
||||
{ ec=1 ; eval "${testfailed}"; }
|
||||
echo "check renewing MIT interface" > messages.log
|
||||
${kinit} --renewable --password-file=${objdir}/foopassword foo@$R || \
|
||||
{ ec=1 ; eval "${testfailed}"; }
|
||||
echo "test_renew"
|
||||
env KRB5CCNAME=${cache} ${test_renew} || \
|
||||
{ ec=1 ; eval "${testfailed}"; }
|
||||
${kdestroy}
|
||||
|
||||
echo "checking server aliases"; > messages.log
|
||||
${kinit} --password-file=${objdir}/foopassword foo@$R || \
|
||||
{ ec=1 ; eval "${testfailed}"; }
|
||||
echo "Getting tickets"; > messages.log
|
||||
${kgetcred} ${alias1}@${R} || { ec=1 ; eval "${testfailed}"; }
|
||||
${kgetcred} ${alias2}@${R} || { ec=1 ; eval "${testfailed}"; }
|
||||
echo " verify entry in keytab"
|
||||
${test_ap_req} ${alias1}@${R} ${keytab} ${cache} || \
|
||||
{ ec=1 ; eval "${testfailed}"; }
|
||||
echo " verify entry in keytab with any"
|
||||
${test_ap_req} --server-any ${alias1}@${R} ${keytab} ${cache} || \
|
||||
{ ec=1 ; eval "${testfailed}"; }
|
||||
echo " verify failure with alias entry"
|
||||
${test_ap_req} ${alias2}@${R} ${keytab} ${cache} 2>/dev/null && \
|
||||
{ ec=1 ; eval "${testfailed}"; }
|
||||
echo " verify alias entry in keytab with any"
|
||||
${test_ap_req} --server-any ${alias2}@${R} ${keytab} ${cache} || \
|
||||
{ ec=1 ; eval "${testfailed}"; }
|
||||
${kdestroy}
|
||||
|
||||
echo "testing removal of keytab"
|
||||
${ktutil} -k ${keytab} destroy || { ec=1 ; eval "${testfailed}"; }
|
||||
test -f ${keytabfile} && { ec=1 ; eval "${testfailed}"; }
|
||||
|
||||
echo "Getting client pw expire"; > messages.log
|
||||
${kinit} --password-file=${objdir}/foopassword \
|
||||
pw-expire@${R} 2>kinit-log.tmp|| \
|
||||
{ ec=1 ; eval "${testfailed}"; }
|
||||
grep 'Your password will expire' kinit-log.tmp > /dev/null || \
|
||||
{ ec=1 ; eval "${testfailed}"; }
|
||||
echo " kinit passes"
|
||||
${test_gic} --client=pw-expire@${R} --password=foo > kinit-log.tmp 2>/dev/null
|
||||
${EGREP} "^e type: 6" kinit-log.tmp > /dev/null || \
|
||||
{ ec=1 ; eval "${testfailed}"; }
|
||||
echo " test_gic passes"
|
||||
${kdestroy}
|
||||
|
||||
echo "killing kdc (${kdcpid})"
|
||||
sh ${leaks_kill} kdc $kdcpid || exit 1
|
||||
|
||||
trap "" EXIT
|
||||
|
||||
exit $ec
|
@@ -69,7 +69,7 @@ client_access(void *ctx,
|
||||
hdb_entry_ex *client, const char *client_name,
|
||||
hdb_entry_ex *server, const char *server_name,
|
||||
KDC_REQ *req,
|
||||
krb5_data *e_data)
|
||||
METHOD_DATA *data)
|
||||
{
|
||||
krb5_warnx(context, "client_access");
|
||||
return 0;
|
||||
|
Reference in New Issue
Block a user