summaryrefslogtreecommitdiffstats
path: root/src/lib/krb5
diff options
context:
space:
mode:
authorNalin Dahyabhai <nalin@redhat.com>2013-07-15 13:37:00 -0400
committerGreg Hudson <ghudson@mit.edu>2013-07-17 14:57:12 -0400
commitce02b69e27bcfa21bcab2ed195dfdbaa8040d773 (patch)
tree1213a149da22345fd53df9cfe85bf269a0aedb36 /src/lib/krb5
parenta3abb0bf5fade0009c9899624d4b996a4e12a49f (diff)
downloadkrb5-ce02b69e27bcfa21bcab2ed195dfdbaa8040d773.tar.gz
krb5-ce02b69e27bcfa21bcab2ed195dfdbaa8040d773.tar.xz
krb5-ce02b69e27bcfa21bcab2ed195dfdbaa8040d773.zip
Add non-JSON APIs for PKINIT responder items
Add wrappers for the JSON-oriented APIs for PKINIT responder items, modeled after the API we provide for OTP items: * krb5_responder_pkinit_get_challenge() returns the list of identities for which we need PINs * krb5_responder_pkinit_challenge_free() frees the structure that was returned by krb5_responder_pkinit_get_challenge() * krb5_responder_pkinit_set_answer() sets the answer to the PIN for one of the identities [ghudson@mit.edu: style cleanup; added comment pointing to main body of PKINIT module] ticket: 7680
Diffstat (limited to 'src/lib/krb5')
-rw-r--r--src/lib/krb5/krb/Makefile.in3
-rw-r--r--src/lib/krb5/krb/deps12
-rw-r--r--src/lib/krb5/krb/preauth_pkinit.c204
-rw-r--r--src/lib/krb5/libkrb5.exports3
4 files changed, 222 insertions, 0 deletions
diff --git a/src/lib/krb5/krb/Makefile.in b/src/lib/krb5/krb/Makefile.in
index d5db2749ba..3cf857e0d2 100644
--- a/src/lib/krb5/krb/Makefile.in
+++ b/src/lib/krb5/krb/Makefile.in
@@ -77,6 +77,7 @@ STLIBOBJS= \
preauth_ec.o \
preauth_encts.o \
preauth_otp.o \
+ preauth_pkinit.o \
preauth_sam2.o \
gic_opt_set_pa.o \
princ_comp.o \
@@ -185,6 +186,7 @@ OBJS= $(OUTPRE)addr_comp.$(OBJEXT) \
$(OUTPRE)preauth_ec.$(OBJEXT) \
$(OUTPRE)preauth_encts.$(OBJEXT) \
$(OUTPRE)preauth_otp.$(OBJEXT) \
+ $(OUTPRE)preauth_pkinit.$(OBJEXT) \
$(OUTPRE)preauth_sam2.$(OBJEXT) \
$(OUTPRE)gic_opt_set_pa.$(OBJEXT) \
$(OUTPRE)princ_comp.$(OBJEXT) \
@@ -293,6 +295,7 @@ SRCS= $(srcdir)/addr_comp.c \
$(srcdir)/preauth_ec.c \
$(srcdir)/preauth_encts.c \
$(srcdir)/preauth_otp.c \
+ $(srcdir)/preauth_pkinit.c \
$(srcdir)/preauth_sam2.c \
$(srcdir)/gic_opt_set_pa.c \
$(srcdir)/princ_comp.c \
diff --git a/src/lib/krb5/krb/deps b/src/lib/krb5/krb/deps
index f4bbc69351..798417308d 100644
--- a/src/lib/krb5/krb/deps
+++ b/src/lib/krb5/krb/deps
@@ -758,6 +758,18 @@ preauth_otp.so preauth_otp.po $(OUTPRE)preauth_otp.$(OBJEXT): \
$(top_srcdir)/include/krb5/clpreauth_plugin.h $(top_srcdir)/include/krb5/plugin.h \
$(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \
int-proto.h preauth_otp.c
+preauth_pkinit.so preauth_pkinit.po $(OUTPRE)preauth_pkinit.$(OBJEXT): \
+ $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+ $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+ $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \
+ $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \
+ $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-json.h \
+ $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \
+ $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \
+ $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \
+ $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \
+ $(top_srcdir)/include/socket-utils.h init_creds_ctx.h \
+ int-proto.h preauth_pkinit.c
preauth_sam2.so preauth_sam2.po $(OUTPRE)preauth_sam2.$(OBJEXT): \
$(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
$(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
diff --git a/src/lib/krb5/krb/preauth_pkinit.c b/src/lib/krb5/krb/preauth_pkinit.c
new file mode 100644
index 0000000000..02810f2bef
--- /dev/null
+++ b/src/lib/krb5/krb/preauth_pkinit.c
@@ -0,0 +1,204 @@
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/* lib/krb5/krb/preauth_pkinit.c - PKINIT clpreauth helpers */
+/*
+ * Copyright 2013 Red Hat, Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * This file defines libkrb5 APIs for manipulating PKINIT responder questions
+ * and answers. The main body of the PKINIT clpreauth module is in the
+ * plugins/preauth/pkinit directory.
+ */
+
+#include "k5-int.h"
+#include "k5-json.h"
+#include "int-proto.h"
+#include "init_creds_ctx.h"
+
+struct get_one_challenge_data {
+ krb5_responder_pkinit_identity **identities;
+ krb5_error_code err;
+};
+
+static void
+get_one_challenge(void *arg, const char *key, k5_json_value val)
+{
+ struct get_one_challenge_data *data;
+ unsigned long token_flags;
+ int i;
+
+ data = arg;
+ if (data->err != 0)
+ return;
+ if (k5_json_get_tid(val) != K5_JSON_TID_NUMBER) {
+ data->err = EINVAL;
+ return;
+ }
+
+ token_flags = k5_json_number_value(val);
+ /* Find the slot for this entry. */
+ for (i = 0; data->identities[i] != NULL; i++)
+ continue;
+ /* Set the identity (a copy of the key) and the token flags. */
+ data->identities[i] = k5alloc(sizeof(*data->identities[i]), &data->err);
+ if (data->identities[i] == NULL)
+ return;
+ data->identities[i]->identity = strdup(key);
+ if (data->identities[i]->identity == NULL) {
+ data->err = ENOMEM;
+ return;
+ }
+ data->identities[i]->token_flags = token_flags;
+}
+
+krb5_error_code KRB5_CALLCONV
+krb5_responder_pkinit_get_challenge(krb5_context ctx,
+ krb5_responder_context rctx,
+ krb5_responder_pkinit_challenge **chl_out)
+{
+ const char *challenge;
+ k5_json_value j;
+ struct get_one_challenge_data get_one_challenge_data;
+ krb5_responder_pkinit_challenge *chl = NULL;
+ unsigned int n_ids;
+ krb5_error_code ret;
+
+ *chl_out = NULL;
+ challenge = krb5_responder_get_challenge(ctx, rctx,
+ KRB5_RESPONDER_QUESTION_PKINIT);
+ if (challenge == NULL)
+ return 0;
+
+ ret = k5_json_decode(challenge, &j);
+ if (ret != 0)
+ return ret;
+
+ /* Create the returned object. */
+ chl = k5alloc(sizeof(*chl), &ret);
+ if (chl == NULL)
+ goto failed;
+
+ /* Create the list of identities. */
+ n_ids = k5_json_object_count(j);
+ chl->identities = k5calloc(n_ids + 1, sizeof(chl->identities[0]), &ret);
+ if (chl->identities == NULL)
+ goto failed;
+
+ /* Populate the object with identities. */
+ memset(&get_one_challenge_data, 0, sizeof(get_one_challenge_data));
+ get_one_challenge_data.identities = chl->identities;
+ k5_json_object_iterate(j, get_one_challenge, &get_one_challenge_data);
+ if (get_one_challenge_data.err != 0) {
+ ret = get_one_challenge_data.err;
+ goto failed;
+ }
+
+ /* All done. */
+ k5_json_release(j);
+ *chl_out = chl;
+ return 0;
+
+failed:
+ k5_json_release(j);
+ krb5_responder_pkinit_challenge_free(ctx, rctx, chl);
+ return ret;
+}
+
+krb5_error_code KRB5_CALLCONV
+krb5_responder_pkinit_set_answer(krb5_context ctx, krb5_responder_context rctx,
+ const char *identity, const char *pin)
+{
+ char *answer = NULL;
+ const char *old_answer;
+ k5_json_value answers = NULL;
+ k5_json_string jpin = NULL;
+ krb5_error_code ret = ENOMEM;
+
+ /* If there's an answer already set, we're adding/removing a value. */
+ old_answer = k5_response_items_get_answer(rctx->items,
+ KRB5_RESPONDER_QUESTION_PKINIT);
+
+ /* If we're removing a value, and we have no values, we're done. */
+ if (old_answer == NULL && pin == NULL)
+ return 0;
+
+ /* Decode the old answers. */
+ if (old_answer == NULL)
+ old_answer = "{}";
+ ret = k5_json_decode(old_answer, &answers);
+ if (ret != 0)
+ goto cleanup;
+
+ if (k5_json_get_tid(answers) != K5_JSON_TID_OBJECT) {
+ ret = EINVAL;
+ goto cleanup;
+ }
+
+ /* Create and add the new pin string, if we're adding a value. */
+ if (pin != NULL) {
+ ret = k5_json_string_create(pin, &jpin);
+ if (ret != 0)
+ goto cleanup;
+ ret = k5_json_object_set(answers, identity, jpin);
+ if (ret != 0)
+ goto cleanup;
+ } else {
+ ret = k5_json_object_set(answers, identity, NULL);
+ if (ret != 0)
+ goto cleanup;
+ }
+
+ /* Encode and we're done. */
+ ret = k5_json_encode(answers, &answer);
+ if (ret != 0)
+ goto cleanup;
+
+ ret = krb5_responder_set_answer(ctx, rctx, KRB5_RESPONDER_QUESTION_PKINIT,
+ answer);
+
+cleanup:
+ k5_json_release(jpin);
+ k5_json_release(answers);
+ free(answer);
+ return ret;
+}
+
+void KRB5_CALLCONV
+krb5_responder_pkinit_challenge_free(krb5_context ctx,
+ krb5_responder_context rctx,
+ krb5_responder_pkinit_challenge *chl)
+{
+ unsigned int i;
+
+ if (chl == NULL)
+ return;
+ for (i = 0; chl->identities != NULL && chl->identities[i] != NULL; i++) {
+ free(chl->identities[i]->identity);
+ free(chl->identities[i]);
+ }
+ free(chl->identities);
+ free(chl);
+}
diff --git a/src/lib/krb5/libkrb5.exports b/src/lib/krb5/libkrb5.exports
index f91e468d77..471671bf1b 100644
--- a/src/lib/krb5/libkrb5.exports
+++ b/src/lib/krb5/libkrb5.exports
@@ -525,6 +525,9 @@ krb5_responder_set_answer
krb5_responder_otp_get_challenge
krb5_responder_otp_set_answer
krb5_responder_otp_challenge_free
+krb5_responder_pkinit_get_challenge
+krb5_responder_pkinit_set_answer
+krb5_responder_pkinit_challenge_free
krb5_salttype_to_string
krb5_sendauth
krb5_sendto_kdc