/* * Close a session. */ int kn_close(int sessid) { struct keynote_session *ks; struct assertion *as, *as2; int i; keynote_errno = 0; if ((keynote_current_session == (struct keynote_session *) NULL) || (keynote_current_session->ks_id != sessid)) { keynote_current_session = keynote_find_session(sessid); if (keynote_current_session == (struct keynote_session *) NULL) { keynote_errno = ERROR_NOTFOUND; return -1; } } ks = keynote_current_session; /* Cleanup environment -- no point using kn_cleanup_action_environment() */ keynote_env_cleanup(ks->ks_env_table, HASHTABLESIZE); keynote_env_cleanup(&(ks->ks_env_regex), 1); /* Cleanup assertions */ for (i = 0; i < HASHTABLESIZE; i++) for (as = ks->ks_assertion_table[i]; as != (struct assertion *) NULL; as = as2) { as2 = as->as_next; keynote_free_assertion(as); } /* Cleanup action authorizers */ keynote_keylist_free(ks->ks_action_authorizers); /* Unlink from chain */ if (ks->ks_prev == (struct keynote_session *) NULL) { keynote_sessions[ks->ks_id % SESSIONTABLESIZE] = ks->ks_next; if (ks->ks_next != (struct keynote_session *) NULL) ks->ks_next->ks_prev = (struct keynote_session *) NULL; } else { ks->ks_prev->ks_next = ks->ks_next; if (ks->ks_next != (struct keynote_session *) NULL) ks->ks_next->ks_prev = ks->ks_prev; } free(ks); keynote_current_session = (struct keynote_session *) NULL; return 0; }
/* * Verify the signature on an assertion. */ int kn_verify_assertion(char *buf, int len) { struct assertion *as; int res; keynote_errno = 0; as = keynote_parse_assertion(buf, len, ASSERT_FLAG_SIGVER); if (as == NULL) return -1; res = keynote_sigverify_assertion(as); keynote_free_assertion(as); return res; }
/* * Produce the signature for an assertion. */ char * kn_sign_assertion(char *buf, int buflen, char *key, char *sigalg, int vflag) { int i, alg, hashtype, encoding, internalenc; struct keynote_deckey dc; struct assertion *as; char *s, *sig; keynote_errno = 0; s = NULL; if (sigalg == NULL || buf == NULL || key == NULL) { keynote_errno = ERROR_NOTFOUND; return NULL; } if (sigalg[0] == '\0' || sigalg[strlen(sigalg) - 1] != ':') { keynote_errno = ERROR_SYNTAX; return NULL; } /* We're using a different format for X509 private keys, so... */ alg = keynote_get_sig_algorithm(sigalg, &hashtype, &encoding, &internalenc); if (alg != KEYNOTE_ALGORITHM_X509) { /* Parse the private key */ s = keynote_get_private_key(key); if (s == NULL) return NULL; /* Decode private key */ i = kn_decode_key(&dc, s, KEYNOTE_PRIVATE_KEY); if (i == -1) { free(s); return NULL; } } else /* X509 private key */ { dc.dec_key = key; dc.dec_algorithm = alg; } as = keynote_parse_assertion(buf, buflen, ASSERT_FLAG_SIGGEN); if (as == NULL) { if (alg != KEYNOTE_ALGORITHM_X509) { keynote_free_key(dc.dec_key, dc.dec_algorithm); free(s); } return NULL; } sig = keynote_sign_assertion(as, sigalg, dc.dec_key, dc.dec_algorithm, vflag); if (alg != KEYNOTE_ALGORITHM_X509) keynote_free_key(dc.dec_key, dc.dec_algorithm); keynote_free_assertion(as); if (s != NULL) free(s); return sig; }
/* * Parse an assertion. Set keynote_errno to ERROR_SYNTAX if parsing * failed due to certificate badness, and ERROR_MEMORY if memory * problem. If more than one assertions have been passed in the * buffer, they will be linked. */ 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 = (char *) NULL; struct assertion *as; /* Allocate memory for assertion */ as = (struct assertion *) calloc(1, sizeof(struct assertion)); if (as == (struct assertion *) NULL) { keynote_errno = ERROR_MEMORY; return (struct assertion *) NULL; } /* Keep a copy of the assertion around */ as->as_buf = strdup(buf); if (as->as_buf == (char *) NULL) { keynote_errno = ERROR_MEMORY; keynote_free_assertion(as); return (struct assertion *) NULL; } as->as_flags = assertion_flags & ~(ASSERT_FLAG_SIGGEN | ASSERT_FLAG_SIGVER); /* Skip any leading whitespace */ for (i = 0, j = len; i < j && isspace((int) as->as_buf[i]); i++) ; /* Keyword must start at begining of buffer or line */ if ((i >= j) || ((i != 0) && (as->as_buf[i - 1] != '\n'))) { keynote_free_assertion(as); keynote_errno = ERROR_SYNTAX; return (struct assertion *) NULL; } while (i < j) /* Decomposition loop */ { ks = as->as_buf + i; /* Mark begining of assertion for signature purposes */ if (as->as_startofsignature == (char *) NULL) as->as_startofsignature = ks; /* This catches comments at the begining of an assertion only */ if (as->as_buf[i] == '#') /* Comment */ { seen_field = 1; /* Skip until the end of line */ while ((i< j) && as->as_buf[++i] != '\n') ; i++; continue; /* Loop */ } /* Advance until we find a keyword separator */ for (; (as->as_buf[i] != ':') && (i < j); i++) ; if (i + 1 > j) { keynote_free_assertion(as); keynote_errno = ERROR_SYNTAX; return (struct assertion *) NULL; } /* ks points at begining of keyword, ke points at end */ ke = as->as_buf + i; /* ts points at begining of value field */ ts = as->as_buf + i + 1; /* Skip ':' */ /* * Find the end of the field -- means end of buffer, * a newline followed by a non-whitespace character, * or two newlines. */ while (++i <= j) { /* If end of buffer, we're at the end of the field */ if (i == j) { end_of_assertion = 1; te = as->as_buf + i; break; } /* If two newlines, end of assertion */ 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 newline followed by non-whitespace or comment character */ if ((as->as_buf[i] == '\n') && (!isspace((int) as->as_buf[i + 1])) && (as->as_buf[i + 1] != '#')) { te = as->as_buf + i; break; } } i++; /* * On each of the cases (except the first), we check that: * - we've already seen a keynote-version field (and that * it's the first one that appears in the assertion) * - the signature field, if present, is the last one * - no field appears more than once */ switch (whichkeyword(ks, ke)) { case -1: keynote_free_assertion(as); return (struct assertion *) NULL; case KEYWORD_VERSION: if ((ver == 1) || (seen_field == 1)) { keynote_free_assertion(as); keynote_errno = ERROR_SYNTAX; return (struct assertion *) NULL; } /* Test for version correctness */ keynote_get_envlist(ts, te, 1); if (keynote_errno != 0) { keynote_free_assertion(as); return (struct assertion *) NULL; } ver = 1; break; case KEYWORD_LOCALINIT: if (as->as_env != (struct environment *) NULL) { keynote_free_assertion(as); keynote_errno = ERROR_SYNTAX; return (struct assertion *) NULL; } as->as_env = keynote_get_envlist(ts, te, 0); if (keynote_errno != 0) { keynote_free_assertion(as); return (struct assertion *) NULL; } break; case KEYWORD_AUTHORIZER: if (as->as_authorizer_string_s != (void *) NULL) { keynote_free_assertion(as); keynote_errno = ERROR_SYNTAX; return (struct assertion *) NULL; } as->as_authorizer_string_s = ts; as->as_authorizer_string_e = te; break; case KEYWORD_LICENSEES: if (as->as_keypred_s != (char *) NULL) { keynote_free_assertion(as); keynote_errno = ERROR_SYNTAX; return (struct assertion *) NULL; } as->as_keypred_s = ts; as->as_keypred_e = te; break; case KEYWORD_CONDITIONS: if (as->as_conditions_s != (char *) NULL) { keynote_free_assertion(as); keynote_errno = ERROR_SYNTAX; return (struct assertion *) NULL; } as->as_conditions_s = ts; as->as_conditions_e = te; break; case KEYWORD_SIGNATURE: if (as->as_signature_string_s != (char *) NULL) { keynote_free_assertion(as); keynote_errno = ERROR_SYNTAX; return (struct assertion *) 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 != (char *) NULL) { keynote_free_assertion(as); keynote_errno = ERROR_SYNTAX; return (struct assertion *) NULL; } as->as_comment_s = ts; as->as_comment_e = te; break; } seen_field = 1; if (end_of_assertion == 1) { /* End of buffer, good termination */ if ((te == as->as_buf + len) || (te + 1 == as->as_buf + len) || (*(te) == '\0') || (*(te + 1) == '\0')) break; /* Check whether there's something else following */ for (k = 1; te + k < as->as_buf + len && *(te + k) != '\n'; k++) if (!isspace((int) *(te + k))) { keynote_free_assertion(as); keynote_errno = ERROR_SYNTAX; return (struct assertion *) NULL; } break; /* Assertion is "properly" terminated */ } } /* Check that the basic fields are there */ if (as->as_authorizer_string_s == (char *) NULL) { keynote_free_assertion(as); keynote_errno = ERROR_SYNTAX; return (struct assertion *) NULL; } /* Signature generation/verification handling */ if (assertion_flags & ASSERT_FLAG_SIGGEN) { if (keynote_fix_fields(as, 0) != RESULT_TRUE) { keynote_free_assertion(as); return (struct assertion *) NULL; } } else if (assertion_flags & ASSERT_FLAG_SIGVER) if (keynote_fix_fields(as, 1) != RESULT_TRUE) { keynote_free_assertion(as); return (struct assertion *) NULL; } return as; }