|
Packit |
fd8b60 |
/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
|
|
Packit |
fd8b60 |
/*
|
|
Packit |
fd8b60 |
* COPYRIGHT (C) 2007
|
|
Packit |
fd8b60 |
* THE REGENTS OF THE UNIVERSITY OF MICHIGAN
|
|
Packit |
fd8b60 |
* ALL RIGHTS RESERVED
|
|
Packit |
fd8b60 |
*
|
|
Packit |
fd8b60 |
* Permission is granted to use, copy, create derivative works
|
|
Packit |
fd8b60 |
* and redistribute this software and such derivative works
|
|
Packit |
fd8b60 |
* for any purpose, so long as the name of The University of
|
|
Packit |
fd8b60 |
* Michigan is not used in any advertising or publicity
|
|
Packit |
fd8b60 |
* pertaining to the use of distribution of this software
|
|
Packit |
fd8b60 |
* without specific, written prior authorization. If the
|
|
Packit |
fd8b60 |
* above copyright notice or any other identification of the
|
|
Packit |
fd8b60 |
* University of Michigan is included in any copy of any
|
|
Packit |
fd8b60 |
* portion of this software, then the disclaimer below must
|
|
Packit |
fd8b60 |
* also be included.
|
|
Packit |
fd8b60 |
*
|
|
Packit |
fd8b60 |
* THIS SOFTWARE IS PROVIDED AS IS, WITHOUT REPRESENTATION
|
|
Packit |
fd8b60 |
* FROM THE UNIVERSITY OF MICHIGAN AS TO ITS FITNESS FOR ANY
|
|
Packit |
fd8b60 |
* PURPOSE, AND WITHOUT WARRANTY BY THE UNIVERSITY OF
|
|
Packit |
fd8b60 |
* MICHIGAN OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING
|
|
Packit |
fd8b60 |
* WITHOUT LIMITATION THE IMPLIED WARRANTIES OF
|
|
Packit |
fd8b60 |
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE
|
|
Packit |
fd8b60 |
* REGENTS OF THE UNIVERSITY OF MICHIGAN SHALL NOT BE LIABLE
|
|
Packit |
fd8b60 |
* FOR ANY DAMAGES, INCLUDING SPECIAL, INDIRECT, INCIDENTAL, OR
|
|
Packit |
fd8b60 |
* CONSEQUENTIAL DAMAGES, WITH RESPECT TO ANY CLAIM ARISING
|
|
Packit |
fd8b60 |
* OUT OF OR IN CONNECTION WITH THE USE OF THE SOFTWARE, EVEN
|
|
Packit |
fd8b60 |
* IF IT HAS BEEN OR IS HEREAFTER ADVISED OF THE POSSIBILITY OF
|
|
Packit |
fd8b60 |
* SUCH DAMAGES.
|
|
Packit |
fd8b60 |
*/
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
#include "pkinit.h"
|
|
Packit |
fd8b60 |
#include <dlfcn.h>
|
|
Packit |
fd8b60 |
#include <dirent.h>
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
static void
|
|
Packit |
fd8b60 |
free_list(char **list)
|
|
Packit |
fd8b60 |
{
|
|
Packit |
fd8b60 |
int i;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
if (list == NULL)
|
|
Packit |
fd8b60 |
return;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
for (i = 0; list[i] != NULL; i++)
|
|
Packit |
fd8b60 |
free(list[i]);
|
|
Packit |
fd8b60 |
free(list);
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
static krb5_error_code
|
|
Packit |
fd8b60 |
copy_list(char ***dst, char **src)
|
|
Packit |
fd8b60 |
{
|
|
Packit |
fd8b60 |
int i;
|
|
Packit |
fd8b60 |
char **newlist;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
if (dst == NULL)
|
|
Packit |
fd8b60 |
return EINVAL;
|
|
Packit |
fd8b60 |
*dst = NULL;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
if (src == NULL)
|
|
Packit |
fd8b60 |
return 0;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
for (i = 0; src[i] != NULL; i++);
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
newlist = calloc(1, (i + 1) * sizeof(*newlist));
|
|
Packit |
fd8b60 |
if (newlist == NULL)
|
|
Packit |
fd8b60 |
return ENOMEM;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
for (i = 0; src[i] != NULL; i++) {
|
|
Packit |
fd8b60 |
newlist[i] = strdup(src[i]);
|
|
Packit |
fd8b60 |
if (newlist[i] == NULL)
|
|
Packit |
fd8b60 |
goto cleanup;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
newlist[i] = NULL;
|
|
Packit |
fd8b60 |
*dst = newlist;
|
|
Packit |
fd8b60 |
return 0;
|
|
Packit |
fd8b60 |
cleanup:
|
|
Packit |
fd8b60 |
free_list(newlist);
|
|
Packit |
fd8b60 |
return ENOMEM;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
char *
|
|
Packit |
fd8b60 |
idtype2string(int idtype)
|
|
Packit |
fd8b60 |
{
|
|
Packit |
fd8b60 |
switch(idtype) {
|
|
Packit |
fd8b60 |
case IDTYPE_FILE: return "FILE"; break;
|
|
Packit |
fd8b60 |
case IDTYPE_DIR: return "DIR"; break;
|
|
Packit |
fd8b60 |
case IDTYPE_PKCS11: return "PKCS11"; break;
|
|
Packit |
fd8b60 |
case IDTYPE_PKCS12: return "PKCS12"; break;
|
|
Packit |
fd8b60 |
case IDTYPE_ENVVAR: return "ENV"; break;
|
|
Packit |
fd8b60 |
default: return "INVALID"; break;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
char *
|
|
Packit |
fd8b60 |
catype2string(int catype)
|
|
Packit |
fd8b60 |
{
|
|
Packit |
fd8b60 |
switch(catype) {
|
|
Packit |
fd8b60 |
case CATYPE_ANCHORS: return "ANCHORS"; break;
|
|
Packit |
fd8b60 |
case CATYPE_INTERMEDIATES: return "INTERMEDIATES"; break;
|
|
Packit |
fd8b60 |
case CATYPE_CRLS: return "CRLS"; break;
|
|
Packit |
fd8b60 |
default: return "INVALID"; break;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
krb5_error_code
|
|
Packit |
fd8b60 |
pkinit_init_identity_opts(pkinit_identity_opts **idopts)
|
|
Packit |
fd8b60 |
{
|
|
Packit |
fd8b60 |
pkinit_identity_opts *opts = NULL;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
*idopts = NULL;
|
|
Packit |
fd8b60 |
opts = calloc(1, sizeof(pkinit_identity_opts));
|
|
Packit |
fd8b60 |
if (opts == NULL)
|
|
Packit |
fd8b60 |
return ENOMEM;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
opts->identity = NULL;
|
|
Packit |
fd8b60 |
opts->anchors = NULL;
|
|
Packit |
fd8b60 |
opts->intermediates = NULL;
|
|
Packit |
fd8b60 |
opts->crls = NULL;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
opts->cert_filename = NULL;
|
|
Packit |
fd8b60 |
opts->key_filename = NULL;
|
|
Packit |
fd8b60 |
#ifndef WITHOUT_PKCS11
|
|
Packit |
fd8b60 |
opts->p11_module_name = NULL;
|
|
Packit |
fd8b60 |
opts->slotid = PK_NOSLOT;
|
|
Packit |
fd8b60 |
opts->token_label = NULL;
|
|
Packit |
fd8b60 |
opts->cert_id_string = NULL;
|
|
Packit |
fd8b60 |
opts->cert_label = NULL;
|
|
Packit |
fd8b60 |
#endif
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
*idopts = opts;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
return 0;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
krb5_error_code
|
|
Packit |
fd8b60 |
pkinit_dup_identity_opts(pkinit_identity_opts *src_opts,
|
|
Packit |
fd8b60 |
pkinit_identity_opts **dest_opts)
|
|
Packit |
fd8b60 |
{
|
|
Packit |
fd8b60 |
pkinit_identity_opts *newopts;
|
|
Packit |
fd8b60 |
krb5_error_code retval;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
*dest_opts = NULL;
|
|
Packit |
fd8b60 |
retval = pkinit_init_identity_opts(&newopts);
|
|
Packit |
fd8b60 |
if (retval)
|
|
Packit |
fd8b60 |
return retval;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
retval = ENOMEM;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
if (src_opts->identity != NULL) {
|
|
Packit |
fd8b60 |
newopts->identity = strdup(src_opts->identity);
|
|
Packit |
fd8b60 |
if (newopts->identity == NULL)
|
|
Packit |
fd8b60 |
goto cleanup;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
retval = copy_list(&newopts->anchors, src_opts->anchors);
|
|
Packit |
fd8b60 |
if (retval)
|
|
Packit |
fd8b60 |
goto cleanup;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
retval = copy_list(&newopts->intermediates,src_opts->intermediates);
|
|
Packit |
fd8b60 |
if (retval)
|
|
Packit |
fd8b60 |
goto cleanup;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
retval = copy_list(&newopts->crls, src_opts->crls);
|
|
Packit |
fd8b60 |
if (retval)
|
|
Packit |
fd8b60 |
goto cleanup;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
if (src_opts->cert_filename != NULL) {
|
|
Packit |
fd8b60 |
newopts->cert_filename = strdup(src_opts->cert_filename);
|
|
Packit |
fd8b60 |
if (newopts->cert_filename == NULL)
|
|
Packit |
fd8b60 |
goto cleanup;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
if (src_opts->key_filename != NULL) {
|
|
Packit |
fd8b60 |
newopts->key_filename = strdup(src_opts->key_filename);
|
|
Packit |
fd8b60 |
if (newopts->key_filename == NULL)
|
|
Packit |
fd8b60 |
goto cleanup;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
#ifndef WITHOUT_PKCS11
|
|
Packit |
fd8b60 |
if (src_opts->p11_module_name != NULL) {
|
|
Packit |
fd8b60 |
newopts->p11_module_name = strdup(src_opts->p11_module_name);
|
|
Packit |
fd8b60 |
if (newopts->p11_module_name == NULL)
|
|
Packit |
fd8b60 |
goto cleanup;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
newopts->slotid = src_opts->slotid;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
if (src_opts->token_label != NULL) {
|
|
Packit |
fd8b60 |
newopts->token_label = strdup(src_opts->token_label);
|
|
Packit |
fd8b60 |
if (newopts->token_label == NULL)
|
|
Packit |
fd8b60 |
goto cleanup;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
if (src_opts->cert_id_string != NULL) {
|
|
Packit |
fd8b60 |
newopts->cert_id_string = strdup(src_opts->cert_id_string);
|
|
Packit |
fd8b60 |
if (newopts->cert_id_string == NULL)
|
|
Packit |
fd8b60 |
goto cleanup;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
if (src_opts->cert_label != NULL) {
|
|
Packit |
fd8b60 |
newopts->cert_label = strdup(src_opts->cert_label);
|
|
Packit |
fd8b60 |
if (newopts->cert_label == NULL)
|
|
Packit |
fd8b60 |
goto cleanup;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
#endif
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
*dest_opts = newopts;
|
|
Packit |
fd8b60 |
return 0;
|
|
Packit |
fd8b60 |
cleanup:
|
|
Packit |
fd8b60 |
pkinit_fini_identity_opts(newopts);
|
|
Packit |
fd8b60 |
return retval;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
void
|
|
Packit |
fd8b60 |
pkinit_fini_identity_opts(pkinit_identity_opts *idopts)
|
|
Packit |
fd8b60 |
{
|
|
Packit |
fd8b60 |
if (idopts == NULL)
|
|
Packit |
fd8b60 |
return;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
if (idopts->identity != NULL)
|
|
Packit |
fd8b60 |
free(idopts->identity);
|
|
Packit |
fd8b60 |
free_list(idopts->anchors);
|
|
Packit |
fd8b60 |
free_list(idopts->intermediates);
|
|
Packit |
fd8b60 |
free_list(idopts->crls);
|
|
Packit |
fd8b60 |
free_list(idopts->identity_alt);
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
free(idopts->cert_filename);
|
|
Packit |
fd8b60 |
free(idopts->key_filename);
|
|
Packit |
fd8b60 |
#ifndef WITHOUT_PKCS11
|
|
Packit |
fd8b60 |
free(idopts->p11_module_name);
|
|
Packit |
fd8b60 |
free(idopts->token_label);
|
|
Packit |
fd8b60 |
free(idopts->cert_id_string);
|
|
Packit |
fd8b60 |
free(idopts->cert_label);
|
|
Packit |
fd8b60 |
#endif
|
|
Packit |
fd8b60 |
free(idopts);
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
#ifndef WITHOUT_PKCS11
|
|
Packit |
fd8b60 |
static krb5_error_code
|
|
Packit |
fd8b60 |
parse_pkcs11_options(krb5_context context,
|
|
Packit |
fd8b60 |
pkinit_identity_opts *idopts,
|
|
Packit |
fd8b60 |
const char *residual)
|
|
Packit |
fd8b60 |
{
|
|
Packit |
fd8b60 |
char *s, *cp, *vp, *save;
|
|
Packit |
fd8b60 |
krb5_error_code retval = ENOMEM;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
if (residual == NULL || residual[0] == '\0')
|
|
Packit |
fd8b60 |
return 0;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
/* Split string into attr=value substrings */
|
|
Packit |
fd8b60 |
s = strdup(residual);
|
|
Packit |
fd8b60 |
if (s == NULL)
|
|
Packit |
fd8b60 |
return retval;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
for (cp = strtok_r(s, ":", &save); cp; cp = strtok_r(NULL, ":", &save)) {
|
|
Packit |
fd8b60 |
vp = strchr(cp, '=');
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
/* If there is no "=", this is a pkcs11 module name */
|
|
Packit |
fd8b60 |
if (vp == NULL) {
|
|
Packit |
fd8b60 |
free(idopts->p11_module_name);
|
|
Packit |
fd8b60 |
idopts->p11_module_name = strdup(cp);
|
|
Packit |
fd8b60 |
if (idopts->p11_module_name == NULL)
|
|
Packit |
fd8b60 |
goto cleanup;
|
|
Packit |
fd8b60 |
continue;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
*vp++ = '\0';
|
|
Packit |
fd8b60 |
if (!strcmp(cp, "module_name")) {
|
|
Packit |
fd8b60 |
free(idopts->p11_module_name);
|
|
Packit |
fd8b60 |
idopts->p11_module_name = strdup(vp);
|
|
Packit |
fd8b60 |
if (idopts->p11_module_name == NULL)
|
|
Packit |
fd8b60 |
goto cleanup;
|
|
Packit |
fd8b60 |
} else if (!strcmp(cp, "slotid")) {
|
|
Packit |
fd8b60 |
long slotid = strtol(vp, NULL, 10);
|
|
Packit |
fd8b60 |
if ((slotid == LONG_MIN || slotid == LONG_MAX) && errno != 0) {
|
|
Packit |
fd8b60 |
retval = EINVAL;
|
|
Packit |
fd8b60 |
goto cleanup;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
if ((long) (int) slotid != slotid) {
|
|
Packit |
fd8b60 |
retval = EINVAL;
|
|
Packit |
fd8b60 |
goto cleanup;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
idopts->slotid = slotid;
|
|
Packit |
fd8b60 |
} else if (!strcmp(cp, "token")) {
|
|
Packit |
fd8b60 |
free(idopts->token_label);
|
|
Packit |
fd8b60 |
idopts->token_label = strdup(vp);
|
|
Packit |
fd8b60 |
if (idopts->token_label == NULL)
|
|
Packit |
fd8b60 |
goto cleanup;
|
|
Packit |
fd8b60 |
} else if (!strcmp(cp, "certid")) {
|
|
Packit |
fd8b60 |
free(idopts->cert_id_string);
|
|
Packit |
fd8b60 |
idopts->cert_id_string = strdup(vp);
|
|
Packit |
fd8b60 |
if (idopts->cert_id_string == NULL)
|
|
Packit |
fd8b60 |
goto cleanup;
|
|
Packit |
fd8b60 |
} else if (!strcmp(cp, "certlabel")) {
|
|
Packit |
fd8b60 |
free(idopts->cert_label);
|
|
Packit |
fd8b60 |
idopts->cert_label = strdup(vp);
|
|
Packit |
fd8b60 |
if (idopts->cert_label == NULL)
|
|
Packit |
fd8b60 |
goto cleanup;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
retval = 0;
|
|
Packit |
fd8b60 |
cleanup:
|
|
Packit |
fd8b60 |
free(s);
|
|
Packit |
fd8b60 |
return retval;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
#endif
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
static krb5_error_code
|
|
Packit |
fd8b60 |
parse_fs_options(krb5_context context,
|
|
Packit |
fd8b60 |
pkinit_identity_opts *idopts,
|
|
Packit |
fd8b60 |
const char *residual)
|
|
Packit |
fd8b60 |
{
|
|
Packit |
fd8b60 |
char *certname, *keyname, *save;
|
|
Packit |
fd8b60 |
char *cert_filename = NULL, *key_filename = NULL;
|
|
Packit |
fd8b60 |
krb5_error_code retval = ENOMEM;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
if (residual == NULL || residual[0] == '\0' || residual[0] == ',')
|
|
Packit |
fd8b60 |
return EINVAL;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
certname = strdup(residual);
|
|
Packit |
fd8b60 |
if (certname == NULL)
|
|
Packit |
fd8b60 |
goto cleanup;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
certname = strtok_r(certname, ",", &save);
|
|
Packit |
fd8b60 |
if (certname == NULL)
|
|
Packit |
fd8b60 |
goto cleanup;
|
|
Packit |
fd8b60 |
keyname = strtok_r(NULL, ",", &save);
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
cert_filename = strdup(certname);
|
|
Packit |
fd8b60 |
if (cert_filename == NULL)
|
|
Packit |
fd8b60 |
goto cleanup;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
key_filename = strdup((keyname != NULL) ? keyname : certname);
|
|
Packit |
fd8b60 |
if (key_filename == NULL)
|
|
Packit |
fd8b60 |
goto cleanup;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
idopts->cert_filename = cert_filename;
|
|
Packit |
fd8b60 |
idopts->key_filename = key_filename;
|
|
Packit |
fd8b60 |
cert_filename = key_filename = NULL;
|
|
Packit |
fd8b60 |
retval = 0;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
cleanup:
|
|
Packit |
fd8b60 |
free(certname);
|
|
Packit |
fd8b60 |
free(cert_filename);
|
|
Packit |
fd8b60 |
free(key_filename);
|
|
Packit |
fd8b60 |
return retval;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
static krb5_error_code
|
|
Packit |
fd8b60 |
parse_pkcs12_options(krb5_context context,
|
|
Packit |
fd8b60 |
pkinit_identity_opts *idopts,
|
|
Packit |
fd8b60 |
const char *residual)
|
|
Packit |
fd8b60 |
{
|
|
Packit |
fd8b60 |
krb5_error_code retval = ENOMEM;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
if (residual == NULL || residual[0] == '\0')
|
|
Packit |
fd8b60 |
return 0;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
idopts->cert_filename = strdup(residual);
|
|
Packit |
fd8b60 |
if (idopts->cert_filename == NULL)
|
|
Packit |
fd8b60 |
goto cleanup;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
idopts->key_filename = strdup(residual);
|
|
Packit |
fd8b60 |
if (idopts->key_filename == NULL)
|
|
Packit |
fd8b60 |
goto cleanup;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
pkiDebug("%s: cert_filename '%s' key_filename '%s'\n",
|
|
Packit |
fd8b60 |
__FUNCTION__, idopts->cert_filename,
|
|
Packit |
fd8b60 |
idopts->key_filename);
|
|
Packit |
fd8b60 |
retval = 0;
|
|
Packit |
fd8b60 |
cleanup:
|
|
Packit |
fd8b60 |
return retval;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
static krb5_error_code
|
|
Packit |
fd8b60 |
process_option_identity(krb5_context context,
|
|
Packit |
fd8b60 |
pkinit_plg_crypto_context plg_cryptoctx,
|
|
Packit |
fd8b60 |
pkinit_req_crypto_context req_cryptoctx,
|
|
Packit |
fd8b60 |
pkinit_identity_opts *idopts,
|
|
Packit |
fd8b60 |
pkinit_identity_crypto_context id_cryptoctx,
|
|
Packit |
fd8b60 |
const char *value)
|
|
Packit |
fd8b60 |
{
|
|
Packit |
fd8b60 |
const char *residual;
|
|
Packit |
fd8b60 |
int idtype;
|
|
Packit |
fd8b60 |
krb5_error_code retval = 0;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
pkiDebug("%s: processing value '%s'\n",
|
|
Packit |
fd8b60 |
__FUNCTION__, value ? value : "NULL");
|
|
Packit |
fd8b60 |
if (value == NULL)
|
|
Packit |
fd8b60 |
return EINVAL;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
residual = strchr(value, ':');
|
|
Packit |
fd8b60 |
if (residual != NULL) {
|
|
Packit |
fd8b60 |
unsigned int typelen;
|
|
Packit |
fd8b60 |
residual++; /* skip past colon */
|
|
Packit |
fd8b60 |
typelen = residual - value;
|
|
Packit |
fd8b60 |
if (strncmp(value, "FILE:", typelen) == 0) {
|
|
Packit |
fd8b60 |
idtype = IDTYPE_FILE;
|
|
Packit |
fd8b60 |
#ifndef WITHOUT_PKCS11
|
|
Packit |
fd8b60 |
} else if (strncmp(value, "PKCS11:", typelen) == 0) {
|
|
Packit |
fd8b60 |
idtype = IDTYPE_PKCS11;
|
|
Packit |
fd8b60 |
#endif
|
|
Packit |
fd8b60 |
} else if (strncmp(value, "PKCS12:", typelen) == 0) {
|
|
Packit |
fd8b60 |
idtype = IDTYPE_PKCS12;
|
|
Packit |
fd8b60 |
} else if (strncmp(value, "DIR:", typelen) == 0) {
|
|
Packit |
fd8b60 |
idtype = IDTYPE_DIR;
|
|
Packit |
fd8b60 |
} else if (strncmp(value, "ENV:", typelen) == 0) {
|
|
Packit |
fd8b60 |
idtype = IDTYPE_ENVVAR;
|
|
Packit |
fd8b60 |
} else {
|
|
Packit |
fd8b60 |
pkiDebug("%s: Unsupported type while processing '%s'\n",
|
|
Packit |
fd8b60 |
__FUNCTION__, value);
|
|
Packit |
fd8b60 |
krb5_set_error_message(context, KRB5_PREAUTH_FAILED,
|
|
Packit |
fd8b60 |
_("Unsupported type while processing "
|
|
Packit |
fd8b60 |
"'%s'\n"), value);
|
|
Packit |
fd8b60 |
return KRB5_PREAUTH_FAILED;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
} else {
|
|
Packit |
fd8b60 |
idtype = IDTYPE_FILE;
|
|
Packit |
fd8b60 |
residual = value;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
idopts->idtype = idtype;
|
|
Packit |
fd8b60 |
pkiDebug("%s: idtype is %s\n", __FUNCTION__, idtype2string(idopts->idtype));
|
|
Packit |
fd8b60 |
switch (idtype) {
|
|
Packit |
fd8b60 |
case IDTYPE_ENVVAR:
|
|
Packit |
fd8b60 |
return process_option_identity(context, plg_cryptoctx, req_cryptoctx,
|
|
Packit |
fd8b60 |
idopts, id_cryptoctx,
|
|
Packit |
fd8b60 |
secure_getenv(residual));
|
|
Packit |
fd8b60 |
break;
|
|
Packit |
fd8b60 |
case IDTYPE_FILE:
|
|
Packit |
fd8b60 |
retval = parse_fs_options(context, idopts, residual);
|
|
Packit |
fd8b60 |
break;
|
|
Packit |
fd8b60 |
case IDTYPE_PKCS12:
|
|
Packit |
fd8b60 |
retval = parse_pkcs12_options(context, idopts, residual);
|
|
Packit |
fd8b60 |
break;
|
|
Packit |
fd8b60 |
#ifndef WITHOUT_PKCS11
|
|
Packit |
fd8b60 |
case IDTYPE_PKCS11:
|
|
Packit |
fd8b60 |
retval = parse_pkcs11_options(context, idopts, residual);
|
|
Packit |
fd8b60 |
break;
|
|
Packit |
fd8b60 |
#endif
|
|
Packit |
fd8b60 |
case IDTYPE_DIR:
|
|
Packit |
fd8b60 |
idopts->cert_filename = strdup(residual);
|
|
Packit |
fd8b60 |
if (idopts->cert_filename == NULL)
|
|
Packit |
fd8b60 |
retval = ENOMEM;
|
|
Packit |
fd8b60 |
break;
|
|
Packit |
fd8b60 |
default:
|
|
Packit |
fd8b60 |
krb5_set_error_message(context, KRB5_PREAUTH_FAILED,
|
|
Packit |
fd8b60 |
_("Internal error parsing "
|
|
Packit |
fd8b60 |
"X509_user_identity\n"));
|
|
Packit |
fd8b60 |
retval = EINVAL;
|
|
Packit |
fd8b60 |
break;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
return retval;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
static krb5_error_code
|
|
Packit |
fd8b60 |
process_option_ca_crl(krb5_context context,
|
|
Packit |
fd8b60 |
pkinit_plg_crypto_context plg_cryptoctx,
|
|
Packit |
fd8b60 |
pkinit_req_crypto_context req_cryptoctx,
|
|
Packit |
fd8b60 |
pkinit_identity_opts *idopts,
|
|
Packit |
fd8b60 |
pkinit_identity_crypto_context id_cryptoctx,
|
|
Packit |
fd8b60 |
const char *value,
|
|
Packit |
fd8b60 |
int catype)
|
|
Packit |
fd8b60 |
{
|
|
Packit |
fd8b60 |
char *residual;
|
|
Packit |
fd8b60 |
unsigned int typelen;
|
|
Packit |
fd8b60 |
int idtype;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
pkiDebug("%s: processing catype %s, value '%s'\n",
|
|
Packit |
fd8b60 |
__FUNCTION__, catype2string(catype), value);
|
|
Packit |
fd8b60 |
residual = strchr(value, ':');
|
|
Packit |
fd8b60 |
if (residual == NULL) {
|
|
Packit |
fd8b60 |
pkiDebug("No type given for '%s'\n", value);
|
|
Packit |
fd8b60 |
return EINVAL;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
residual++; /* skip past colon */
|
|
Packit |
fd8b60 |
typelen = residual - value;
|
|
Packit |
fd8b60 |
if (strncmp(value, "FILE:", typelen) == 0) {
|
|
Packit |
fd8b60 |
idtype = IDTYPE_FILE;
|
|
Packit |
fd8b60 |
} else if (strncmp(value, "DIR:", typelen) == 0) {
|
|
Packit |
fd8b60 |
idtype = IDTYPE_DIR;
|
|
Packit |
fd8b60 |
} else {
|
|
Packit |
fd8b60 |
return ENOTSUP;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
return crypto_load_cas_and_crls(context,
|
|
Packit |
fd8b60 |
plg_cryptoctx,
|
|
Packit |
fd8b60 |
req_cryptoctx,
|
|
Packit |
fd8b60 |
idopts, id_cryptoctx,
|
|
Packit |
fd8b60 |
idtype, catype, residual);
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
/*
|
|
Packit |
fd8b60 |
* Load any identity information which doesn't require us to ask a controlling
|
|
Packit |
fd8b60 |
* user any questions, and record the names of anything else which would
|
|
Packit |
fd8b60 |
* require us to ask questions.
|
|
Packit |
fd8b60 |
*/
|
|
Packit |
fd8b60 |
krb5_error_code
|
|
Packit |
fd8b60 |
pkinit_identity_initialize(krb5_context context,
|
|
Packit |
fd8b60 |
pkinit_plg_crypto_context plg_cryptoctx,
|
|
Packit |
fd8b60 |
pkinit_req_crypto_context req_cryptoctx,
|
|
Packit |
fd8b60 |
pkinit_identity_opts *idopts,
|
|
Packit |
fd8b60 |
pkinit_identity_crypto_context id_cryptoctx,
|
|
Packit |
fd8b60 |
krb5_clpreauth_callbacks cb,
|
|
Packit |
fd8b60 |
krb5_clpreauth_rock rock,
|
|
Packit |
fd8b60 |
krb5_principal princ)
|
|
Packit |
fd8b60 |
{
|
|
Packit |
fd8b60 |
krb5_error_code retval = EINVAL;
|
|
Packit |
fd8b60 |
int i;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
pkiDebug("%s: %p %p %p\n", __FUNCTION__, context, idopts, id_cryptoctx);
|
|
Packit |
fd8b60 |
if (!(princ &&
|
|
Packit |
fd8b60 |
krb5_principal_compare_any_realm(context, princ,
|
|
Packit |
fd8b60 |
krb5_anonymous_principal()))) {
|
|
Packit |
fd8b60 |
if (idopts == NULL || id_cryptoctx == NULL)
|
|
Packit |
fd8b60 |
goto errout;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
/*
|
|
Packit |
fd8b60 |
* If identity was specified, use that. (For the kdc, this
|
|
Packit |
fd8b60 |
* is specified as pkinit_identity in the kdc.conf. For users,
|
|
Packit |
fd8b60 |
* this is specified on the command line via X509_user_identity.)
|
|
Packit |
fd8b60 |
* If a user did not specify identity on the command line,
|
|
Packit |
fd8b60 |
* then we will try alternatives which may have been specified
|
|
Packit |
fd8b60 |
* in the config file.
|
|
Packit |
fd8b60 |
*/
|
|
Packit |
fd8b60 |
if (idopts->identity != NULL) {
|
|
Packit |
fd8b60 |
retval = process_option_identity(context, plg_cryptoctx,
|
|
Packit |
fd8b60 |
req_cryptoctx, idopts,
|
|
Packit |
fd8b60 |
id_cryptoctx, idopts->identity);
|
|
Packit |
fd8b60 |
} else if (idopts->identity_alt != NULL) {
|
|
Packit |
fd8b60 |
for (i = 0; retval != 0 && idopts->identity_alt[i] != NULL; i++) {
|
|
Packit |
fd8b60 |
retval = process_option_identity(context, plg_cryptoctx,
|
|
Packit |
fd8b60 |
req_cryptoctx, idopts,
|
|
Packit |
fd8b60 |
id_cryptoctx,
|
|
Packit |
fd8b60 |
idopts->identity_alt[i]);
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
} else {
|
|
Packit |
fd8b60 |
retval = KRB5_PREAUTH_FAILED;
|
|
Packit |
fd8b60 |
krb5_set_error_message(context, retval,
|
|
Packit |
fd8b60 |
_("No user identity options specified"));
|
|
Packit |
fd8b60 |
pkiDebug("%s: no user identity options specified\n", __FUNCTION__);
|
|
Packit |
fd8b60 |
goto errout;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
if (retval)
|
|
Packit |
fd8b60 |
goto errout;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
retval = crypto_load_certs(context, plg_cryptoctx, req_cryptoctx,
|
|
Packit |
fd8b60 |
idopts, id_cryptoctx, princ, TRUE);
|
|
Packit |
fd8b60 |
if (retval)
|
|
Packit |
fd8b60 |
goto errout;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
crypto_free_cert_info(context, plg_cryptoctx, req_cryptoctx,
|
|
Packit |
fd8b60 |
id_cryptoctx);
|
|
Packit |
fd8b60 |
} else {
|
|
Packit |
fd8b60 |
/* We're the anonymous principal. */
|
|
Packit |
fd8b60 |
retval = 0;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
errout:
|
|
Packit |
fd8b60 |
return retval;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
/*
|
|
Packit |
fd8b60 |
* Load identity information, including that which requires us to ask a
|
|
Packit |
fd8b60 |
* controlling user any questions. If we have PIN/password values which
|
|
Packit |
fd8b60 |
* correspond to a given identity, use that, otherwise, if one is available,
|
|
Packit |
fd8b60 |
* we'll use the prompter callback.
|
|
Packit |
fd8b60 |
*/
|
|
Packit |
fd8b60 |
krb5_error_code
|
|
Packit |
fd8b60 |
pkinit_identity_prompt(krb5_context context,
|
|
Packit |
fd8b60 |
pkinit_plg_crypto_context plg_cryptoctx,
|
|
Packit |
fd8b60 |
pkinit_req_crypto_context req_cryptoctx,
|
|
Packit |
fd8b60 |
pkinit_identity_opts *idopts,
|
|
Packit |
fd8b60 |
pkinit_identity_crypto_context id_cryptoctx,
|
|
Packit |
fd8b60 |
krb5_clpreauth_callbacks cb,
|
|
Packit |
fd8b60 |
krb5_clpreauth_rock rock,
|
|
Packit |
fd8b60 |
int do_matching,
|
|
Packit |
fd8b60 |
krb5_principal princ)
|
|
Packit |
fd8b60 |
{
|
|
Packit |
fd8b60 |
krb5_error_code retval = EINVAL;
|
|
Packit |
fd8b60 |
const char *signer_identity;
|
|
Packit |
fd8b60 |
int i;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
pkiDebug("%s: %p %p %p\n", __FUNCTION__, context, idopts, id_cryptoctx);
|
|
Packit |
fd8b60 |
if (!(princ &&
|
|
Packit |
fd8b60 |
krb5_principal_compare_any_realm(context, princ,
|
|
Packit |
fd8b60 |
krb5_anonymous_principal()))) {
|
|
Packit |
fd8b60 |
retval = crypto_load_certs(context, plg_cryptoctx, req_cryptoctx,
|
|
Packit |
fd8b60 |
idopts, id_cryptoctx, princ, FALSE);
|
|
Packit |
fd8b60 |
if (retval)
|
|
Packit |
fd8b60 |
goto errout;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
if (do_matching) {
|
|
Packit |
fd8b60 |
/*
|
|
Packit |
fd8b60 |
* Try to select exactly one certificate based on matching
|
|
Packit |
fd8b60 |
* criteria. Typical used for clients.
|
|
Packit |
fd8b60 |
*/
|
|
Packit |
fd8b60 |
retval = pkinit_cert_matching(context, plg_cryptoctx,
|
|
Packit |
fd8b60 |
req_cryptoctx, id_cryptoctx, princ);
|
|
Packit |
fd8b60 |
if (retval) {
|
|
Packit |
fd8b60 |
crypto_free_cert_info(context, plg_cryptoctx, req_cryptoctx,
|
|
Packit |
fd8b60 |
id_cryptoctx);
|
|
Packit |
fd8b60 |
goto errout;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
} else {
|
|
Packit |
fd8b60 |
/*
|
|
Packit |
fd8b60 |
* Tell crypto code to use the "default" identity. Typically used
|
|
Packit |
fd8b60 |
* for KDCs.
|
|
Packit |
fd8b60 |
*/
|
|
Packit |
fd8b60 |
retval = crypto_cert_select_default(context, plg_cryptoctx,
|
|
Packit |
fd8b60 |
req_cryptoctx, id_cryptoctx);
|
|
Packit |
fd8b60 |
if (retval) {
|
|
Packit |
fd8b60 |
crypto_free_cert_info(context, plg_cryptoctx, req_cryptoctx,
|
|
Packit |
fd8b60 |
id_cryptoctx);
|
|
Packit |
fd8b60 |
goto errout;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
if (rock != NULL && cb != NULL && retval == 0) {
|
|
Packit |
fd8b60 |
/* Save the signer identity if we're the client. */
|
|
Packit |
fd8b60 |
if (crypto_retrieve_signer_identity(context, id_cryptoctx,
|
|
Packit |
fd8b60 |
&signer_identity) == 0) {
|
|
Packit |
fd8b60 |
cb->set_cc_config(context, rock, "X509_user_identity",
|
|
Packit |
fd8b60 |
signer_identity);
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
retval = crypto_free_cert_info(context, plg_cryptoctx, req_cryptoctx,
|
|
Packit |
fd8b60 |
id_cryptoctx);
|
|
Packit |
fd8b60 |
if (retval)
|
|
Packit |
fd8b60 |
goto errout;
|
|
Packit |
fd8b60 |
} /* Not anonymous principal */
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
for (i = 0; idopts->anchors != NULL && idopts->anchors[i] != NULL; i++) {
|
|
Packit |
fd8b60 |
retval = process_option_ca_crl(context, plg_cryptoctx, req_cryptoctx,
|
|
Packit |
fd8b60 |
idopts, id_cryptoctx,
|
|
Packit |
fd8b60 |
idopts->anchors[i], CATYPE_ANCHORS);
|
|
Packit |
fd8b60 |
if (retval)
|
|
Packit |
fd8b60 |
goto errout;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
for (i = 0; idopts->intermediates != NULL
|
|
Packit |
fd8b60 |
&& idopts->intermediates[i] != NULL; i++) {
|
|
Packit |
fd8b60 |
retval = process_option_ca_crl(context, plg_cryptoctx, req_cryptoctx,
|
|
Packit |
fd8b60 |
idopts, id_cryptoctx,
|
|
Packit |
fd8b60 |
idopts->intermediates[i],
|
|
Packit |
fd8b60 |
CATYPE_INTERMEDIATES);
|
|
Packit |
fd8b60 |
if (retval)
|
|
Packit |
fd8b60 |
goto errout;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
for (i = 0; idopts->crls != NULL && idopts->crls[i] != NULL; i++) {
|
|
Packit |
fd8b60 |
retval = process_option_ca_crl(context, plg_cryptoctx, req_cryptoctx,
|
|
Packit |
fd8b60 |
idopts, id_cryptoctx, idopts->crls[i],
|
|
Packit |
fd8b60 |
CATYPE_CRLS);
|
|
Packit |
fd8b60 |
if (retval)
|
|
Packit |
fd8b60 |
goto errout;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
errout:
|
|
Packit |
fd8b60 |
return retval;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
/*
|
|
Packit |
fd8b60 |
* Create an entry in the passed-in list for the named identity, optionally
|
|
Packit |
fd8b60 |
* with the specified token flag value and/or supplied password, replacing any
|
|
Packit |
fd8b60 |
* existing entry with the same identity name.
|
|
Packit |
fd8b60 |
*/
|
|
Packit |
fd8b60 |
krb5_error_code
|
|
Packit |
fd8b60 |
pkinit_set_deferred_id(pkinit_deferred_id **identities,
|
|
Packit |
fd8b60 |
const char *identity, unsigned long ck_flags,
|
|
Packit |
fd8b60 |
const char *password)
|
|
Packit |
fd8b60 |
{
|
|
Packit |
fd8b60 |
int i;
|
|
Packit |
fd8b60 |
pkinit_deferred_id *out = NULL, *ids;
|
|
Packit |
fd8b60 |
char *tmp;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
/* Search for an entry that's already in the list. */
|
|
Packit |
fd8b60 |
ids = *identities;
|
|
Packit |
fd8b60 |
for (i = 0; ids != NULL && ids[i] != NULL; i++) {
|
|
Packit |
fd8b60 |
if (strcmp(ids[i]->identity, identity) == 0) {
|
|
Packit |
fd8b60 |
/* Replace its password value, then we're done. */
|
|
Packit |
fd8b60 |
tmp = password ? strdup(password) : NULL;
|
|
Packit |
fd8b60 |
if (password != NULL && tmp == NULL)
|
|
Packit |
fd8b60 |
return ENOMEM;
|
|
Packit |
fd8b60 |
ids[i]->ck_flags = ck_flags;
|
|
Packit |
fd8b60 |
free(ids[i]->password);
|
|
Packit |
fd8b60 |
ids[i]->password = tmp;
|
|
Packit |
fd8b60 |
return 0;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
/* Resize the list. */
|
|
Packit |
fd8b60 |
out = realloc(ids, sizeof(*ids) * (i + 2));
|
|
Packit |
fd8b60 |
if (out == NULL)
|
|
Packit |
fd8b60 |
goto oom;
|
|
Packit |
fd8b60 |
*identities = out;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
/* Allocate the new final entry. */
|
|
Packit |
fd8b60 |
out[i] = malloc(sizeof(*(out[i])));
|
|
Packit |
fd8b60 |
if (out[i] == NULL)
|
|
Packit |
fd8b60 |
goto oom;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
/* Populate the new entry. */
|
|
Packit |
fd8b60 |
out[i]->magic = PKINIT_DEFERRED_ID_MAGIC;
|
|
Packit |
fd8b60 |
out[i]->identity = strdup(identity);
|
|
Packit |
fd8b60 |
if (out[i]->identity == NULL)
|
|
Packit |
fd8b60 |
goto oom;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
out[i]->ck_flags = ck_flags;
|
|
Packit |
fd8b60 |
out[i]->password = password ? strdup(password) : NULL;
|
|
Packit |
fd8b60 |
if (password != NULL && out[i]->password == NULL)
|
|
Packit |
fd8b60 |
goto oom;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
/* Terminate the list. */
|
|
Packit |
fd8b60 |
out[i + 1] = NULL;
|
|
Packit |
fd8b60 |
return 0;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
oom:
|
|
Packit |
fd8b60 |
if (out != NULL && out[i] != NULL) {
|
|
Packit |
fd8b60 |
free(out[i]->identity);
|
|
Packit |
fd8b60 |
free(out[i]);
|
|
Packit |
fd8b60 |
out[i] = NULL;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
return ENOMEM;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
/*
|
|
Packit |
fd8b60 |
* Return a password which we've associated with the named identity, if we've
|
|
Packit |
fd8b60 |
* stored one. Otherwise return NULL.
|
|
Packit |
fd8b60 |
*/
|
|
Packit |
fd8b60 |
const char *
|
|
Packit |
fd8b60 |
pkinit_find_deferred_id(pkinit_deferred_id *identities,
|
|
Packit |
fd8b60 |
const char *identity)
|
|
Packit |
fd8b60 |
{
|
|
Packit |
fd8b60 |
int i;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
for (i = 0; identities != NULL && identities[i] != NULL; i++) {
|
|
Packit |
fd8b60 |
if (strcmp(identities[i]->identity, identity) == 0)
|
|
Packit |
fd8b60 |
return identities[i]->password;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
return NULL;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
/*
|
|
Packit |
fd8b60 |
* Return the flags associated with the specified identity, or 0 if we don't
|
|
Packit |
fd8b60 |
* have such an identity.
|
|
Packit |
fd8b60 |
*/
|
|
Packit |
fd8b60 |
unsigned long
|
|
Packit |
fd8b60 |
pkinit_get_deferred_id_flags(pkinit_deferred_id *identities,
|
|
Packit |
fd8b60 |
const char *identity)
|
|
Packit |
fd8b60 |
{
|
|
Packit |
fd8b60 |
int i;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
for (i = 0; identities != NULL && identities[i] != NULL; i++) {
|
|
Packit |
fd8b60 |
if (strcmp(identities[i]->identity, identity) == 0)
|
|
Packit |
fd8b60 |
return identities[i]->ck_flags;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
return 0;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
/*
|
|
Packit |
fd8b60 |
* Free a deferred_id list.
|
|
Packit |
fd8b60 |
*/
|
|
Packit |
fd8b60 |
void
|
|
Packit |
fd8b60 |
pkinit_free_deferred_ids(pkinit_deferred_id *identities)
|
|
Packit |
fd8b60 |
{
|
|
Packit |
fd8b60 |
int i;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
for (i = 0; identities != NULL && identities[i] != NULL; i++) {
|
|
Packit |
fd8b60 |
free(identities[i]->identity);
|
|
Packit |
fd8b60 |
free(identities[i]->password);
|
|
Packit |
fd8b60 |
free(identities[i]);
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
free(identities);
|
|
Packit |
fd8b60 |
}
|