2 * COPYRIGHT (C) 2006,2007
3 * THE REGENTS OF THE UNIVERSITY OF MICHIGAN
6 * Permission is granted to use, copy, create derivative works
7 * and redistribute this software and such derivative works
8 * for any purpose, so long as the name of The University of
9 * Michigan is not used in any advertising or publicity
10 * pertaining to the use of distribution of this software
11 * without specific, written prior authorization. If the
12 * above copyright notice or any other identification of the
13 * University of Michigan is included in any copy of any
14 * portion of this software, then the disclaimer below must
17 * THIS SOFTWARE IS PROVIDED AS IS, WITHOUT REPRESENTATION
18 * FROM THE UNIVERSITY OF MICHIGAN AS TO ITS FITNESS FOR ANY
19 * PURPOSE, AND WITHOUT WARRANTY BY THE UNIVERSITY OF
20 * MICHIGAN OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING
21 * WITHOUT LIMITATION THE IMPLIED WARRANTIES OF
22 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE
23 * REGENTS OF THE UNIVERSITY OF MICHIGAN SHALL NOT BE LIABLE
24 * FOR ANY DAMAGES, INCLUDING SPECIAL, INDIRECT, INCIDENTAL, OR
25 * CONSEQUENTIAL DAMAGES, WITH RESPECT TO ANY CLAIM ARISING
26 * OUT OF OR IN CONNECTION WITH THE USE OF THE SOFTWARE, EVEN
27 * IF IT HAS BEEN OR IS HEREAFTER ADVISED OF THE POSSIBILITY OF
34 #include <krb5/krb5.h>
35 #include <krb5/preauth_plugin.h>
36 #include <k5-platform.h>
37 #include <k5-int-pkinit.h>
40 #include "pkinit_accessor.h"
41 #include "pkinit_trace.h"
44 * It is anticipated that all the special checks currently
45 * required when talking to a Longhorn server will go away
46 * by the time it is officially released and all references
47 * to the longhorn global can be removed and any code
48 * #ifdef'd with LONGHORN_BETA_COMPAT can be removed.
51 #define LONGHORN_BETA_COMPAT 1
52 #ifdef LONGHORN_BETA_COMPAT
53 extern int longhorn; /* XXX Talking to a Longhorn server? */
57 #ifndef WITHOUT_PKCS11
60 #define PKCS11_MODNAME "opensc-pkcs11.so"
61 #define PK_SIGLEN_GUESS 1000
62 #define PK_NOSLOT 999999
66 #define RSA_PROTOCOL 2
68 #define TD_TRUSTED_CERTIFIERS 104
69 #define TD_INVALID_CERTIFICATES 105
70 #define TD_DH_PARAMETERS 109
72 #define PKINIT_CTX_MAGIC 0x05551212
73 #define PKINIT_REQ_CTX_MAGIC 0xdeadbeef
75 #define PKINIT_DEFAULT_DH_MIN_BITS 2048
77 #define KRB5_CONF_KDCDEFAULTS "kdcdefaults"
78 #define KRB5_CONF_LIBDEFAULTS "libdefaults"
79 #define KRB5_CONF_REALMS "realms"
80 #define KRB5_CONF_PKINIT_ALLOW_UPN "pkinit_allow_upn"
81 #define KRB5_CONF_PKINIT_ANCHORS "pkinit_anchors"
82 #define KRB5_CONF_PKINIT_CERT_MATCH "pkinit_cert_match"
83 #define KRB5_CONF_PKINIT_DH_MIN_BITS "pkinit_dh_min_bits"
84 #define KRB5_CONF_PKINIT_EKU_CHECKING "pkinit_eku_checking"
85 #define KRB5_CONF_PKINIT_IDENTITIES "pkinit_identities"
86 #define KRB5_CONF_PKINIT_IDENTITY "pkinit_identity"
87 #define KRB5_CONF_PKINIT_KDC_HOSTNAME "pkinit_kdc_hostname"
88 #define KRB5_CONF_PKINIT_KDC_OCSP "pkinit_kdc_ocsp"
89 #define KRB5_CONF_PKINIT_LONGHORN "pkinit_longhorn"
90 #define KRB5_CONF_PKINIT_MAPPING_FILE "pkinit_mapping_file"
91 #define KRB5_CONF_PKINIT_POOL "pkinit_pool"
92 #define KRB5_CONF_PKINIT_REQUIRE_CRL_CHECKING "pkinit_require_crl_checking"
93 #define KRB5_CONF_PKINIT_REVOKE "pkinit_revoke"
94 #define KRB5_CONF_PKINIT_WIN2K "pkinit_win2k"
95 #define KRB5_CONF_PKINIT_WIN2K_REQUIRE_BINDING "pkinit_win2k_require_binding"
97 /* Make pkiDebug(fmt,...) print, or not. */
99 #define pkiDebug printf
101 /* Still evaluates for side effects. */
102 static inline void pkiDebug (const char *fmt, ...) { }
103 /* This is better if the compiler doesn't inline variadic functions
104 well, but gcc will warn about "left-hand operand of comma
105 expression has no effect". Still evaluates for side effects. */
106 /* #define pkiDebug (void) */
109 /* Solaris compiler doesn't grok __FUNCTION__
110 * hack for now. Fix all the uses eventually. */
111 #define __FUNCTION__ __func__
113 /* Macros to deal with converting between various data types... */
114 #define PADATA_TO_KRB5DATA(pad, k5d) \
115 (k5d)->length = (pad)->length; (k5d)->data = (char *)(pad)->contents;
116 #define OCTETDATA_TO_KRB5DATA(octd, k5d) \
117 (k5d)->length = (octd)->length; (k5d)->data = (char *)(octd)->data;
119 extern const krb5_data dh_oid;
122 * notes about crypto contexts:
124 * the basic idea is that there are crypto contexts that live at
125 * both the plugin level and request level. the identity context (that
126 * keeps info about your own certs and such) is separate because
127 * it is needed at different levels for the kdc and and the client.
128 * (the kdc's identity is at the plugin level, the client's identity
129 * information could change per-request.)
130 * the identity context is meant to have the entity's cert,
131 * a list of trusted and intermediate cas, a list of crls, and any
132 * pkcs11 information. the req context is meant to have the
133 * received certificate and the DH related information. the plugin
134 * context is meant to have global crypto information, i.e., OIDs
135 * and constant DH parameter information.
139 * plugin crypto context should keep plugin common information,
140 * eg., OIDs, known DHparams
142 typedef struct _pkinit_plg_crypto_context *pkinit_plg_crypto_context;
145 * request crypto context should keep reqyest common information,
146 * eg., received credentials, DH parameters of this request
148 typedef struct _pkinit_req_crypto_context *pkinit_req_crypto_context;
151 * identity context should keep information about credentials
152 * for the request, eg., my credentials, trusted ca certs,
153 * intermediate ca certs, crls, pkcs11 info
155 typedef struct _pkinit_identity_crypto_context *pkinit_identity_crypto_context;
158 * this structure keeps information about the config options
160 typedef struct _pkinit_plg_opts {
161 int require_eku; /* require EKU checking (default is true) */
162 int accept_secondary_eku;/* accept secondary EKU (default is false) */
163 int allow_upn; /* allow UPN-SAN instead of pkinit-SAN */
164 int dh_or_rsa; /* selects DH or RSA based pkinit */
165 int require_crl_checking; /* require CRL for a CA (default is false) */
166 int dh_min_bits; /* minimum DH modulus size allowed */
170 * this structure keeps options used for a given request
172 typedef struct _pkinit_req_opts {
174 int accept_secondary_eku;
177 int require_crl_checking;
178 int dh_size; /* initial request DH modulus size (default=1024) */
179 int require_hostname_match;
181 int win2k_require_cksum;
185 * information about identity from config file or command line
188 typedef struct _pkinit_identity_opts {
192 char **intermediates;
195 char *dn_mapping_file;
199 #ifndef WITHOUT_PKCS11
200 char *p11_module_name;
203 char *cert_id_string;
206 } pkinit_identity_opts;
210 * Client's plugin context
212 struct _pkinit_context {
214 pkinit_plg_crypto_context cryptoctx;
215 pkinit_plg_opts *opts;
216 pkinit_identity_opts *idopts;
218 typedef struct _pkinit_context *pkinit_context;
221 * Client's per-request context
223 struct _pkinit_req_context {
225 pkinit_req_crypto_context cryptoctx;
226 pkinit_req_opts *opts;
227 pkinit_identity_crypto_context idctx;
228 pkinit_identity_opts *idopts;
229 krb5_preauthtype pa_type;
232 typedef struct _pkinit_req_context *pkinit_req_context;
235 * KDC's (per-realm) plugin context
237 struct _pkinit_kdc_context {
239 pkinit_plg_crypto_context cryptoctx;
240 pkinit_plg_opts *opts;
241 pkinit_identity_crypto_context idctx;
242 pkinit_identity_opts *idopts;
244 unsigned int realmname_len;
246 typedef struct _pkinit_kdc_context *pkinit_kdc_context;
249 * KDC's per-request context
251 struct _pkinit_kdc_req_context {
253 pkinit_req_crypto_context cryptoctx;
254 krb5_auth_pack *rcv_auth_pack;
255 krb5_auth_pack_draft9 *rcv_auth_pack9;
256 krb5_preauthtype pa_type;
258 typedef struct _pkinit_kdc_req_context *pkinit_kdc_req_context;
261 * Functions in pkinit_lib.c
264 krb5_error_code pkinit_init_req_opts(pkinit_req_opts **);
265 void pkinit_fini_req_opts(pkinit_req_opts *);
267 krb5_error_code pkinit_init_plg_opts(pkinit_plg_opts **);
268 void pkinit_fini_plg_opts(pkinit_plg_opts *);
270 krb5_error_code pkinit_init_identity_opts(pkinit_identity_opts **idopts);
271 void pkinit_fini_identity_opts(pkinit_identity_opts *idopts);
272 krb5_error_code pkinit_dup_identity_opts(pkinit_identity_opts *src_opts,
273 pkinit_identity_opts **dest_opts);
276 * Functions in pkinit_identity.c
278 char * idtype2string(int idtype);
279 char * catype2string(int catype);
281 krb5_error_code pkinit_identity_initialize
282 (krb5_context context, /* IN */
283 pkinit_plg_crypto_context plg_cryptoctx, /* IN */
284 pkinit_req_crypto_context req_cryptoctx, /* IN */
285 pkinit_identity_opts *idopts, /* IN */
286 pkinit_identity_crypto_context id_cryptoctx, /* IN/OUT */
287 int do_matching, /* IN */
288 krb5_principal princ); /* IN (optional) */
290 krb5_error_code pkinit_cert_matching
291 (krb5_context context,
292 pkinit_plg_crypto_context plg_cryptoctx,
293 pkinit_req_crypto_context req_cryptoctx,
294 pkinit_identity_crypto_context id_cryptoctx,
295 krb5_principal princ);
298 * initialization and free functions
300 void init_krb5_pa_pk_as_req(krb5_pa_pk_as_req **in);
301 void init_krb5_pa_pk_as_req_draft9(krb5_pa_pk_as_req_draft9 **in);
302 void init_krb5_reply_key_pack(krb5_reply_key_pack **in);
303 void init_krb5_reply_key_pack_draft9(krb5_reply_key_pack_draft9 **in);
305 void init_krb5_auth_pack(krb5_auth_pack **in);
306 void init_krb5_auth_pack_draft9(krb5_auth_pack_draft9 **in);
307 void init_krb5_pa_pk_as_rep(krb5_pa_pk_as_rep **in);
308 void init_krb5_pa_pk_as_rep_draft9(krb5_pa_pk_as_rep_draft9 **in);
309 void init_krb5_subject_pk_info(krb5_subject_pk_info **in);
311 void free_krb5_pa_pk_as_req(krb5_pa_pk_as_req **in);
312 void free_krb5_pa_pk_as_req_draft9(krb5_pa_pk_as_req_draft9 **in);
313 void free_krb5_reply_key_pack(krb5_reply_key_pack **in);
314 void free_krb5_reply_key_pack_draft9(krb5_reply_key_pack_draft9 **in);
315 void free_krb5_auth_pack(krb5_auth_pack **in);
316 void free_krb5_auth_pack_draft9(krb5_context, krb5_auth_pack_draft9 **in);
317 void free_krb5_pa_pk_as_rep(krb5_pa_pk_as_rep **in);
318 void free_krb5_pa_pk_as_rep_draft9(krb5_pa_pk_as_rep_draft9 **in);
319 void free_krb5_external_principal_identifier(krb5_external_principal_identifier ***in);
320 void free_krb5_algorithm_identifiers(krb5_algorithm_identifier ***in);
321 void free_krb5_algorithm_identifier(krb5_algorithm_identifier *in);
322 void free_krb5_kdc_dh_key_info(krb5_kdc_dh_key_info **in);
323 void free_krb5_subject_pk_info(krb5_subject_pk_info **in);
324 krb5_error_code pkinit_copy_krb5_data(krb5_data *dst, const krb5_data *src);
328 * Functions in pkinit_profile.c
330 krb5_error_code pkinit_kdcdefault_strings
331 (krb5_context context, const char *realmname, const char *option,
333 krb5_error_code pkinit_kdcdefault_string
334 (krb5_context context, const char *realmname, const char *option,
336 krb5_error_code pkinit_kdcdefault_boolean
337 (krb5_context context, const char *realmname, const char *option,
338 int default_value, int *ret_value);
339 krb5_error_code pkinit_kdcdefault_integer
340 (krb5_context context, const char *realmname, const char *option,
341 int default_value, int *ret_value);
344 krb5_error_code pkinit_libdefault_strings
345 (krb5_context context, const krb5_data *realm,
346 const char *option, char ***ret_value);
347 krb5_error_code pkinit_libdefault_string
348 (krb5_context context, const krb5_data *realm,
349 const char *option, char **ret_value);
350 krb5_error_code pkinit_libdefault_boolean
351 (krb5_context context, const krb5_data *realm, const char *option,
352 int default_value, int *ret_value);
353 krb5_error_code pkinit_libdefault_integer
354 (krb5_context context, const krb5_data *realm, const char *option,
355 int default_value, int *ret_value);
358 * debugging functions
360 void print_buffer(const unsigned char *, unsigned int);
361 void print_buffer_bin(unsigned char *, unsigned int, char *);
364 * Now get crypto function declarations
366 #include "pkinit_crypto.h"
368 #endif /* _PKINIT_H */