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