Commit 9abb167c authored by Niels Möller's avatar Niels Möller
Browse files

Deleted old spki implementation.

(spki_lookup, spki_authorize): New functions.
(do_spki_acl_db_mark, do_spki_acl_db_free): New functions.

Rev: src/spki.c:1.44
parent 0b5a08cb
......@@ -6,7 +6,7 @@
/* lsh, an implementation of the ssh protocol
*
* Copyright (C) 1999 Balzs Scheidler, Niels Mller
* Copyright (C) 1999, 2003 Balzs Scheidler, Niels Mller
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
......@@ -41,15 +41,24 @@
#include "nettle/sexp.h"
#include "spki/parse.h"
#include "spki/tag.h"
#include <assert.h>
#include <string.h>
/* Forward declarations */
static void
do_spki_acl_db_mark(struct spki_acl_db *db,
void (*mark)(struct lsh_object *o));
static void
do_spki_acl_db_free(struct spki_acl_db *db);
#define GABA_DEFINE
#include "spki.h.x"
# include "spki.h.x"
#undef GABA_DEFINE
#include "spki.c.x"
/* FIXME: This should create different tags for hostnames that are not
* dns fqdn:s. */
......@@ -193,695 +202,86 @@ spki_hash_data(const struct hash_algorithm *algorithm,
HASH_SIZE(hash), out);
}
/* 5-tuples */
struct spki_subject *
make_spki_subject(struct sexp_iterator *i,
struct verifier *verifier,
const struct lsh_string *sha1,
const struct lsh_string *md5)
{
NEW(spki_subject, self);
self->key = lsh_sexp_copy(i);
self->verifier = verifier;
self->sha1 = sha1;
self->md5 = md5;
return self;
}
#if 0
static int
subject_match_hash(struct spki_subject *self,
int method,
const struct lsh_string *h1)
{
const struct lsh_string *h2;
switch (method)
{
case ATOM_SHA1:
if (self->sha1)
h2 = self->sha1;
#if 0
else if (self->key)
h2 = self->sha1
= hash_string(&sha1_algorithm, self->key, 0);
#endif
else
return 0;
break;
case ATOM_MD5:
if (self->md5)
h2 = self->md5;
#if 0
else if (self->key)
h2 = self->md5
= hash_string(&md5_algorithm, self->key, 0);
#endif
else
return 0;
break;
default:
return 0;
}
return lsh_string_eq(h1, h2);
}
#endif
struct spki_5_tuple *
make_spki_5_tuple(struct spki_subject *issuer,
struct spki_subject *subject,
int propagate,
struct spki_tag *authorization,
int before_limit, time_t not_before,
int after_limit, time_t not_after)
{
NEW(spki_5_tuple, self);
self->issuer = issuer;
self->subject = subject;
self->propagate = propagate;
self->authorization = authorization;
self->validity.before_limit = before_limit;
self->validity.not_before = not_before;
self->validity.after_limit = after_limit;
self->validity.not_after = not_after;
return self;
}
/* Sets of authorizations, representing the (tag ...) expressions in
* acl:s and certificates. */
/* An authorization represented as a string (optionally with display
* type). */
/* GABA:
(class
(name spki_tag_atom)
(super spki_tag)
(vars
(display string)
(resource string)))
*/
static int
do_spki_tag_atom_match(struct spki_tag *s,
struct sexp_iterator *e)
{
CAST(spki_tag_atom, self, s);
if (e->type != SEXP_ATOM
|| !lsh_string_eq_l(self->resource, e->atom_length, e->atom))
return 0;
if (self->display)
{
if (! (e->display &&
lsh_string_eq_l(self->display, e->display_length, e->display)))
return 0;
}
else if (e->display)
return 0;
return sexp_iterator_next(e);
}
static struct spki_tag *
make_spki_tag_atom(struct sexp_iterator *i)
{
NEW(spki_tag_atom, self);
assert(i->type == SEXP_ATOM);
self->super.type = SPKI_TAG_ATOM;
self->super.match = do_spki_tag_atom_match;
self->resource = lsh_sexp_to_string(i, &self->display);
if (!self->resource)
{
KILL(self);
return NULL;
}
return &self->super;
}
/* An authorization represented as a list. Includes all authorizations
* that for which a prefix matches the list. */
/* GABA:
(class
(name spki_tag_list)
(super spki_tag)
(vars
(list object object_list)))
*/
static int
do_spki_tag_list_match(struct spki_tag *s,
struct sexp_iterator *j)
{
CAST(spki_tag_list, self, s);
unsigned i;
if (!sexp_iterator_enter_list(j))
return 0;
for (i = 0;
i<LIST_LENGTH(self->list);
i++)
{
CAST_SUBTYPE(spki_tag, tag, LIST(self->list)[i]);
if (j->type == SEXP_END
|| !SPKI_TAG_MATCH(tag, j))
return 0;
}
return sexp_iterator_exit_list(j);
}
static struct spki_tag *
make_spki_tag_list(struct object_list *list)
{
NEW(spki_tag_list, self);
self->super.type = SPKI_TAG_LIST;
self->super.match = do_spki_tag_list_match;
self->list = list;
return &self->super;
}
/* A (* set ...) construction */
/* GABA:
(class
(name spki_tag_set)
(super spki_tag)
(vars
(set object object_list)))
*/
static int
do_spki_tag_set_match(struct spki_tag *s,
struct sexp_iterator *e)
{
CAST(spki_tag_set, self, s);
unsigned i;
for (i = 0; i<LIST_LENGTH(self->set); i++)
{
struct sexp_iterator j = *e;
CAST_SUBTYPE(spki_tag, tag, LIST(self->set)[i]);
if (SPKI_TAG_MATCH(tag, &j))
{
*e = j;
return 1;
}
}
return 0;
}
static struct spki_tag *
make_spki_tag_set(struct object_list *set)
{
NEW(spki_tag_set, self);
self->super.type = SPKI_TAG_SET;
self->super.match = do_spki_tag_set_match;
self->set = set;
return &self->super;
}
/* Authorizations represented as a string prefix. If display types are
* present, they must be equal. */
/* GABA:
(class
(name spki_tag_prefix)
(super spki_tag)
(vars
(display string)
(prefix string)))
*/
static int
do_spki_tag_prefix_match(struct spki_tag *s,
struct sexp_iterator *i)
{
CAST(spki_tag_prefix, self, s);
if (i->type != SEXP_ATOM)
return 0;
if (self->display)
{
if (!i->display
|| !lsh_string_eq_l(self->display, i->display_length, i->display))
return 0;
}
else if (i->display)
return 0;
return i->atom_length >= self->prefix->length
&& !memcmp(i->atom, self->prefix->data, self->prefix->length);
}
static struct spki_tag *
make_spki_tag_prefix(struct sexp_iterator *i)
static void
do_spki_acl_db_mark(struct spki_acl_db *db,
void (*mark)(struct lsh_object *o))
{
NEW(spki_tag_prefix, self);
struct spki_principal *p;
assert(i->type == SEXP_ATOM);
self->super.type = SPKI_TAG_PREFIX;
self->super.match = do_spki_tag_prefix_match;
self->prefix = lsh_sexp_to_string(i, &self->display);
if (!self->prefix)
{
KILL(self);
return NULL;
}
return &self->super;
for (p = db->first_principal; p; p = p->next)
mark(p->verifier);
}
static int
do_spki_tag_any_match(struct spki_tag *self UNUSED,
struct sexp_iterator *i)
static void
do_spki_acl_db_free(struct spki_acl_db *db)
{
return sexp_iterator_next(i);
spki_acl_clear(db);
}
/* FIXME: Make this const */
struct spki_tag spki_tag_any =
{ STATIC_HEADER, SPKI_TAG_ANY, do_spki_tag_any_match };
struct spki_principal *
spki_lookup(struct spki_context *self,
unsigned length,
const uint8_t *key,
struct verifier *v)
static struct object_list *
spki_sexp_to_tag_list(struct sexp_iterator *i, unsigned limit)
{
struct object_queue q;
struct spki_principal *principal;
struct spki_iterator i;
struct sexp_iterator sexp;
if (i->type == SEXP_END)
if (!sexp_iterator_first(&sexp, length, key)
|| !spki_iterator_first_sexp(&i, &sexp)
|| !spki_parse_principal(&self->db, i, &principal))
{
werror("spki_sexp_to_tag_list: Empty list.\n");
werror("do_spki_lookup: Invalid expression.\n");
return NULL;
}
object_queue_init(&q);
while (i->type != SEXP_END)
if (!principal->verifier)
{
struct spki_tag *tag = spki_sexp_to_tag(i, limit);
if (!tag)
{
/* FIXME: We could explicitly kill the elements of the queue
* as well. */
object_queue_kill(&q);
return NULL;
}
object_queue_add_tail(&q, &tag->super);
}
return queue_to_list_and_kill(&q);
}
struct spki_tag *
spki_sexp_to_tag(struct sexp_iterator *i,
/* Some limit on the recursion */
unsigned limit)
{
switch (i->type)
{
default:
abort();
case SEXP_ATOM:
return make_spki_tag_atom(i);
case SEXP_END:
/* Should this ever happen? */
abort();
case SEXP_LIST:
{
if (!limit)
{
werror("spki_sexp_to_tag: Nesting too deep.\n");
return NULL;
}
if (!sexp_iterator_enter_list(i))
return NULL;
if (i->type == SEXP_ATOM && !i->display
&& i->atom_length == 1 && i->atom[0] == '*')
{
if (!sexp_iterator_next(i))
return NULL;
if (i->type != SEXP_ATOM || i->display)
{
werror("spki_sexp_to_tag: Invalid (* ...) tag.\n");
return NULL;
}
switch (lsh_sexp_to_atom(i))
{
case ATOM_SET:
{
struct object_list *l = spki_sexp_to_tag_list(i, limit - 1);
return l ? make_spki_tag_set(l) : NULL;
}
case ATOM_PREFIX:
return make_spki_tag_prefix(i);
default:
werror("spki_sexp_to_tag: Invalid (* ...) tag.\n");
return NULL;
}
}
else
{
struct object_list *l = spki_sexp_to_tag_list(i, limit - 1);
return l ? make_spki_tag_list(l) : NULL;
}
}
if (v)
principal->verifier = v;
else
principal->verifier = spki_make_verifier(self->algorithms);
}
}
#define SPKI_NESTING_LIMIT 17
/* The iterator should point at the element after the tag of an expression
*
* (entry (public-key|hash|name ...) (propagate)? (tag ...) (valid ...)? )
*/
struct spki_5_tuple *
spki_acl_entry_to_5_tuple(struct spki_context *ctx,
struct sexp_iterator *i)
{
struct spki_subject *subject;
struct spki_tag *authorization;
int propagate = 0;
int type;
subject = SPKI_LOOKUP(ctx, i, NULL);
if (!subject)
return NULL;
type = lsh_sexp_get_type(i);
if (type == ATOM_PROPAGATE)
{
propagate = 1;
if (!sexp_iterator_enter_list(i))
return 0;
type = lsh_sexp_get_type(i);
}
if (type != ATOM_TAG)
{
werror("spki_acl_entry_to_5_tuple: Invalid entry.\n");
return NULL;
}
else
{
authorization = spki_sexp_to_tag(i, SPKI_NESTING_LIMIT);
if (!authorization || !sexp_iterator_exit_list(i))
return NULL;
}
if (i->type != SEXP_END || !sexp_iterator_exit_list(i))
{
werror("spki_acl_entry_to_5_tuple: Garbage at end of entry.\n");
return NULL;
}
/* Create a 5-tuple with a NULL (i.e. self) issuer */
return make_spki_5_tuple(NULL, subject, propagate,
authorization, 0, 0, 0, 0);
return principal;
}
/* Takes an spki_context and an ACL s-expression, and adds
* corresponding 5-tuples to the context. Returns 1 if all entries
* were correct, 0 on any error. */
int
spki_add_acl(struct spki_context *ctx,
struct sexp_iterator *i)
spki_authorize(struct spki_context *self,
struct spki_principal *user,
time_t t,
const struct lsh_string *access)
{
if (!sexp_iterator_check_type(i, "acl"))
{
werror("spki_read_acls: Invalid acl\n");
return 0;
}
/* FIXME: Accept at least (version "0") */
#if 0
if (sexp_check_type(SEXP_GET(i), ATOM_VERSION, NULL))
{
werror("spki_read_acls: Unsupported acl version\n");
return 0;
}
#endif
while (i->type != SEXP_END)
{
struct spki_5_tuple *acl;
if (!sexp_iterator_check_type(i, "entry"))
return 0;
acl = spki_acl_entry_to_5_tuple(ctx, i);
if (!acl)
return 0;
SPKI_ADD_TUPLE(ctx, acl);
}
return sexp_iterator_exit_list(i);
}
/* SPKI context */
/* GABA:
(class
(name spki_state)
(super spki_context)
(vars
; Signature algorithms
(algorithms object alist)
;; FIXME: Could have a alist of hash algorithms as well.
; We could use some kind of hash table instead
(keys struct object_queue)
; Five tuples.
(db struct object_queue)))
*/
#if 0
static struct spki_subject *
spki_subject_by_hash(struct spki_state *self,
int algorithm,
const struct lsh_string *hash)
{
FOR_OBJECT_QUEUE(&self->keys, n)
{
CAST(spki_subject, subject, n);
if (subject_match_hash(subject, algorithm, hash))
return subject;
}
return NULL;
}
#endif
static struct spki_subject *
do_spki_lookup(struct spki_context *s,
struct sexp_iterator *i,
struct verifier *v)
struct spki_5_tuple *acl;
struct spki_date date;
{
CAST(spki_state, self, s);
spki_date_from_time_t(&date, t);
switch (lsh_sexp_get_type(i))
for (acl = spki_acl_by_subject_first(&self->db, user);
acl;
acl = spki_acl_by_subject_next(&self->db, acl, user))
{
case ATOM_HASH:
{
/* Syntax: (hash <hash-alg-name> <hash-value> <uris>) */
struct spki_subject *subject;
const struct lsh_string *hash;
int method = lsh_sexp_to_atom(i);
if (!method)
return NULL;
hash = lsh_sexp_to_string(i, NULL);
if (!hash)
return NULL;
if (i->type != SEXP_END
|| !sexp_iterator_exit_list(i))
return NULL;
#if 0
subject = spki_subject_by_hash(self, method, hash);
if (subject)
lsh_string_free(hash);
else
#endif
{
switch (method)
{
case ATOM_SHA1:
subject = make_spki_subject(NULL, NULL, hash, NULL);
break;
case ATOM_MD5:
subject = make_spki_subject(NULL, NULL, NULL, hash);
break;
default:
lsh_string_free(hash);
return NULL;
}
object_queue_add_tail(&self->keys, &subject->super);
}
<