1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
|
-- $Id$
-- Version 2 of the kx509 protocol is documented in RFC6717.
--
-- Our version here has extensions without changing the version number on the
-- wire.
KX509 DEFINITIONS ::= BEGIN
IMPORTS Extensions FROM rfc2459
KerberosTime FROM krb5;
KX509-ERROR-CODE ::= INTEGER {
KX509-STATUS-GOOD(0),
KX509-STATUS-CLIENT-BAD(1),
KX509-STATUS-CLIENT-FIX(2),
KX509-STATUS-CLIENT-TEMP(3),
KX509-STATUS-SERVER-BAD(4),
KX509-STATUS-SERVER-TEMP(5),
-- 6 is used internally in the umich client, avoid that
KX509-STATUS-SERVER-KEY(7),
-- CSR use negotiation:
KX509-STATUS-CLIENT-USE-CSR(8)
-- Let us reserve 1000+ for Kebreros protocol wire error codes -Nico
}
-- Originally kx509 requests carried only a public key. We'd like to have
-- proof of possession, and the ability to carry additional options, both, in
-- cleartext and otherwise.
--
-- We'll use a CSR for proof of posession and desired certificate extensions.
--
-- We'll also provide a non-CSR-based method of conveying desired certificate
-- extensions. The reason for this is simply that we may want to have a [e.g.,
-- RESTful HTTP] proxy for the kx509 service, and we want clients to be able to
-- be as simple as possible -cargo-culted even- with support for attributes
-- (desired certificate extensions) as parameters outside the CSR that the
-- proxy can encode without having the private key for the CSR (naturally).
--
-- I.e., ultimately we'll have a REST endpoint, /kx509, say, with query
-- parameters like:
--
-- - csr=<base64-encoding-of-DER-encoded-CSR>
-- - eku=<OID>
-- - ku=<key-usage-flag-name>
-- - rfc822Name=<URL-escaped-email-address>
-- - xMPPName=<URL-escaped-jabber-address>
-- - dNSName=<URL-escaped-FQDN>
-- - dNSSrv=<URL-escaped-_service.FQDN>
-- - registeredID=<OID>
-- - principalName=<URL-escaped-RFC1964-format-Kerberos-Principal-Name>
--
-- with exactly one CSR and zero, one, or more of the other parameters.
--
-- We'll even have a way to convey a bearer token from the REST proxy so that
-- we may have a way to get PKIX credentials using bearer tokens. And then,
-- using PKINIT, we may have a way to get Kerberos credentials using bearer
-- tokens.
--
-- To do this we define a Kx509CSRPlus that we can use in the `pk-key' field of
-- Kx509Request (see below):
Kx509CSRPlus ::= [APPLICATION 35] SEQUENCE {
-- PKCS#10, DER-encoded CSR, with or without meaningful attributes
csr OCTET STRING,
-- Desired certificate Extensions such as KeyUsage, ExtKeyUsage, or
-- subjectAlternativeName (SAN)
exts Extensions OPTIONAL,
-- Desired certificate lifetime
req-life KerberosTime OPTIONAL,
...
}
-- Version 2
Kx509Request ::= SEQUENCE {
authenticator OCTET STRING,
pk-hash OCTET STRING, -- HMAC(ticket_session_key, pk-key)
pk-key OCTET STRING -- one of:
-- - the public key, DER-encoded (RSA, basically)
-- - a Kx509CSRPlus
}
-- Kx509ErrorCode is a Heimdal-specific enhancement with no change on the wire,
-- and really only just so the error-code field below can fit on one line.
Kx509ErrorCode ::= INTEGER (-2147483648..2147483647)
Kx509Response ::= SEQUENCE {
error-code[0] Kx509ErrorCode DEFAULT 0,
hash[1] OCTET STRING OPTIONAL, -- HMAC(session_key, ...)
certificate[2] OCTET STRING OPTIONAL, -- DER-encoded Certificate
-- if client sent raw RSA SPK
-- or DER-encoded Certificates
-- (i.e., SEQ. OF Certificate)
-- if client used a
-- Kx509CSRPlus
e-text[3] VisibleString OPTIONAL
}
-- Offset for Kerberos protocol errors when error-code set to one:
kx509-krb5-error-base INTEGER ::= 1000
-- RFC6717 says this about error codes:
--
-- +------------+-----------------------------+------------------------+
-- | error-code | Condition | Example |
-- +------------+-----------------------------+------------------------+
-- | 1 | Permanent problem with | Incompatible version |
-- | | client request | |
-- | 2 | Solvable problem with | Expired Kerberos |
-- | | client request | credentials |
-- | 3 | Temporary problem with | Packet loss |
-- | | client request | |
-- | 4 | Permanent problem with the | Internal |
-- | | server | misconfiguration |
-- | 5 | Temporary problem with the | Server overloaded |
-- | | server | |
-- +------------+-----------------------------+------------------------+
--
-- Looking at UMich CITI's kca (server-side of kx509) implementation, it always
-- sends 0 as the status code, and the UMich CITI kx509 client never checks it.
-- All of these error codes are local only in the UMich CITI implementation.
--
-- Meanwhile, Heimdal used to never send error responses at all.
--
-- As a result we can use whatever error codes we want. We'll send Kerberos
-- protocol errors + 1000. And we'll never use RFC6717 error codes at all.
--
-- Looking at umich source...
--
-- #define KX509_STATUS_GOOD 0 /* No problems handling client request */
-- #define KX509_STATUS_CLNT_BAD 1 /* Client-side permanent problem */
-- /* ex. version incompatible */
-- #define KX509_STATUS_CLNT_FIX 2 /* Client-side solvable problem */
-- /* ex. re-authenticate */
-- #define KX509_STATUS_CLNT_TMP 3 /* Client-side temporary problem */
-- /* ex. packet loss */
-- #define KX509_STATUS_SRVR_BAD 4 /* Server-side permanent problem */
-- /* ex. server broken */
-- #define KX509_STATUS_SRVR_TMP 5 /* Server-side temporary problem */
-- /* ex. server overloaded */
-- #define KX509_STATUS_SRVR_CANT_CLNT_VERS 6 /* Server-side doesn't handle */
-- /* existence of client_version */
-- /* field in KX509_REQUEST */
--
-- The umich server uses these errors in these situations:
--
-- - KX509_STATUS_SRVR_TMP is for:
-- - request decode errors
-- - krb5_is_ap_req() errors
-- - wrong Kerberos protocol vno in AP-REQ
-- - some ENOMEMs
-- - UDP read errors (??)
-- - LDAP issues (they use LDAP to map realm-chopped user princ names to
-- full names)
-- - pk decode errors
-- - KX509_STATUS_CLNT_TMP is for:
-- - HMAC mismatch
-- - some ENOMEMs
-- - failure to accept AP-REQ
-- - failure to unparse princ names from AP-REQ's Ticket
-- - KX509_STATUS_SRVR_BAD is for:
-- - configuration issues (missing issuer creds)
-- - serial number transaction issues (we should randomize)
-- - subjectName construction issues
-- - certificate construction issues (ENOMEM, say)
-- - failure to authenticate (never happens, since KX509_STATUS_CLNT_TMP is
-- used earlier when krb5_rd_req() fails)
-- - KX509_STATUS_CLNT_FIX is for:
-- - more than one component client principals
-- - client princ name component zero string length shorter than 3 or
-- longer than 8 (WTF)
-- - other policy issues
-- - KX509_STATUS_CLNT_BAD
-- - wrong protocol version number (version_2_0)
-- Possible new version designs:
--
-- - keep the protocol the same but use a CSR instead of a raw RSA public key
-- - on the server try decoding first a CSR, then a raw RSA public key
--
-- - keep the protocol the same but use either a CSR or a self-signed cert
-- - on the server try decoding first a Certificate, then a CSR, then a raw
-- RSA public key
--
-- CSRs are a pain to deal with. Self-signed certificates can act as a
-- CSR of a sort. Use notBefore == 1970-01-01T00:00:00Z and an EKU
-- denoting "this certificate is really a much-easier-to-work-with CSR
-- alternative".
--
-- - keep the protocol similar, but use the checksum field of the
-- Authenticator to authenticate the request data; use a KRB-PRIV for the
-- reply
--
-- - extend the KDC/AS/TGS protocols to support certificate issuance, either
-- at the same time as ticket acquisition, or as an alternative
-- - send a CSR as a authz-data element
-- - expect an EncryptedData with the issued Certificate inside as the
-- Ticket in the result (again, ugly hack)
-- - or maybe just add new messages, but, the thing is that the existing
-- "AP-REP + stuff" kx509 protocol is a fine design pattern, there's no
-- need to radically change it, just slightly.
--
-- The main benefit of using an extension to the KDC/AS/TGS protocols is that
-- we could then use FAST for confidentiality protection.
END
|