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

📄 nat_traversal.c

📁 ipsec vpn
💻 C
📖 第 1 页 / 共 2 页
字号:
/* Openswan NAT-Traversal * Copyright (C) 2002-2003 Mathieu Lafon - Arkoon Network Security * * 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: nat_traversal.c,v 1.26.2.6 2006/01/04 18:57:52 ken Exp $ */#ifdef NAT_TRAVERSAL#include <stdio.h>#include <stdlib.h>#include <ctype.h>#include <stdarg.h>#include <syslog.h>#include <errno.h>#include <string.h>#include <unistd.h>#include <signal.h>     /* used only if MSG_NOSIGNAL not defined */#include <sys/queue.h>#include <openswan.h>#include <openswan/ipsec_policy.h>#include <pfkeyv2.h>#include <pfkey.h>#include "constants.h"#include "oswlog.h"#include "defs.h"#include "log.h"#include "server.h"#include "state.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"#include "packet.h"#include "demux.h"#include "kernel.h"#include "whack.h"#include "timer.h"#include "ike_alg.h"#include "cookie.h"#include "sha1.h"#include "md5.h"#include "crypto.h"#include "vendor.h"#include "natt_defines.h"#include "nat_traversal.h"#define NAT_D_DEBUG#define NAT_T_SUPPORT_LAST_DRAFTS#define DEFAULT_KEEP_ALIVE_PERIOD  20bool nat_traversal_enabled = FALSE;bool nat_traversal_support_non_ike = FALSE;bool nat_traversal_support_port_floating = FALSE;static unsigned int _kap = 0;static unsigned int _ka_evt = 0;static bool _force_ka = 0;static const char *natt_version = "0.6c";void init_nat_traversal (bool activate, unsigned int keep_alive_period,	bool fka, bool spf){	nat_traversal_enabled = activate;	nat_traversal_support_non_ike = activate;#ifdef NAT_T_SUPPORT_LAST_DRAFTS	nat_traversal_support_port_floating = activate ? spf : FALSE;	openswan_log("Setting NAT-Traversal port-4500 floating to %s"		     , nat_traversal_support_port_floating ? "on" : "off");	openswan_log("   port floating activation criteria nat_t=%d/port_fload=%d"		     , activate, spf);#endif        {          FILE *f = fopen("/proc/net/ipsec/natt", "r");          char n;          if(f != NULL) {            n=getc(f);            if(n=='0') {              nat_traversal_enabled = FALSE;              nat_traversal_support_non_ike=FALSE;              nat_traversal_support_port_floating=FALSE;              openswan_log("  KLIPS does not have NAT-Traversal built in (see /proc/net/ipsec/natt)\n");            }            fclose(f);          }        }	_force_ka = fka;	_kap = keep_alive_period ? keep_alive_period : DEFAULT_KEEP_ALIVE_PERIOD;	plog("  including NAT-Traversal patch (Version %s)%s%s%s",		natt_version, activate ? "" : " [disabled]",		activate & fka ? " [Force KeepAlive]" : "",		activate & !spf ? " [Port Floating disabled]" : "");}static void disable_nat_traversal(int type){	if (type == ESPINUDP_WITH_NON_IKE)		nat_traversal_support_non_ike = FALSE;	else {	  openswan_log("NAT-Traversal port floating turned off");	  nat_traversal_support_port_floating = FALSE;	}	if (!nat_traversal_support_non_ike &&	    !nat_traversal_support_port_floating) {	    openswan_log("NAT-Traversal is turned OFF due to lack of KERNEL support: %d/%d"			 , nat_traversal_support_non_ike			 , nat_traversal_support_port_floating);	    nat_traversal_enabled = FALSE;	}}static void _natd_hash(const struct hash_desc *hasher, char *hash,	u_int8_t *icookie, u_int8_t *rcookie,	const ip_address *ip, u_int16_t port /* network order */){	union hash_ctx ctx;	if (is_zero_cookie(icookie))		DBG_log("_natd_hash: Warning, icookie is zero !!");	if (is_zero_cookie(rcookie))		DBG_log("_natd_hash: Warning, rcookie is zero !!");	/**	 * draft-ietf-ipsec-nat-t-ike-01.txt	 *	 *   HASH = HASH(CKY-I | CKY-R | IP | Port)	 *	 * All values in network order	 */	hasher->hash_init(&ctx);	hasher->hash_update(&ctx, icookie, COOKIE_SIZE);	hasher->hash_update(&ctx, rcookie, COOKIE_SIZE);	switch (addrtypeof(ip)) {		case AF_INET:			hasher->hash_update(&ctx,				(const u_char *)&ip->u.v4.sin_addr.s_addr,				sizeof(ip->u.v4.sin_addr.s_addr));			break;		case AF_INET6:			hasher->hash_update(&ctx,				(const u_char *)&ip->u.v6.sin6_addr.s6_addr,				sizeof(ip->u.v6.sin6_addr.s6_addr));			break;	}	hasher->hash_update(&ctx, (const u_char *)&port, sizeof(u_int16_t));	hasher->hash_final(hash, &ctx);#ifdef NAT_D_DEBUG	DBG(DBG_NATT,		DBG_log("_natd_hash: hasher=%p(%d)", hasher, (int)hasher->hash_digest_len);		DBG_dump("_natd_hash: icookie=", icookie, COOKIE_SIZE);		DBG_dump("_natd_hash: rcookie=", rcookie, COOKIE_SIZE);		switch (addrtypeof(ip)) {			case AF_INET:				DBG_dump("_natd_hash: ip=", &ip->u.v4.sin_addr.s_addr,					sizeof(ip->u.v4.sin_addr.s_addr));				break;		}		DBG_log("_natd_hash: port=%d", ntohs(port));		DBG_dump("_natd_hash: hash=", hash, hasher->hash_digest_len);	);#endif}/** * Add NAT-Traversal VIDs (supported ones) * * Used when we're Initiator */bool nat_traversal_add_vid(u_int8_t np, pb_stream *outs){	bool r = TRUE;	DBG(DBG_NATT	    , DBG_log("nat add vid. port: %d nonike: %d"		      , nat_traversal_support_port_floating		      , nat_traversal_support_non_ike));		      	if (nat_traversal_support_port_floating) {		if (r) r = out_vendorid(np, outs, VID_NATT_RFC);		if (r) r = out_vendorid(np, outs, VID_NATT_IETF_03);		if (r) r = out_vendorid(np, outs, VID_NATT_IETF_02);		if (r) r = out_vendorid(np, outs, VID_NATT_IETF_02_N);	}	if (nat_traversal_support_non_ike) {		if (r) r = out_vendorid(np, outs, VID_NATT_IETF_00);	}	return r;}u_int32_t nat_traversal_vid_to_method(unsigned short nat_t_vid){	switch (nat_t_vid) {		case VID_NATT_IETF_00:			return LELEM(NAT_TRAVERSAL_IETF_00_01);			break;		case VID_NATT_IETF_02:		case VID_NATT_IETF_02_N:		case VID_NATT_IETF_03:			return LELEM(NAT_TRAVERSAL_IETF_02_03);			break;		case VID_NATT_DRAFT_IETF_IPSEC_NAT_T_IKE:			return LELEM(NAT_TRAVERSAL_OSX);			break;		case VID_NATT_RFC:			return LELEM(NAT_TRAVERSAL_RFC);			break;	}	return 0;}void nat_traversal_natd_lookup(struct msg_digest *md){	unsigned char hash_me[MAX_DIGEST_LEN];	unsigned char hash_him[MAX_DIGEST_LEN];	struct payload_digest *p;	struct state *st = md->st;	bool found_me = FALSE;	bool found_him= FALSE;	int i;	if (!st || !md->iface || !st->st_oakley.hasher) {		loglog(RC_LOG_SERIOUS, "NAT-Traversal: assert failed %s:%d",			__FILE__, __LINE__);		return;	}	/** Count NAT-D **/	for (p = md->chain[ISAKMP_NEXT_NATD_RFC], i=0;	     p != NULL;	     p = p->next, i++);	/**	 * We need at least 2 NAT-D (1 for us, many for peer)	 */	if (i < 2) {		loglog(RC_LOG_SERIOUS,		"NAT-Traversal: Only %d NAT-D - Aborting NAT-Traversal negotiation", i);		st->hidden_variables.st_nat_traversal = 0;		return;	}	/**	 * First one with my IP & port	 */	_natd_hash(st->st_oakley.hasher, hash_me		   , st->st_icookie, st->st_rcookie		   , &(md->iface->ip_addr)		   , ntohs(md->iface->port));	/**	 * The others with sender IP & port	 */	_natd_hash(st->st_oakley.hasher, hash_him		   , st->st_icookie, st->st_rcookie		   , &(md->sender), ntohs(md->sender_port));	for (p = md->chain[ISAKMP_NEXT_NATD_RFC], i=0;	     p != NULL && (!found_me || !found_him);	     p = p->next)	  {#ifdef NAT_D_DEBUG	    DBG(DBG_NATT,		DBG_log("NAT_TRAVERSAL hash=%d (me:%d) (him:%d)"			, i, found_me, found_him);		DBG_dump("expected NAT-D(me):", hash_me,			 st->st_oakley.hasher->hash_digest_len);		DBG_dump("expected NAT-D(him):", hash_him,			 st->st_oakley.hasher->hash_digest_len);		DBG_dump("received NAT-D:", p->pbs.cur, pbs_left(&p->pbs));		);#endif	    if ( (pbs_left(&p->pbs) == st->st_oakley.hasher->hash_digest_len)		 && (memcmp(p->pbs.cur, hash_me			    , st->st_oakley.hasher->hash_digest_len)==0))	      {		found_me = TRUE;	      } 	    	    if ( (pbs_left(&p->pbs) == st->st_oakley.hasher->hash_digest_len)		 && (memcmp(p->pbs.cur, hash_him			    , st->st_oakley.hasher->hash_digest_len)==0))	      {		found_him = TRUE;	      } 	    	    i++;	  }		DBG(DBG_NATT,	    DBG_log("NAT_TRAVERSAL hash=%d (me:%d) (him:%d)"		    , i, found_me, found_him));	    	if(!found_me) {	    st->hidden_variables.st_nat_traversal |= LELEM(NAT_TRAVERSAL_NAT_BHND_ME);	}	if(!found_him) {	    st->hidden_variables.st_nat_traversal |= LELEM(NAT_TRAVERSAL_NAT_BHND_PEER);	    st->hidden_variables.st_natd = md->sender;	}	if(st->st_connection->forceencaps) {	    st->hidden_variables.st_nat_traversal |= LELEM(NAT_TRAVERSAL_NAT_BHND_PEER);	    st->hidden_variables.st_nat_traversal |= LELEM(NAT_TRAVERSAL_NAT_BHND_ME);	}}bool nat_traversal_add_natd(u_int8_t np, pb_stream *outs,	struct msg_digest *md){	char hash[MAX_DIGEST_LEN];	struct state *st = md->st;	unsigned int nat_np;	if (!st || !st->st_oakley.hasher) {		loglog(RC_LOG_SERIOUS, "NAT-Traversal: assert failed %s:%d",			__FILE__, __LINE__);		return FALSE;	}	DBG(DBG_EMITTING, DBG_log("sending NATD payloads"));	nat_np = (st->hidden_variables.st_nat_traversal & NAT_T_WITH_RFC_VALUES	      ? ISAKMP_NEXT_NATD_RFC	      : (st->hidden_variables.st_nat_traversal & NAT_T_WITH_NATD_BADDRAFT_VALUES	      ? ISAKMP_NEXT_NATD_BADDRAFTS : ISAKMP_NEXT_NATD_DRAFTS));	if (!out_modify_previous_np(nat_np, outs)) {		return FALSE;	}	/**	 * First one with sender IP & port	 */	if(st->st_connection->forceencaps) {	    _natd_hash(st->st_oakley.hasher		       , hash, st->st_icookie		       , is_zero_cookie(st->st_rcookie) ? md->hdr.isa_rcookie : st->st_rcookie		       , &(md->sender)		       , 0);	} else {	    _natd_hash(st->st_oakley.hasher, hash, st->st_icookie		       , is_zero_cookie(st->st_rcookie) ? md->hdr.isa_rcookie : st->st_rcookie		       , &(md->sender)		       , htons(md->sender_port));	}	if (!out_generic_raw(nat_np, &isakmp_nat_d, outs			     , hash			     , st->st_oakley.hasher->hash_digest_len			     , "NAT-D")) {	    return FALSE;	}	/**	 * Second one with my IP & port	 */	if(st->st_connection->forceencaps) {	    _natd_hash(st->st_oakley.hasher, hash		       , st->st_icookie		       , is_zero_cookie(st->st_rcookie) ? md->hdr.isa_rcookie : st->st_rcookie		       , &(md->iface->ip_addr),0);	} else {	    _natd_hash(st->st_oakley.hasher, hash		       , st->st_icookie		       , is_zero_cookie(st->st_rcookie) ? md->hdr.isa_rcookie : st->st_rcookie		       , &(md->iface->ip_addr)		       , htons(md->iface->port));	}	return (out_generic_raw(np, &isakmp_nat_d, outs,		hash, st->st_oakley.hasher->hash_digest_len, "NAT-D"));}/** * nat_traversal_natoa_lookup() *  * Look for NAT-OA in message */void nat_traversal_natoa_lookup(struct msg_digest *md){	struct payload_digest *p;	struct state *st = md->st;	int i;	ip_address ip;	if (!st || !md->iface) {		loglog(RC_LOG_SERIOUS, "NAT-Traversal: assert failed %s:%d",			__FILE__, __LINE__);		return;	}	/** Initialize NAT-OA */	anyaddr(AF_INET, &st->hidden_variables.st_nat_oa);	/** Count NAT-OA **/	for (p = md->chain[ISAKMP_NEXT_NATOA_RFC], i=0;	     p != NULL;	     p = p->next, i++);	DBG(DBG_NATT,		DBG_log("NAT-Traversal: received %d NAT-OA.", i);	);	if (i==0) {		return;	}	else if (!(st->hidden_variables.st_nat_traversal & LELEM(NAT_TRAVERSAL_NAT_BHND_PEER))) {		loglog(RC_LOG_SERIOUS, "NAT-Traversal: received %d NAT-OA. "			"ignored because peer is not NATed", i);		return;	}	else if (i>1) {		loglog(RC_LOG_SERIOUS, "NAT-Traversal: received %d NAT-OA. "			"using first, ignoring others", i);	}	/** Take first **/	p = md->chain[ISAKMP_NEXT_NATOA_RFC];	DBG(DBG_PARSING,		DBG_dump("NAT-OA:", p->pbs.start, pbs_room(&p->pbs));	);	switch (p->payload.nat_oa.isanoa_idtype) {		case ID_IPV4_ADDR:			if (pbs_left(&p->pbs) == sizeof(struct in_addr)) {				initaddr(p->pbs.cur, pbs_left(&p->pbs)					 , AF_INET, &ip);			}			else {				loglog(RC_LOG_SERIOUS				       , "NAT-Traversal: received IPv4 NAT-OA "				       "with invalid IP size (%d)"				       , (int)pbs_left(&p->pbs));				return;			}			break;		case ID_IPV6_ADDR:			if (pbs_left(&p->pbs) == sizeof(struct in6_addr)) {				initaddr(p->pbs.cur, pbs_left(&p->pbs)					 , AF_INET6, &ip);			}			else {				loglog(RC_LOG_SERIOUS				       , "NAT-Traversal: received IPv6 NAT-OA "				       "with invalid IP size (%d)"				       , (int)pbs_left(&p->pbs));				return;			}			break;		default:			loglog(RC_LOG_SERIOUS, "NAT-Traversal: "				"invalid ID Type (%d) in NAT-OA - ignored",				p->payload.nat_oa.isanoa_idtype);			return;			break;	}	DBG(DBG_NATT,		{			char ip_t[ADDRTOT_BUF];			addrtot(&ip, 0, ip_t, sizeof(ip_t));			DBG_log("received NAT-OA: %s", ip_t);		}	);	if (isanyaddr(&ip)) {		loglog(RC_LOG_SERIOUS		       , "NAT-Traversal: received %%any NAT-OA...");	}	else {		st->hidden_variables.st_nat_oa = ip;	}}bool nat_traversal_add_natoa(u_int8_t np, pb_stream *outs,	struct state *st){	struct isakmp_nat_oa natoa;	pb_stream pbs;	unsigned char ip_val[sizeof(struct in6_addr)];	size_t ip_len = 0;	ip_address *ip;	unsigned int nat_np;	if ((!st) || (!st->st_connection)) {		loglog(RC_LOG_SERIOUS, "NAT-Traversal: assert failed %s:%d",

⌨️ 快捷键说明

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