#include <sys/types.h>
#include <ctype.h>
#include <limits.h>
#include <regex.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "keynote.h"
#include "assertion.h"
#include "signature.h"
static int
rec_evaluate_query(struct assertion *as)
{
struct assertion *ast;
struct keylist *kl;
int i, s;
as->as_kresult = KRESULT_IN_PROGRESS;
keynote_evaluate_assertion(as);
if (keynote_errno != 0)
{
as->as_kresult = KRESULT_DONE;
if (keynote_errno)
as->as_error = keynote_errno;
if (keynote_errno == ERROR_MEMORY)
return -1;
else
{
keynote_errno = 0;
return 0;
}
}
if (as->as_result == 0)
{
as->as_kresult = KRESULT_DONE;
return as->as_result;
}
for (kl = as->as_keylist;
kl != NULL;
kl = kl->key_next)
{
switch (keynote_in_action_authorizers(kl->key_key, kl->key_alg))
{
case -1:
as->as_kresult = KRESULT_DONE;
if (keynote_errno == ERROR_MEMORY)
{
as->as_error = ERROR_MEMORY;
return -1;
}
else
{
keynote_errno = 0;
continue;
}
case RESULT_FALSE:
break;
case RESULT_TRUE:
keynote_current_assertion = NULL;
continue;
}
for (i = 0;; i++)
{
ast = keynote_find_assertion(kl->key_key, i, kl->key_alg);
if (ast == NULL)
break;
if (ast->as_kresult == KRESULT_IN_PROGRESS)
continue;
if (ast->as_kresult == KRESULT_UNTOUCHED)
rec_evaluate_query(ast);
if (keynote_errno == ERROR_MEMORY)
{
as->as_error = ERROR_MEMORY;
as->as_kresult = KRESULT_DONE;
return -1;
}
else
keynote_errno = 0;
}
}
keynote_current_assertion = as;
s = keynote_parse_keypred(as, 0);
keynote_current_assertion = NULL;
if (keynote_errno == ERROR_MEMORY)
{
as->as_error = ERROR_MEMORY;
as->as_kresult = KRESULT_DONE;
return -1;
}
else
if (keynote_errno)
{
keynote_errno = 0;
s = 0;
}
as->as_result = (as->as_result < s ? as->as_result : s);
if (as->as_sigresult == SIGRESULT_UNTOUCHED)
{
if (!(as->as_flags & ASSERT_FLAG_LOCAL))
as->as_sigresult = keynote_sigverify_assertion(as);
else
as->as_sigresult = SIGRESULT_TRUE;
}
if (as->as_sigresult != SIGRESULT_TRUE)
{
as->as_result = 0;
as->as_sigresult = SIGRESULT_FALSE;
if (keynote_errno != ERROR_MEMORY)
keynote_errno = 0;
else
{
as->as_error = ERROR_MEMORY;
as->as_kresult = KRESULT_DONE;
return -1;
}
}
as->as_kresult = KRESULT_DONE;
return as->as_result;
}
static int
keynote_fix_fields(struct assertion *ast, int sigfield)
{
struct assertion *as;
int i;
if (ast != NULL)
{
if (keynote_evaluate_authorizer(ast, 1) != RESULT_TRUE)
return -1;
if ((sigfield) && (ast->as_signature_string_s != NULL))
if (keynote_evaluate_authorizer(ast, 0) != RESULT_TRUE)
return -1;
return RESULT_TRUE;
}
for (i = 0; i < HASHTABLESIZE; i++)
for (as = keynote_current_session->ks_assertion_table[i];
as != NULL;
as = as->as_next)
{
if (!(as->as_internalflags & ASSERT_IFLAG_NEEDPROC) &&
!(as->as_internalflags & ASSERT_IFLAG_WEIRDLICS) &&
!(as->as_internalflags & ASSERT_IFLAG_WEIRDAUTH) &&
!(as->as_internalflags & ASSERT_IFLAG_WEIRDSIG))
continue;
if (((as->as_internalflags & ASSERT_IFLAG_WEIRDSIG) ||
(as->as_internalflags & ASSERT_IFLAG_NEEDPROC)) &&
(as->as_signature_string_s != NULL))
if (keynote_evaluate_authorizer(as, 0) == -1)
{
if (keynote_errno)
as->as_error = keynote_errno;
if (keynote_errno == ERROR_MEMORY)
return -1;
else
keynote_errno = 0;
}
if ((as->as_internalflags & ASSERT_IFLAG_WEIRDLICS) ||
(as->as_internalflags & ASSERT_IFLAG_NEEDPROC))
if (keynote_parse_keypred(as, 1) == -1)
{
if (keynote_errno)
as->as_error = keynote_errno;
if (keynote_errno == ERROR_MEMORY)
return -1;
else
keynote_errno = 0;
}
if ((as->as_internalflags & ASSERT_IFLAG_WEIRDAUTH) ||
(as->as_internalflags & ASSERT_IFLAG_NEEDPROC))
if (keynote_evaluate_authorizer(as, 1) == -1)
{
if (keynote_errno)
as->as_error = keynote_errno;
if (keynote_errno == ERROR_MEMORY)
return -1;
else
keynote_errno = 0;
}
}
for (i = 0; i < HASHTABLESIZE; i++)
for (as = keynote_current_session->ks_assertion_table[i];
as != NULL;
as = as->as_next)
if (((as->as_internalflags & ASSERT_IFLAG_WEIRDAUTH) &&
!(as->as_internalflags & ASSERT_IFLAG_PROCESSED)) ||
(as->as_internalflags & ASSERT_IFLAG_NEEDPROC))
{
as->as_internalflags &= ~ASSERT_IFLAG_NEEDPROC;
as->as_internalflags |= ASSERT_IFLAG_PROCESSED;
keynote_sremove_assertion(keynote_current_session->ks_id,
as->as_id);
if (keynote_add_htable(as, 1) != RESULT_TRUE)
return -1;
i--;
break;
}
return RESULT_TRUE;
}
int
keynote_evaluate_query(void)
{
struct assertion *as;
int p, prev;
int i;
if (keynote_fix_fields(NULL, 0) != RESULT_TRUE)
return -1;
for (i = 0, prev = 0; i < HASHTABLESIZE; i++)
for (as = keynote_current_session->ks_assertion_table[i];
as != NULL;
as = as->as_next)
if ((as->as_authorizer != NULL) &&
(as->as_signeralgorithm == KEYNOTE_ALGORITHM_NONE))
if ((!strcmp("POLICY", as->as_authorizer)) &&
(as->as_flags & ASSERT_FLAG_LOCAL))
{
if ((p = rec_evaluate_query(as)) == -1)
{
if (keynote_errno)
as->as_error = keynote_errno;
if (keynote_errno == ERROR_MEMORY)
return -1;
else
{
keynote_errno = 0;
continue;
}
}
if (p > prev)
prev = p;
if (prev == (keynote_current_session->ks_values_num - 1))
return prev;
}
return prev;
}
static int
whichkeyword(char *start, char *end)
{
int len = (end - start);
if (len <= 0)
{
keynote_errno = ERROR_MEMORY;
return -1;
}
if (!strncasecmp("keynote-version:", start, len))
return KEYWORD_VERSION;
if (!strncasecmp("local-constants:", start, len))
return KEYWORD_LOCALINIT;
if (!strncasecmp("authorizer:", start, len))
return KEYWORD_AUTHORIZER;
if (!strncasecmp("licensees:", start, len))
return KEYWORD_LICENSEES;
if (!strncasecmp("conditions:", start, len))
return KEYWORD_CONDITIONS;
if (!strncasecmp("signature:", start, len))
return KEYWORD_SIGNATURE;
if (!strncasecmp("comment:", start, len))
return KEYWORD_COMMENT;
keynote_errno = ERROR_SYNTAX;
return -1;
}
struct assertion *
keynote_parse_assertion(char *buf, int len, int assertion_flags)
{
int k, i, j, seen_field = 0, ver = 0, end_of_assertion = 0;
char *ks, *ke, *ts, *te = NULL;
struct assertion *as;
as = calloc(1, sizeof(struct assertion));
if (as == NULL)
{
keynote_errno = ERROR_MEMORY;
return NULL;
}
as->as_buf = strdup(buf);
if (as->as_buf == NULL)
{
keynote_errno = ERROR_MEMORY;
keynote_free_assertion(as);
return NULL;
}
as->as_flags = assertion_flags & ~(ASSERT_FLAG_SIGGEN |
ASSERT_FLAG_SIGVER);
for (i = 0, j = len; i < j && isspace((unsigned char)as->as_buf[i]); i++)
;
if ((i >= j) || ((i != 0) && (as->as_buf[i - 1] != '\n')))
{
keynote_free_assertion(as);
keynote_errno = ERROR_SYNTAX;
return NULL;
}
while (i < j)
{
ks = as->as_buf + i;
if (as->as_startofsignature == NULL)
as->as_startofsignature = ks;
if (as->as_buf[i] == '#')
{
seen_field = 1;
while ((i< j) && as->as_buf[++i] != '\n')
;
i++;
continue;
}
for (; (as->as_buf[i] != ':') && (i < j); i++)
;
if (i + 1 > j)
{
keynote_free_assertion(as);
keynote_errno = ERROR_SYNTAX;
return NULL;
}
ke = as->as_buf + i;
ts = as->as_buf + i + 1;
while (++i <= j)
{
if (i == j)
{
end_of_assertion = 1;
te = as->as_buf + i;
break;
}
if ((as->as_buf[i] == '\n') && (i + 1 < j) &&
(as->as_buf[i + 1] == '\n'))
{
end_of_assertion = 1;
te = as->as_buf + i;
break;
}
if ((as->as_buf[i] == '\n') &&
(!isspace((unsigned char)as->as_buf[i + 1])) &&
(as->as_buf[i + 1] != '#'))
{
te = as->as_buf + i;
break;
}
}
i++;
switch (whichkeyword(ks, ke))
{
case -1:
keynote_free_assertion(as);
return NULL;
case KEYWORD_VERSION:
if ((ver == 1) || (seen_field == 1))
{
keynote_free_assertion(as);
keynote_errno = ERROR_SYNTAX;
return NULL;
}
keynote_get_envlist(ts, te, 1);
if (keynote_errno != 0)
{
keynote_free_assertion(as);
return NULL;
}
ver = 1;
break;
case KEYWORD_LOCALINIT:
if (as->as_env != NULL)
{
keynote_free_assertion(as);
keynote_errno = ERROR_SYNTAX;
return NULL;
}
as->as_env = keynote_get_envlist(ts, te, 0);
if (keynote_errno != 0)
{
keynote_free_assertion(as);
return NULL;
}
break;
case KEYWORD_AUTHORIZER:
if (as->as_authorizer_string_s != NULL)
{
keynote_free_assertion(as);
keynote_errno = ERROR_SYNTAX;
return NULL;
}
as->as_authorizer_string_s = ts;
as->as_authorizer_string_e = te;
break;
case KEYWORD_LICENSEES:
if (as->as_keypred_s != NULL)
{
keynote_free_assertion(as);
keynote_errno = ERROR_SYNTAX;
return NULL;
}
as->as_keypred_s = ts;
as->as_keypred_e = te;
break;
case KEYWORD_CONDITIONS:
if (as->as_conditions_s != NULL)
{
keynote_free_assertion(as);
keynote_errno = ERROR_SYNTAX;
return NULL;
}
as->as_conditions_s = ts;
as->as_conditions_e = te;
break;
case KEYWORD_SIGNATURE:
if (as->as_signature_string_s != NULL)
{
keynote_free_assertion(as);
keynote_errno = ERROR_SYNTAX;
return NULL;
}
end_of_assertion = 1;
as->as_allbutsignature = ks;
as->as_signature_string_s = ts;
as->as_signature_string_e = te;
break;
case KEYWORD_COMMENT:
if (as->as_comment_s != NULL)
{
keynote_free_assertion(as);
keynote_errno = ERROR_SYNTAX;
return NULL;
}
as->as_comment_s = ts;
as->as_comment_e = te;
break;
}
seen_field = 1;
if (end_of_assertion == 1)
{
if ((te == as->as_buf + len) || (te + 1 == as->as_buf + len) ||
(*(te) == '\0') || (*(te + 1) == '\0'))
break;
for (k = 1; te + k < as->as_buf + len && *(te + k) != '\n'; k++)
if (!isspace((unsigned char)*(te + k)))
{
keynote_free_assertion(as);
keynote_errno = ERROR_SYNTAX;
return NULL;
}
break;
}
}
if (as->as_authorizer_string_s == NULL)
{
keynote_free_assertion(as);
keynote_errno = ERROR_SYNTAX;
return NULL;
}
if (assertion_flags & ASSERT_FLAG_SIGGEN)
{
if (keynote_fix_fields(as, 0) != RESULT_TRUE)
{
keynote_free_assertion(as);
return NULL;
}
}
else
if (assertion_flags & ASSERT_FLAG_SIGVER)
if (keynote_fix_fields(as, 1) != RESULT_TRUE)
{
keynote_free_assertion(as);
return NULL;
}
return as;
}