⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ipsec_doi.c

📁 This a good VPN source
💻 C
📖 第 1 页 / 共 5 页
字号:
	r_hash_start = r_hdr_pbs.cur; /* hash from after HASH(1) */    }    /* Notification Payload */    {	pb_stream not_pbs;	struct isakmp_notification isan;	isan.isan_doi = ISAKMP_DOI_IPSEC;	isan.isan_np = ISAKMP_NEXT_NONE;	isan.isan_type = type;	isan.isan_spisize = spisize;	isan.isan_protoid = protoid;	if (!out_struct(&isan, &isakmp_notification_desc, &r_hdr_pbs, &not_pbs)	    || !out_raw(spi, spisize, &not_pbs, "spi"))	    impossible();	close_output_pbs(&not_pbs);    }    /* calculate hash value and patch into Hash Payload */    if (encst)    {	struct hmac_ctx ctx;	hmac_init_chunk(&ctx, encst->st_oakley.hasher, encst->st_skeyid_a);	hmac_update(&ctx, (u_char *) &msgid, sizeof(msgid_t));	hmac_update(&ctx, r_hash_start, r_hdr_pbs.cur-r_hash_start);	hmac_final(r_hashval, &ctx);	DBG(DBG_CRYPT,	    DBG_log("HASH(1) computed:");	    DBG_dump("", r_hashval, ctx.hmac_digest_len);	)    }    /* Encrypt message (preserve st_iv) */    if (encst)    {	u_char old_iv[MAX_DIGEST_LEN];	u_int old_iv_len = encst->st_iv_len;	if (old_iv_len > MAX_DIGEST_LEN)	    impossible();	memcpy(old_iv, encst->st_iv, old_iv_len);		if (!IS_ISAKMP_SA_ESTABLISHED(encst->st_state))	{	    if (encst->st_new_iv_len > MAX_DIGEST_LEN)		impossible();	    memcpy(encst->st_iv, encst->st_new_iv, encst->st_new_iv_len);	    encst->st_iv_len = encst->st_new_iv_len;	}	init_phase2_iv(encst, &msgid);	if (!encrypt_message(&r_hdr_pbs, encst))	    impossible();	    	/* restore preserved st_iv*/	memcpy(encst->st_iv, old_iv, old_iv_len);	encst->st_iv_len = old_iv_len;    }    else    {	close_output_pbs(&r_hdr_pbs);    }    /* Send packet (preserve st_tpacket) */    {	chunk_t saved_tpacket = sndst->st_tpacket;	setchunk(sndst->st_tpacket, pbs.start, pbs_offset(&pbs));	send_packet(sndst, "notification packet");	sndst->st_tpacket = saved_tpacket;    }}voidsend_notification_from_state(struct state *st, enum state_kind state,    u_int16_t type){    struct state *p1st;    passert(st);    if (state == STATE_UNDEFINED)	state = st->st_state;    if (IS_QUICK(state)) {	p1st = find_phase1_state(st->st_connection, ISAKMP_SA_ESTABLISHED_STATES);	if ((p1st == NULL) || (!IS_ISAKMP_SA_ESTABLISHED(p1st->st_state))) {	    loglog(RC_LOG_SERIOUS,		"no Phase1 state for Quick mode notification");	    return;	}	send_notification(st, type, p1st, generate_msgid(p1st),	    st->st_icookie, st->st_rcookie, NULL, 0, PROTO_ISAKMP);    }    else if (IS_ISAKMP_ENCRYPTED(state)) {	send_notification(st, type, st, generate_msgid(st),	    st->st_icookie, st->st_rcookie, NULL, 0, PROTO_ISAKMP);    }    else {	/* no ISAKMP SA established - don't encrypt notification */	send_notification(st, type, NULL, 0,	    st->st_icookie, st->st_rcookie, NULL, 0, PROTO_ISAKMP);    }}voidsend_notification_from_md(struct msg_digest *md, u_int16_t type){    /**     * Create a dummy state to be able to use send_packet in     * send_notification     *     * we need to set:     *   st_connection->that.host_addr     *   st_connection->that.host_port     *   st_connection->interface     */    struct state st;    struct connection cnx;    passert(md);    memset(&st, 0, sizeof(st));    memset(&cnx, 0, sizeof(cnx));    st.st_connection = &cnx;    cnx.spd.that.host_addr = md->sender;    cnx.spd.that.host_port = md->sender_port;    cnx.interface = md->iface;    send_notification(&st, type, NULL, 0,	md->hdr.isa_icookie, md->hdr.isa_rcookie, NULL, 0, PROTO_ISAKMP);}/** Send a Delete Notification to announce deletion of ISAKMP SA or * inbound IPSEC SAs.  Does nothing if no such SAs are being deleted. * Delete Notifications cannot announce deletion of outbound IPSEC/ISAKMP SAs. *  * @param st State struct (hopefully has some SA's related to it)  */voidsend_delete(struct state *st){    pb_stream reply_pbs;    pb_stream r_hdr_pbs;    msgid_t	msgid;    u_char buffer[8192];    struct state *p1st;    ip_said said[EM_MAXRELSPIS];    ip_said *ns = said;    u_char	*r_hashval,	/* where in reply to jam hash value */	*r_hash_start;	/* start of what is to be hashed */    bool isakmp_sa = FALSE;    /* If there are IPsec SA's related to this state struct... */    if (IS_IPSEC_SA_ESTABLISHED(st->st_state))    {        /* Find their phase1 state object */	p1st = find_phase1_state(st->st_connection, ISAKMP_SA_ESTABLISHED_STATES);	if (p1st == NULL)	{	    DBG(DBG_CONTROL, DBG_log("no Phase 1 state for Delete"));	    return;	}	if (st->st_ah.present)	{	    ns->spi = st->st_ah.our_spi;	    ns->dst = st->st_connection->spd.this.host_addr;	    ns->proto = PROTO_IPSEC_AH;	    ns++;	}	if (st->st_esp.present)	{	    ns->spi = st->st_esp.our_spi;	    ns->dst = st->st_connection->spd.this.host_addr;	    ns->proto = PROTO_IPSEC_ESP;	    ns++;	}	passert(ns != said);    /* there must be some SAs to delete */    }    /* or ISAKMP SA's... */    else if (IS_ISAKMP_SA_ESTABLISHED(st->st_state))    {	p1st = st;	isakmp_sa = TRUE;    }    else    {	return; /* nothing to do */    }    msgid = generate_msgid(p1st);    zero(buffer);    init_pbs(&reply_pbs, buffer, sizeof(buffer), "delete msg");    /* HDR* */    {	struct isakmp_hdr hdr;	hdr.isa_version = ISAKMP_MAJOR_VERSION << ISA_MAJ_SHIFT | ISAKMP_MINOR_VERSION;	hdr.isa_np = ISAKMP_NEXT_HASH;	hdr.isa_xchg = ISAKMP_XCHG_INFO;	hdr.isa_msgid = msgid;	hdr.isa_flags = ISAKMP_FLAG_ENCRYPTION;	memcpy(hdr.isa_icookie, p1st->st_icookie, COOKIE_SIZE);	memcpy(hdr.isa_rcookie, p1st->st_rcookie, COOKIE_SIZE);	if (!out_struct(&hdr, &isakmp_hdr_desc, &reply_pbs, &r_hdr_pbs))	    impossible();    }    /* HASH -- value to be filled later */    {	pb_stream hash_pbs;	if (!out_generic(ISAKMP_NEXT_D, &isakmp_hash_desc, &r_hdr_pbs, &hash_pbs))	    impossible();	r_hashval = hash_pbs.cur;	/* remember where to plant value */	if (!out_zero(p1st->st_oakley.hasher->hash_digest_len, &hash_pbs, "HASH(1)"))	    impossible();	close_output_pbs(&hash_pbs);	r_hash_start = r_hdr_pbs.cur;	/* hash from after HASH(1) */    }    /* Delete Payloads */    if (isakmp_sa)    {	pb_stream del_pbs;	struct isakmp_delete isad;	u_char isakmp_spi[2*COOKIE_SIZE];	isad.isad_doi = ISAKMP_DOI_IPSEC;	isad.isad_np = ISAKMP_NEXT_NONE;	isad.isad_spisize = (2 * COOKIE_SIZE);	isad.isad_protoid = PROTO_ISAKMP;	isad.isad_nospi = 1;	memcpy(isakmp_spi, st->st_icookie, COOKIE_SIZE);	memcpy(isakmp_spi+COOKIE_SIZE, st->st_rcookie, COOKIE_SIZE);	if (!out_struct(&isad, &isakmp_delete_desc, &r_hdr_pbs, &del_pbs)	|| !out_raw(&isakmp_spi, (2*COOKIE_SIZE), &del_pbs, "delete payload"))	    impossible();	close_output_pbs(&del_pbs);    }    else    {	while (ns != said)	{	    pb_stream del_pbs;	    struct isakmp_delete isad;	    ns--;	    isad.isad_doi = ISAKMP_DOI_IPSEC;	    isad.isad_np = ns == said? ISAKMP_NEXT_NONE : ISAKMP_NEXT_D;	    isad.isad_spisize = sizeof(ipsec_spi_t);	    isad.isad_protoid = ns->proto;	    isad.isad_nospi = 1;	    if (!out_struct(&isad, &isakmp_delete_desc, &r_hdr_pbs, &del_pbs)	    || !out_raw(&ns->spi, sizeof(ipsec_spi_t), &del_pbs, "delete payload"))		impossible();	    close_output_pbs(&del_pbs);	}    }    /* calculate hash value and patch into Hash Payload */    {	struct hmac_ctx ctx;	hmac_init_chunk(&ctx, p1st->st_oakley.hasher, p1st->st_skeyid_a);	hmac_update(&ctx, (u_char *) &msgid, sizeof(msgid_t));	hmac_update(&ctx, r_hash_start, r_hdr_pbs.cur-r_hash_start);	hmac_final(r_hashval, &ctx);	DBG(DBG_CRYPT,	    DBG_log("HASH(1) computed:");	    DBG_dump("", r_hashval, ctx.hmac_digest_len);	)    }    /* Do a dance to avoid needing a new state object.     * We use the Phase 1 State.  This is the one with right     * IV, for one thing.     * The tricky bits are:     * - we need to preserve (save/restore) st_iv (but not st_iv_new)     * - we need to preserve (save/restore) st_tpacket.     */    {	u_char old_iv[MAX_DIGEST_LEN];	chunk_t saved_tpacket = p1st->st_tpacket;	save_iv(p1st, old_iv);	init_phase2_iv(p1st, &msgid);	if (!encrypt_message(&r_hdr_pbs, p1st))	    impossible();	setchunk(p1st->st_tpacket, reply_pbs.start, pbs_offset(&reply_pbs));	send_packet(p1st, "delete notify");	p1st->st_tpacket = saved_tpacket;	/* get back old IV for this state */	set_iv(p1st, old_iv);    }}/** Accept a Delete SA notification, and process it if valid. *  * @param st State structure * @param md Message Digest * @param p Payload digest */voidaccept_delete(struct state *st, struct msg_digest *md, struct payload_digest *p){    struct isakmp_delete *d = &(p->payload.delete);    size_t sizespi;    int i;    /* We only listen to encrypted notifications */    if (!md->encrypted)    {	loglog(RC_LOG_SERIOUS, "ignoring Delete SA payload: not encrypted");	return;    }    /* If there is no SA related to this request, but it was encrypted */    if (!IS_ISAKMP_SA_ESTABLISHED(st->st_state))    {	/* can't happen (if msg is encrypt), but just to be sure */	loglog(RC_LOG_SERIOUS, "ignoring Delete SA payload: "	"ISAKMP SA not established");	return;    }    if (d->isad_nospi == 0)    {	loglog(RC_LOG_SERIOUS, "ignoring Delete SA payload: no SPI");	return;    }    switch (d->isad_protoid)    {    case PROTO_ISAKMP:	sizespi = 2 * COOKIE_SIZE;	break;    case PROTO_IPSEC_AH:    case PROTO_IPSEC_ESP:	sizespi = sizeof(ipsec_spi_t);	break;    case PROTO_IPCOMP:	/* nothing interesting to delete */	return;    default:	loglog(RC_LOG_SERIOUS	    , "ignoring Delete SA payload: unknown Protocol ID (%s)"	    , enum_show(&protocol_names, d->isad_protoid));	return;    }    if (d->isad_spisize != sizespi)    {	loglog(RC_LOG_SERIOUS	    , "ignoring Delete SA payload: bad SPI size (%d) for %s"	    , d->isad_spisize, enum_show(&protocol_names, d->isad_protoid));	return;    }    if (pbs_left(&p->pbs) != d->isad_nospi * sizespi)    {	loglog(RC_LOG_SERIOUS	    , "ignoring Delete SA payload: invalid payload size");	return;    }    for (i = 0; i < d->isad_nospi; i++)    {	u_char *spi = p->pbs.cur + (i * sizespi);	if (d->isad_protoid == PROTO_ISAKMP)	{	    /**	     * ISAKMP	     */	    struct state *dst = find_state(spi /*iCookie*/		, spi+COOKIE_SIZE /*rCookie*/		, &st->st_connection->spd.that.host_addr		, MAINMODE_MSGID);	    if (dst == NULL)	    {		loglog(RC_LOG_SERIOUS, "ignoring Delete SA payload: "		    "ISAKMP SA not found (maybe expired)");	    }	    else if (!same_peer_ids(st->st_connection, dst->st_connection, NULL))	    {		/* we've not authenticated the relevant identities */		loglog(RC_LOG_SERIOUS, "ignoring Delete SA payload: "		    "ISAKMP SA used to convey Delete has different IDs from ISAKMP SA it deletes");	    }	    else	    {		struct connection *oldc;				oldc = cur_connection;		set_cur_connection(dst->st_connection);#ifdef NAT_TRAVERSAL		if (nat_traversal_enabled) {		    nat_traversal_change_port_lookup(md, dst);		}#endif		loglog(RC_LOG_SERIOUS, "received Delete SA payload: "		    "deleting ISAKMP State #%lu", dst->st_serialno);		delete_state(dst);		set_cur_connection(oldc);	    }	}	else	{	    /**	     * IPSEC (ESP/AH)	     */	    bool bogus;	    struct state *dst = find_phase2_state_to_delete(st		, d->isad_protoid		, *(ipsec_spi_t *)spi	/* network order */		, &bogus);	    if (dst == NULL)	    {		loglog(RC_LOG_SERIOUS		       , "ignoring Delete SA payload: %s SA(0x%08lx) not found (%s)"		       , enum_show(&protocol_names, d->isad_protoid)		       , (unsigned long)ntohl((unsigned long)*(ipsec_spi_t *)spi)		       , bogus ? "our SPI - bogus implementation" : "maybe expired");	    }	    else	    {		struct connection *rc = dst->st_connection;		struct connection *oldc;				oldc = cur_connection;		set_cur_connection(rc);#ifdef NAT_TRAVERSAL		if (nat_traversal_enabled) {		    nat_traversal_change_port_lookup(md, dst);		}#endif		if (rc->newest_ipsec_sa == dst->st_serialno		&& (rc->policy & POLICY_UP))		    {		    /* Last IPSec SA for a permanent connection that we		     * have initiated.  Replace it in a few seconds.		     *		     * Useful if the other peer is rebooting.		     */#define DELETE_SA_DELAY  EVENT_RETRANSMIT_DELAY_0		    if (dst->st_event != NULL		    && dst->st_event->ev_type == EVENT_SA_REPLACE		    && dst->st_event->ev_time <= DELETE_SA_DELAY + now())		    {			/* Patch from Angus Lees to ignore retransmited			 * Delete SA.			 */			loglog(RC_LOG_SERIOUS, "received Delete SA payload: "

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -