-- $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= -- - eku= -- - ku= -- - rfc822Name= -- - xMPPName= -- - dNSName= -- - dNSSrv= -- - registeredID= -- - principalName= -- -- 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