summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAngelos D. Keromytis <angelos@cvs.openbsd.org>1999-11-05 00:27:19 +0000
committerAngelos D. Keromytis <angelos@cvs.openbsd.org>1999-11-05 00:27:19 +0000
commite576f6b24979b2eccc2c49bc5c8a89b130112985 (patch)
treef66fa288d4332b1bf71284880e15b36765427d1f
parent98ba299dfa58d2afca5f511d6774e0b2d0eaba5b (diff)
Add a sample application as a usage guide, minor manpage correction.
-rw-r--r--lib/libkeynote/Makefile.in9
-rw-r--r--lib/libkeynote/README5
-rw-r--r--lib/libkeynote/TODO3
-rw-r--r--lib/libkeynote/keynote-sigver.c18
-rw-r--r--lib/libkeynote/keynote.312
-rw-r--r--lib/libkeynote/sample-app.c544
6 files changed, 577 insertions, 14 deletions
diff --git a/lib/libkeynote/Makefile.in b/lib/libkeynote/Makefile.in
index 14f97cbfce3..a07f101b665 100644
--- a/lib/libkeynote/Makefile.in
+++ b/lib/libkeynote/Makefile.in
@@ -1,4 +1,4 @@
-# $OpenBSD: Makefile.in,v 1.7 1999/10/26 22:31:37 angelos Exp $
+# $OpenBSD: Makefile.in,v 1.8 1999/11/05 00:27:18 angelos Exp $
#
# The author of this code is Angelos D. Keromytis (angelos@dsl.cis.upenn.edu)
#
@@ -62,11 +62,13 @@ LIBS = -L. -lkeynote @LIBS@
TARGET = libkeynote.a
TARGET2 = keynote
+TARGET3 = sample-app
OBJS = k.tab.o lex.kn.o environment.o parse_assertion.o \
signature.o aux.o base64.o
OBJS2 = z.tab.o lex.kv.o keynote-verify.o keynote-sign.o \
keynote-sigver.o keynote-keygen.o keynote-main.o @LIBOBJS@
+OBJS3 = sample-app.o
crypto: all
@@ -120,7 +122,7 @@ cleandir: cleanall
cleanall: clean
$(RM) $(RMFLAGS) *.o k.tab.c lex.kn.c k.tab.h z.tab.c z.tab.h
$(RM) $(RMFLAGS) lex.kv.c y.output z.output ${DISTFILE}
- $(RM) $(RMFLAGS) $(TARGET) $(TARGET2) man/*.0 config.cache
+ $(RM) $(RMFLAGS) $(TARGET) $(TARGET2) $(TARGET3) man/*.0 config.cache
$(RM) $(RMFLAGS) config.log config.status config.h Makefile
$(RM) $(RMFLAGS) man/*.cat?
@@ -129,6 +131,9 @@ $(SSLCERT) $(SSLKEY):
-new -x509 -nodes -out $(SSLCERT) \
-keyout $(SSLKEY)
+test-sample: all $(OBJS3)
+ $(CC) $(CFLAGS) -o $(TARGET3) $(OBJS3) $(LIBS)
+
test-sig: all $(SSLCERT) $(SSLKEY)
$(SED) -e 's/--.*//' < $(SSLCERT) > $(SSLCERT).1
$(ECHO) -n 'authorizer: "x509-base64:' > $(SSLCERT).2
diff --git a/lib/libkeynote/README b/lib/libkeynote/README
index 9fca97dda7b..707bfde53fb 100644
--- a/lib/libkeynote/README
+++ b/lib/libkeynote/README
@@ -1,4 +1,4 @@
-# $OpenBSD: README,v 1.7 1999/11/03 19:52:21 angelos Exp $
+# $OpenBSD: README,v 1.8 1999/11/05 00:27:18 angelos Exp $
This is release 2.2 of the KeyNote trust management library reference
implementation (in case you are wondering, there was never an official 1.0
@@ -14,6 +14,9 @@ crypto support, use "make nocrypto" instead (you still need to run
"configure"). If you have built crypto support, "make test-sig" will run
some more tests on the cryptographic algorithms.
+A sample application is provided in sample-app.c. To build it, use
+"make test-sample".
+
Compile tips:
- You need the SSLeay/OpenSSL library if you compile with crypto
(default), version 0.8.1b or later. You can find it in various
diff --git a/lib/libkeynote/TODO b/lib/libkeynote/TODO
index 888b02f3eaa..58f8298e673 100644
--- a/lib/libkeynote/TODO
+++ b/lib/libkeynote/TODO
@@ -1,8 +1,7 @@
-# $OpenBSD: TODO,v 1.6 1999/10/26 22:31:37 angelos Exp $
+# $OpenBSD: TODO,v 1.7 1999/11/05 00:27:18 angelos Exp $
TODOs:
- Write key/signature algorithm drafts
- - Sample application
- More interesting/comprehensive testsuite
- Make X509 support be non-RSA specific
- Recursive parser
diff --git a/lib/libkeynote/keynote-sigver.c b/lib/libkeynote/keynote-sigver.c
index 81332a4ff10..760eb793e32 100644
--- a/lib/libkeynote/keynote-sigver.c
+++ b/lib/libkeynote/keynote-sigver.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: keynote-sigver.c,v 1.9 1999/11/03 19:52:22 angelos Exp $ */
+/* $OpenBSD: keynote-sigver.c,v 1.10 1999/11/05 00:27:18 angelos Exp $ */
/*
* The author of this code is Angelos D. Keromytis (angelos@dsl.cis.upenn.edu)
*
@@ -102,13 +102,17 @@ keynote_sigver(int argc, char *argv[])
close(fd);
assertlist = kn_read_asserts(buf, sb.st_size, &n);
- if ((assertlist == NULL) || (n == 0))
+ if (assertlist == NULL)
{
- if (keynote_errno == ERROR_MEMORY)
- fprintf(stderr, "Out of memory while allocating memory for "
- "assertions.\n");
- else
- fprintf(stderr, "No assertions found.\n");
+ fprintf(stderr, "Out of memory while allocating memory for "
+ "assertions.\n");
+ exit(-1);
+ }
+
+ if (n == 0)
+ {
+ fprintf(stderr, "No assertions found in %s.\n", argv[1]);
+ free(assertlist);
exit(-1);
}
diff --git a/lib/libkeynote/keynote.3 b/lib/libkeynote/keynote.3
index ee405941922..004db2389aa 100644
--- a/lib/libkeynote/keynote.3
+++ b/lib/libkeynote/keynote.3
@@ -1,4 +1,4 @@
-.\" $OpenBSD: keynote.3,v 1.17 1999/11/03 19:52:22 angelos Exp $
+.\" $OpenBSD: keynote.3,v 1.18 1999/11/05 00:27:18 angelos Exp $
.\"
.\" The author of this code is Angelos D. Keromytis (angelos@dsl.cis.upenn.edu)
.\"
@@ -454,7 +454,9 @@ no longer needed.
contains the number of assertions (and thus strings in the returned
array) found in
.Fa array .
-On failure, this function returns \-1 and sets
+On failure, this function returns
+.Dv NULL
+and sets
.Va keynote_errno
to
.Er ERROR_MEMORY
@@ -464,6 +466,12 @@ if
.Fa array
was
.Dv NULL .
+Note that if there were no assertions found in
+.Fa array ,
+a valid pointer will be returned, but
+.Fa numassertions
+will contain the value zero on return. The returned pointer should be
+freed by the programmer.
.Pp
.Fn kn_keycompare
compares
diff --git a/lib/libkeynote/sample-app.c b/lib/libkeynote/sample-app.c
new file mode 100644
index 00000000000..59f12a706e5
--- /dev/null
+++ b/lib/libkeynote/sample-app.c
@@ -0,0 +1,544 @@
+/* $OpenBSD: sample-app.c,v 1.1 1999/11/05 00:27:18 angelos Exp $ */
+/*
+ * The author of this code is Angelos D. Keromytis (angelos@dsl.cis.upenn.edu)
+ *
+ * This code was written by Angelos D. Keromytis in Philadelphia, PA, USA,
+ * in April-May 1998
+ *
+ * Copyright (C) 1998, 1999 by Angelos D. Keromytis.
+ *
+ * Permission to use, copy, and modify this software without fee
+ * is hereby granted, provided that this entire notice is included in
+ * all copies of any software which is or includes a copy or
+ * modification of this software.
+ *
+ * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTY. IN PARTICULAR, THE AUTHORS MAKES NO
+ * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE
+ * MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR
+ * PURPOSE.
+ */
+#include <sys/types.h>
+#include <stdio.h>
+#include <regex.h>
+#include "keynote.h"
+
+/* These is only needed to pull in the SSL include files */
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif /* HAVE_CONFIG_H */
+
+#include "header.h"
+
+char policy_assertions[] =
+"Authorizer: \"POLICY\"\n" \
+"Licensees: \"rsa-hex:3048024100d15d08ce7d2103d93ef21a87330361\\\n" \
+" ff123096b14330f9f0936e8f2064ef815ffdaabbb7d3ba47b\\\n" \
+" 49fac090cf44818af7ac7d66c2910f32d8d5eb261328558e1\\\n" \
+" 0203010001\"\n" \
+"Comment: This is our first policy assertion\n" \
+"Conditions: app_domain == \"test application\" -> \"true\";\n" \
+"\n" \
+"Authorizer: \"POLICY\"\n" \
+"Licensees: KEY1 || KEY2\n" \
+"Local-Constants: \n" \
+" KEY1 = \"rsa-base64:MEgCQQCzxWCi619s3Bqf8QOZTREBFelqWvljw\\\n" \
+" vCwktO7/5zufcz+P0UBRBFNtasWgkP6/tAIK8MnLMUnejGsye\\\n" \
+" DS2EVzAgMBAAE=\"\n" \
+" KEY2 = \"dsa-base64:MIHfAkEAhRzwrvhbRXIJH+nGfQB/tRp3ueF0j\\\n" \
+" 4OqVU4GmC6eIlrmlKxR+Me6tjqtWJr5gf/AEOnzoQAPRIlpiP\\\n" \
+" VJX1mRjwJBAKHTpHS7M938wVr+lIMjq0H0Aav5T4jlxS2rphI\\\n" \
+" 4fbc7tJm6wPW9p2KyHbe9GaZgzYK1OdnNXdanM/AkLW4OKz0C\\\n" \
+" FQDF69A/EHKoQC1H6DxCi0L3HfW9uwJANCLE6ViRxnv4Jj0gV\\\n" \
+" 8aO/b5AD+uA63+0EXUxO0Hqp91lzhDg/61BusMxFq7mQI0CLv\\\n" \
+" S+dlCGShsYyB+VjSub7Q==\"\n" \
+"Comment: A slightly more complicated policy\n" \
+"Conditions: app_domain == \"test application\" && @some_num == 1 && \n" \
+" (some_var == \"some value\" || \n" \
+" some_var == \"some other value\") -> \"true\";";
+
+char credential_assertions[] =
+"KeyNote-Version: 2\n"\
+"Authorizer: KEY1\n"
+"Local-Constants: \n" \
+" KEY1 = \"rsa-base64:MEgCQQCzxWCi619s3Bqf8QOZTREBFelqWvljw\\\n" \
+" vCwktO7/5zufcz+P0UBRBFNtasWgkP6/tAIK8MnLMUnejGsye\\\n" \
+" DS2EVzAgMBAAE=\"\n" \
+"Licensees: \"dsa-hex:3081de02402121e160209f7ecef1b6866c907e8d\\\n" \
+" d65e9a67ef0fbd6ece7760b7c8bb0d9a0b71a0dd921b949f0\\\n" \
+" 9a16092eb3f50e33892bc3e9f1c8409f5298de40461493ef1\\\n" \
+" 024100a60b7e77f317e156566b388aaa32c3866a086831649\\\n" \
+" 1a55ab6fb8e57f7ade4a2a31e43017c383ab2a3e54f49688d\\\n" \
+" d66a326b7362beb974f2f1fb7dd573dd1bdf021500909807a\\\n" \
+" 4937f198fe893be6c63a7d627f13a385b02405811292c9949\\\n" \
+" 7aa80911c781a0ff51a5843423b9b4d03ad7e708ae2bfacaf\\\n" \
+" 11477f4f197dbba534194f8afd1e0b73261bb0a2c04af35db\\\n" \
+" 0507f5cffe74ed4f1a\"\n" \
+"Conditions: app_domain == \"test application\" && \n" \
+" another_var == \"foo\" -> \"true\";\n" \
+"Signature: \"sig-rsa-sha1-base64:E2OhrczI0LtAYAoJ6fSlqvlQDA4r\\\n" \
+" GiIX73T6p9eExpyHZbfjxPxXEIf6tbBre6x2Y26wBQCx/yCj5\\\n" \
+" 4IS3tuY2w==\"\n";
+
+char action_authorizer[] =
+"dsa-hex:3081de02402121e160209f7ecef1b6866c907e8d" \
+"d65e9a67ef0fbd6ece7760b7c8bb0d9a0b71a0dd921b949f0" \
+"9a16092eb3f50e33892bc3e9f1c8409f5298de40461493ef1" \
+"024100a60b7e77f317e156566b388aaa32c3866a086831649" \
+"1a55ab6fb8e57f7ade4a2a31e43017c383ab2a3e54f49688d" \
+"d66a326b7362beb974f2f1fb7dd573dd1bdf021500909807a" \
+"4937f198fe893be6c63a7d627f13a385b02405811292c9949" \
+"7aa80911c781a0ff51a5843423b9b4d03ad7e708ae2bfacaf" \
+"11477f4f197dbba534194f8afd1e0b73261bb0a2c04af35db" \
+"0507f5cffe74ed4f1a";
+
+#define NUM_RETURN_VALUES 2
+
+char *returnvalues[NUM_RETURN_VALUES];
+
+/*
+ * Sample application. We do the following:
+ * - create a session
+ * - read a "file" with our KeyNote policy assertions
+ * - obtain a credential
+ * - obtain the requester's public key
+ * - construct an action attribute set
+ * - do the query
+ *
+ * Since this is a sample application, we won't be actually reading any
+ * real files or sockets. See the comments in the code below.
+ */
+
+int
+main(int argc, char **argv)
+{
+ int sessionid, num, i, j;
+ char **decomposed;
+
+ /*
+ * We are creating a new KeyNote session here. A session may be temporary
+ * (we create it, add policies, credentials, authorizers, action set, do
+ * the query, and then we destroy it), or it may be persistent (if, for
+ * example, policies remain the same for a while).
+ *
+ * In this example, we'll just assume the session is temporary, but there
+ * will be comments as to what to do if this were a persistent session.
+ */
+ sessionid = kn_init();
+ if (sessionid == -1)
+ {
+ fprintf(stderr, "Failed to create a new session.\n");
+ exit(-1);
+ }
+
+ /*
+ * Assume we have read a file, or somehow securely acquired our policy
+ * assertions, and we have stored them in policy_assertions.
+ */
+
+ /* Let's find how many policies we just "read". */
+ decomposed = kn_read_asserts(policy_assertions, strlen(policy_assertions),
+ &num);
+ if (decomposed == NULL)
+ {
+ fprintf(stderr, "Failed to allocate memory for policy assertions.\n");
+ exit(-1);
+ }
+
+ /*
+ * If there were no assertions in the first argument to kn_read_asserts,
+ * we'll get a valid pointer back, which we need to free. Note that this
+ * is an error; we always MUST have at least one policy assertion.
+ */
+ if (num == 0)
+ {
+ free(decomposed);
+ fprintf(stderr, "No policy assertions provided.\n");
+ exit(-1);
+ }
+
+ /*
+ * We no longer need a copy of policy_assertions, so we could
+ * free it here.
+ */
+
+ /*
+ * decomposed now contains num pointers to strings, each containing a
+ * single assertion. We now add them all to the session. Note that
+ * we must provide the ASSERT_FLAG_LOCAL flag to indicate that these
+ * are policy assertions and thus do not have a signature field.
+ */
+ for (i = 0; i < num; i++)
+ {
+ j = kn_add_assertion(sessionid, decomposed[i],
+ strlen(decomposed[i]), ASSERT_FLAG_LOCAL);
+ if (j == -1)
+ {
+ switch (keynote_errno)
+ {
+ case ERROR_MEMORY:
+ fprintf(stderr, "Out of memory, trying to add policy "
+ "assertion %d.\n", j);
+ break;
+
+ case ERROR_SYNTAX:
+ fprintf(stderr, "Syntax error parsing policy "
+ "assertion %d.\n", j);
+ break;
+
+ case ERROR_NOTFOUND:
+ fprintf(stderr, "Session %d not found while adding "
+ "policy assertion %d.\n", sessionid, j);
+ default:
+ fprintf(stderr, "Unspecified error %d (shouldn't happen) "
+ "while adding policy assertion %d.\n",
+ keynote_errno, j);
+ break;
+ }
+
+ /* We don't need the assertion any more. */
+ free(decomposed[i]);
+ }
+ }
+
+ /* Now free decomposed itself. */
+ free(decomposed);
+
+ /*
+ * Now, assume we have somehow acquired (through some application-dependent
+ * means) one or more KeyNote credentials, and the key of the action
+ * authorizer. For example, if this were an HTTP authorization application,
+ * we would have acquired the credential(s) and the key after completing
+ * an SSL protocol exchange.
+ *
+ * So, we have some credentials in credential_assertions, and a key
+ * in action_authorizer.
+ */
+
+ /* Let's find how many credentials we just "received". */
+ decomposed = kn_read_asserts(credential_assertions,
+ strlen(credential_assertions), &num);
+ if (decomposed == NULL)
+ {
+ fprintf(stderr, "Failed to allocate memory for credential "
+ "assertions.\n");
+ exit(-1);
+ }
+
+ /*
+ * If there were no assertions in the first argument to kn_read_asserts,
+ * we'll get a valid pointer back, which we need to free. Note that
+ * it is legal to have zero credentials.
+ */
+ if (num == 0)
+ {
+ free(decomposed);
+ fprintf(stderr, "No credential assertions provided.\n");
+ }
+
+ /*
+ * We no longer need a copy of credential_assertions, so we could
+ * free it here.
+ */
+
+ /*
+ * decomposed now contains num pointers to strings, each containing a
+ * single assertion. We now add them all to the session. Note that here
+ * we must NOT provide the ASSERT_FLAG_LOCAL flag, since these are
+ * all credential assertions and need to be cryptographically verified.
+ */
+ for (i = 0; i < num; i++)
+ {
+ /*
+ * The value returned by kn_add_assertion() is an ID for that
+ * assertion (unless it's a -1, which indicates an error). We could
+ * use this ID to remove the assertion from the session in the future,
+ * if we needed to. We would need to store the IDs somewhere of
+ * course.
+ *
+ * If this were a persistent session, it may make sense to delete
+ * the credentials we just added after we are done with the query,
+ * simply to conserve memory. On the other hand, we could just leave
+ * them in the session; this has no security implications.
+ *
+ * Also note that we could do the same with policy assertions.
+ * However, if we want to delete policy assertions, it usually then
+ * makes sense to just destroy the whole session via kn_close(),
+ * which frees all allocated resources.
+ */
+ j = kn_add_assertion(sessionid, decomposed[i],
+ strlen(decomposed[i]), 0);
+ if (j == -1)
+ {
+ switch (keynote_errno)
+ {
+ case ERROR_MEMORY:
+ fprintf(stderr, "Out of memory, trying to add credential "
+ "assertion %d.\n", j);
+ break;
+
+ case ERROR_SYNTAX:
+ fprintf(stderr, "Syntax error parsing credential "
+ "assertion %d.\n", j);
+ break;
+
+ case ERROR_NOTFOUND:
+ fprintf(stderr, "Session %d not found while adding "
+ "credential assertion %d.\n", sessionid, j);
+ default:
+ fprintf(stderr, "Unspecified error %d (shouldn't happen) "
+ "while adding credential assertion %d.\n",
+ keynote_errno, j);
+ break;
+ }
+
+ /* We don't need the assertion any more. */
+ free(decomposed[i]);
+ }
+ }
+
+ /* No longer needed. */
+ free(decomposed);
+
+ /*
+ * Now add the action authorizer. If we have more than one, just
+ * repeat. Note that the value returned here is just a success or
+ * failure indicator. If we want to later on delete an authorizer from
+ * the session (which we MUST do if this is a persistent session),
+ * we must keep a copy of the key.
+ */
+ if (kn_add_authorizer(sessionid, action_authorizer) == -1)
+ {
+ switch (keynote_errno)
+ {
+ case ERROR_MEMORY:
+ fprintf(stderr, "Out of memory while adding action "
+ "authorizer.\n");
+ break;
+
+ case ERROR_SYNTAX:
+ fprintf(stderr, "Malformed action authorizer.\n");
+ break;
+
+ case ERROR_NOTFOUND:
+ fprintf(stderr, "Session %d not found while adding action "
+ "authorizer.\n", sessionid);
+ break;
+
+ default:
+ fprintf(stderr, "Unspecified error while adding action "
+ "authorizer.\n");
+ break;
+ }
+ }
+
+ /*
+ * If we don't need action_authorizer any more (i.e., this is a temporary
+ * session), we could free it now.
+ */
+
+ /*
+ * Now we need to construct the action set. In a real application, we
+ * would be gathering the relevant information. Here, we just construct
+ * a fixed action set.
+ */
+
+ /*
+ * Add the relevant action attributes. Flags is zero, since we are not
+ * using any callback functions (ENVIRONMENT_FLAG_FUNC) or a regular
+ * expression for action attribute names (ENVIRONMENT_FLAG_REGEX).
+ */
+ if (kn_add_action(sessionid, "app_domain", "test application", 0) == -1)
+ {
+ switch (keynote_errno)
+ {
+ case ERROR_SYNTAX:
+ fprintf(stderr, "Invalid name action attribute name "
+ "[app_domain]\n");
+ break;
+
+ case ERROR_MEMORY:
+ fprintf(stderr, "Out of memory adding action attribute "
+ "[app_domain = \"test application\"]\n");
+ break;
+
+ case ERROR_NOTFOUND:
+ fprintf(stderr, "Session %d not found while addiing action "
+ "attribute [app_domain = \"test application\"]\n",
+ sessionid);
+ break;
+
+ default:
+ fprintf(stderr, "Unspecified error %d (shouldn't happen) "
+ "while adding action attribute [app_domain = "
+ "\"test application\"]\n", keynote_errno);
+ break;
+ }
+ }
+
+ if (kn_add_action(sessionid, "some_num", "1", 0) == -1)
+ {
+ switch (keynote_errno)
+ {
+ case ERROR_SYNTAX:
+ fprintf(stderr, "Invalid name action attribute name "
+ "[some_num]\n");
+ break;
+
+ case ERROR_MEMORY:
+ fprintf(stderr, "Out of memory adding action attribute "
+ "[some_num = \"1\"]\n");
+ break;
+
+ case ERROR_NOTFOUND:
+ fprintf(stderr, "Session %d not found while addiing action "
+ "attribute [some_num = \"1\"]\n", sessionid);
+ break;
+
+ default:
+ fprintf(stderr, "Unspecified error %d (shouldn't happen) "
+ "while adding action attribute [some_num = \"1\"]",
+ keynote_errno);
+ break;
+ }
+ }
+
+ if (kn_add_action(sessionid, "some_var", "some other value", 0) == -1)
+ {
+ switch (keynote_errno)
+ {
+ case ERROR_SYNTAX:
+ fprintf(stderr, "Invalid name action attribute name "
+ "[some_var]\n");
+ break;
+
+ case ERROR_MEMORY:
+ fprintf(stderr, "Out of memory adding action attribute "
+ "[some_var = \"some other value\"]\n");
+ break;
+
+ case ERROR_NOTFOUND:
+ fprintf(stderr, "Session %d not found while addiing action "
+ "attribute [some_var = \"some other value\"]\n",
+ sessionid);
+ break;
+
+ default:
+ fprintf(stderr, "Unspecified error %d (shouldn't happen) "
+ "while adding action attribute [some_var = "
+ "\"some other value\"]\n", keynote_errno);
+ break;
+ }
+ }
+
+ if (kn_add_action(sessionid, "another_var", "foo", 0) == -1)
+ {
+ switch (keynote_errno)
+ {
+ case ERROR_SYNTAX:
+ fprintf(stderr, "Invalid name action attribute name "
+ "[another_var]\n");
+ break;
+
+ case ERROR_MEMORY:
+ fprintf(stderr, "Out of memory adding action attribute "
+ "[another_var = \"foo\"]\n");
+ break;
+
+ case ERROR_NOTFOUND:
+ fprintf(stderr, "Session %d not found while addiing action "
+ "attribute [another_var = \"foo\"]\n", sessionid);
+ break;
+
+ default:
+ fprintf(stderr, "Unspecified error %d (shouldn't happen) "
+ "while adding action attribute [another_var = "
+ "\"foo\"]\n", keynote_errno);
+ break;
+ }
+ }
+
+ /* Set the return values for this application -- just "false" and "true" */
+ returnvalues[0] = "false";
+ returnvalues[1] = "true";
+
+ /* Just do the query. */
+ j = kn_do_query(sessionid, returnvalues, NUM_RETURN_VALUES);
+ if (j == -1)
+ {
+ switch (j)
+ {
+ case ERROR_MEMORY:
+ fprintf(stderr, "Out of memory while performing authorization "
+ "query.\n");
+ break;
+
+ case ERROR_NOTFOUND:
+ fprintf(stderr, "Session %d not found while performing "
+ "authorization query.\n", sessionid);
+ break;
+
+ default:
+ fprintf(stderr, "Unspecified error %d (shouldn't happen) "
+ "while performing authorization query.\n",
+ keynote_errno);
+ break;
+ }
+ }
+ else
+ {
+ fprintf(stdout, "Return value is [%s]\n", returnvalues[j]);
+ }
+
+ /*
+ * Once the query is done, we can find what assertions failed in what way.
+ * One way is just going through the list of assertions, as shown here
+ * for assertions that failed due to memory exhaustion.
+ */
+ j = 0;
+
+ do
+ {
+ i = kn_get_failed(sessionid, KEYNOTE_ERROR_MEMORY, j++);
+ if (i != -1)
+ fprintf(stderr, "Assertion %d failed due to memory exhaustion.\n",
+ i);
+ } while (i != -1);
+
+ /*
+ * Another way is to go through the list of failed assertions by deleting
+ * the "first" one.
+ */
+ do
+ {
+ i = kn_get_failed(sessionid, KEYNOTE_ERROR_SYNTAX, 0);
+ if (i != -1)
+ {
+ fprintf(stderr, "Assertion %d failed due to some syntax error.\n",
+ i);
+ kn_remove_assertion(sessionid, i); /* Delete assertion */
+ }
+ } while (i != -1);
+
+ /*
+ * Signature failures, another way.
+ */
+ for (j = 0, i = kn_get_failed(sessionid, KEYNOTE_ERROR_SIGNATURE, 0);
+ i != -1; i = kn_get_failed(sessionid, KEYNOTE_ERROR_SIGNATURE, j++))
+ fprintf(stderr, "Failed to verify signature on assertion %d.\n", i);
+
+ /*
+ * Here's how to find all errors.
+ */
+ for (i = kn_get_failed(sessionid, KEYNOTE_ERROR_ANY, 0); i != -1;
+ i = kn_get_failed(sessionid, KEYNOTE_ERROR_ANY, 0))
+ {
+ fprintf(stderr, "Unspecified error in processing assertion %d.\n", i);
+ kn_remove_assertion(sessionid, i);
+ }
+
+ /* Destroy the session, freeing all allocated memory. */
+ kn_close(sessionid);
+
+ exit(0);
+}