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
43const krb5_octet_data
44	dh_oid = { 0, 7, (unsigned char *)"\x2A\x86\x48\xce\x3e\x02\x01" };
45
46
47krb5_error_code
48pkinit_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
72void
73pkinit_fini_req_opts(pkinit_req_opts *opts)
74{
75    if (opts != NULL)
76	free(opts);
77    return;
78}
79
80krb5_error_code
81pkinit_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
104void
105pkinit_fini_plg_opts(pkinit_plg_opts *opts)
106{
107    if (opts != NULL)
108	free(opts);
109    return;
110}
111
112void
113free_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
125void
126free_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
140void
141free_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
151void
152free_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
160void
161free_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
180void
181free_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
189void
190free_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
208void
209free_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
217void
218free_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
235void
236free_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
261void
262free_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
275void
276free_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
287void
288free_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
299void
300free_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
310void
311free_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
319void
320init_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
331void
332init_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
345void
346init_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
356void
357init_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
365void
366init_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
377void
378init_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
385void
386init_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
398void
399init_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
409void
410init_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
419void
420init_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
430krb5_error_code
431pkinit_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 */
449void
450print_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
462void
463print_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