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 #include <stdio.h>
32 #include <stdlib.h>
33 #include <errno.h>
34 #include <unistd.h>
35 #include <string.h>
36 #include <ctype.h>
37 #include <assert.h>
38 
39 #include "pkinit.h"
40 
41 #define FAKECERT
42 
43 const krb5_octet_data
44 	dh_oid = { 0, 7, (unsigned char *)"\x2A\x86\x48\xce\x3e\x02\x01" };
45 
46 
47 krb5_error_code
pkinit_init_req_opts(pkinit_req_opts ** reqopts)48 pkinit_init_req_opts(pkinit_req_opts **reqopts)
49 {
50     krb5_error_code retval = ENOMEM;
51     pkinit_req_opts *opts = NULL;
52 
53     *reqopts = NULL;
54     opts = (pkinit_req_opts *) calloc(1, sizeof(pkinit_req_opts));
55     if (opts == NULL)
56 	return retval;
57 
58     opts->require_eku = 1;
59     opts->accept_secondary_eku = 0;
60     opts->allow_upn = 0;
61     opts->dh_or_rsa = DH_PROTOCOL;
62     opts->require_crl_checking = 0;
63     opts->dh_size = PKINIT_DEFAULT_DH_MIN_BITS;
64     opts->win2k_target = 0;
65     opts->win2k_require_cksum = 0;
66 
67     *reqopts = opts;
68 
69     return 0;
70 }
71 
72 void
pkinit_fini_req_opts(pkinit_req_opts * opts)73 pkinit_fini_req_opts(pkinit_req_opts *opts)
74 {
75     if (opts != NULL)
76 	free(opts);
77     return;
78 }
79 
80 krb5_error_code
pkinit_init_plg_opts(pkinit_plg_opts ** plgopts)81 pkinit_init_plg_opts(pkinit_plg_opts **plgopts)
82 {
83     krb5_error_code retval = ENOMEM;
84     pkinit_plg_opts *opts = NULL;
85 
86     *plgopts = NULL;
87     opts = (pkinit_plg_opts *) calloc(1, sizeof(pkinit_plg_opts));
88     if (opts == NULL)
89 	return retval;
90 
91     opts->require_eku = 1;
92     opts->accept_secondary_eku = 0;
93     opts->dh_or_rsa = DH_PROTOCOL;
94     opts->allow_upn = 0;
95     opts->require_crl_checking = 0;
96 
97     opts->dh_min_bits = PKINIT_DEFAULT_DH_MIN_BITS;
98 
99     *plgopts = opts;
100 
101     return 0;
102 }
103 
104 void
pkinit_fini_plg_opts(pkinit_plg_opts * opts)105 pkinit_fini_plg_opts(pkinit_plg_opts *opts)
106 {
107     if (opts != NULL)
108 	free(opts);
109     return;
110 }
111 
112 void
free_krb5_pa_pk_as_req(krb5_pa_pk_as_req ** in)113 free_krb5_pa_pk_as_req(krb5_pa_pk_as_req **in)
114 {
115     if (*in == NULL) return;
116     if ((*in)->signedAuthPack.data != NULL)
117 	free((*in)->signedAuthPack.data);
118     if ((*in)->trustedCertifiers != NULL)
119 	free_krb5_external_principal_identifier(&(*in)->trustedCertifiers);
120     if ((*in)->kdcPkId.data != NULL)
121 	free((*in)->kdcPkId.data);
122     free(*in);
123 }
124 
125 void
free_krb5_pa_pk_as_req_draft9(krb5_pa_pk_as_req_draft9 ** in)126 free_krb5_pa_pk_as_req_draft9(krb5_pa_pk_as_req_draft9 **in)
127 {
128     if (*in == NULL) return;
129     if ((*in)->signedAuthPack.data != NULL)
130 	free((*in)->signedAuthPack.data);
131     if ((*in)->kdcCert.data != NULL)
132 	free((*in)->kdcCert.data);
133     if ((*in)->encryptionCert.data != NULL)
134 	free((*in)->encryptionCert.data);
135     if ((*in)->trustedCertifiers != NULL)
136 	free_krb5_trusted_ca(&(*in)->trustedCertifiers);
137     free(*in);
138 }
139 
140 void
free_krb5_reply_key_pack(krb5_reply_key_pack ** in)141 free_krb5_reply_key_pack(krb5_reply_key_pack **in)
142 {
143     if (*in == NULL) return;
144     if ((*in)->replyKey.contents != NULL)
145 	free((*in)->replyKey.contents);
146     if ((*in)->asChecksum.contents != NULL)
147 	free((*in)->asChecksum.contents);
148     free(*in);
149 }
150 
151 void
free_krb5_reply_key_pack_draft9(krb5_reply_key_pack_draft9 ** in)152 free_krb5_reply_key_pack_draft9(krb5_reply_key_pack_draft9 **in)
153 {
154     if (*in == NULL) return;
155     if ((*in)->replyKey.contents != NULL)
156 	free((*in)->replyKey.contents);
157     free(*in);
158 }
159 
160 void
free_krb5_auth_pack(krb5_auth_pack ** in)161 free_krb5_auth_pack(krb5_auth_pack **in)
162 {
163     if ((*in) == NULL) return;
164     if ((*in)->clientPublicValue != NULL) {
165 	if ((*in)->clientPublicValue->algorithm.algorithm.data != NULL)
166 	    free((*in)->clientPublicValue->algorithm.algorithm.data);
167 	if ((*in)->clientPublicValue->algorithm.parameters.data != NULL)
168 	    free((*in)->clientPublicValue->algorithm.parameters.data);
169 	if ((*in)->clientPublicValue->subjectPublicKey.data != NULL)
170 	    free((*in)->clientPublicValue->subjectPublicKey.data);
171 	free((*in)->clientPublicValue);
172     }
173     if ((*in)->pkAuthenticator.paChecksum.contents != NULL)
174 	free((*in)->pkAuthenticator.paChecksum.contents);
175     if ((*in)->supportedCMSTypes != NULL)
176 	free_krb5_algorithm_identifiers(&((*in)->supportedCMSTypes));
177     free(*in);
178 }
179 
180 void
free_krb5_auth_pack_draft9(krb5_context context,krb5_auth_pack_draft9 ** in)181 free_krb5_auth_pack_draft9(krb5_context context,
182 				krb5_auth_pack_draft9 **in)
183 {
184     if ((*in) == NULL) return;
185     krb5_free_principal(context, (*in)->pkAuthenticator.kdcName);
186     free(*in);
187 }
188 
189 void
free_krb5_pa_pk_as_rep(krb5_pa_pk_as_rep ** in)190 free_krb5_pa_pk_as_rep(krb5_pa_pk_as_rep **in)
191 {
192     if (*in == NULL) return;
193     switch ((*in)->choice) {
194 	case choice_pa_pk_as_rep_dhInfo:
195 	    if ((*in)->u.dh_Info.dhSignedData.data != NULL)
196 		free((*in)->u.dh_Info.dhSignedData.data);
197 	    break;
198 	case choice_pa_pk_as_rep_encKeyPack:
199 	    if ((*in)->u.encKeyPack.data != NULL)
200 		free((*in)->u.encKeyPack.data);
201 	    break;
202 	default:
203 	    break;
204     }
205     free(*in);
206 }
207 
208 void
free_krb5_pa_pk_as_rep_draft9(krb5_pa_pk_as_rep_draft9 ** in)209 free_krb5_pa_pk_as_rep_draft9(krb5_pa_pk_as_rep_draft9 **in)
210 {
211     if (*in == NULL) return;
212     if ((*in)->u.encKeyPack.data != NULL)
213 	free((*in)->u.encKeyPack.data);
214     free(*in);
215 }
216 
217 void
free_krb5_external_principal_identifier(krb5_external_principal_identifier *** in)218 free_krb5_external_principal_identifier(krb5_external_principal_identifier ***in)
219 {
220     int i = 0;
221     if (*in == NULL) return;
222     while ((*in)[i] != NULL) {
223 	if ((*in)[i]->subjectName.data != NULL)
224 	    free((*in)[i]->subjectName.data);
225 	if ((*in)[i]->issuerAndSerialNumber.data != NULL)
226 	    free((*in)[i]->issuerAndSerialNumber.data);
227 	if ((*in)[i]->subjectKeyIdentifier.data != NULL)
228 	    free((*in)[i]->subjectKeyIdentifier.data);
229 	free((*in)[i]);
230 	i++;
231     }
232     free(*in);
233 }
234 
235 void
free_krb5_trusted_ca(krb5_trusted_ca *** in)236 free_krb5_trusted_ca(krb5_trusted_ca ***in)
237 {
238     int i = 0;
239     if (*in == NULL) return;
240     while ((*in)[i] != NULL) {
241 	switch((*in)[i]->choice) {
242 	    case choice_trusted_cas_principalName:
243 		break;
244 	    case choice_trusted_cas_caName:
245 		if ((*in)[i]->u.caName.data != NULL)
246 		    free((*in)[i]->u.caName.data);
247 		break;
248 	    case choice_trusted_cas_issuerAndSerial:
249 		if ((*in)[i]->u.issuerAndSerial.data != NULL)
250 		    free((*in)[i]->u.issuerAndSerial.data);
251 		break;
252 	    case choice_trusted_cas_UNKNOWN:
253 		break;
254 	}
255 	free((*in)[i]);
256 	i++;
257     }
258     free(*in);
259 }
260 
261 void
free_krb5_typed_data(krb5_typed_data *** in)262 free_krb5_typed_data(krb5_typed_data ***in)
263 {
264     int i = 0;
265     if (*in == NULL) return;
266     while ((*in)[i] != NULL) {
267 	if ((*in)[i]->data != NULL)
268 	    free((*in)[i]->data);
269 	free((*in)[i]);
270 	i++;
271     }
272     free(*in);
273 }
274 
275 void
free_krb5_algorithm_identifier(krb5_algorithm_identifier * in)276 free_krb5_algorithm_identifier(krb5_algorithm_identifier *in)
277 {
278     if (in == NULL)
279 	return;
280     if (in->algorithm.data != NULL)
281 	free(in->algorithm.data);
282     if (in->parameters.data != NULL)
283 	free(in->parameters.data);
284     free(in);
285 }
286 
287 void
free_krb5_algorithm_identifiers(krb5_algorithm_identifier *** in)288 free_krb5_algorithm_identifiers(krb5_algorithm_identifier ***in)
289 {
290     int i;
291     if (in == NULL || *in == NULL)
292 	return;
293     for (i = 0; (*in)[i] != NULL; i++) {
294 	free_krb5_algorithm_identifier((*in)[i]);
295     }
296     free(*in);
297 }
298 
299 void
free_krb5_subject_pk_info(krb5_subject_pk_info ** in)300 free_krb5_subject_pk_info(krb5_subject_pk_info **in)
301 {
302     if ((*in) == NULL) return;
303     if ((*in)->algorithm.parameters.data != NULL)
304 	free((*in)->algorithm.parameters.data);
305     if ((*in)->subjectPublicKey.data != NULL)
306 	free((*in)->subjectPublicKey.data);
307     free(*in);
308 }
309 
310 void
free_krb5_kdc_dh_key_info(krb5_kdc_dh_key_info ** in)311 free_krb5_kdc_dh_key_info(krb5_kdc_dh_key_info **in)
312 {
313     if (*in == NULL) return;
314     if ((*in)->subjectPublicKey.data != NULL)
315 	free((*in)->subjectPublicKey.data);
316     free(*in);
317 }
318 
319 void
init_krb5_pa_pk_as_req(krb5_pa_pk_as_req ** in)320 init_krb5_pa_pk_as_req(krb5_pa_pk_as_req **in)
321 {
322     (*in) = malloc(sizeof(krb5_pa_pk_as_req));
323     if ((*in) == NULL) return;
324     (*in)->signedAuthPack.data = NULL;
325     (*in)->signedAuthPack.length = 0;
326     (*in)->trustedCertifiers = NULL;
327     (*in)->kdcPkId.data = NULL;
328     (*in)->kdcPkId.length = 0;
329 }
330 
331 void
init_krb5_pa_pk_as_req_draft9(krb5_pa_pk_as_req_draft9 ** in)332 init_krb5_pa_pk_as_req_draft9(krb5_pa_pk_as_req_draft9 **in)
333 {
334     (*in) = malloc(sizeof(krb5_pa_pk_as_req_draft9));
335     if ((*in) == NULL) return;
336     (*in)->signedAuthPack.data = NULL;
337     (*in)->signedAuthPack.length = 0;
338     (*in)->trustedCertifiers = NULL;
339     (*in)->kdcCert.data = NULL;
340     (*in)->kdcCert.length = 0;
341     (*in)->encryptionCert.data = NULL;
342     (*in)->encryptionCert.length = 0;
343 }
344 
345 void
init_krb5_reply_key_pack(krb5_reply_key_pack ** in)346 init_krb5_reply_key_pack(krb5_reply_key_pack **in)
347 {
348     (*in) = malloc(sizeof(krb5_reply_key_pack));
349     if ((*in) == NULL) return;
350     (*in)->replyKey.contents = NULL;
351     (*in)->replyKey.length = 0;
352     (*in)->asChecksum.contents = NULL;
353     (*in)->asChecksum.length = 0;
354 }
355 
356 void
init_krb5_reply_key_pack_draft9(krb5_reply_key_pack_draft9 ** in)357 init_krb5_reply_key_pack_draft9(krb5_reply_key_pack_draft9 **in)
358 {
359     (*in) = malloc(sizeof(krb5_reply_key_pack_draft9));
360     if ((*in) == NULL) return;
361     (*in)->replyKey.contents = NULL;
362     (*in)->replyKey.length = 0;
363 }
364 
365 void
init_krb5_auth_pack(krb5_auth_pack ** in)366 init_krb5_auth_pack(krb5_auth_pack **in)
367 {
368     (*in) = malloc(sizeof(krb5_auth_pack));
369     if ((*in) == NULL) return;
370     (*in)->clientPublicValue = NULL;
371     (*in)->supportedCMSTypes = NULL;
372     (*in)->clientDHNonce.length = 0;
373     (*in)->clientDHNonce.data = NULL;
374     (*in)->pkAuthenticator.paChecksum.contents = NULL;
375 }
376 
377 void
init_krb5_auth_pack_draft9(krb5_auth_pack_draft9 ** in)378 init_krb5_auth_pack_draft9(krb5_auth_pack_draft9 **in)
379 {
380     (*in) = malloc(sizeof(krb5_auth_pack_draft9));
381     if ((*in) == NULL) return;
382     (*in)->clientPublicValue = NULL;
383 }
384 
385 void
init_krb5_pa_pk_as_rep(krb5_pa_pk_as_rep ** in)386 init_krb5_pa_pk_as_rep(krb5_pa_pk_as_rep **in)
387 {
388     (*in) = malloc(sizeof(krb5_pa_pk_as_rep));
389     if ((*in) == NULL) return;
390     (*in)->u.dh_Info.serverDHNonce.length = 0;
391     (*in)->u.dh_Info.serverDHNonce.data = NULL;
392     (*in)->u.dh_Info.dhSignedData.length = 0;
393     (*in)->u.dh_Info.dhSignedData.data = NULL;
394     (*in)->u.encKeyPack.length = 0;
395     (*in)->u.encKeyPack.data = NULL;
396 }
397 
398 void
init_krb5_pa_pk_as_rep_draft9(krb5_pa_pk_as_rep_draft9 ** in)399 init_krb5_pa_pk_as_rep_draft9(krb5_pa_pk_as_rep_draft9 **in)
400 {
401     (*in) = malloc(sizeof(krb5_pa_pk_as_rep_draft9));
402     if ((*in) == NULL) return;
403     (*in)->u.dhSignedData.length = 0;
404     (*in)->u.dhSignedData.data = NULL;
405     (*in)->u.encKeyPack.length = 0;
406     (*in)->u.encKeyPack.data = NULL;
407 }
408 
409 void
init_krb5_typed_data(krb5_typed_data ** in)410 init_krb5_typed_data(krb5_typed_data **in)
411 {
412     (*in) = malloc(sizeof(krb5_typed_data));
413     if ((*in) == NULL) return;
414     (*in)->type = 0;
415     (*in)->length = 0;
416     (*in)->data = NULL;
417 }
418 
419 void
init_krb5_subject_pk_info(krb5_subject_pk_info ** in)420 init_krb5_subject_pk_info(krb5_subject_pk_info **in)
421 {
422     (*in) = malloc(sizeof(krb5_subject_pk_info));
423     if ((*in) == NULL) return;
424     (*in)->algorithm.parameters.data = NULL;
425     (*in)->algorithm.parameters.length = 0;
426     (*in)->subjectPublicKey.data = NULL;
427     (*in)->subjectPublicKey.length = 0;
428 }
429 
430 krb5_error_code
pkinit_copy_krb5_octet_data(krb5_octet_data * dst,const krb5_octet_data * src)431 pkinit_copy_krb5_octet_data(krb5_octet_data *dst, const krb5_octet_data *src)
432 {
433     if (dst == NULL || src == NULL)
434 	return EINVAL;
435     if (src->data == NULL) {
436 	dst->data = NULL;
437 	dst->length = 0;
438 	return 0;
439     }
440     dst->data = malloc(src->length);
441     if (dst->data == NULL)
442 	return ENOMEM;
443     (void) memcpy(dst->data, src->data, src->length);
444     dst->length = src->length;
445     return 0;
446 }
447 
448 /* debugging functions */
449 void
print_buffer(unsigned char * buf,unsigned int len)450 print_buffer(unsigned char *buf, unsigned int len)
451 {
452     int i = 0;
453     /* Solaris Kerberos: len is unsigned (lint) */
454     if (len == 0)
455 	return;
456 
457     for (i = 0; i < len; i++)
458 	pkiDebug("%02x ", buf[i]);
459     pkiDebug("\n");
460 }
461 
462 void
print_buffer_bin(unsigned char * buf,unsigned int len,char * filename)463 print_buffer_bin(unsigned char *buf, unsigned int len, char *filename)
464 {
465     FILE *f = NULL;
466     int i = 0;
467 
468     /* Solaris Kerberos: len is unsigned (lint) */
469     if (len == 0 || filename == NULL)
470 	return;
471 
472     if ((f = fopen(filename, "w")) == NULL)
473 	return;
474 
475     for (i = 0; i < len; i++)
476 	(void) fputc(buf[i], f);
477 
478     (void) fclose(f);
479 }
480