1 /*
2 * COPYRIGHT (C) 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 /*
32 * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
33 */
34
35 #include <errno.h>
36 #include <string.h>
37 #include <stdio.h>
38 #include <stdlib.h>
39 #include <dlfcn.h>
40 #include <unistd.h>
41 #include <dirent.h>
42
43 #include <libintl.h>
44
45 #include "pkinit.h"
46
47 static void
free_list(char ** list)48 free_list(char **list)
49 {
50 int i;
51
52 if (list == NULL)
53 return;
54
55 for (i = 0; list[i] != NULL; i++)
56 free(list[i]);
57 free(list);
58 }
59
60 static krb5_error_code
copy_list(char *** dst,char ** src)61 copy_list(char ***dst, char **src)
62 {
63 int i;
64 char **newlist;
65
66 if (dst == NULL)
67 return EINVAL;
68 *dst = NULL;
69
70 if (src == NULL)
71 return 0;
72
73 for (i = 0; src[i] != NULL; i++);
74
75 newlist = calloc(1, (i + 1) * sizeof(*newlist));
76 if (newlist == NULL)
77 return ENOMEM;
78
79 for (i = 0; src[i] != NULL; i++) {
80 newlist[i] = strdup(src[i]);
81 if (newlist[i] == NULL)
82 goto cleanup;
83 }
84 newlist[i] = NULL;
85 *dst = newlist;
86 return 0;
87 cleanup:
88 free_list(newlist);
89 return ENOMEM;
90 }
91
92 char *
idtype2string(int idtype)93 idtype2string(int idtype)
94 {
95 /* Solaris Kerberos: Removed "break"s (lint) */
96 switch(idtype) {
97 case IDTYPE_FILE: return "FILE";
98 case IDTYPE_DIR: return "DIR";
99 case IDTYPE_PKCS11: return "PKCS11";
100 case IDTYPE_PKCS12: return "PKCS12";
101 case IDTYPE_ENVVAR: return "ENV";
102 default: return "INVALID";
103 }
104 }
105
106 char *
catype2string(int catype)107 catype2string(int catype)
108 {
109 /* Solaris Kerberos: Removed "break"s (lint) */
110 switch(catype) {
111 case CATYPE_ANCHORS: return "ANCHORS";
112 case CATYPE_INTERMEDIATES: return "INTERMEDIATES";
113 case CATYPE_CRLS: return "CRLS";
114 default: return "INVALID";
115 }
116 }
117
118 krb5_error_code
pkinit_init_identity_opts(pkinit_identity_opts ** idopts)119 pkinit_init_identity_opts(pkinit_identity_opts **idopts)
120 {
121 pkinit_identity_opts *opts = NULL;
122
123 *idopts = NULL;
124 opts = (pkinit_identity_opts *) calloc(1, sizeof(pkinit_identity_opts));
125 if (opts == NULL)
126 return ENOMEM;
127
128 opts->identity = NULL;
129 opts->anchors = NULL;
130 opts->intermediates = NULL;
131 opts->crls = NULL;
132 opts->ocsp = NULL;
133 opts->dn_mapping_file = NULL;
134
135 opts->cert_filename = NULL;
136 opts->key_filename = NULL;
137 #ifndef WITHOUT_PKCS11
138 opts->p11_module_name = NULL;
139 opts->slotid = PK_NOSLOT;
140 opts->token_label = NULL;
141 opts->cert_id_string = NULL;
142 opts->cert_label = NULL;
143 opts->PIN = NULL;
144 #endif
145
146 *idopts = opts;
147
148 return 0;
149 }
150
151 krb5_error_code
pkinit_dup_identity_opts(pkinit_identity_opts * src_opts,pkinit_identity_opts ** dest_opts)152 pkinit_dup_identity_opts(pkinit_identity_opts *src_opts,
153 pkinit_identity_opts **dest_opts)
154 {
155 pkinit_identity_opts *newopts;
156 krb5_error_code retval;
157
158 *dest_opts = NULL;
159 retval = pkinit_init_identity_opts(&newopts);
160 if (retval)
161 return retval;
162
163 retval = ENOMEM;
164
165 if (src_opts->identity != NULL) {
166 newopts->identity = strdup(src_opts->identity);
167 if (newopts->identity == NULL)
168 goto cleanup;
169 }
170
171 retval = copy_list(&newopts->anchors, src_opts->anchors);
172 if (retval)
173 goto cleanup;
174
175 retval = copy_list(&newopts->intermediates,src_opts->intermediates);
176 if (retval)
177 goto cleanup;
178
179 retval = copy_list(&newopts->crls, src_opts->crls);
180 if (retval)
181 goto cleanup;
182
183 if (src_opts->ocsp != NULL) {
184 newopts->ocsp = strdup(src_opts->ocsp);
185 if (newopts->ocsp == NULL)
186 goto cleanup;
187 }
188
189 if (src_opts->cert_filename != NULL) {
190 newopts->cert_filename = strdup(src_opts->cert_filename);
191 if (newopts->cert_filename == NULL)
192 goto cleanup;
193 }
194
195 if (src_opts->key_filename != NULL) {
196 newopts->key_filename = strdup(src_opts->key_filename);
197 if (newopts->key_filename == NULL)
198 goto cleanup;
199 }
200
201 #ifndef WITHOUT_PKCS11
202 if (src_opts->p11_module_name != NULL) {
203 newopts->p11_module_name = strdup(src_opts->p11_module_name);
204 if (newopts->p11_module_name == NULL)
205 goto cleanup;
206 }
207
208 newopts->slotid = src_opts->slotid;
209
210 if (src_opts->token_label != NULL) {
211 newopts->token_label = strdup(src_opts->token_label);
212 if (newopts->token_label == NULL)
213 goto cleanup;
214 }
215
216 if (src_opts->cert_id_string != NULL) {
217 newopts->cert_id_string = strdup(src_opts->cert_id_string);
218 if (newopts->cert_id_string == NULL)
219 goto cleanup;
220 }
221
222 if (src_opts->cert_label != NULL) {
223 newopts->cert_label = strdup(src_opts->cert_label);
224 if (newopts->cert_label == NULL)
225 goto cleanup;
226 }
227 if (src_opts->PIN != NULL) {
228 newopts->PIN = strdup(src_opts->PIN);
229 if (newopts->PIN == NULL)
230 goto cleanup;
231 }
232 #endif
233
234
235 *dest_opts = newopts;
236 return 0;
237 cleanup:
238 pkinit_fini_identity_opts(newopts);
239 return retval;
240 }
241
242 void
pkinit_fini_identity_opts(pkinit_identity_opts * idopts)243 pkinit_fini_identity_opts(pkinit_identity_opts *idopts)
244 {
245 if (idopts == NULL)
246 return;
247
248 if (idopts->identity != NULL)
249 free(idopts->identity);
250 free_list(idopts->anchors);
251 free_list(idopts->intermediates);
252 free_list(idopts->crls);
253 free_list(idopts->identity_alt);
254
255 if (idopts->cert_filename != NULL)
256 free(idopts->cert_filename);
257 if (idopts->key_filename != NULL)
258 free(idopts->key_filename);
259 #ifndef WITHOUT_PKCS11
260 if (idopts->p11_module_name != NULL)
261 free(idopts->p11_module_name);
262 if (idopts->token_label != NULL)
263 free(idopts->token_label);
264 if (idopts->cert_id_string != NULL)
265 free(idopts->cert_id_string);
266 if (idopts->cert_label != NULL)
267 free(idopts->cert_label);
268 if (idopts->PIN != NULL) {
269 (void) memset(idopts->PIN, 0, strlen(idopts->PIN));
270 free(idopts->PIN);
271 }
272 #endif
273 free(idopts);
274 }
275
276 #ifndef WITHOUT_PKCS11
277 /* ARGSUSED */
278 static krb5_error_code
parse_pkcs11_options(krb5_context context,pkinit_identity_opts * idopts,const char * residual)279 parse_pkcs11_options(krb5_context context,
280 pkinit_identity_opts *idopts,
281 const char *residual)
282 {
283 char *s, *cp, *vp;
284 krb5_error_code retval = ENOMEM;
285
286 if (residual == NULL || residual[0] == '\0')
287 return 0;
288
289 /* Split string into attr=value substrings */
290 s = strdup(residual);
291 if (s == NULL)
292 return retval;
293
294 for ((cp = strtok(s, ":")); cp; (cp = strtok(NULL, ":"))) {
295 vp = strchr(cp, '=');
296
297 /* If there is no "=", this is a pkcs11 module name */
298 if (vp == NULL) {
299 if (idopts->p11_module_name != NULL)
300 free(idopts->p11_module_name);
301 idopts->p11_module_name = strdup(cp);
302 if (idopts->p11_module_name == NULL)
303 goto cleanup;
304 continue;
305 }
306 *vp++ = '\0';
307 if (!strcmp(cp, "module_name")) {
308 if (idopts->p11_module_name != NULL)
309 free(idopts->p11_module_name);
310 idopts->p11_module_name = strdup(vp);
311 if (idopts->p11_module_name == NULL)
312 goto cleanup;
313 } else if (!strcmp(cp, "slotid")) {
314 long slotid = strtol(vp, NULL, 10);
315 if ((slotid == LONG_MIN || slotid == LONG_MAX) && errno != 0) {
316 retval = EINVAL;
317 goto cleanup;
318 }
319 if ((long) (int) slotid != slotid) {
320 retval = EINVAL;
321 goto cleanup;
322 }
323 idopts->slotid = slotid;
324 } else if (!strcmp(cp, "token")) {
325 if (idopts->token_label != NULL)
326 free(idopts->token_label);
327 idopts->token_label = strdup(vp);
328 if (idopts->token_label == NULL)
329 goto cleanup;
330 } else if (!strcmp(cp, "certid")) {
331 if (idopts->cert_id_string != NULL)
332 free(idopts->cert_id_string);
333 idopts->cert_id_string = strdup(vp);
334 if (idopts->cert_id_string == NULL)
335 goto cleanup;
336 } else if (!strcmp(cp, "certlabel")) {
337 if (idopts->cert_label != NULL)
338 free(idopts->cert_label);
339 idopts->cert_label = strdup(vp);
340 if (idopts->cert_label == NULL)
341 goto cleanup;
342 }
343 }
344 retval = 0;
345 cleanup:
346 free(s);
347 return retval;
348 }
349 #endif
350
351 /* ARGSUSED */
352 static krb5_error_code
parse_fs_options(krb5_context context,pkinit_identity_opts * idopts,const char * residual)353 parse_fs_options(krb5_context context,
354 pkinit_identity_opts *idopts,
355 const char *residual)
356 {
357 char *certname, *keyname;
358 krb5_error_code retval = ENOMEM;
359
360 if (residual == NULL || residual[0] == '\0')
361 return 0;
362
363 certname = strdup(residual);
364 if (certname == NULL)
365 goto cleanup;
366
367 certname = strtok(certname, ",");
368 keyname = strtok(NULL, ",");
369
370 idopts->cert_filename = strdup(certname);
371 if (idopts->cert_filename == NULL)
372 goto cleanup;
373
374 idopts->key_filename = strdup(keyname ? keyname : certname);
375 if (idopts->key_filename == NULL)
376 goto cleanup;
377
378 retval = 0;
379 cleanup:
380 if (certname != NULL)
381 free(certname);
382 return retval;
383 }
384
385 /* ARGSUSED */
386 static krb5_error_code
parse_pkcs12_options(krb5_context context,pkinit_identity_opts * idopts,const char * residual)387 parse_pkcs12_options(krb5_context context,
388 pkinit_identity_opts *idopts,
389 const char *residual)
390 {
391 krb5_error_code retval = ENOMEM;
392
393 if (residual == NULL || residual[0] == '\0')
394 return 0;
395
396 idopts->cert_filename = strdup(residual);
397 if (idopts->cert_filename == NULL)
398 goto cleanup;
399
400 idopts->key_filename = strdup(residual);
401 if (idopts->key_filename == NULL)
402 goto cleanup;
403
404 pkiDebug("%s: cert_filename '%s' key_filename '%s'\n",
405 __FUNCTION__, idopts->cert_filename,
406 idopts->key_filename);
407 retval = 0;
408 cleanup:
409 return retval;
410 }
411
412 static krb5_error_code
process_option_identity(krb5_context context,pkinit_plg_crypto_context plg_cryptoctx,pkinit_req_crypto_context req_cryptoctx,pkinit_identity_opts * idopts,pkinit_identity_crypto_context id_cryptoctx,const char * value)413 process_option_identity(krb5_context context,
414 pkinit_plg_crypto_context plg_cryptoctx,
415 pkinit_req_crypto_context req_cryptoctx,
416 pkinit_identity_opts *idopts,
417 pkinit_identity_crypto_context id_cryptoctx,
418 const char *value)
419 {
420 const char *residual;
421 int idtype;
422 krb5_error_code retval = 0;
423
424 pkiDebug("%s: processing value '%s'\n",
425 __FUNCTION__, value ? value : "NULL");
426 if (value == NULL)
427 return EINVAL;
428
429 residual = strchr(value, ':');
430 if (residual != NULL) {
431 unsigned int typelen;
432 residual++; /* skip past colon */
433 typelen = residual - value;
434 if (strncmp(value, "FILE:", typelen) == 0) {
435 idtype = IDTYPE_FILE;
436 #ifndef WITHOUT_PKCS11
437 } else if (strncmp(value, "PKCS11:", typelen) == 0) {
438 idtype = IDTYPE_PKCS11;
439 #endif
440 } else if (strncmp(value, "PKCS12:", typelen) == 0) {
441 idtype = IDTYPE_PKCS12;
442 } else if (strncmp(value, "DIR:", typelen) == 0) {
443 idtype = IDTYPE_DIR;
444 } else if (strncmp(value, "ENV:", typelen) == 0) {
445 idtype = IDTYPE_ENVVAR;
446 } else {
447 pkiDebug("%s: Unsupported type while processing '%s'\n",
448 __FUNCTION__, value);
449 krb5_set_error_message(context, KRB5_PREAUTH_FAILED,
450 "Unsupported type while processing '%s'\n",
451 value);
452 return KRB5_PREAUTH_FAILED;
453 }
454 } else {
455 idtype = IDTYPE_FILE;
456 residual = value;
457 }
458
459 idopts->idtype = idtype;
460 pkiDebug("%s: idtype is %s\n", __FUNCTION__, idtype2string(idopts->idtype));
461 switch (idtype) {
462 case IDTYPE_ENVVAR: {
463 /* Solaris Kerberos: Improved error messages */
464 char *envvar = getenv(residual);
465 if (envvar == NULL) {
466 krb5_set_error_message(context, EINVAL,
467 gettext("failed to find environmental variable \'%s\'"),
468 residual);
469 return EINVAL;
470 }
471 return process_option_identity(context, plg_cryptoctx,
472 req_cryptoctx, idopts, id_cryptoctx,
473 envvar);
474 /* Solaris Kerberos: not reached */
475 }
476 case IDTYPE_FILE:
477 retval = parse_fs_options(context, idopts, residual);
478 break;
479 case IDTYPE_PKCS12:
480 retval = parse_pkcs12_options(context, idopts, residual);
481 break;
482 #ifndef WITHOUT_PKCS11
483 case IDTYPE_PKCS11:
484 retval = parse_pkcs11_options(context, idopts, residual);
485 break;
486 #endif
487 case IDTYPE_DIR:
488 idopts->cert_filename = strdup(residual);
489 if (idopts->cert_filename == NULL)
490 retval = ENOMEM;
491 break;
492 default:
493 krb5_set_error_message(context, KRB5_PREAUTH_FAILED,
494 "Internal error parsing X509_user_identity\n");
495 retval = EINVAL;
496 break;
497 }
498 return retval;
499 }
500
501 static krb5_error_code
process_option_ca_crl(krb5_context context,pkinit_plg_crypto_context plg_cryptoctx,pkinit_req_crypto_context req_cryptoctx,pkinit_identity_opts * idopts,pkinit_identity_crypto_context id_cryptoctx,const char * value,int catype)502 process_option_ca_crl(krb5_context context,
503 pkinit_plg_crypto_context plg_cryptoctx,
504 pkinit_req_crypto_context req_cryptoctx,
505 pkinit_identity_opts *idopts,
506 pkinit_identity_crypto_context id_cryptoctx,
507 const char *value,
508 int catype)
509 {
510 char *residual;
511 unsigned int typelen;
512 int idtype;
513
514 pkiDebug("%s: processing catype %s, value '%s'\n",
515 __FUNCTION__, catype2string(catype), value);
516 residual = strchr(value, ':');
517 if (residual == NULL) {
518 pkiDebug("No type given for '%s'\n", value);
519 return EINVAL;
520 }
521 residual++; /* skip past colon */
522 typelen = residual - value;
523 if (strncmp(value, "FILE:", typelen) == 0) {
524 idtype = IDTYPE_FILE;
525 } else if (strncmp(value, "DIR:", typelen) == 0) {
526 idtype = IDTYPE_DIR;
527 } else {
528 return ENOTSUP;
529 }
530 return crypto_load_cas_and_crls(context,
531 plg_cryptoctx,
532 req_cryptoctx,
533 idopts, id_cryptoctx,
534 idtype, catype, residual);
535 }
536
537 static krb5_error_code
pkinit_identity_process_option(krb5_context context,pkinit_plg_crypto_context plg_cryptoctx,pkinit_req_crypto_context req_cryptoctx,pkinit_identity_opts * idopts,pkinit_identity_crypto_context id_cryptoctx,int attr,const char * value)538 pkinit_identity_process_option(krb5_context context,
539 pkinit_plg_crypto_context plg_cryptoctx,
540 pkinit_req_crypto_context req_cryptoctx,
541 pkinit_identity_opts *idopts,
542 pkinit_identity_crypto_context id_cryptoctx,
543 int attr,
544 const char *value)
545 {
546 krb5_error_code retval = 0;
547
548 switch (attr) {
549 case PKINIT_ID_OPT_USER_IDENTITY:
550 retval = process_option_identity(context, plg_cryptoctx,
551 req_cryptoctx, idopts,
552 id_cryptoctx, value);
553 break;
554 case PKINIT_ID_OPT_ANCHOR_CAS:
555 retval = process_option_ca_crl(context, plg_cryptoctx,
556 req_cryptoctx, idopts,
557 id_cryptoctx, value,
558 CATYPE_ANCHORS);
559 break;
560 case PKINIT_ID_OPT_INTERMEDIATE_CAS:
561 retval = process_option_ca_crl(context, plg_cryptoctx,
562 req_cryptoctx, idopts,
563 id_cryptoctx,
564 value, CATYPE_INTERMEDIATES);
565 break;
566 case PKINIT_ID_OPT_CRLS:
567 retval = process_option_ca_crl(context, plg_cryptoctx,
568 req_cryptoctx, idopts,
569 id_cryptoctx,
570 value, CATYPE_CRLS);
571 break;
572 case PKINIT_ID_OPT_OCSP:
573 retval = ENOTSUP;
574 break;
575 default:
576 retval = EINVAL;
577 break;
578 }
579 return retval;
580 }
581
582 krb5_error_code
pkinit_identity_initialize(krb5_context context,pkinit_plg_crypto_context plg_cryptoctx,pkinit_req_crypto_context req_cryptoctx,pkinit_identity_opts * idopts,pkinit_identity_crypto_context id_cryptoctx,int do_matching,krb5_principal princ)583 pkinit_identity_initialize(krb5_context context,
584 pkinit_plg_crypto_context plg_cryptoctx,
585 pkinit_req_crypto_context req_cryptoctx,
586 pkinit_identity_opts *idopts,
587 pkinit_identity_crypto_context id_cryptoctx,
588 int do_matching,
589 krb5_principal princ)
590 {
591 krb5_error_code retval = EINVAL;
592 int i;
593
594 pkiDebug("%s: %p %p %p\n", __FUNCTION__, context, idopts, id_cryptoctx);
595 if (idopts == NULL || id_cryptoctx == NULL)
596 goto errout;
597
598 /*
599 * If identity was specified, use that. (For the kdc, this
600 * is specified as pkinit_identity in the kdc.conf. For users,
601 * this is specified on the command line via X509_user_identity.)
602 * If a user did not specify identity on the command line,
603 * then we will try alternatives which may have been specified
604 * in the config file.
605 */
606 if (idopts->identity != NULL) {
607 retval = pkinit_identity_process_option(context, plg_cryptoctx,
608 req_cryptoctx, idopts,
609 id_cryptoctx,
610 PKINIT_ID_OPT_USER_IDENTITY,
611 idopts->identity);
612 } else if (idopts->identity_alt != NULL) {
613 for (i = 0; retval != 0 && idopts->identity_alt[i] != NULL; i++)
614 retval = pkinit_identity_process_option(context, plg_cryptoctx,
615 req_cryptoctx, idopts,
616 id_cryptoctx,
617 PKINIT_ID_OPT_USER_IDENTITY,
618 idopts->identity_alt[i]);
619 } else {
620 pkiDebug("%s: no user identity options specified\n", __FUNCTION__);
621 goto errout;
622 }
623 if (retval)
624 goto errout;
625
626 retval = crypto_load_certs(context, plg_cryptoctx, req_cryptoctx,
627 idopts, id_cryptoctx, princ, do_matching);
628 if (retval)
629 goto errout;
630
631 if (do_matching) {
632 retval = pkinit_cert_matching(context, plg_cryptoctx, req_cryptoctx,
633 id_cryptoctx, princ, TRUE);
634 if (retval) {
635 pkiDebug("%s: No matching certificate found\n", __FUNCTION__);
636 (void) crypto_free_cert_info(context, plg_cryptoctx, req_cryptoctx,
637 id_cryptoctx);
638 goto errout;
639 }
640 } else {
641 /* Tell crypto code to use the "default" */
642 retval = crypto_cert_select_default(context, plg_cryptoctx,
643 req_cryptoctx, id_cryptoctx);
644 if (retval) {
645 pkiDebug("%s: Failed while selecting default certificate\n",
646 __FUNCTION__);
647 (void) crypto_free_cert_info(context, plg_cryptoctx, req_cryptoctx,
648 id_cryptoctx);
649 goto errout;
650 }
651 }
652
653 retval = crypto_free_cert_info(context, plg_cryptoctx, req_cryptoctx,
654 id_cryptoctx);
655 if (retval)
656 goto errout;
657
658 for (i = 0; idopts->anchors != NULL && idopts->anchors[i] != NULL; i++) {
659 retval = pkinit_identity_process_option(context, plg_cryptoctx,
660 req_cryptoctx, idopts,
661 id_cryptoctx,
662 PKINIT_ID_OPT_ANCHOR_CAS,
663 idopts->anchors[i]);
664 if (retval)
665 goto errout;
666 }
667 for (i = 0; idopts->intermediates != NULL
668 && idopts->intermediates[i] != NULL; i++) {
669 retval = pkinit_identity_process_option(context, plg_cryptoctx,
670 req_cryptoctx, idopts,
671 id_cryptoctx,
672 PKINIT_ID_OPT_INTERMEDIATE_CAS,
673 idopts->intermediates[i]);
674 if (retval)
675 goto errout;
676 }
677 for (i = 0; idopts->crls != NULL && idopts->crls[i] != NULL; i++) {
678 retval = pkinit_identity_process_option(context, plg_cryptoctx,
679 req_cryptoctx, idopts,
680 id_cryptoctx,
681 PKINIT_ID_OPT_CRLS,
682 idopts->crls[i]);
683 if (retval)
684 goto errout;
685 }
686 if (idopts->ocsp != NULL) {
687 retval = pkinit_identity_process_option(context, plg_cryptoctx,
688 req_cryptoctx, idopts,
689 id_cryptoctx,
690 PKINIT_ID_OPT_OCSP,
691 idopts->ocsp);
692 if (retval)
693 goto errout;
694 }
695
696 errout:
697 return retval;
698 }
699
700