1*85616838Smsf /* $OpenBSD: sample-app.c,v 1.7 2004/06/29 11:35:56 msf Exp $ */
2805e681cSangelos /*
3805e681cSangelos * The author of this code is Angelos D. Keromytis (angelos@dsl.cis.upenn.edu)
4805e681cSangelos *
5805e681cSangelos * This code was written by Angelos D. Keromytis in Philadelphia, PA, USA,
6805e681cSangelos * in April-May 1998
7805e681cSangelos *
8805e681cSangelos * Copyright (C) 1998, 1999 by Angelos D. Keromytis.
9805e681cSangelos *
105e4ac158Sderaadt * Permission to use, copy, and modify this software with or without fee
11805e681cSangelos * is hereby granted, provided that this entire notice is included in
12805e681cSangelos * all copies of any software which is or includes a copy or
13805e681cSangelos * modification of this software.
14805e681cSangelos *
15805e681cSangelos * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR
16805e681cSangelos * IMPLIED WARRANTY. IN PARTICULAR, THE AUTHORS MAKES NO
17805e681cSangelos * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE
18805e681cSangelos * MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR
19805e681cSangelos * PURPOSE.
20805e681cSangelos */
21e0758482Smsf
22805e681cSangelos #include <sys/types.h>
23e0758482Smsf
24805e681cSangelos #include <stdio.h>
25*85616838Smsf #include <stdlib.h>
26805e681cSangelos #include <regex.h>
27*85616838Smsf #include <keynote.h>
28805e681cSangelos
29805e681cSangelos
30805e681cSangelos char policy_assertions[] =
31805e681cSangelos "Authorizer: \"POLICY\"\n" \
32805e681cSangelos "Licensees: \"rsa-hex:3048024100d15d08ce7d2103d93ef21a87330361\\\n" \
33805e681cSangelos " ff123096b14330f9f0936e8f2064ef815ffdaabbb7d3ba47b\\\n" \
34805e681cSangelos " 49fac090cf44818af7ac7d66c2910f32d8d5eb261328558e1\\\n" \
35805e681cSangelos " 0203010001\"\n" \
36805e681cSangelos "Comment: This is our first policy assertion\n" \
37805e681cSangelos "Conditions: app_domain == \"test application\" -> \"true\";\n" \
38805e681cSangelos "\n" \
39805e681cSangelos "Authorizer: \"POLICY\"\n" \
40805e681cSangelos "Licensees: KEY1 || KEY2\n" \
41805e681cSangelos "Local-Constants: \n" \
42805e681cSangelos " KEY1 = \"rsa-base64:MEgCQQCzxWCi619s3Bqf8QOZTREBFelqWvljw\\\n" \
43805e681cSangelos " vCwktO7/5zufcz+P0UBRBFNtasWgkP6/tAIK8MnLMUnejGsye\\\n" \
44805e681cSangelos " DS2EVzAgMBAAE=\"\n" \
45805e681cSangelos " KEY2 = \"dsa-base64:MIHfAkEAhRzwrvhbRXIJH+nGfQB/tRp3ueF0j\\\n" \
46805e681cSangelos " 4OqVU4GmC6eIlrmlKxR+Me6tjqtWJr5gf/AEOnzoQAPRIlpiP\\\n" \
47805e681cSangelos " VJX1mRjwJBAKHTpHS7M938wVr+lIMjq0H0Aav5T4jlxS2rphI\\\n" \
48805e681cSangelos " 4fbc7tJm6wPW9p2KyHbe9GaZgzYK1OdnNXdanM/AkLW4OKz0C\\\n" \
49805e681cSangelos " FQDF69A/EHKoQC1H6DxCi0L3HfW9uwJANCLE6ViRxnv4Jj0gV\\\n" \
50805e681cSangelos " 8aO/b5AD+uA63+0EXUxO0Hqp91lzhDg/61BusMxFq7mQI0CLv\\\n" \
51805e681cSangelos " S+dlCGShsYyB+VjSub7Q==\"\n" \
52805e681cSangelos "Comment: A slightly more complicated policy\n" \
53805e681cSangelos "Conditions: app_domain == \"test application\" && @some_num == 1 && \n" \
54805e681cSangelos " (some_var == \"some value\" || \n" \
55805e681cSangelos " some_var == \"some other value\") -> \"true\";";
56805e681cSangelos
57805e681cSangelos char credential_assertions[] =
58805e681cSangelos "KeyNote-Version: 2\n"\
59805e681cSangelos "Authorizer: KEY1\n"
60805e681cSangelos "Local-Constants: \n" \
61805e681cSangelos " KEY1 = \"rsa-base64:MEgCQQCzxWCi619s3Bqf8QOZTREBFelqWvljw\\\n" \
62805e681cSangelos " vCwktO7/5zufcz+P0UBRBFNtasWgkP6/tAIK8MnLMUnejGsye\\\n" \
63805e681cSangelos " DS2EVzAgMBAAE=\"\n" \
64805e681cSangelos "Licensees: \"dsa-hex:3081de02402121e160209f7ecef1b6866c907e8d\\\n" \
65805e681cSangelos " d65e9a67ef0fbd6ece7760b7c8bb0d9a0b71a0dd921b949f0\\\n" \
66805e681cSangelos " 9a16092eb3f50e33892bc3e9f1c8409f5298de40461493ef1\\\n" \
67805e681cSangelos " 024100a60b7e77f317e156566b388aaa32c3866a086831649\\\n" \
68805e681cSangelos " 1a55ab6fb8e57f7ade4a2a31e43017c383ab2a3e54f49688d\\\n" \
69805e681cSangelos " d66a326b7362beb974f2f1fb7dd573dd1bdf021500909807a\\\n" \
70805e681cSangelos " 4937f198fe893be6c63a7d627f13a385b02405811292c9949\\\n" \
71805e681cSangelos " 7aa80911c781a0ff51a5843423b9b4d03ad7e708ae2bfacaf\\\n" \
72805e681cSangelos " 11477f4f197dbba534194f8afd1e0b73261bb0a2c04af35db\\\n" \
73805e681cSangelos " 0507f5cffe74ed4f1a\"\n" \
74805e681cSangelos "Conditions: app_domain == \"test application\" && \n" \
75805e681cSangelos " another_var == \"foo\" -> \"true\";\n" \
76805e681cSangelos "Signature: \"sig-rsa-sha1-base64:E2OhrczI0LtAYAoJ6fSlqvlQDA4r\\\n" \
77805e681cSangelos " GiIX73T6p9eExpyHZbfjxPxXEIf6tbBre6x2Y26wBQCx/yCj5\\\n" \
78805e681cSangelos " 4IS3tuY2w==\"\n";
79805e681cSangelos
80805e681cSangelos char action_authorizer[] =
81805e681cSangelos "dsa-hex:3081de02402121e160209f7ecef1b6866c907e8d" \
82805e681cSangelos "d65e9a67ef0fbd6ece7760b7c8bb0d9a0b71a0dd921b949f0" \
83805e681cSangelos "9a16092eb3f50e33892bc3e9f1c8409f5298de40461493ef1" \
84805e681cSangelos "024100a60b7e77f317e156566b388aaa32c3866a086831649" \
85805e681cSangelos "1a55ab6fb8e57f7ade4a2a31e43017c383ab2a3e54f49688d" \
86805e681cSangelos "d66a326b7362beb974f2f1fb7dd573dd1bdf021500909807a" \
87805e681cSangelos "4937f198fe893be6c63a7d627f13a385b02405811292c9949" \
88805e681cSangelos "7aa80911c781a0ff51a5843423b9b4d03ad7e708ae2bfacaf" \
89805e681cSangelos "11477f4f197dbba534194f8afd1e0b73261bb0a2c04af35db" \
90805e681cSangelos "0507f5cffe74ed4f1a";
91805e681cSangelos
92805e681cSangelos #define NUM_RETURN_VALUES 2
93805e681cSangelos
94805e681cSangelos char *returnvalues[NUM_RETURN_VALUES];
95805e681cSangelos
96805e681cSangelos /*
97805e681cSangelos * Sample application. We do the following:
98805e681cSangelos * - create a session
99805e681cSangelos * - read a "file" with our KeyNote policy assertions
100805e681cSangelos * - obtain a credential
101805e681cSangelos * - obtain the requester's public key
102805e681cSangelos * - construct an action attribute set
103805e681cSangelos * - do the query
104805e681cSangelos *
105805e681cSangelos * Since this is a sample application, we won't be actually reading any
106805e681cSangelos * real files or sockets. See the comments in the code below.
107805e681cSangelos */
108805e681cSangelos
109805e681cSangelos int
main(int argc,char ** argv)110805e681cSangelos main(int argc, char **argv)
111805e681cSangelos {
112805e681cSangelos int sessionid, num, i, j;
113805e681cSangelos char **decomposed;
114805e681cSangelos
115805e681cSangelos /*
116805e681cSangelos * We are creating a new KeyNote session here. A session may be temporary
117805e681cSangelos * (we create it, add policies, credentials, authorizers, action set, do
118805e681cSangelos * the query, and then we destroy it), or it may be persistent (if, for
119805e681cSangelos * example, policies remain the same for a while).
120805e681cSangelos *
121805e681cSangelos * In this example, we'll just assume the session is temporary, but there
122805e681cSangelos * will be comments as to what to do if this were a persistent session.
123805e681cSangelos */
124805e681cSangelos sessionid = kn_init();
125805e681cSangelos if (sessionid == -1)
126805e681cSangelos {
127805e681cSangelos fprintf(stderr, "Failed to create a new session.\n");
1283cb7a939Sangelos exit(1);
129805e681cSangelos }
130805e681cSangelos
131805e681cSangelos /*
132805e681cSangelos * Assume we have read a file, or somehow securely acquired our policy
133805e681cSangelos * assertions, and we have stored them in policy_assertions.
134805e681cSangelos */
135805e681cSangelos
136805e681cSangelos /* Let's find how many policies we just "read". */
137805e681cSangelos decomposed = kn_read_asserts(policy_assertions, strlen(policy_assertions),
138805e681cSangelos &num);
139805e681cSangelos if (decomposed == NULL)
140805e681cSangelos {
141805e681cSangelos fprintf(stderr, "Failed to allocate memory for policy assertions.\n");
1423cb7a939Sangelos exit(1);
143805e681cSangelos }
144805e681cSangelos
145805e681cSangelos /*
146805e681cSangelos * If there were no assertions in the first argument to kn_read_asserts,
147805e681cSangelos * we'll get a valid pointer back, which we need to free. Note that this
148805e681cSangelos * is an error; we always MUST have at least one policy assertion.
149805e681cSangelos */
150805e681cSangelos if (num == 0)
151805e681cSangelos {
152805e681cSangelos free(decomposed);
153805e681cSangelos fprintf(stderr, "No policy assertions provided.\n");
1543cb7a939Sangelos exit(1);
155805e681cSangelos }
156805e681cSangelos
157805e681cSangelos /*
158805e681cSangelos * We no longer need a copy of policy_assertions, so we could
159805e681cSangelos * free it here.
160805e681cSangelos */
161805e681cSangelos
162805e681cSangelos /*
163805e681cSangelos * decomposed now contains num pointers to strings, each containing a
164805e681cSangelos * single assertion. We now add them all to the session. Note that
165805e681cSangelos * we must provide the ASSERT_FLAG_LOCAL flag to indicate that these
166805e681cSangelos * are policy assertions and thus do not have a signature field.
167805e681cSangelos */
168805e681cSangelos for (i = 0; i < num; i++)
169805e681cSangelos {
170805e681cSangelos j = kn_add_assertion(sessionid, decomposed[i],
171805e681cSangelos strlen(decomposed[i]), ASSERT_FLAG_LOCAL);
172805e681cSangelos if (j == -1)
173805e681cSangelos {
174805e681cSangelos switch (keynote_errno)
175805e681cSangelos {
176805e681cSangelos case ERROR_MEMORY:
177805e681cSangelos fprintf(stderr, "Out of memory, trying to add policy "
178805e681cSangelos "assertion %d.\n", j);
179805e681cSangelos break;
180805e681cSangelos
181805e681cSangelos case ERROR_SYNTAX:
182805e681cSangelos fprintf(stderr, "Syntax error parsing policy "
183805e681cSangelos "assertion %d.\n", j);
184805e681cSangelos break;
185805e681cSangelos
186805e681cSangelos case ERROR_NOTFOUND:
187805e681cSangelos fprintf(stderr, "Session %d not found while adding "
188805e681cSangelos "policy assertion %d.\n", sessionid, j);
189805e681cSangelos default:
190805e681cSangelos fprintf(stderr, "Unspecified error %d (shouldn't happen) "
191805e681cSangelos "while adding policy assertion %d.\n",
192805e681cSangelos keynote_errno, j);
193805e681cSangelos break;
194805e681cSangelos }
195805e681cSangelos
196805e681cSangelos /* We don't need the assertion any more. */
197805e681cSangelos free(decomposed[i]);
198805e681cSangelos }
199805e681cSangelos }
200805e681cSangelos
201805e681cSangelos /* Now free decomposed itself. */
202805e681cSangelos free(decomposed);
203805e681cSangelos
204805e681cSangelos /*
205805e681cSangelos * Now, assume we have somehow acquired (through some application-dependent
206805e681cSangelos * means) one or more KeyNote credentials, and the key of the action
207805e681cSangelos * authorizer. For example, if this were an HTTP authorization application,
208805e681cSangelos * we would have acquired the credential(s) and the key after completing
209805e681cSangelos * an SSL protocol exchange.
210805e681cSangelos *
211805e681cSangelos * So, we have some credentials in credential_assertions, and a key
212805e681cSangelos * in action_authorizer.
213805e681cSangelos */
214805e681cSangelos
215805e681cSangelos /* Let's find how many credentials we just "received". */
216805e681cSangelos decomposed = kn_read_asserts(credential_assertions,
217805e681cSangelos strlen(credential_assertions), &num);
218805e681cSangelos if (decomposed == NULL)
219805e681cSangelos {
220805e681cSangelos fprintf(stderr, "Failed to allocate memory for credential "
221805e681cSangelos "assertions.\n");
2223cb7a939Sangelos exit(1);
223805e681cSangelos }
224805e681cSangelos
225805e681cSangelos /*
226805e681cSangelos * If there were no assertions in the first argument to kn_read_asserts,
227805e681cSangelos * we'll get a valid pointer back, which we need to free. Note that
228805e681cSangelos * it is legal to have zero credentials.
229805e681cSangelos */
230805e681cSangelos if (num == 0)
231805e681cSangelos {
232805e681cSangelos free(decomposed);
233805e681cSangelos fprintf(stderr, "No credential assertions provided.\n");
234805e681cSangelos }
235805e681cSangelos
236805e681cSangelos /*
237805e681cSangelos * We no longer need a copy of credential_assertions, so we could
238805e681cSangelos * free it here.
239805e681cSangelos */
240805e681cSangelos
241805e681cSangelos /*
242805e681cSangelos * decomposed now contains num pointers to strings, each containing a
243805e681cSangelos * single assertion. We now add them all to the session. Note that here
244805e681cSangelos * we must NOT provide the ASSERT_FLAG_LOCAL flag, since these are
245805e681cSangelos * all credential assertions and need to be cryptographically verified.
246805e681cSangelos */
247805e681cSangelos for (i = 0; i < num; i++)
248805e681cSangelos {
249805e681cSangelos /*
250805e681cSangelos * The value returned by kn_add_assertion() is an ID for that
251805e681cSangelos * assertion (unless it's a -1, which indicates an error). We could
252805e681cSangelos * use this ID to remove the assertion from the session in the future,
253805e681cSangelos * if we needed to. We would need to store the IDs somewhere of
254805e681cSangelos * course.
255805e681cSangelos *
256805e681cSangelos * If this were a persistent session, it may make sense to delete
257805e681cSangelos * the credentials we just added after we are done with the query,
258805e681cSangelos * simply to conserve memory. On the other hand, we could just leave
259805e681cSangelos * them in the session; this has no security implications.
260805e681cSangelos *
261805e681cSangelos * Also note that we could do the same with policy assertions.
262805e681cSangelos * However, if we want to delete policy assertions, it usually then
263805e681cSangelos * makes sense to just destroy the whole session via kn_close(),
264805e681cSangelos * which frees all allocated resources.
265805e681cSangelos */
266805e681cSangelos j = kn_add_assertion(sessionid, decomposed[i],
267805e681cSangelos strlen(decomposed[i]), 0);
268805e681cSangelos if (j == -1)
269805e681cSangelos {
270805e681cSangelos switch (keynote_errno)
271805e681cSangelos {
272805e681cSangelos case ERROR_MEMORY:
273805e681cSangelos fprintf(stderr, "Out of memory, trying to add credential "
274805e681cSangelos "assertion %d.\n", j);
275805e681cSangelos break;
276805e681cSangelos
277805e681cSangelos case ERROR_SYNTAX:
278805e681cSangelos fprintf(stderr, "Syntax error parsing credential "
279805e681cSangelos "assertion %d.\n", j);
280805e681cSangelos break;
281805e681cSangelos
282805e681cSangelos case ERROR_NOTFOUND:
283805e681cSangelos fprintf(stderr, "Session %d not found while adding "
284805e681cSangelos "credential assertion %d.\n", sessionid, j);
285805e681cSangelos default:
286805e681cSangelos fprintf(stderr, "Unspecified error %d (shouldn't happen) "
287805e681cSangelos "while adding credential assertion %d.\n",
288805e681cSangelos keynote_errno, j);
289805e681cSangelos break;
290805e681cSangelos }
291805e681cSangelos
292805e681cSangelos /* We don't need the assertion any more. */
293805e681cSangelos free(decomposed[i]);
294805e681cSangelos }
295805e681cSangelos }
296805e681cSangelos
297805e681cSangelos /* No longer needed. */
298805e681cSangelos free(decomposed);
299805e681cSangelos
300805e681cSangelos /*
301805e681cSangelos * Now add the action authorizer. If we have more than one, just
302805e681cSangelos * repeat. Note that the value returned here is just a success or
303805e681cSangelos * failure indicator. If we want to later on delete an authorizer from
304805e681cSangelos * the session (which we MUST do if this is a persistent session),
305805e681cSangelos * we must keep a copy of the key.
306805e681cSangelos */
307805e681cSangelos if (kn_add_authorizer(sessionid, action_authorizer) == -1)
308805e681cSangelos {
309805e681cSangelos switch (keynote_errno)
310805e681cSangelos {
311805e681cSangelos case ERROR_MEMORY:
312805e681cSangelos fprintf(stderr, "Out of memory while adding action "
313805e681cSangelos "authorizer.\n");
314805e681cSangelos break;
315805e681cSangelos
316805e681cSangelos case ERROR_SYNTAX:
317805e681cSangelos fprintf(stderr, "Malformed action authorizer.\n");
318805e681cSangelos break;
319805e681cSangelos
320805e681cSangelos case ERROR_NOTFOUND:
321805e681cSangelos fprintf(stderr, "Session %d not found while adding action "
322805e681cSangelos "authorizer.\n", sessionid);
323805e681cSangelos break;
324805e681cSangelos
325805e681cSangelos default:
326805e681cSangelos fprintf(stderr, "Unspecified error while adding action "
327805e681cSangelos "authorizer.\n");
328805e681cSangelos break;
329805e681cSangelos }
330805e681cSangelos }
331805e681cSangelos
332805e681cSangelos /*
333805e681cSangelos * If we don't need action_authorizer any more (i.e., this is a temporary
334805e681cSangelos * session), we could free it now.
335805e681cSangelos */
336805e681cSangelos
337805e681cSangelos /*
338805e681cSangelos * Now we need to construct the action set. In a real application, we
339805e681cSangelos * would be gathering the relevant information. Here, we just construct
340805e681cSangelos * a fixed action set.
341805e681cSangelos */
342805e681cSangelos
343805e681cSangelos /*
344805e681cSangelos * Add the relevant action attributes. Flags is zero, since we are not
345805e681cSangelos * using any callback functions (ENVIRONMENT_FLAG_FUNC) or a regular
346805e681cSangelos * expression for action attribute names (ENVIRONMENT_FLAG_REGEX).
347805e681cSangelos */
348805e681cSangelos if (kn_add_action(sessionid, "app_domain", "test application", 0) == -1)
349805e681cSangelos {
350805e681cSangelos switch (keynote_errno)
351805e681cSangelos {
352805e681cSangelos case ERROR_SYNTAX:
353805e681cSangelos fprintf(stderr, "Invalid name action attribute name "
354805e681cSangelos "[app_domain]\n");
355805e681cSangelos break;
356805e681cSangelos
357805e681cSangelos case ERROR_MEMORY:
358805e681cSangelos fprintf(stderr, "Out of memory adding action attribute "
359805e681cSangelos "[app_domain = \"test application\"]\n");
360805e681cSangelos break;
361805e681cSangelos
362805e681cSangelos case ERROR_NOTFOUND:
363db3575e7Smillert fprintf(stderr, "Session %d not found while adding action "
364805e681cSangelos "attribute [app_domain = \"test application\"]\n",
365805e681cSangelos sessionid);
366805e681cSangelos break;
367805e681cSangelos
368805e681cSangelos default:
369805e681cSangelos fprintf(stderr, "Unspecified error %d (shouldn't happen) "
370805e681cSangelos "while adding action attribute [app_domain = "
371805e681cSangelos "\"test application\"]\n", keynote_errno);
372805e681cSangelos break;
373805e681cSangelos }
374805e681cSangelos }
375805e681cSangelos
376805e681cSangelos if (kn_add_action(sessionid, "some_num", "1", 0) == -1)
377805e681cSangelos {
378805e681cSangelos switch (keynote_errno)
379805e681cSangelos {
380805e681cSangelos case ERROR_SYNTAX:
381805e681cSangelos fprintf(stderr, "Invalid name action attribute name "
382805e681cSangelos "[some_num]\n");
383805e681cSangelos break;
384805e681cSangelos
385805e681cSangelos case ERROR_MEMORY:
386805e681cSangelos fprintf(stderr, "Out of memory adding action attribute "
387805e681cSangelos "[some_num = \"1\"]\n");
388805e681cSangelos break;
389805e681cSangelos
390805e681cSangelos case ERROR_NOTFOUND:
391db3575e7Smillert fprintf(stderr, "Session %d not found while adding action "
392805e681cSangelos "attribute [some_num = \"1\"]\n", sessionid);
393805e681cSangelos break;
394805e681cSangelos
395805e681cSangelos default:
396805e681cSangelos fprintf(stderr, "Unspecified error %d (shouldn't happen) "
397805e681cSangelos "while adding action attribute [some_num = \"1\"]",
398805e681cSangelos keynote_errno);
399805e681cSangelos break;
400805e681cSangelos }
401805e681cSangelos }
402805e681cSangelos
403805e681cSangelos if (kn_add_action(sessionid, "some_var", "some other value", 0) == -1)
404805e681cSangelos {
405805e681cSangelos switch (keynote_errno)
406805e681cSangelos {
407805e681cSangelos case ERROR_SYNTAX:
408805e681cSangelos fprintf(stderr, "Invalid name action attribute name "
409805e681cSangelos "[some_var]\n");
410805e681cSangelos break;
411805e681cSangelos
412805e681cSangelos case ERROR_MEMORY:
413805e681cSangelos fprintf(stderr, "Out of memory adding action attribute "
414805e681cSangelos "[some_var = \"some other value\"]\n");
415805e681cSangelos break;
416805e681cSangelos
417805e681cSangelos case ERROR_NOTFOUND:
418db3575e7Smillert fprintf(stderr, "Session %d not found while adding action "
419805e681cSangelos "attribute [some_var = \"some other value\"]\n",
420805e681cSangelos sessionid);
421805e681cSangelos break;
422805e681cSangelos
423805e681cSangelos default:
424805e681cSangelos fprintf(stderr, "Unspecified error %d (shouldn't happen) "
425805e681cSangelos "while adding action attribute [some_var = "
426805e681cSangelos "\"some other value\"]\n", keynote_errno);
427805e681cSangelos break;
428805e681cSangelos }
429805e681cSangelos }
430805e681cSangelos
431805e681cSangelos if (kn_add_action(sessionid, "another_var", "foo", 0) == -1)
432805e681cSangelos {
433805e681cSangelos switch (keynote_errno)
434805e681cSangelos {
435805e681cSangelos case ERROR_SYNTAX:
436805e681cSangelos fprintf(stderr, "Invalid name action attribute name "
437805e681cSangelos "[another_var]\n");
438805e681cSangelos break;
439805e681cSangelos
440805e681cSangelos case ERROR_MEMORY:
441805e681cSangelos fprintf(stderr, "Out of memory adding action attribute "
442805e681cSangelos "[another_var = \"foo\"]\n");
443805e681cSangelos break;
444805e681cSangelos
445805e681cSangelos case ERROR_NOTFOUND:
446db3575e7Smillert fprintf(stderr, "Session %d not found while adding action "
447805e681cSangelos "attribute [another_var = \"foo\"]\n", sessionid);
448805e681cSangelos break;
449805e681cSangelos
450805e681cSangelos default:
451805e681cSangelos fprintf(stderr, "Unspecified error %d (shouldn't happen) "
452805e681cSangelos "while adding action attribute [another_var = "
453805e681cSangelos "\"foo\"]\n", keynote_errno);
454805e681cSangelos break;
455805e681cSangelos }
456805e681cSangelos }
457805e681cSangelos
458805e681cSangelos /* Set the return values for this application -- just "false" and "true" */
459805e681cSangelos returnvalues[0] = "false";
460805e681cSangelos returnvalues[1] = "true";
461805e681cSangelos
462805e681cSangelos /* Just do the query. */
463805e681cSangelos j = kn_do_query(sessionid, returnvalues, NUM_RETURN_VALUES);
464805e681cSangelos if (j == -1)
465805e681cSangelos {
46625d42aecSmillert switch (keynote_errno)
467805e681cSangelos {
468805e681cSangelos case ERROR_MEMORY:
469805e681cSangelos fprintf(stderr, "Out of memory while performing authorization "
470805e681cSangelos "query.\n");
471805e681cSangelos break;
472805e681cSangelos
473805e681cSangelos case ERROR_NOTFOUND:
474805e681cSangelos fprintf(stderr, "Session %d not found while performing "
475805e681cSangelos "authorization query.\n", sessionid);
476805e681cSangelos break;
477805e681cSangelos
478805e681cSangelos default:
479805e681cSangelos fprintf(stderr, "Unspecified error %d (shouldn't happen) "
480805e681cSangelos "while performing authorization query.\n",
481805e681cSangelos keynote_errno);
482805e681cSangelos break;
483805e681cSangelos }
484805e681cSangelos }
485805e681cSangelos else
486805e681cSangelos {
487805e681cSangelos fprintf(stdout, "Return value is [%s]\n", returnvalues[j]);
488805e681cSangelos }
489805e681cSangelos
490805e681cSangelos /*
491805e681cSangelos * Once the query is done, we can find what assertions failed in what way.
492805e681cSangelos * One way is just going through the list of assertions, as shown here
493805e681cSangelos * for assertions that failed due to memory exhaustion.
494805e681cSangelos */
495805e681cSangelos j = 0;
496805e681cSangelos
497805e681cSangelos do
498805e681cSangelos {
499805e681cSangelos i = kn_get_failed(sessionid, KEYNOTE_ERROR_MEMORY, j++);
500805e681cSangelos if (i != -1)
501805e681cSangelos fprintf(stderr, "Assertion %d failed due to memory exhaustion.\n",
502805e681cSangelos i);
503805e681cSangelos } while (i != -1);
504805e681cSangelos
505805e681cSangelos /*
506805e681cSangelos * Another way is to go through the list of failed assertions by deleting
507805e681cSangelos * the "first" one.
508805e681cSangelos */
509805e681cSangelos do
510805e681cSangelos {
511805e681cSangelos i = kn_get_failed(sessionid, KEYNOTE_ERROR_SYNTAX, 0);
512805e681cSangelos if (i != -1)
513805e681cSangelos {
514805e681cSangelos fprintf(stderr, "Assertion %d failed due to some syntax error.\n",
515805e681cSangelos i);
516805e681cSangelos kn_remove_assertion(sessionid, i); /* Delete assertion */
517805e681cSangelos }
518805e681cSangelos } while (i != -1);
519805e681cSangelos
520805e681cSangelos /*
521805e681cSangelos * Signature failures, another way.
522805e681cSangelos */
523805e681cSangelos for (j = 0, i = kn_get_failed(sessionid, KEYNOTE_ERROR_SIGNATURE, 0);
524805e681cSangelos i != -1; i = kn_get_failed(sessionid, KEYNOTE_ERROR_SIGNATURE, j++))
525805e681cSangelos fprintf(stderr, "Failed to verify signature on assertion %d.\n", i);
526805e681cSangelos
527805e681cSangelos /*
528805e681cSangelos * Here's how to find all errors.
529805e681cSangelos */
530805e681cSangelos for (i = kn_get_failed(sessionid, KEYNOTE_ERROR_ANY, 0); i != -1;
531805e681cSangelos i = kn_get_failed(sessionid, KEYNOTE_ERROR_ANY, 0))
532805e681cSangelos {
533805e681cSangelos fprintf(stderr, "Unspecified error in processing assertion %d.\n", i);
534805e681cSangelos kn_remove_assertion(sessionid, i);
535805e681cSangelos }
536805e681cSangelos
537805e681cSangelos /* Destroy the session, freeing all allocated memory. */
538805e681cSangelos kn_close(sessionid);
539805e681cSangelos
540805e681cSangelos exit(0);
541805e681cSangelos }
542