diff options
Diffstat (limited to 'ipsec-tools/src/racoon/rsalist.c')
-rw-r--r-- | ipsec-tools/src/racoon/rsalist.c | 275 |
1 files changed, 275 insertions, 0 deletions
diff --git a/ipsec-tools/src/racoon/rsalist.c b/ipsec-tools/src/racoon/rsalist.c new file mode 100644 index 00000000..f152c825 --- /dev/null +++ b/ipsec-tools/src/racoon/rsalist.c @@ -0,0 +1,275 @@ +/* $NetBSD: rsalist.c,v 1.6 2011/03/14 15:50:36 vanhu Exp $ */ + +/* Id: rsalist.c,v 1.3 2004/11/08 12:04:23 ludvigm Exp */ + +/* + * Copyright (C) 2004 SuSE Linux AG, Nuernberg, Germany. + * Contributed by: Michal Ludvig <mludvig@suse.cz>, SUSE Labs + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the project nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "config.h" + +#include <stdio.h> +#include <string.h> + +#include <sys/types.h> +#include <sys/queue.h> +#include <sys/socket.h> +#include <netdb.h> + +#include <openssl/bn.h> +#include <openssl/rsa.h> + +#include "misc.h" +#include "plog.h" +#include "sockmisc.h" +#include "rsalist.h" +#include "genlist.h" +#include "remoteconf.h" +#include "crypto_openssl.h" + +#ifndef LIST_FIRST +#define LIST_FIRST(head) ((head)->lh_first) +#endif + +#ifndef LIST_NEXT +#define LIST_NEXT(elm, field) ((elm)->field.le_next) +#endif + +/* from prsa_tok.l */ +int prsa_parse_file(struct genlist *list, const char *fname, enum rsa_key_type type); + +int +rsa_key_insert(struct genlist *list, struct netaddr *src, + struct netaddr *dst, RSA *rsa) +{ + struct rsa_key *rsa_key; + + rsa_key = calloc(sizeof(struct rsa_key), 1); + rsa_key->rsa = rsa; + + if (src) + rsa_key->src = src; + else + rsa_key->src = calloc(sizeof(*rsa_key->src), 1); + + if (dst) + rsa_key->dst = dst; + else + rsa_key->dst = calloc(sizeof(*rsa_key->dst), 1); + + genlist_append(list, rsa_key); + + return 0; +} + +struct rsa_key * +rsa_key_dup(struct rsa_key *key) +{ + struct rsa_key *new; + + new = calloc(sizeof(struct rsa_key), 1); + if (new == NULL) + return NULL; + + if (key->rsa) { + new->rsa = key->rsa->d != NULL ? RSAPrivateKey_dup(key->rsa) : RSAPublicKey_dup(key->rsa); + if (new->rsa == NULL) + goto dup_error; + } + + if (key->src) { + new->src = malloc(sizeof(*new->src)); + if (new->src == NULL) + goto dup_error; + memcpy(new->src, key->src, sizeof(*new->src)); + } + if (key->dst) { + new->dst = malloc(sizeof(*new->dst)); + if (new->dst == NULL) + goto dup_error; + memcpy(new->dst, key->dst, sizeof(*new->dst)); + } + + return new; + +dup_error: + if (new->rsa != NULL) + RSA_free(new->rsa); + if (new->dst != NULL) + free(new->dst); + if (new->src != NULL) + free(new->src); + + free(new); + return NULL; +} + +void +rsa_key_free(void *data) +{ + struct rsa_key *rsa_key; + + + rsa_key = (struct rsa_key *)data; + if (rsa_key->src) + free(rsa_key->src); + if (rsa_key->dst) + free(rsa_key->dst); + if (rsa_key->rsa) + RSA_free(rsa_key->rsa); + + free(rsa_key); +} + +static void * +rsa_key_dump_one(void *entry, void *arg) +{ + struct rsa_key *key = entry; + + plog(LLV_DEBUG, LOCATION, NULL, "Entry %s\n", + naddrwop2str_fromto("%s -> %s", key->src, + key->dst)); + if (loglevel > LLV_DEBUG) + RSA_print_fp(stdout, key->rsa, 4); + + return NULL; +} + +void +rsa_key_dump(struct genlist *list) +{ + genlist_foreach(list, rsa_key_dump_one, NULL); +} + +static void * +rsa_list_count_one(void *entry, void *arg) +{ + if (arg) + (*(unsigned long *)arg)++; + return NULL; +} + +unsigned long +rsa_list_count(struct genlist *list) +{ + unsigned long count = 0; + genlist_foreach(list, rsa_list_count_one, &count); + return count; +} + +struct lookup_result { + struct ph1handle *iph1; + int max_score; + struct genlist *winners; +}; + +static void * +rsa_lookup_key_one(void *entry, void *data) +{ + int local_score, remote_score; + struct lookup_result *req = data; + struct rsa_key *key = entry; + + local_score = naddr_score(key->src, req->iph1->local); + remote_score = naddr_score(key->dst, req->iph1->remote); + + plog(LLV_DEBUG, LOCATION, NULL, "Entry %s scored %d/%d\n", + naddrwop2str_fromto("%s -> %s", key->src, key->dst), + local_score, remote_score); + + if (local_score >= 0 && remote_score >= 0) { + if (local_score + remote_score > req->max_score) { + req->max_score = local_score + remote_score; +// genlist_free(req->winners, NULL); + } + + if (local_score + remote_score >= req->max_score) { + genlist_append(req->winners, key); + } + } + + /* Always traverse the whole list */ + return NULL; +} + +struct genlist * +rsa_lookup_keys(struct ph1handle *iph1, int my) +{ + struct genlist *list; + struct lookup_result r; + + plog(LLV_DEBUG, LOCATION, NULL, "Looking up RSA key for %s\n", + saddr2str_fromto("%s <-> %s", iph1->local, iph1->remote)); + + r.iph1 = iph1; + r.max_score = -1; + r.winners = genlist_init(); + + if (my) + list = iph1->rmconf->rsa_private; + else + list = iph1->rmconf->rsa_public; + + genlist_foreach(list, rsa_lookup_key_one, &r); + + if (loglevel >= LLV_DEBUG) + rsa_key_dump(r.winners); + + return r.winners; +} + +int +rsa_parse_file(struct genlist *list, const char *fname, enum rsa_key_type type) +{ + int ret; + + plog(LLV_DEBUG, LOCATION, NULL, "Parsing %s\n", fname); + ret = prsa_parse_file(list, fname, type); + if (loglevel >= LLV_DEBUG) + rsa_key_dump(list); + return ret; +} + +RSA * +rsa_try_check_rsasign(vchar_t *source, vchar_t *sig, struct genlist *list) +{ + struct rsa_key *key; + struct genlist_entry *gp; + + for(key = genlist_next(list, &gp); key; key = genlist_next(NULL, &gp)) { + plog(LLV_DEBUG, LOCATION, NULL, "Checking key %s...\n", + naddrwop2str_fromto("%s -> %s", key->src, key->dst)); + if (eay_check_rsasign(source, sig, key->rsa) == 0) { + plog(LLV_DEBUG, LOCATION, NULL, " ... YEAH!\n"); + return key->rsa; + } + plog(LLV_DEBUG, LOCATION, NULL, " ... nope.\n"); + } + return NULL; +} |