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

📄 spdb_struct.c

📁 This a good VPN source
💻 C
📖 第 1 页 / 共 5 页
字号:
/* Security Policy Data Base (such as it is) * Copyright (C) 1998-2001  D. Hugh Redelmeier. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License * for more details. * * RCSID $Id: spdb_struct.c,v 1.8 2004/12/09 18:13:08 mcr Exp $ */#include <stdio.h>#include <string.h>#include <stdlib.h>#include <sys/socket.h>#include <netinet/in.h>#include <arpa/inet.h>#include <sys/queue.h>#include <openswan.h>#include <openswan/ipsec_policy.h>#include "constants.h"#include "oswlog.h"#include "defs.h"#include "id.h"#include "x509.h"#include "pgp.h"#include "certs.h"#include "smartcard.h"#ifdef XAUTH_USEPAM#include <security/pam_appl.h>#endif#include "connections.h"	/* needs id.h */#include "state.h"#include "packet.h"#include "keys.h"#include "kernel.h"	/* needs connections.h */#include "log.h"#include "spdb.h"#include "whack.h"	/* for RC_LOG_SERIOUS */#include "sha1.h"#include "md5.h"#include "crypto.h" /* requires sha1.h and md5.h */#include "alg_info.h"#include "kernel_alg.h"#include "ike_alg.h"#include "db_ops.h"#ifdef NAT_TRAVERSAL#include "nat_traversal.h"#endif/** output an attribute (within an SA) */boolout_attr(int type	 , unsigned long val	 , struct_desc *attr_desc	 , enum_names **attr_val_descs USED_BY_DEBUG	 , pb_stream *pbs){    struct isakmp_attribute attr;    if (val >> 16 == 0)    {	/* short value: use TV form */	attr.isaat_af_type = type | ISAKMP_ATTR_AF_TV;	attr.isaat_lv = val;	if (!out_struct(&attr, attr_desc, pbs, NULL))	    return FALSE;    }    else    {	/* This is a real fudge!  Since we rarely use long attributes	 * and since this is the only place where we can cause an	 * ISAKMP message length to be other than a multiple of 4 octets,	 * we force the length of the value to be a multiple of 4 octets.	 * Furthermore, we only handle values up to 4 octets in length.	 * Voila: a fixed format!	 */	pb_stream val_pbs;	u_int32_t nval = htonl(val);	attr.isaat_af_type = type | ISAKMP_ATTR_AF_TLV;	if (!out_struct(&attr, attr_desc, pbs, &val_pbs)	|| !out_raw(&nval, sizeof(nval), &val_pbs, "long attribute value"))	    return FALSE;	close_output_pbs(&val_pbs);    }    DBG(DBG_EMITTING,	enum_names *d = attr_val_descs[type];	if (d != NULL)	    DBG_log("    [%lu is %s]"		, val, enum_show(d, val)));    return TRUE;}#define return_on(var, val) do { var=val;goto return_out; } while(0);/** * Output an SA, as described by a db_sa. * This has the side-effect of allocating SPIs for us. * */boolout_sa(pb_stream *outs       , struct db_sa *sadb       , struct state *st       , bool oakley_mode       , bool aggressive_mode UNUSED       , u_int8_t np){    pb_stream sa_pbs;    int pcn;    bool ret = FALSE;    bool ah_spi_generated = FALSE	, esp_spi_generated = FALSE	, ipcomp_cpi_generated = FALSE;    struct db_sa *revised_sadb;    if(oakley_mode) {	revised_sadb=oakley_alg_makedb(st->st_connection->alg_info_ike				       , sadb				       , aggressive_mode ? 1 : -1);    } else {	revised_sadb=kernel_alg_makedb(st->st_connection->alg_info_esp);    }    if(revised_sadb != NULL) {	sadb = revised_sadb;    }    /* SA header out */    {	struct isakmp_sa sa;	sa.isasa_np = np;	st->st_doi = sa.isasa_doi = ISAKMP_DOI_IPSEC;	/* all we know */	if (!out_struct(&sa, &isakmp_sa_desc, outs, &sa_pbs))	    return_on(ret, FALSE);    }    /* within SA: situation out */    st->st_situation = SIT_IDENTITY_ONLY;    if (!out_struct(&st->st_situation, &ipsec_sit_desc, &sa_pbs, NULL))	return_on(ret, FALSE);    /* within SA: Proposal Payloads     *     * Multiple Proposals with the same number are simultaneous     * (conjuncts) and must deal with different protocols (AH or ESP).     * Proposals with different numbers are alternatives (disjuncts),     * in preference order.     * Proposal numbers must be monotonic.     * See RFC 2408 "ISAKMP" 4.2     */    for (pcn = 0; pcn < sadb->prop_conj_cnt; pcn++)    {	struct db_prop_conj *pc;	int pn;	int valid_prop_cnt;		pc = &sadb->prop_conjs[pcn];	/*	 * figure out how many proposals we are going to make,	 * so we'll know when we are finished! This repeats some calculations	 * but this seems like the best method to avoid empty proposals.	 */	valid_prop_cnt = 0;	for (pn = 0; pn < pc->prop_cnt; pn++)	{	    struct db_prop *p;	    p = &pc->props[pn];	    valid_prop_cnt++;	}	    	DBG(DBG_EMITTING, 	    DBG_log("out_sa pcn: %d has %d valid proposals",		    pcn, valid_prop_cnt));	for (pn = 0; pn < pc->prop_cnt; pn++)	{	    struct db_prop *p;	    pb_stream proposal_pbs;	    struct isakmp_proposal proposal;	    struct_desc *trans_desc;	    struct_desc *attr_desc;	    enum_names **attr_val_descs;	    int tn;	    bool tunnel_mode;	    /*	     * set the tunnel_mode bit on the last proposal only, and	     * only if we are trying to negotiate tunnel mode in the first	     * place.	     */	    tunnel_mode = (valid_prop_cnt == 1)		&& (st->st_policy & POLICY_TUNNEL);	    /*	     * pick the part of the proposal we are trying to work on	     */	    p = &pc->props[pn];	    proposal.isap_proposal = pcn;	    proposal.isap_protoid = p->protoid;	    proposal.isap_spisize = oakley_mode ? 0		: p->protoid == PROTO_IPCOMP ? IPCOMP_CPI_SIZE		: IPSEC_DOI_SPI_SIZE;	    DBG(DBG_EMITTING, 		DBG_log("out_sa pcn: %d pn: %d<%d valid_count: %d",			pcn, pn, pc->prop_cnt, valid_prop_cnt));	    /* but, skip things if the transform count is zero */	    if(p->trans_cnt == 0) continue; 	    /* Proposal header */	    if(--valid_prop_cnt > 0) {		proposal.isap_np = ISAKMP_NEXT_P;	    } else {		proposal.isap_np = ISAKMP_NEXT_NONE;	    }	    proposal.isap_notrans = p->trans_cnt;	    if (!out_struct(&proposal, &isakmp_proposal_desc			    , &sa_pbs, &proposal_pbs))		return_on(ret, FALSE);	    /* Per-protocols stuff:	     * Set trans_desc.	     * Set attr_desc.	     * Set attr_val_descs.	     * If not oakley_mode, emit SPI.	     * We allocate SPIs on demand.	     * All ESPs in an SA will share a single SPI.	     * All AHs in an SAwill share a single SPI.	     * AHs' SPI will be distinct from ESPs'.	     * This latter is needed because KLIPS doesn't	     * use the protocol when looking up a (dest, protocol, spi).	     * ??? If multiple ESPs are composed, how should their SPIs	     * be allocated?	     */	    {		ipsec_spi_t *spi_ptr = NULL;		int proto = 0;		bool *spi_generated;		switch (p->protoid)		{		case PROTO_ISAKMP:		    passert(oakley_mode);		    trans_desc = &isakmp_isakmp_transform_desc;		    attr_desc = &isakmp_oakley_attribute_desc;		    attr_val_descs = oakley_attr_val_descs;		    /* no SPI needed */		    break;		    		case PROTO_IPSEC_AH:		    passert(!oakley_mode);		    trans_desc = &isakmp_ah_transform_desc;		    attr_desc = &isakmp_ipsec_attribute_desc;		    attr_val_descs = ipsec_attr_val_descs;		    spi_ptr = &st->st_ah.our_spi;		    spi_generated = &ah_spi_generated;		    proto = IPPROTO_AH;		    break;		    		case PROTO_IPSEC_ESP:		    passert(!oakley_mode);		    trans_desc = &isakmp_esp_transform_desc;		    attr_desc = &isakmp_ipsec_attribute_desc;		    attr_val_descs = ipsec_attr_val_descs;		    spi_ptr = &st->st_esp.our_spi;		    spi_generated = &esp_spi_generated;		    proto = IPPROTO_ESP;		    break;		    		case PROTO_IPCOMP:		    passert(!oakley_mode);		    trans_desc = &isakmp_ipcomp_transform_desc;		    attr_desc = &isakmp_ipsec_attribute_desc;		    attr_val_descs = ipsec_attr_val_descs;		    /* a CPI isn't quite the same as an SPI		     * so we use specialized code to emit it.		     */		    if (!ipcomp_cpi_generated)		    {			st->st_ipcomp.our_spi = get_my_cpi(			    &st->st_connection->spd, tunnel_mode);			if (st->st_ipcomp.our_spi == 0)			    return_on(ret, FALSE);	/* problem generating CPI */			ipcomp_cpi_generated = TRUE;		    }		    /* CPI is stored in network low order end of an		     * ipsec_spi_t.  So we start a couple of bytes in.		     */		    if (!out_raw((u_char *)&st->st_ipcomp.our_spi		     + IPSEC_DOI_SPI_SIZE - IPCOMP_CPI_SIZE		    , IPCOMP_CPI_SIZE		    , &proposal_pbs, "CPI"))			return_on(ret, FALSE);		    break;		    		default:		    bad_case(p->protoid);		}				if (spi_ptr != NULL)		{		    if (!*spi_generated)		    {			*spi_ptr = get_ipsec_spi(0			    , proto			    , &st->st_connection->spd			    , tunnel_mode);			if (*spi_ptr == 0)			    return FALSE;			*spi_generated = TRUE;		    }		    if (!out_raw((u_char *)spi_ptr, IPSEC_DOI_SPI_SIZE		    , &proposal_pbs, "SPI"))			return_on(ret, FALSE);		}	    }	    /* within proposal: Transform Payloads */	    for (tn = 0; tn != p->trans_cnt; tn++)	    {		struct db_trans *t = &p->trans[tn];		pb_stream trans_pbs;		struct isakmp_transform trans;		int an;		trans.isat_np = (tn == p->trans_cnt - 1)		    ? ISAKMP_NEXT_NONE : ISAKMP_NEXT_T;		trans.isat_transnum = tn;		trans.isat_transid = t->transid;		if (!out_struct(&trans, trans_desc, &proposal_pbs, &trans_pbs))		    return_on(ret, FALSE);		/* Within tranform: Attributes. */		/* For Phase 2 / Quick Mode, GROUP_DESCRIPTION is		 * automatically generated because it must be the same		 * in every transform.  Except IPCOMP.		 */		if (p->protoid != PROTO_IPCOMP		&& st->st_pfs_group != NULL)		{		    passert(!oakley_mode);		    passert(st->st_pfs_group != &unset_group);		    out_attr(GROUP_DESCRIPTION, st->st_pfs_group->group			, attr_desc, attr_val_descs			, &trans_pbs);		}		/* automatically generate duration		 * and, for Phase 2 / Quick Mode, encapsulation.		 */		if (oakley_mode)		{		    out_attr(OAKLEY_LIFE_TYPE, OAKLEY_LIFE_SECONDS			, attr_desc, attr_val_descs			, &trans_pbs);		    out_attr(OAKLEY_LIFE_DURATION			, st->st_connection->sa_ike_life_seconds			, attr_desc, attr_val_descs			, &trans_pbs);		}		else		{		    /* RFC 2407 (IPSEC DOI) 4.5 specifies that		     * the default is "unspecified (host-dependent)".		     * This makes little sense, so we always specify it.		     *		     * Unlike other IPSEC transforms, IPCOMP defaults		     * to Transport Mode, so we can exploit the default		     * (draft-shacham-ippcp-rfc2393bis-05.txt 4.1).		     */		    if (p->protoid != PROTO_IPCOMP		    || st->st_policy & POLICY_TUNNEL)		    {#ifdef NAT_TRAVERSAL#ifndef I_KNOW_TRANSPORT_MODE_HAS_SECURITY_CONCERN_BUT_I_WANT_IT			if ((st->nat_traversal & NAT_T_DETECTED) &&				(!(st->st_policy & POLICY_TUNNEL))) {				/* Inform user that we will not respect policy and only				 * propose Tunnel Mode				 */				loglog(RC_LOG_SERIOUS, "NAT-Traversal: "					"Transport Mode not allowed due to security concerns -- "					"using Tunnel mode.  Rebuild Openswan with USE_NAT_TRAVERSAL_TRANSPORT_MODE=true in Makefile.inc to support transport mode.");			}#endif#endif			out_attr(ENCAPSULATION_MODE#ifdef NAT_TRAVERSAL#ifdef I_KNOW_TRANSPORT_MODE_HAS_SECURITY_CONCERN_BUT_I_WANT_IT			    , NAT_T_ENCAPSULATION_MODE(st,st->st_policy)#else				/* If NAT-T is detected, use UDP_TUNNEL as long as Transport				 * Mode has security concerns.				 *				 * User has been informed of that				 */			    , NAT_T_ENCAPSULATION_MODE(st,POLICY_TUNNEL)#endif#else /* ! NAT_TRAVERSAL */			    , st->st_policy & POLICY_TUNNEL			      ? ENCAPSULATION_MODE_TUNNEL : ENCAPSULATION_MODE_TRANSPORT#endif			    , attr_desc, attr_val_descs			    , &trans_pbs);		    }		    out_attr(SA_LIFE_TYPE, SA_LIFE_TYPE_SECONDS			, attr_desc, attr_val_descs			, &trans_pbs);		    out_attr(SA_LIFE_DURATION			, st->st_connection->sa_ipsec_life_seconds			, attr_desc, attr_val_descs			, &trans_pbs);		}		/* spit out attributes from table */		for (an = 0; an != t->attr_cnt; an++)		{		    struct db_attr *a = &t->attrs[an];		    out_attr(a->type, a->val			, attr_desc, attr_val_descs			, &trans_pbs);		}		close_output_pbs(&trans_pbs);	    }	    close_output_pbs(&proposal_pbs);	}	/* end of a conjunction of proposals */    }    close_output_pbs(&sa_pbs);    ret = TRUE;

⌨️ 快捷键说明

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