X-Git-Url: http://git.rot13.org/?a=blobdiff_plain;f=userapps%2Fopensource%2Fipsec-tools%2Fsrc%2Fracoon%2Fhandler.c;fp=userapps%2Fopensource%2Fipsec-tools%2Fsrc%2Fracoon%2Fhandler.c;h=0000000000000000000000000000000000000000;hb=3f05a9da74f56df22d185b66ee663a6fd8053cb3;hp=8f49cc5c197c0a69d3f04de628f268208917f76f;hpb=864458111a0e69d94bbae210d5b7349ca072a6b7;p=bcm963xx.git diff --git a/userapps/opensource/ipsec-tools/src/racoon/handler.c b/userapps/opensource/ipsec-tools/src/racoon/handler.c deleted file mode 100755 index 8f49cc5c..00000000 --- a/userapps/opensource/ipsec-tools/src/racoon/handler.c +++ /dev/null @@ -1,953 +0,0 @@ -/* $Id: handler.c,v 1.13 2004/11/21 19:36:26 manubsd Exp $ */ - -/* - * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. - * 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 -#include -#include - -#include -#include -#include -#include -#include - -#include "var.h" -#include "misc.h" -#include "vmbuf.h" -#include "plog.h" -#include "sockmisc.h" -#include "debug.h" - -#include "schedule.h" -#include "grabmyaddr.h" -#include "algorithm.h" -#include "crypto_openssl.h" -#include "policy.h" -#include "proposal.h" -#include "isakmp_var.h" -#include "evt.h" -#include "isakmp.h" -#ifdef ENABLE_HYBRID -#include "isakmp_xauth.h" -#include "isakmp_cfg.h" -#endif -#include "isakmp_inf.h" -#include "oakley.h" -#include "remoteconf.h" -#include "localconf.h" -#include "handler.h" -#include "gcmalloc.h" -#include "nattraversal.h" - -#ifdef HAVE_GSSAPI -#include "gssapi.h" -#endif - -static LIST_HEAD(_ph1tree_, ph1handle) ph1tree; -static LIST_HEAD(_ph2tree_, ph2handle) ph2tree; -static LIST_HEAD(_ctdtree_, contacted) ctdtree; -static LIST_HEAD(_rcptree_, recvdpkt) rcptree; - -static void del_recvdpkt __P((struct recvdpkt *)); -static void rem_recvdpkt __P((struct recvdpkt *)); -static void sweep_recvdpkt __P((void *)); - -/* - * functions about management of the isakmp status table - */ -/* %%% management phase 1 handler */ -/* - * search for isakmpsa handler with isakmp index. - */ - -extern caddr_t val2str(const char *, size_t); - -struct ph1handle * -getph1byindex(index) - isakmp_index *index; -{ - struct ph1handle *p; - - LIST_FOREACH(p, &ph1tree, chain) { - if (p->status == PHASE1ST_EXPIRED) - continue; - if (memcmp(&p->index, index, sizeof(*index)) == 0) - return p; - } - - return NULL; -} - -/* - * search for isakmp handler by i_ck in index. - */ -struct ph1handle * -getph1byindex0(index) - isakmp_index *index; -{ - struct ph1handle *p; - - LIST_FOREACH(p, &ph1tree, chain) { - if (p->status == PHASE1ST_EXPIRED) - continue; - if (memcmp(&p->index, index, sizeof(cookie_t)) == 0) - return p; - } - - return NULL; -} - -/* - * search for isakmpsa handler by source and remote address. - * don't use port number to search because this function search - * with phase 2's destinaion. - */ -struct ph1handle * -getph1byaddr(local, remote) - struct sockaddr *local, *remote; -{ - struct ph1handle *p; - - LIST_FOREACH(p, &ph1tree, chain) { - if (p->status == PHASE1ST_EXPIRED) - continue; - if (cmpsaddrwop(local, p->local) == 0 - && cmpsaddrwop(remote, p->remote) == 0) - return p; - } - - return NULL; -} - -/* - * search for isakmpsa handler by remote address. - * don't use port number to search because this function search - * with phase 2's destinaion. - */ -struct ph1handle * -getph1bydstaddr(remote) - struct sockaddr *remote; -{ - struct ph1handle *p; - - LIST_FOREACH(p, &ph1tree, chain) { - if (p->status == PHASE1ST_EXPIRED) - continue; - if (cmpsaddrwop(remote, p->remote) == 0) - return p; - } - - return NULL; -} - -/* - * dump isakmp-sa - */ -vchar_t * -dumpph1() -{ - struct ph1handle *iph1; - struct ph1dump *pd; - int cnt = 0; - vchar_t *buf; - - /* get length of buffer */ - LIST_FOREACH(iph1, &ph1tree, chain) - cnt++; - - buf = vmalloc(cnt * sizeof(struct ph1dump)); - if (buf == NULL) { - plog(LLV_ERROR, LOCATION, NULL, - "failed to get buffer\n"); - return NULL; - } - pd = (struct ph1dump *)buf->v; - - LIST_FOREACH(iph1, &ph1tree, chain) { - memcpy(&pd->index, &iph1->index, sizeof(iph1->index)); - pd->status = iph1->status; - pd->side = iph1->side; - memcpy(&pd->remote, iph1->remote, sysdep_sa_len(iph1->remote)); - memcpy(&pd->local, iph1->local, sysdep_sa_len(iph1->local)); - pd->version = iph1->version; - pd->etype = iph1->etype; - pd->created = iph1->created; - pd->ph2cnt = iph1->ph2cnt; - pd++; - } - - return buf; -} - -/* - * create new isakmp Phase 1 status record to handle isakmp in Phase1 - */ -struct ph1handle * -newph1() -{ - struct ph1handle *iph1; - - /* create new iph1 */ - iph1 = racoon_calloc(1, sizeof(*iph1)); - if (iph1 == NULL) - return NULL; - - iph1->status = PHASE1ST_SPAWN; - -#ifdef ENABLE_DPD - iph1->dpd_support = 0; - iph1->dpd_lastack = 0; - iph1->dpd_seq = 0; - iph1->dpd_fails = 0; - iph1->dpd_r_u = NULL; -#endif - - return iph1; -} - -/* - * delete new isakmp Phase 1 status record to handle isakmp in Phase1 - */ -void -delph1(iph1) - struct ph1handle *iph1; -{ - /* SA down shell script hook */ - if (iph1 != NULL) - script_hook(iph1, SCRIPT_PHASE1_DOWN); - - EVT_PUSH(iph1->local, iph1->remote, EVTT_PHASE1_DOWN, NULL); - -#ifdef ENABLE_NATT - if (iph1->natt_flags & NAT_KA_QUEUED) - natt_keepalive_remove (iph1->local, iph1->remote); - - if (iph1->natt_options) { - racoon_free(iph1->natt_options); - iph1->natt_options = NULL; - } -#endif - - if (iph1->remote) { - racoon_free(iph1->remote); - iph1->remote = NULL; - } - if (iph1->local) { - racoon_free(iph1->local); - iph1->local = NULL; - } - -#ifdef ENABLE_HYBRID - if (iph1->mode_cfg) - isakmp_cfg_rmstate(iph1); -#endif - - VPTRINIT(iph1->authstr); - - sched_scrub_param(iph1); - iph1->sce = NULL; - iph1->scr = NULL; - - VPTRINIT(iph1->sendbuf); - - VPTRINIT(iph1->dhpriv); - VPTRINIT(iph1->dhpub); - VPTRINIT(iph1->dhpub_p); - VPTRINIT(iph1->dhgxy); - VPTRINIT(iph1->nonce); - VPTRINIT(iph1->nonce_p); - VPTRINIT(iph1->skeyid); - VPTRINIT(iph1->skeyid_d); - VPTRINIT(iph1->skeyid_a); - VPTRINIT(iph1->skeyid_e); - VPTRINIT(iph1->key); - VPTRINIT(iph1->hash); - VPTRINIT(iph1->sig); - VPTRINIT(iph1->sig_p); - oakley_delcert(iph1->cert); - iph1->cert = NULL; - oakley_delcert(iph1->cert_p); - iph1->cert_p = NULL; - oakley_delcert(iph1->crl_p); - iph1->crl_p = NULL; - oakley_delcert(iph1->cr_p); - iph1->cr_p = NULL; - VPTRINIT(iph1->id); - VPTRINIT(iph1->id_p); - - if (iph1->ivm) { - oakley_delivm(iph1->ivm); - iph1->ivm = NULL; - } - - VPTRINIT(iph1->sa); - VPTRINIT(iph1->sa_ret); - -#ifdef HAVE_GSSAPI - VPTRINIT(iph1->gi_i); - VPTRINIT(iph1->gi_r); - - gssapi_free_state(iph1); -#endif - - racoon_free(iph1); -} - -/* - * create new isakmp Phase 1 status record to handle isakmp in Phase1 - */ -int -insph1(iph1) - struct ph1handle *iph1; -{ - /* validity check */ - if (iph1->remote == NULL) { - plog(LLV_ERROR, LOCATION, NULL, - "invalid isakmp SA handler. no remote address.\n"); - return -1; - } - LIST_INSERT_HEAD(&ph1tree, iph1, chain); - - return 0; -} - -void -remph1(iph1) - struct ph1handle *iph1; -{ - LIST_REMOVE(iph1, chain); -} - -/* - * flush isakmp-sa - */ -void -flushph1() -{ - struct ph1handle *p, *next; - - for (p = LIST_FIRST(&ph1tree); p; p = next) { - next = LIST_NEXT(p, chain); - - /* send delete information */ - if (p->status == PHASE1ST_ESTABLISHED) - isakmp_info_send_d1(p); - - remph1(p); - delph1(p); - } -} - -void -initph1tree() -{ - LIST_INIT(&ph1tree); -} - -/* %%% management phase 2 handler */ -/* - * search ph2handle with policy id. - */ -struct ph2handle * -getph2byspid(spid) - u_int32_t spid; -{ - struct ph2handle *p; - - LIST_FOREACH(p, &ph2tree, chain) { - /* - * there are ph2handle independent on policy - * such like informational exchange. - */ - if (p->spid == spid) - return p; - } - - return NULL; -} - -/* - * search ph2handle with sequence number. - */ -struct ph2handle * -getph2byseq(seq) - u_int32_t seq; -{ - struct ph2handle *p; - - LIST_FOREACH(p, &ph2tree, chain) { - if (p->seq == seq) - return p; - } - - return NULL; -} - -/* - * search ph2handle with message id. - */ -struct ph2handle * -getph2bymsgid(iph1, msgid) - struct ph1handle *iph1; - u_int32_t msgid; -{ - struct ph2handle *p; - - LIST_FOREACH(p, &ph2tree, chain) { - if (p->msgid == msgid) - return p; - } - - return NULL; -} - -/* - * call by pk_recvexpire(). - */ -struct ph2handle * -getph2bysaidx(src, dst, proto_id, spi) - struct sockaddr *src, *dst; - u_int proto_id; - u_int32_t spi; -{ - struct ph2handle *iph2; - struct saproto *pr; - - LIST_FOREACH(iph2, &ph2tree, chain) { - if (iph2->proposal == NULL && iph2->approval == NULL) - continue; - if (iph2->approval != NULL) { - for (pr = iph2->approval->head; pr != NULL; - pr = pr->next) { - if (proto_id != pr->proto_id) - break; - if (spi == pr->spi || spi == pr->spi_p) - return iph2; - } - } else if (iph2->proposal != NULL) { - for (pr = iph2->proposal->head; pr != NULL; - pr = pr->next) { - if (proto_id != pr->proto_id) - break; - if (spi == pr->spi) - return iph2; - } - } - } - - return NULL; -} - -/* - * create new isakmp Phase 2 status record to handle isakmp in Phase2 - */ -struct ph2handle * -newph2() -{ - struct ph2handle *iph2 = NULL; - - /* create new iph2 */ - iph2 = racoon_calloc(1, sizeof(*iph2)); - if (iph2 == NULL) - return NULL; - - iph2->status = PHASE1ST_SPAWN; - - return iph2; -} - -/* - * initialize ph2handle - * NOTE: don't initialize src/dst. - * SPI in the proposal is cleared. - */ -void -initph2(iph2) - struct ph2handle *iph2; -{ - sched_scrub_param(iph2); - iph2->sce = NULL; - iph2->scr = NULL; - - VPTRINIT(iph2->sendbuf); - VPTRINIT(iph2->msg1); - - /* clear spi, keep variables in the proposal */ - if (iph2->proposal) { - struct saproto *pr; - for (pr = iph2->proposal->head; pr != NULL; pr = pr->next) - pr->spi = 0; - } - - /* clear approval */ - if (iph2->approval) { - flushsaprop(iph2->approval); - iph2->approval = NULL; - } - - /* clear the generated policy */ - if (iph2->spidx_gen) { - delsp_bothdir((struct policyindex *)iph2->spidx_gen); - racoon_free(iph2->spidx_gen); - iph2->spidx_gen = NULL; - } - - if (iph2->pfsgrp) { - oakley_dhgrp_free(iph2->pfsgrp); - iph2->pfsgrp = NULL; - } - - VPTRINIT(iph2->dhpriv); - VPTRINIT(iph2->dhpub); - VPTRINIT(iph2->dhpub_p); - VPTRINIT(iph2->dhgxy); - VPTRINIT(iph2->id); - VPTRINIT(iph2->id_p); - VPTRINIT(iph2->nonce); - VPTRINIT(iph2->nonce_p); - VPTRINIT(iph2->sa); - VPTRINIT(iph2->sa_ret); - - if (iph2->ivm) { - oakley_delivm(iph2->ivm); - iph2->ivm = NULL; - } -} - -/* - * delete new isakmp Phase 2 status record to handle isakmp in Phase2 - */ -void -delph2(iph2) - struct ph2handle *iph2; -{ - initph2(iph2); - - if (iph2->src) { - racoon_free(iph2->src); - iph2->src = NULL; - } - if (iph2->dst) { - racoon_free(iph2->dst); - iph2->dst = NULL; - } - if (iph2->src_id) { - racoon_free(iph2->src_id); - iph2->src_id = NULL; - } - if (iph2->dst_id) { - racoon_free(iph2->dst_id); - iph2->dst_id = NULL; - } - - if (iph2->proposal) { - flushsaprop(iph2->proposal); - iph2->proposal = NULL; - } - - racoon_free(iph2); -} - -/* - * create new isakmp Phase 2 status record to handle isakmp in Phase2 - */ -int -insph2(iph2) - struct ph2handle *iph2; -{ - LIST_INSERT_HEAD(&ph2tree, iph2, chain); - - return 0; -} - -void -remph2(iph2) - struct ph2handle *iph2; -{ - LIST_REMOVE(iph2, chain); -} - -void -initph2tree() -{ - LIST_INIT(&ph2tree); -} - -void -flushph2() -{ - struct ph2handle *p, *next; - - for (p = LIST_FIRST(&ph2tree); p; p = next) { - next = LIST_NEXT(p, chain); - - /* send delete information */ - if (p->status == PHASE2ST_ESTABLISHED) - isakmp_info_send_d2(p); - - unbindph12(p); - remph2(p); - delph2(p); - } -} - -/* - * Delete all Phase 2 handlers for this src/dst/proto. This - * is used during INITIAL-CONTACT processing (so no need to - * send a message to the peer). - */ -void -deleteallph2(src, dst, proto_id) - struct sockaddr *src, *dst; - u_int proto_id; -{ - struct ph2handle *iph2, *next; - struct saproto *pr; - - for (iph2 = LIST_FIRST(&ph2tree); iph2 != NULL; iph2 = next) { - next = LIST_NEXT(iph2, chain); - if (iph2->proposal == NULL && iph2->approval == NULL) - continue; - if (iph2->approval != NULL) { - for (pr = iph2->approval->head; pr != NULL; - pr = pr->next) { - if (proto_id == pr->proto_id) - goto zap_it; - } - } else if (iph2->proposal != NULL) { - for (pr = iph2->proposal->head; pr != NULL; - pr = pr->next) { - if (proto_id == pr->proto_id) - goto zap_it; - } - } - continue; - zap_it: - unbindph12(iph2); - remph2(iph2); - delph2(iph2); - } -} - -/* %%% */ -void -bindph12(iph1, iph2) - struct ph1handle *iph1; - struct ph2handle *iph2; -{ - iph2->ph1 = iph1; - LIST_INSERT_HEAD(&iph1->ph2tree, iph2, ph1bind); -} - -void -unbindph12(iph2) - struct ph2handle *iph2; -{ - if (iph2->ph1 != NULL) { - iph2->ph1 = NULL; - LIST_REMOVE(iph2, ph1bind); - } -} - -/* %%% management contacted list */ -/* - * search contacted list. - */ -struct contacted * -getcontacted(remote) - struct sockaddr *remote; -{ - struct contacted *p; - - LIST_FOREACH(p, &ctdtree, chain) { - if (cmpsaddrstrict(remote, p->remote) == 0) - return p; - } - - return NULL; -} - -/* - * create new isakmp Phase 2 status record to handle isakmp in Phase2 - */ -int -inscontacted(remote) - struct sockaddr *remote; -{ - struct contacted *new; - - /* create new iph2 */ - new = racoon_calloc(1, sizeof(*new)); - if (new == NULL) - return -1; - - new->remote = dupsaddr(remote); - - LIST_INSERT_HEAD(&ctdtree, new, chain); - - return 0; -} - -void -initctdtree() -{ - LIST_INIT(&ctdtree); -} - -/* - * check the response has been sent to the peer. when not, simply reply - * the buffered packet to the peer. - * OUT: - * 0: the packet is received at the first time. - * 1: the packet was processed before. - * 2: the packet was processed before, but the address mismatches. - * -1: error happened. - */ -int -check_recvdpkt(remote, local, rbuf) - struct sockaddr *remote, *local; - vchar_t *rbuf; -{ - vchar_t *hash; - struct recvdpkt *r; - time_t t; - int len, s; - - /* set current time */ - t = time(NULL); - - hash = eay_md5_one(rbuf); - if (!hash) { - plog(LLV_ERROR, LOCATION, NULL, - "failed to allocate buffer.\n"); - return -1; - } - - LIST_FOREACH(r, &rcptree, chain) { - if (memcmp(hash->v, r->hash->v, r->hash->l) == 0) - break; - } - vfree(hash); - - /* this is the first time to receive the packet */ - if (r == NULL) - return 0; - - /* - * the packet was processed before, but the remote address mismatches. - */ - if (cmpsaddrstrict(remote, r->remote) != 0) - return 2; - - /* - * it should not check the local address because the packet - * may arrive at other interface. - */ - - /* check the previous time to send */ - if (t - r->time_send < 1) { - plog(LLV_WARNING, LOCATION, NULL, - "the packet retransmitted in a short time from %s\n", - saddr2str(remote)); - /*XXX should it be error ? */ - } - - /* select the socket to be sent */ - s = getsockmyaddr(r->local); - if (s == -1) - return -1; - - /* resend the packet if needed */ - len = sendfromto(s, r->sendbuf->v, r->sendbuf->l, - r->local, r->remote, lcconf->count_persend); - if (len == -1) { - plog(LLV_ERROR, LOCATION, NULL, "sendfromto failed\n"); - return -1; - } - - /* check the retry counter */ - r->retry_counter--; - if (r->retry_counter <= 0) { - rem_recvdpkt(r); - del_recvdpkt(r); - plog(LLV_DEBUG, LOCATION, NULL, - "deleted the retransmission packet to %s.\n", - saddr2str(remote)); - } else - r->time_send = t; - - return 1; -} - -/* - * adding a hash of received packet into the received list. - */ -int -add_recvdpkt(remote, local, sbuf, rbuf) - struct sockaddr *remote, *local; - vchar_t *sbuf, *rbuf; -{ - struct recvdpkt *new = NULL; - - if (lcconf->retry_counter == 0) { - /* no need to add it */ - return 0; - } - - new = racoon_calloc(1, sizeof(*new)); - if (!new) { - plog(LLV_ERROR, LOCATION, NULL, - "failed to allocate buffer.\n"); - return -1; - } - - new->hash = eay_md5_one(rbuf); - if (!new->hash) { - plog(LLV_ERROR, LOCATION, NULL, - "failed to allocate buffer.\n"); - del_recvdpkt(new); - return -1; - } - new->remote = dupsaddr(remote); - if (new->remote == NULL) { - plog(LLV_ERROR, LOCATION, NULL, - "failed to allocate buffer.\n"); - del_recvdpkt(new); - return -1; - } - new->local = dupsaddr(local); - if (new->local == NULL) { - plog(LLV_ERROR, LOCATION, NULL, - "failed to allocate buffer.\n"); - del_recvdpkt(new); - return -1; - } - new->sendbuf = vdup(sbuf); - if (new->sendbuf == NULL) { - plog(LLV_ERROR, LOCATION, NULL, - "failed to allocate buffer.\n"); - del_recvdpkt(new); - return -1; - } - - new->retry_counter = lcconf->retry_counter; - new->time_send = 0; - new->created = time(NULL); - - LIST_INSERT_HEAD(&rcptree, new, chain); - - return 0; -} - -void -del_recvdpkt(r) - struct recvdpkt *r; -{ - if (r->remote) - racoon_free(r->remote); - if (r->local) - racoon_free(r->local); - if (r->hash) - vfree(r->hash); - if (r->sendbuf) - vfree(r->sendbuf); - racoon_free(r); -} - -void -rem_recvdpkt(r) - struct recvdpkt *r; -{ - LIST_REMOVE(r, chain); -} - -void -sweep_recvdpkt(dummy) - void *dummy; -{ - struct recvdpkt *r, *next; - time_t t, lt; - - /* set current time */ - t = time(NULL); - - /* set the lifetime of the retransmission */ - lt = lcconf->retry_counter * lcconf->retry_interval; - - for (r = LIST_FIRST(&rcptree); r; r = next) { - next = LIST_NEXT(r, chain); - - if (t - r->created > lt) { - rem_recvdpkt(r); - del_recvdpkt(r); - } - } - - sched_new(lt, sweep_recvdpkt, NULL); -} - -void -init_recvdpkt() -{ - time_t lt = lcconf->retry_counter * lcconf->retry_interval; - - LIST_INIT(&rcptree); - - sched_new(lt, sweep_recvdpkt, NULL); -} - -#ifdef ENABLE_HYBRID -/* - * Retruns 0 if the address was obtained by ISAKMP mode config, 1 otherwise - * This should be in isakmp_cfg.c but ph1tree being private, it must be there - */ -int -exclude_cfg_addr(addr) - const struct sockaddr *addr; -{ - struct ph1handle *p; - struct sockaddr_in *sin; - - LIST_FOREACH(p, &ph1tree, chain) { - if ((p->mode_cfg != NULL) && - (p->mode_cfg->flags & ISAKMP_CFG_GOT_ADDR4) && - (addr->sa_family == AF_INET)) { - sin = (struct sockaddr_in *)addr; - if (sin->sin_addr.s_addr == p->mode_cfg->addr4.s_addr) - return 0; - } - } - - return 1; -} -#endif