1 /*
2  * COPYRIGHT (C) 2006,2007
3  * THE REGENTS OF THE UNIVERSITY OF MICHIGAN
4  * ALL RIGHTS RESERVED
5  *
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
15  * also be included.
16  *
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
28  * SUCH DAMAGES.
29  */
30 
31 #ifndef _PKINIT_H
32 #define _PKINIT_H
33 
34 /* Solaris Kerberos */
35 #include <preauth_plugin.h>
36 #include <k5-int-pkinit.h>
37 #include <profile.h>
38 #include "pkinit_accessor.h"
39 
40 /*
41  * It is anticipated that all the special checks currently
42  * required when talking to a Longhorn server will go away
43  * by the time it is officially released and all references
44  * to the longhorn global can be removed and any code
45  * #ifdef'd with LONGHORN_BETA_COMPAT can be removed.
46  * And this #define!
47  */
48 #define LONGHORN_BETA_COMPAT 1
49 #ifdef LONGHORN_BETA_COMPAT
50 extern int longhorn;	    /* XXX Talking to a Longhorn server? */
51 #endif
52 
53 
54 #ifndef WITHOUT_PKCS11
55 /* Solaris Kerberos */
56 #include <security/cryptoki.h>
57 #include <security/pkcs11.h>
58 
59 /* Solaris Kerberos */
60 #define PKCS11_MODNAME "/usr/lib/libpkcs11.so"
61 
62 #define PK_SIGLEN_GUESS 1000
63 #define PK_NOSLOT 999999
64 #endif
65 
66 #define DH_PROTOCOL     1
67 #define RSA_PROTOCOL    2
68 
69 #define TD_TRUSTED_CERTIFIERS 104
70 #define TD_INVALID_CERTIFICATES 105
71 #define TD_DH_PARAMETERS 109
72 
73 #define PKINIT_CTX_MAGIC	0x05551212
74 #define PKINIT_REQ_CTX_MAGIC	0xdeadbeef
75 
76 #define PKINIT_DEFAULT_DH_MIN_BITS  2048
77 
78 /* Make pkiDebug(fmt,...) print, or not.  */
79 #ifdef DEBUG
80 #define pkiDebug	printf
81 #else
82 /* Still evaluates for side effects.  */
83 /* ARGSUSED */
84 static void pkiDebug (const char *fmt, ...) { }
85 /* This is better if the compiler doesn't inline variadic functions
86    well, but gcc will warn about "left-hand operand of comma
87    expression has no effect".  Still evaluates for side effects.  */
88 /* #define pkiDebug	(void) */
89 #endif
90 
91 /* Solaris Kerberos */
92 #if (__STDC_VERSION__ >= 199901L) || \
93     (defined(__SUNPRO_C) && defined(__C99FEATURES__))
94 #define __FUNCTION__ __func__
95 #else
96 #define __FUNCTION__ ""
97 #endif
98 
99 
100 /* Macros to deal with converting between various data types... */
101 #define PADATA_TO_KRB5DATA(pad, k5d) \
102     (k5d)->length = (pad)->length; (k5d)->data = (char *)(pad)->contents;
103 #define OCTETDATA_TO_KRB5DATA(octd, k5d) \
104     (k5d)->length = (octd)->length; (k5d)->data = (char *)(octd)->data;
105 
106 extern const krb5_octet_data dh_oid;
107 
108 /*
109  * notes about crypto contexts:
110  *
111  * the basic idea is that there are crypto contexts that live at
112  * both the plugin level and request level. the identity context (that
113  * keeps info about your own certs and such) is separate because
114  * it is needed at different levels for the kdc and and the client.
115  * (the kdc's identity is at the plugin level, the client's identity
116  * information could change per-request.)
117  * the identity context is meant to have the entity's cert,
118  * a list of trusted and intermediate cas, a list of crls, and any
119  * pkcs11 information.  the req context is meant to have the
120  * received certificate and the DH related information. the plugin
121  * context is meant to have global crypto information, i.e., OIDs
122  * and constant DH parameter information.
123  */
124 
125 /*
126  * plugin crypto context should keep plugin common information,
127  * eg., OIDs, known DHparams
128  */
129 typedef struct _pkinit_plg_crypto_context *pkinit_plg_crypto_context;
130 
131 /*
132  * request crypto context should keep reqyest common information,
133  * eg., received credentials, DH parameters of this request
134  */
135 typedef struct _pkinit_req_crypto_context *pkinit_req_crypto_context;
136 
137 /*
138  * identity context should keep information about credentials
139  * for the request, eg., my credentials, trusted ca certs,
140  * intermediate ca certs, crls, pkcs11 info
141  */
142 typedef struct _pkinit_identity_crypto_context *pkinit_identity_crypto_context;
143 
144 /*
145  * this structure keeps information about the config options
146  */
147 typedef struct _pkinit_plg_opts {
148     int require_eku;	    /* require EKU checking (default is true) */
149     int accept_secondary_eku;/* accept secondary EKU (default is false) */
150     int allow_upn;	    /* allow UPN-SAN instead of pkinit-SAN */
151     int dh_or_rsa;	    /* selects DH or RSA based pkinit */
152     int require_crl_checking; /* require CRL for a CA (default is false) */
153     int dh_min_bits;	    /* minimum DH modulus size allowed */
154 } pkinit_plg_opts;
155 
156 /*
157  * this structure keeps options used for a given request
158  */
159 typedef struct _pkinit_req_opts {
160     int require_eku;
161     int accept_secondary_eku;
162     int allow_upn;
163     int dh_or_rsa;
164     int require_crl_checking;
165     int dh_size;	    /* initial request DH modulus size (default=1024) */
166     int require_hostname_match;
167     int win2k_target;
168     int win2k_require_cksum;
169 } pkinit_req_opts;
170 
171 /*
172  * information about identity from config file or command line
173  */
174 
175 #define PKINIT_ID_OPT_USER_IDENTITY	1
176 #define PKINIT_ID_OPT_ANCHOR_CAS	2
177 #define PKINIT_ID_OPT_INTERMEDIATE_CAS	3
178 #define PKINIT_ID_OPT_CRLS		4
179 #define PKINIT_ID_OPT_OCSP		5
180 #define PKINIT_ID_OPT_DN_MAPPING	6   /* XXX ? */
181 
182 typedef struct _pkinit_identity_opts {
183     char *identity;
184     char **identity_alt;
185     char **anchors;
186     char **intermediates;
187     char **crls;
188     char *ocsp;
189     char *dn_mapping_file;
190     int  idtype;
191     char *cert_filename;
192     char *key_filename;
193 #ifndef WITHOUT_PKCS11
194     char *p11_module_name;
195     CK_SLOT_ID slotid;
196     char *token_label;
197     char *cert_id_string;
198     char *cert_label;
199 #endif
200 } pkinit_identity_opts;
201 
202 
203 /*
204  * Client's plugin context
205  */
206 struct _pkinit_context {
207     int magic;
208     pkinit_plg_crypto_context cryptoctx;
209     pkinit_plg_opts *opts;
210     pkinit_identity_opts *idopts;
211 };
212 typedef struct _pkinit_context *pkinit_context;
213 
214 /*
215  * Client's per-request context
216  */
217 struct _pkinit_req_context {
218     int magic;
219     pkinit_req_crypto_context cryptoctx;
220     pkinit_req_opts *opts;
221     pkinit_identity_crypto_context idctx;
222     pkinit_identity_opts *idopts;
223     krb5_preauthtype pa_type;
224 };
225 typedef struct _pkinit_kdc_context *pkinit_kdc_context;
226 
227 /*
228  * KDC's (per-realm) plugin context
229  */
230 struct _pkinit_kdc_context {
231     int magic;
232     pkinit_plg_crypto_context cryptoctx;
233     pkinit_plg_opts *opts;
234     pkinit_identity_crypto_context idctx;
235     pkinit_identity_opts *idopts;
236     char *realmname;
237     unsigned int realmname_len;
238 };
239 typedef struct _pkinit_req_context *pkinit_req_context;
240 
241 /*
242  * KDC's per-request context
243  */
244 struct _pkinit_kdc_req_context {
245     int magic;
246     pkinit_req_crypto_context cryptoctx;
247     krb5_auth_pack *rcv_auth_pack;
248     krb5_auth_pack_draft9 *rcv_auth_pack9;
249     krb5_preauthtype pa_type;
250 };
251 typedef struct _pkinit_kdc_req_context *pkinit_kdc_req_context;
252 
253 /*
254  * Functions in pkinit_lib.c
255  */
256 
257 krb5_error_code pkinit_init_req_opts(pkinit_req_opts **);
258 void pkinit_fini_req_opts(pkinit_req_opts *);
259 
260 krb5_error_code pkinit_init_plg_opts(pkinit_plg_opts **);
261 void pkinit_fini_plg_opts(pkinit_plg_opts *);
262 
263 krb5_error_code pkinit_init_identity_opts(pkinit_identity_opts **idopts);
264 void pkinit_fini_identity_opts(pkinit_identity_opts *idopts);
265 krb5_error_code pkinit_dup_identity_opts(pkinit_identity_opts *src_opts,
266 					 pkinit_identity_opts **dest_opts);
267 
268 /*
269  * Functions in pkinit_identity.c
270  */
271 char * idtype2string(int idtype);
272 char * catype2string(int catype);
273 
274 krb5_error_code pkinit_identity_initialize
275 	(krb5_context context,				/* IN */
276 	 pkinit_plg_crypto_context plg_cryptoctx,	/* IN */
277 	 pkinit_req_crypto_context req_cryptoctx,	/* IN */
278 	 pkinit_identity_opts *idopts,			/* IN */
279 	 pkinit_identity_crypto_context id_cryptoctx,	/* IN/OUT */
280 	 int do_matching,				/* IN */
281 	 krb5_principal princ);				/* IN (optional) */
282 
283 krb5_error_code pkinit_cert_matching
284 	(krb5_context context,
285 	pkinit_plg_crypto_context plg_cryptoctx,
286 	pkinit_req_crypto_context req_cryptoctx,
287 	pkinit_identity_crypto_context id_cryptoctx,
288 	krb5_principal princ);
289 
290 /*
291  * initialization and free functions
292  */
293 void init_krb5_pa_pk_as_req(krb5_pa_pk_as_req **in);
294 void init_krb5_pa_pk_as_req_draft9(krb5_pa_pk_as_req_draft9 **in);
295 void init_krb5_reply_key_pack(krb5_reply_key_pack **in);
296 void init_krb5_reply_key_pack_draft9(krb5_reply_key_pack_draft9 **in);
297 
298 void init_krb5_auth_pack(krb5_auth_pack **in);
299 void init_krb5_auth_pack_draft9(krb5_auth_pack_draft9 **in);
300 void init_krb5_pa_pk_as_rep(krb5_pa_pk_as_rep **in);
301 void init_krb5_pa_pk_as_rep_draft9(krb5_pa_pk_as_rep_draft9 **in);
302 void init_krb5_typed_data(krb5_typed_data **in);
303 void init_krb5_subject_pk_info(krb5_subject_pk_info **in);
304 
305 void free_krb5_pa_pk_as_req(krb5_pa_pk_as_req **in);
306 void free_krb5_pa_pk_as_req_draft9(krb5_pa_pk_as_req_draft9 **in);
307 void free_krb5_reply_key_pack(krb5_reply_key_pack **in);
308 void free_krb5_reply_key_pack_draft9(krb5_reply_key_pack_draft9 **in);
309 void free_krb5_auth_pack(krb5_auth_pack **in);
310 void free_krb5_auth_pack_draft9(krb5_context, krb5_auth_pack_draft9 **in);
311 void free_krb5_pa_pk_as_rep(krb5_pa_pk_as_rep **in);
312 void free_krb5_pa_pk_as_rep_draft9(krb5_pa_pk_as_rep_draft9 **in);
313 void free_krb5_external_principal_identifier(krb5_external_principal_identifier ***in);
314 void free_krb5_trusted_ca(krb5_trusted_ca ***in);
315 void free_krb5_typed_data(krb5_typed_data ***in);
316 void free_krb5_algorithm_identifiers(krb5_algorithm_identifier ***in);
317 void free_krb5_algorithm_identifier(krb5_algorithm_identifier *in);
318 void free_krb5_kdc_dh_key_info(krb5_kdc_dh_key_info **in);
319 void free_krb5_subject_pk_info(krb5_subject_pk_info **in);
320 krb5_error_code pkinit_copy_krb5_octet_data(krb5_octet_data *dst, const krb5_octet_data *src);
321 
322 
323 /*
324  * Functions in pkinit_profile.c
325  */
326 krb5_error_code pkinit_kdcdefault_strings
327 	(krb5_context context, const char *realmname, const char *option,
328 	 char ***ret_value);
329 krb5_error_code pkinit_kdcdefault_string
330 	(krb5_context context, const char *realmname, const char *option,
331 	 char **ret_value);
332 krb5_error_code pkinit_kdcdefault_boolean
333 	(krb5_context context, const char *realmname, const char *option,
334 	 int default_value, int *ret_value);
335 krb5_error_code pkinit_kdcdefault_integer
336 	(krb5_context context, const char *realmname, const char *option,
337 	 int default_value, int *ret_value);
338 
339 
340 krb5_error_code pkinit_libdefault_strings
341 	(krb5_context context, const krb5_data *realm,
342 	 const char *option, char ***ret_value);
343 krb5_error_code pkinit_libdefault_string
344 	(krb5_context context, const krb5_data *realm,
345 	 const char *option, char **ret_value);
346 krb5_error_code pkinit_libdefault_boolean
347 	(krb5_context context, const krb5_data *realm, const char *option,
348 	 int default_value, int *ret_value);
349 krb5_error_code pkinit_libdefault_integer
350 	(krb5_context context, const krb5_data *realm, const char *option,
351 	 int default_value, int *ret_value);
352 
353 /*
354  * debugging functions
355  */
356 void print_buffer(unsigned char *, unsigned int);
357 void print_buffer_bin(unsigned char *, unsigned int, char *);
358 
359 /*
360  * Now get crypto function declarations
361  */
362 #include "pkinit_crypto.h"
363 
364 #endif	/* _PKINIT_H */
365