#define PKINIT_CTX_MAGIC 0x05551212
#define PKINIT_REQ_CTX_MAGIC 0xdeadbeef
+#define PKINIT_DEFERRED_ID_MAGIC 0x3ca20d21
#define PKINIT_DEFAULT_DH_MIN_BITS 2048
#define PKINIT_DH_MIN_CONFIG_BITS 1024
pkinit_identity_crypto_context id_cryptoctx,
krb5_principal princ);
+/*
+ * Client's list of identities for which it needs PINs or passwords
+ */
+struct _pkinit_deferred_id {
+ int magic;
+ char *identity;
+ unsigned long ck_flags;
+ char *password;
+};
+typedef struct _pkinit_deferred_id *pkinit_deferred_id;
+
+krb5_error_code pkinit_set_deferred_id
+ (pkinit_deferred_id **identities, const char *identity,
+ unsigned long ck_flags, const char *password);
+const char * pkinit_find_deferred_id
+ (pkinit_deferred_id *identities, const char *identity);
+unsigned long pkinit_get_deferred_id_flags
+ (pkinit_deferred_id *identities, const char *identity);
+void pkinit_free_deferred_ids(pkinit_deferred_id *identities);
+
/*
* initialization and free functions
*/
unsigned int *kdcId_len); /* OUT
receives length of encoded kdcPKId */
+/*
+ * These functions manipulate the deferred-identities list in the identity
+ * context, which is opaque outside of the crypto-specific bits.
+ */
+const pkinit_deferred_id * crypto_get_deferred_ids
+ (krb5_context context, pkinit_identity_crypto_context id_cryptoctx);
+krb5_error_code crypto_set_deferred_id
+ (krb5_context context,
+ pkinit_identity_crypto_context id_cryptoctx,
+ const char *identity, const char *password);
+
/*
* process the values from idopts and obtain the cert(s)
* specified by those options, populating the id_cryptoctx.
krb5_prompter_fct prompter;
void *prompter_data;
} pwcb_args;
+ krb5_boolean defer_id_prompt;
+ pkinit_deferred_id *deferred_ids;
};
struct _pkinit_cert_info { /* aka _pkinit_cert_handle */
pkiDebug("%s\n", __FUNCTION__);
/* The order of cleanup here is intended to ensure that nothing gets
* freed before anything that might have a reference to it. */
+ if (id_cryptoctx->deferred_ids != NULL)
+ pkinit_free_deferred_ids(id_cryptoctx->deferred_ids);
if (id_cryptoctx->id_cert != NULL)
CERT_DestroyCertificate(id_cryptoctx->id_cert);
CERT_DestroyCertList(id_cryptoctx->ca_certs);
{
SECStatus status;
+ id_cryptoctx->defer_id_prompt = defer_id_prompts;
+
switch (idopts->idtype) {
case IDTYPE_FILE:
status = crypto_load_files(context,
return 0;
}
+
+/*
+ * Add an item to the pkinit_identity_crypto_context's list of deferred
+ * identities.
+ */
+krb5_error_code
+crypto_set_deferred_id(krb5_context context,
+ pkinit_identity_crypto_context id_cryptoctx,
+ const char *identity, const char *password)
+{
+ unsigned long ck_flags;
+
+ ck_flags = pkinit_get_deferred_id_flags(id_cryptoctx->deferred_ids,
+ identity);
+ return pkinit_set_deferred_id(&id_cryptoctx->deferred_ids,
+ identity, ck_flags, password);
+}
+
+/*
+ * Retrieve a read-only copy of the pkinit_identity_crypto_context's list of
+ * deferred identities, sure to be valid only until the next time someone calls
+ * either pkinit_set_deferred_id() or crypto_set_deferred_id().
+ */
+const pkinit_deferred_id *
+crypto_get_deferred_ids(krb5_context context,
+ pkinit_identity_crypto_context id_cryptoctx)
+{
+ pkinit_deferred_id *deferred;
+ const pkinit_deferred_id *ret;
+
+ deferred = id_cryptoctx->deferred_ids;
+ ret = (const pkinit_deferred_id *)deferred;
+ return ret;
+}
return;
pkiDebug("%s: freeing ctx at %p\n", __FUNCTION__, idctx);
+ if (idctx->deferred_ids != NULL)
+ pkinit_free_deferred_ids(idctx->deferred_ids);
free(idctx->identity);
pkinit_fini_certs(idctx);
pkinit_fini_pkcs11(idctx);
{
krb5_error_code retval;
+ id_cryptoctx->defer_id_prompt = defer_id_prompts;
+
switch(idopts->idtype) {
case IDTYPE_FILE:
retval = pkinit_get_certs_fs(context, plg_cryptoctx,
snprintf(uc, sizeof(uc), _("unknown code 0x%x"), err);
return (uc);
}
+
+/*
+ * Add an item to the pkinit_identity_crypto_context's list of deferred
+ * identities.
+ */
+krb5_error_code
+crypto_set_deferred_id(krb5_context context,
+ pkinit_identity_crypto_context id_cryptoctx,
+ const char *identity, const char *password)
+{
+ unsigned long flags;
+
+ flags = pkinit_get_deferred_id_flags(id_cryptoctx->deferred_ids,
+ identity);
+ return pkinit_set_deferred_id(&id_cryptoctx->deferred_ids,
+ identity, flags, password);
+}
+
+/*
+ * Retrieve a read-only copy of the pkinit_identity_crypto_context's list of
+ * deferred identities, sure to be valid only until the next time someone calls
+ * either pkinit_set_deferred_id() or crypto_set_deferred_id().
+ */
+const pkinit_deferred_id *
+crypto_get_deferred_ids(krb5_context context,
+ pkinit_identity_crypto_context id_cryptoctx)
+{
+ pkinit_deferred_id *deferred;
+ const pkinit_deferred_id *ret;
+
+ deferred = id_cryptoctx->deferred_ids;
+ ret = (const pkinit_deferred_id *)deferred;
+ return ret;
+}
int cert_id_len;
CK_MECHANISM_TYPE mech;
#endif
+ krb5_boolean defer_id_prompt;
+ pkinit_deferred_id *deferred_ids;
};
struct _pkinit_plg_crypto_context {
errout:
return retval;
}
+
+/*
+ * Create an entry in the passed-in list for the named identity, optionally
+ * with the specified token flag value and/or supplied password, replacing any
+ * existing entry with the same identity name.
+ */
+krb5_error_code
+pkinit_set_deferred_id(pkinit_deferred_id **identities,
+ const char *identity, unsigned long ck_flags,
+ const char *password)
+{
+ int i;
+ pkinit_deferred_id *out = NULL, *ids;
+ char *tmp;
+
+ /* Search for an entry that's already in the list. */
+ ids = *identities;
+ for (i = 0; ids != NULL && ids[i] != NULL; i++) {
+ if (strcmp(ids[i]->identity, identity) == 0) {
+ /* Replace its password value, then we're done. */
+ tmp = password ? strdup(password) : NULL;
+ if (password != NULL && tmp == NULL)
+ return ENOMEM;
+ ids[i]->ck_flags = ck_flags;
+ free(ids[i]->password);
+ ids[i]->password = tmp;
+ return 0;
+ }
+ }
+
+ /* Resize the list. */
+ out = realloc(ids, sizeof(*ids) * (i + 2));
+ if (out == NULL)
+ goto oom;
+ *identities = out;
+
+ /* Allocate the new final entry. */
+ out[i] = malloc(sizeof(*(out[i])));
+ if (out[i] == NULL)
+ goto oom;
+
+ /* Populate the new entry. */
+ out[i]->magic = PKINIT_DEFERRED_ID_MAGIC;
+ out[i]->identity = strdup(identity);
+ if (out[i]->identity == NULL)
+ goto oom;
+
+ out[i]->ck_flags = ck_flags;
+ out[i]->password = password ? strdup(password) : NULL;
+ if (password != NULL && out[i]->password == NULL)
+ goto oom;
+
+ /* Terminate the list. */
+ out[i + 1] = NULL;
+ return 0;
+
+oom:
+ if (out != NULL && out[i] != NULL) {
+ free(out[i]->identity);
+ free(out[i]);
+ out[i] = NULL;
+ }
+ return ENOMEM;
+}
+
+/*
+ * Return a password which we've associated with the named identity, if we've
+ * stored one. Otherwise return NULL.
+ */
+const char *
+pkinit_find_deferred_id(pkinit_deferred_id *identities,
+ const char *identity)
+{
+ int i;
+
+ for (i = 0; identities != NULL && identities[i] != NULL; i++) {
+ if (strcmp(identities[i]->identity, identity) == 0)
+ return identities[i]->password;
+ }
+ return NULL;
+}
+
+/*
+ * Return the flags associated with the specified identity, or 0 if we don't
+ * have such an identity.
+ */
+unsigned long
+pkinit_get_deferred_id_flags(pkinit_deferred_id *identities,
+ const char *identity)
+{
+ int i;
+
+ for (i = 0; identities != NULL && identities[i] != NULL; i++) {
+ if (strcmp(identities[i]->identity, identity) == 0)
+ return identities[i]->ck_flags;
+ }
+ return 0;
+}
+
+/*
+ * Free a deferred_id list.
+ */
+void
+pkinit_free_deferred_ids(pkinit_deferred_id *identities)
+{
+ int i;
+
+ for (i = 0; identities != NULL && identities[i] != NULL; i++) {
+ free(identities[i]->identity);
+ free(identities[i]->password);
+ free(identities[i]);
+ }
+ free(identities);
+}