159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan/*
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan * COPYRIGHT (C) 2007
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan * THE REGENTS OF THE UNIVERSITY OF MICHIGAN
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan * ALL RIGHTS RESERVED
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan *
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan * Permission is granted to use, copy, create derivative works
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan * and redistribute this software and such derivative works
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan * for any purpose, so long as the name of The University of
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan * Michigan is not used in any advertising or publicity
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan * pertaining to the use of distribution of this software
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan * without specific, written prior authorization. If the
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan * above copyright notice or any other identification of the
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan * University of Michigan is included in any copy of any
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan * portion of this software, then the disclaimer below must
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan * also be included.
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan *
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan * THIS SOFTWARE IS PROVIDED AS IS, WITHOUT REPRESENTATION
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan * FROM THE UNIVERSITY OF MICHIGAN AS TO ITS FITNESS FOR ANY
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan * PURPOSE, AND WITHOUT WARRANTY BY THE UNIVERSITY OF
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan * MICHIGAN OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan * WITHOUT LIMITATION THE IMPLIED WARRANTIES OF
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan * REGENTS OF THE UNIVERSITY OF MICHIGAN SHALL NOT BE LIABLE
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan * FOR ANY DAMAGES, INCLUDING SPECIAL, INDIRECT, INCIDENTAL, OR
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan * CONSEQUENTIAL DAMAGES, WITH RESPECT TO ANY CLAIM ARISING
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan * OUT OF OR IN CONNECTION WITH THE USE OF THE SOFTWARE, EVEN
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan * IF IT HAS BEEN OR IS HEREAFTER ADVISED OF THE POSSIBILITY OF
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan * SUCH DAMAGES.
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan */
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan
488060a6285c53d78d4e5360e7db00d6d544d960Will Fiveash/*
488060a6285c53d78d4e5360e7db00d6d544d960Will Fiveash * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
488060a6285c53d78d4e5360e7db00d6d544d960Will Fiveash */
488060a6285c53d78d4e5360e7db00d6d544d960Will Fiveash
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#include <errno.h>
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#include <string.h>
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#include <stdio.h>
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#include <stdlib.h>
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#include <dlfcn.h>
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#include <unistd.h>
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#include <dirent.h>
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#include <libintl.h>
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#include "pkinit.h"
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalanstatic void
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalanfree_list(char **list)
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan{
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan int i;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan if (list == NULL)
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan return;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan for (i = 0; list[i] != NULL; i++)
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan free(list[i]);
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan free(list);
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan}
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalanstatic krb5_error_code
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalancopy_list(char ***dst, char **src)
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan{
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan int i;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan char **newlist;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan if (dst == NULL)
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan return EINVAL;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan *dst = NULL;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan if (src == NULL)
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan return 0;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan for (i = 0; src[i] != NULL; i++);
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan newlist = calloc(1, (i + 1) * sizeof(*newlist));
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan if (newlist == NULL)
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan return ENOMEM;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan for (i = 0; src[i] != NULL; i++) {
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan newlist[i] = strdup(src[i]);
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan if (newlist[i] == NULL)
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan goto cleanup;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan }
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan newlist[i] = NULL;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan *dst = newlist;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan return 0;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalancleanup:
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan free_list(newlist);
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan return ENOMEM;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan}
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalanchar *
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalanidtype2string(int idtype)
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan{
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan/* Solaris Kerberos: Removed "break"s (lint) */
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan switch(idtype) {
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan case IDTYPE_FILE: return "FILE";
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan case IDTYPE_DIR: return "DIR";
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan case IDTYPE_PKCS11: return "PKCS11";
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan case IDTYPE_PKCS12: return "PKCS12";
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan case IDTYPE_ENVVAR: return "ENV";
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan default: return "INVALID";
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan }
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan}
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalanchar *
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalancatype2string(int catype)
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan{
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan/* Solaris Kerberos: Removed "break"s (lint) */
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan switch(catype) {
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan case CATYPE_ANCHORS: return "ANCHORS";
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan case CATYPE_INTERMEDIATES: return "INTERMEDIATES";
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan case CATYPE_CRLS: return "CRLS";
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan default: return "INVALID";
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan }
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan}
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalankrb5_error_code
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalanpkinit_init_identity_opts(pkinit_identity_opts **idopts)
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan{
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan pkinit_identity_opts *opts = NULL;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan *idopts = NULL;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan opts = (pkinit_identity_opts *) calloc(1, sizeof(pkinit_identity_opts));
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan if (opts == NULL)
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan return ENOMEM;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan opts->identity = NULL;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan opts->anchors = NULL;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan opts->intermediates = NULL;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan opts->crls = NULL;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan opts->ocsp = NULL;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan opts->dn_mapping_file = NULL;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan opts->cert_filename = NULL;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan opts->key_filename = NULL;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#ifndef WITHOUT_PKCS11
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan opts->p11_module_name = NULL;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan opts->slotid = PK_NOSLOT;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan opts->token_label = NULL;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan opts->cert_id_string = NULL;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan opts->cert_label = NULL;
488060a6285c53d78d4e5360e7db00d6d544d960Will Fiveash opts->PIN = NULL;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#endif
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan *idopts = opts;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan return 0;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan}
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalankrb5_error_code
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalanpkinit_dup_identity_opts(pkinit_identity_opts *src_opts,
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan pkinit_identity_opts **dest_opts)
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan{
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan pkinit_identity_opts *newopts;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan krb5_error_code retval;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan *dest_opts = NULL;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan retval = pkinit_init_identity_opts(&newopts);
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan if (retval)
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan return retval;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan retval = ENOMEM;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan if (src_opts->identity != NULL) {
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan newopts->identity = strdup(src_opts->identity);
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan if (newopts->identity == NULL)
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan goto cleanup;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan }
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan retval = copy_list(&newopts->anchors, src_opts->anchors);
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan if (retval)
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan goto cleanup;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan retval = copy_list(&newopts->intermediates,src_opts->intermediates);
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan if (retval)
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan goto cleanup;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan retval = copy_list(&newopts->crls, src_opts->crls);
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan if (retval)
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan goto cleanup;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan if (src_opts->ocsp != NULL) {
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan newopts->ocsp = strdup(src_opts->ocsp);
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan if (newopts->ocsp == NULL)
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan goto cleanup;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan }
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan if (src_opts->cert_filename != NULL) {
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan newopts->cert_filename = strdup(src_opts->cert_filename);
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan if (newopts->cert_filename == NULL)
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan goto cleanup;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan }
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan if (src_opts->key_filename != NULL) {
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan newopts->key_filename = strdup(src_opts->key_filename);
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan if (newopts->key_filename == NULL)
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan goto cleanup;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan }
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#ifndef WITHOUT_PKCS11
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan if (src_opts->p11_module_name != NULL) {
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan newopts->p11_module_name = strdup(src_opts->p11_module_name);
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan if (newopts->p11_module_name == NULL)
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan goto cleanup;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan }
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan newopts->slotid = src_opts->slotid;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan if (src_opts->token_label != NULL) {
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan newopts->token_label = strdup(src_opts->token_label);
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan if (newopts->token_label == NULL)
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan goto cleanup;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan }
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan if (src_opts->cert_id_string != NULL) {
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan newopts->cert_id_string = strdup(src_opts->cert_id_string);
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan if (newopts->cert_id_string == NULL)
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan goto cleanup;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan }
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan if (src_opts->cert_label != NULL) {
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan newopts->cert_label = strdup(src_opts->cert_label);
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan if (newopts->cert_label == NULL)
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan goto cleanup;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan }
488060a6285c53d78d4e5360e7db00d6d544d960Will Fiveash if (src_opts->PIN != NULL) {
488060a6285c53d78d4e5360e7db00d6d544d960Will Fiveash newopts->PIN = strdup(src_opts->PIN);
488060a6285c53d78d4e5360e7db00d6d544d960Will Fiveash if (newopts->PIN == NULL)
488060a6285c53d78d4e5360e7db00d6d544d960Will Fiveash goto cleanup;
488060a6285c53d78d4e5360e7db00d6d544d960Will Fiveash }
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#endif
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan *dest_opts = newopts;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan return 0;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalancleanup:
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan pkinit_fini_identity_opts(newopts);
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan return retval;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan}
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalanvoid
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalanpkinit_fini_identity_opts(pkinit_identity_opts *idopts)
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan{
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan if (idopts == NULL)
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan return;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan if (idopts->identity != NULL)
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan free(idopts->identity);
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan free_list(idopts->anchors);
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan free_list(idopts->intermediates);
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan free_list(idopts->crls);
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan free_list(idopts->identity_alt);
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan if (idopts->cert_filename != NULL)
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan free(idopts->cert_filename);
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan if (idopts->key_filename != NULL)
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan free(idopts->key_filename);
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#ifndef WITHOUT_PKCS11
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan if (idopts->p11_module_name != NULL)
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan free(idopts->p11_module_name);
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan if (idopts->token_label != NULL)
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan free(idopts->token_label);
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan if (idopts->cert_id_string != NULL)
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan free(idopts->cert_id_string);
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan if (idopts->cert_label != NULL)
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan free(idopts->cert_label);
488060a6285c53d78d4e5360e7db00d6d544d960Will Fiveash if (idopts->PIN != NULL) {
488060a6285c53d78d4e5360e7db00d6d544d960Will Fiveash (void) memset(idopts->PIN, 0, strlen(idopts->PIN));
488060a6285c53d78d4e5360e7db00d6d544d960Will Fiveash free(idopts->PIN);
488060a6285c53d78d4e5360e7db00d6d544d960Will Fiveash }
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#endif
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan free(idopts);
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan}
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#ifndef WITHOUT_PKCS11
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan/* ARGSUSED */
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalanstatic krb5_error_code
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalanparse_pkcs11_options(krb5_context context,
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan pkinit_identity_opts *idopts,
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan const char *residual)
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan{
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan char *s, *cp, *vp;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan krb5_error_code retval = ENOMEM;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan if (residual == NULL || residual[0] == '\0')
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan return 0;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan /* Split string into attr=value substrings */
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan s = strdup(residual);
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan if (s == NULL)
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan return retval;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan for ((cp = strtok(s, ":")); cp; (cp = strtok(NULL, ":"))) {
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan vp = strchr(cp, '=');
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan /* If there is no "=", this is a pkcs11 module name */
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan if (vp == NULL) {
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan if (idopts->p11_module_name != NULL)
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan free(idopts->p11_module_name);
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan idopts->p11_module_name = strdup(cp);
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan if (idopts->p11_module_name == NULL)
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan goto cleanup;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan continue;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan }
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan *vp++ = '\0';
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan if (!strcmp(cp, "module_name")) {
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan if (idopts->p11_module_name != NULL)
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan free(idopts->p11_module_name);
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan idopts->p11_module_name = strdup(vp);
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan if (idopts->p11_module_name == NULL)
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan goto cleanup;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan } else if (!strcmp(cp, "slotid")) {
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan long slotid = strtol(vp, NULL, 10);
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan if ((slotid == LONG_MIN || slotid == LONG_MAX) && errno != 0) {
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan retval = EINVAL;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan goto cleanup;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan }
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan if ((long) (int) slotid != slotid) {
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan retval = EINVAL;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan goto cleanup;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan }
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan idopts->slotid = slotid;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan } else if (!strcmp(cp, "token")) {
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan if (idopts->token_label != NULL)
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan free(idopts->token_label);
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan idopts->token_label = strdup(vp);
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan if (idopts->token_label == NULL)
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan goto cleanup;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan } else if (!strcmp(cp, "certid")) {
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan if (idopts->cert_id_string != NULL)
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan free(idopts->cert_id_string);
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan idopts->cert_id_string = strdup(vp);
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan if (idopts->cert_id_string == NULL)
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan goto cleanup;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan } else if (!strcmp(cp, "certlabel")) {
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan if (idopts->cert_label != NULL)
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan free(idopts->cert_label);
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan idopts->cert_label = strdup(vp);
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan if (idopts->cert_label == NULL)
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan goto cleanup;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan }
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan }
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan retval = 0;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalancleanup:
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan free(s);
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan return retval;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan}
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#endif
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan/* ARGSUSED */
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalanstatic krb5_error_code
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalanparse_fs_options(krb5_context context,
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan pkinit_identity_opts *idopts,
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan const char *residual)
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan{
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan char *certname, *keyname;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan krb5_error_code retval = ENOMEM;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan if (residual == NULL || residual[0] == '\0')
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan return 0;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan certname = strdup(residual);
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan if (certname == NULL)
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan goto cleanup;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan certname = strtok(certname, ",");
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan keyname = strtok(NULL, ",");
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan idopts->cert_filename = strdup(certname);
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan if (idopts->cert_filename == NULL)
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan goto cleanup;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan idopts->key_filename = strdup(keyname ? keyname : certname);
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan if (idopts->key_filename == NULL)
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan goto cleanup;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan retval = 0;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalancleanup:
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan if (certname != NULL)
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan free(certname);
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan return retval;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan}
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan/* ARGSUSED */
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalanstatic krb5_error_code
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalanparse_pkcs12_options(krb5_context context,
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan pkinit_identity_opts *idopts,
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan const char *residual)
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan{
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan krb5_error_code retval = ENOMEM;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan if (residual == NULL || residual[0] == '\0')
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan return 0;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan idopts->cert_filename = strdup(residual);
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan if (idopts->cert_filename == NULL)
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan goto cleanup;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan idopts->key_filename = strdup(residual);
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan if (idopts->key_filename == NULL)
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan goto cleanup;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan pkiDebug("%s: cert_filename '%s' key_filename '%s'\n",
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan __FUNCTION__, idopts->cert_filename,
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan idopts->key_filename);
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan retval = 0;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalancleanup:
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan return retval;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan}
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalanstatic krb5_error_code
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalanprocess_option_identity(krb5_context context,
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan pkinit_plg_crypto_context plg_cryptoctx,
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan pkinit_req_crypto_context req_cryptoctx,
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan pkinit_identity_opts *idopts,
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan pkinit_identity_crypto_context id_cryptoctx,
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan const char *value)
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan{
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan const char *residual;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan int idtype;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan krb5_error_code retval = 0;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan pkiDebug("%s: processing value '%s'\n",
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan __FUNCTION__, value ? value : "NULL");
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan if (value == NULL)
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan return EINVAL;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan residual = strchr(value, ':');
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan if (residual != NULL) {
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan unsigned int typelen;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan residual++; /* skip past colon */
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan typelen = residual - value;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan if (strncmp(value, "FILE:", typelen) == 0) {
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan idtype = IDTYPE_FILE;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#ifndef WITHOUT_PKCS11
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan } else if (strncmp(value, "PKCS11:", typelen) == 0) {
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan idtype = IDTYPE_PKCS11;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#endif
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan } else if (strncmp(value, "PKCS12:", typelen) == 0) {
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan idtype = IDTYPE_PKCS12;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan } else if (strncmp(value, "DIR:", typelen) == 0) {
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan idtype = IDTYPE_DIR;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan } else if (strncmp(value, "ENV:", typelen) == 0) {
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan idtype = IDTYPE_ENVVAR;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan } else {
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan pkiDebug("%s: Unsupported type while processing '%s'\n",
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan __FUNCTION__, value);
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan krb5_set_error_message(context, KRB5_PREAUTH_FAILED,
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan "Unsupported type while processing '%s'\n",
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan value);
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan return KRB5_PREAUTH_FAILED;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan }
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan } else {
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan idtype = IDTYPE_FILE;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan residual = value;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan }
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan idopts->idtype = idtype;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan pkiDebug("%s: idtype is %s\n", __FUNCTION__, idtype2string(idopts->idtype));
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan switch (idtype) {
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan case IDTYPE_ENVVAR: {
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan /* Solaris Kerberos: Improved error messages */
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan char *envvar = getenv(residual);
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan if (envvar == NULL) {
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan krb5_set_error_message(context, EINVAL,
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan gettext("failed to find environmental variable \'%s\'"),
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan residual);
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan return EINVAL;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan }
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan return process_option_identity(context, plg_cryptoctx,
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan req_cryptoctx, idopts, id_cryptoctx,
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan envvar);
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan /* Solaris Kerberos: not reached */
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan }
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan case IDTYPE_FILE:
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan retval = parse_fs_options(context, idopts, residual);
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan break;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan case IDTYPE_PKCS12:
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan retval = parse_pkcs12_options(context, idopts, residual);
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan break;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#ifndef WITHOUT_PKCS11
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan case IDTYPE_PKCS11:
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan retval = parse_pkcs11_options(context, idopts, residual);
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan break;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#endif
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan case IDTYPE_DIR:
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan idopts->cert_filename = strdup(residual);
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan if (idopts->cert_filename == NULL)
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan retval = ENOMEM;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan break;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan default:
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan krb5_set_error_message(context, KRB5_PREAUTH_FAILED,
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan "Internal error parsing X509_user_identity\n");
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan retval = EINVAL;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan break;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan }
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan return retval;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan}
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalanstatic krb5_error_code
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalanprocess_option_ca_crl(krb5_context context,
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan pkinit_plg_crypto_context plg_cryptoctx,
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan pkinit_req_crypto_context req_cryptoctx,
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan pkinit_identity_opts *idopts,
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan pkinit_identity_crypto_context id_cryptoctx,
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan const char *value,
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan int catype)
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan{
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan char *residual;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan unsigned int typelen;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan int idtype;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan pkiDebug("%s: processing catype %s, value '%s'\n",
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan __FUNCTION__, catype2string(catype), value);
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan residual = strchr(value, ':');
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan if (residual == NULL) {
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan pkiDebug("No type given for '%s'\n", value);
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan return EINVAL;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan }
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan residual++; /* skip past colon */
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan typelen = residual - value;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan if (strncmp(value, "FILE:", typelen) == 0) {
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan idtype = IDTYPE_FILE;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan } else if (strncmp(value, "DIR:", typelen) == 0) {
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan idtype = IDTYPE_DIR;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan } else {
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan return ENOTSUP;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan }
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan return crypto_load_cas_and_crls(context,
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan plg_cryptoctx,
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan req_cryptoctx,
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan idopts, id_cryptoctx,
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan idtype, catype, residual);
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan}
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalanstatic krb5_error_code
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalanpkinit_identity_process_option(krb5_context context,
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan pkinit_plg_crypto_context plg_cryptoctx,
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan pkinit_req_crypto_context req_cryptoctx,
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan pkinit_identity_opts *idopts,
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan pkinit_identity_crypto_context id_cryptoctx,
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan int attr,
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan const char *value)
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan{
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan krb5_error_code retval = 0;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan switch (attr) {
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan case PKINIT_ID_OPT_USER_IDENTITY:
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan retval = process_option_identity(context, plg_cryptoctx,
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan req_cryptoctx, idopts,
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan id_cryptoctx, value);
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan break;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan case PKINIT_ID_OPT_ANCHOR_CAS:
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan retval = process_option_ca_crl(context, plg_cryptoctx,
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan req_cryptoctx, idopts,
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan id_cryptoctx, value,
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan CATYPE_ANCHORS);
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan break;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan case PKINIT_ID_OPT_INTERMEDIATE_CAS:
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan retval = process_option_ca_crl(context, plg_cryptoctx,
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan req_cryptoctx, idopts,
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan id_cryptoctx,
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan value, CATYPE_INTERMEDIATES);
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan break;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan case PKINIT_ID_OPT_CRLS:
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan retval = process_option_ca_crl(context, plg_cryptoctx,
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan req_cryptoctx, idopts,
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan id_cryptoctx,
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan value, CATYPE_CRLS);
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan break;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan case PKINIT_ID_OPT_OCSP:
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan retval = ENOTSUP;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan break;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan default:
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan retval = EINVAL;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan break;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan }
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan return retval;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan}
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalankrb5_error_code
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalanpkinit_identity_initialize(krb5_context context,
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan pkinit_plg_crypto_context plg_cryptoctx,
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan pkinit_req_crypto_context req_cryptoctx,
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan pkinit_identity_opts *idopts,
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan pkinit_identity_crypto_context id_cryptoctx,
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan int do_matching,
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan krb5_principal princ)
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan{
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan krb5_error_code retval = EINVAL;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan int i;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan pkiDebug("%s: %p %p %p\n", __FUNCTION__, context, idopts, id_cryptoctx);
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan if (idopts == NULL || id_cryptoctx == NULL)
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan goto errout;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan /*
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan * If identity was specified, use that. (For the kdc, this
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan * is specified as pkinit_identity in the kdc.conf. For users,
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan * this is specified on the command line via X509_user_identity.)
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan * If a user did not specify identity on the command line,
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan * then we will try alternatives which may have been specified
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan * in the config file.
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan */
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan if (idopts->identity != NULL) {
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan retval = pkinit_identity_process_option(context, plg_cryptoctx,
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan req_cryptoctx, idopts,
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan id_cryptoctx,
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan PKINIT_ID_OPT_USER_IDENTITY,
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan idopts->identity);
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan } else if (idopts->identity_alt != NULL) {
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan for (i = 0; retval != 0 && idopts->identity_alt[i] != NULL; i++)
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan retval = pkinit_identity_process_option(context, plg_cryptoctx,
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan req_cryptoctx, idopts,
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan id_cryptoctx,
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan PKINIT_ID_OPT_USER_IDENTITY,
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan idopts->identity_alt[i]);
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan } else {
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan pkiDebug("%s: no user identity options specified\n", __FUNCTION__);
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan goto errout;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan }
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan if (retval)
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan goto errout;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan retval = crypto_load_certs(context, plg_cryptoctx, req_cryptoctx,
9e11d51c0ad2b26ad2cd7f23707e4fb3005fd5b4Will Fiveash idopts, id_cryptoctx, princ, do_matching);
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan if (retval)
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan goto errout;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan if (do_matching) {
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan retval = pkinit_cert_matching(context, plg_cryptoctx, req_cryptoctx,
9e11d51c0ad2b26ad2cd7f23707e4fb3005fd5b4Will Fiveash id_cryptoctx, princ, TRUE);
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan if (retval) {
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan pkiDebug("%s: No matching certificate found\n", __FUNCTION__);
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan (void) crypto_free_cert_info(context, plg_cryptoctx, req_cryptoctx,
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan id_cryptoctx);
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan goto errout;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan }
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan } else {
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan /* Tell crypto code to use the "default" */
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan retval = crypto_cert_select_default(context, plg_cryptoctx,
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan req_cryptoctx, id_cryptoctx);
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan if (retval) {
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan pkiDebug("%s: Failed while selecting default certificate\n",
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan __FUNCTION__);
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan (void) crypto_free_cert_info(context, plg_cryptoctx, req_cryptoctx,
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan id_cryptoctx);
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan goto errout;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan }
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan }
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan retval = crypto_free_cert_info(context, plg_cryptoctx, req_cryptoctx,
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan id_cryptoctx);
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan if (retval)
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan goto errout;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan for (i = 0; idopts->anchors != NULL && idopts->anchors[i] != NULL; i++) {
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan retval = pkinit_identity_process_option(context, plg_cryptoctx,
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan req_cryptoctx, idopts,
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan id_cryptoctx,
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan PKINIT_ID_OPT_ANCHOR_CAS,
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan idopts->anchors[i]);
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan if (retval)
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan goto errout;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan }
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan for (i = 0; idopts->intermediates != NULL
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan && idopts->intermediates[i] != NULL; i++) {
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan retval = pkinit_identity_process_option(context, plg_cryptoctx,
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan req_cryptoctx, idopts,
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan id_cryptoctx,
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan PKINIT_ID_OPT_INTERMEDIATE_CAS,
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan idopts->intermediates[i]);
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan if (retval)
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan goto errout;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan }
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan for (i = 0; idopts->crls != NULL && idopts->crls[i] != NULL; i++) {
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan retval = pkinit_identity_process_option(context, plg_cryptoctx,
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan req_cryptoctx, idopts,
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan id_cryptoctx,
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan PKINIT_ID_OPT_CRLS,
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan idopts->crls[i]);
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan if (retval)
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan goto errout;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan }
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan if (idopts->ocsp != NULL) {
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan retval = pkinit_identity_process_option(context, plg_cryptoctx,
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan req_cryptoctx, idopts,
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan id_cryptoctx,
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan PKINIT_ID_OPT_OCSP,
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan idopts->ocsp);
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan if (retval)
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan goto errout;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan }
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalanerrout:
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan return retval;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan}
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan