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

📄 fa_request.c

📁 mobile ip 在linux下的一种实现
💻 C
📖 第 1 页 / 共 4 页
字号:
/* $Id: fa_request.c,v 1.81 2001/09/27 17:33:54 jm Exp $ * Foreign Agent - registration request handling * * Dynamic hierarchial IP tunnel * Copyright (C) 1998-2001, Dynamics group * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. See README and COPYING for * more details. */#ifdef HAVE_CONFIG_H#include <config.h>#endif#include <stdlib.h>#include <sys/socket.h>#include <netinet/in.h>#include <arpa/inet.h>#include <syslog.h>#include <assert.h>#include <string.h>#include <errno.h>#include "fa.h"#include "fa_hash.h"#include "fa_mn_addr.h"#include "tunnel.h"#include "debug.h"#include "auth.h"#include "dyn_ip.h"#include "authorized.h"#include "util.h"#include "agent_utils.h"#include "md5_mac.h"#include "list.h"extern struct fa_config *config;extern struct sockaddr_in upper_fa_addr;extern struct interface_entry *up_interface;extern struct msg_key *fa_public_key;extern struct hashtable *tunnels_hash;extern struct bindingtable *bindings_hash;extern struct binding_counters bcounters;extern struct challenge_ext **last_challenges;/* Check if enough memory and other resources to   accept new registration request   returns:      0 = if enough resources      1 = if not enough resources*/static intcheck_resources(void){	if (bcounters.bindingcount >= config->max_bindings) {		LOG2(LOG_ALERT, "check_resources: too many concurrent "		     "bindings - refusing new ones\n");		return 1;	}	/* If needed, some other checks might be added here */	return 0;}static intcoaddr_ok(struct in_addr coaddr){	struct interface_entry *iface;	struct node *node;	if (coaddr.s_addr == config->highest_fa_addr.s_addr)		return 1;	for (node = list_get_first(&config->interfaces); node != NULL;	     node = list_get_next(node)) {		iface = (struct interface_entry *) node;		if (iface->addr.s_addr == coaddr.s_addr)			return 1;	}	return 0;}/* returns: *   0 = auth. ext. ok *   1 = ff_auth missing/invalid *   2 = mf_auth missing/invalid */static intcheck_auth_ext(struct in_addr addr, struct msg_extensions *ext){	struct fa_spi_entry *fa_spi;	fa_spi = get_fa_spi(0, addr, SPI_AGENT_FA);	if (fa_spi != NULL) {		if (ext->ff_auth == NULL ||		    !auth_check_vendor(AUTH_ALG_MD5, fa_spi->shared_secret,				       fa_spi->shared_secret_len,				       (unsigned char *) ext->req,				       ext->ff_auth))			return 1;		else			return 0;	}	fa_spi = get_fa_spi(0, ext->req->home_addr, SPI_AGENT_MN);	if (fa_spi != NULL) {		if (ext->mf_auth == NULL ||		    !auth_check(fa_spi->alg, fa_spi->shared_secret,				fa_spi->shared_secret_len,				(unsigned char *) ext->req,				ext->mf_auth))			return 2;		else			return 0;	} else if (ext->mf_auth != NULL)		return 2;	return 0;}/* returns 1 on invalid request or 0 on valid request */static intvalidate_request(struct msg_extensions *ext, struct packet_from_info *info){	int error_code = 0, i;	char dev[IFNAMSIZ], error_buf[256];	char *error_text = NULL;	int discard_silently = 0;	if (ext->mh_auth == NULL) {		error_text = "no mh_auth";		error_code = REGREP_BAD_REQUEST_FA;	} else if (!auth_is_protected(ext->mn_nai, ext->mh_auth)) {		error_text = "mh_auth does not protect mn_nai";		error_code = REGREP_BAD_REQUEST_FA;	} else if (ext->mf_auth != NULL &&		   !auth_is_protected(ext->mn_nai, ext->mf_auth)) {		error_text = "mf_auth does not protect mn_nai";		error_code = REGREP_BAD_REQUEST_FA;	} else if (ext->mn_fa_key_req_aaa != NULL &&		   (ext->mn_aaa_auth == NULL ||		    !auth_is_protected(ext->mn_fa_key_req_aaa,				       ext->mn_aaa_auth))) {		error_text = "mn_aaa_auth does not protect mn_fa_key_req";		error_code = REGREP_BAD_REQUEST_FA;	} else if (ext->mn_ha_key_req_aaa != NULL &&		   (ext->mn_aaa_auth == NULL ||		    !auth_is_protected(ext->mn_ha_key_req_aaa,				       ext->mn_aaa_auth)))	{		error_text = "mn_aaa_auth does not protect mn_ha_key_req";		error_code = REGREP_BAD_REQUEST_FA;	} else if (ext->challenge != NULL &&		   (ext->mf_auth == NULL ||		    !auth_is_protected(ext->challenge, ext->mf_auth)) &&		   (ext->mn_aaa_auth == NULL ||		    !auth_is_protected(ext->challenge, ext->mn_aaa_auth))) {		/* FIX: check only in the lowest FA (?) */		error_text = "mf_auth/mn_aaa_auth does not protect challenge";		error_code = REGREP_MN_FAILED_AUTH_FA;		discard_silently = 1;#ifndef DEBUG_SIMULATED_TEST	} else if (dyn_ip_route_get(ext->req->ha_addr, dev, IFNAMSIZ) == 0 &&		   strcmp(dev, "lo") == 0) {		error_text = "HA address points to local interface - "			"possible loop";		error_code = REGREP_UNKNOWN_HA_HA; /* RFC 2002: 3.7.2 */#endif	} else if ((ext->req->opts & REGREQ_RESERVED) != 0) {		error_text = "reserved option set";		error_code = REGREP_BAD_REQUEST_FA;	} else if (ext->encaps_del &&		   (ext->req->opts & REGREQ_REVERSE_TUNNEL) == 0) {		error_text = "encapsulating delivery, "			"but no reverse tunneling\n";		error_code = REGREP_BAD_REQUEST_FA;	} else if ((ext->req->opts & REGREQ_VJ_HC) != 0) {		error_text = "unsupported van Jacobson compression option set";		error_code = REGREP_VJ_UNAVAIL_FA;	} else if ((ext->req->opts & (REGREQ_GRE_ENCAPS |				      REGREQ_MINIMAL_ENCAPS)) != 0) {		error_text = "unavailable encapsulation";		error_code = REGREP_ENCAP_UNAVAIL_FA;	} else if ((ext->req->opts & REGREQ_MN_DECAPS) == 0 &&		   !config->enable_fa_decapsulation &&		   is_sender_mobile(ext)) {		/* check this only if this FA is the lowest FA */		error_text = "FA decapsulation denied";		error_code = REGREP_ENCAP_UNAVAIL_FA;	} else if ((ext->req->opts & REGREQ_REVERSE_TUNNEL) != 0 &&		   config->enable_reverse_tunneling == 0) {		error_text = "reverse tunneling not allowed";		error_code = REGREP_REVERSE_TUNNEL_UNAVAIL_FA;	} else if ((ext->req->opts & REGREQ_REVERSE_TUNNEL) == 0 &&		   config->enable_reverse_tunneling != 0 &&		   config->enable_triangle_tunneling == 0 &&		   config->force_reverse_tunneling == 0) {		error_text = "denied request for triangle tunnel - "		     "reverse tunnel required";		error_code = REGREP_REVERSE_TUNNEL_MANDATORY_FA;	} else if ((ext->req->opts & REGREQ_REVERSE_TUNNEL) == 0 &&		   config->enable_triangle_tunneling == 0) {		error_text = "denied request for triangle tunnel";		error_code = REGREP_ADMIN_PROHIBITED_FA;	} else if (!authorized_check(config->authorized_networks,			      info->src.sin_addr)) {		error_text = "request from an unauthorized address";		error_code = REGREP_ADMIN_PROHIBITED_FA;	} else if (is_sender_mobile(ext) &&		   config->allow_mobile_nodes == FALSE) {		error_text = "MNs not allowed in this FA";		error_code = REGREP_ADMIN_PROHIBITED_FA;	} else if ((ext->req->opts & REGREQ_MN_DECAPS) == 0 &&		   !coaddr_ok(ext->req->co_addr)) {		error_text = "MN trying to use invalid care-of address";		error_code = REGREP_INVALID_CAREOF_FA;	} else if (info->ttl < 255 && is_sender_mobile(ext) &&		   (config->reg_ttl_check == TTL_CHECK_ALL ||		    (config->reg_ttl_check == TTL_CHECK_REVERSE &&		     (ext->req->opts & REGREQ_REVERSE_TUNNEL) != 0))) {		error_text = "MN too distant - TTL < 255";		error_code = REGREP_REVERSE_TUNNEL_MN_TOO_DISTANT_FA;	} else if ((i = check_auth_ext(info->src.sin_addr, ext)) != 0) {		if (i == 2) {			error_text = "invalid mf_auth";			error_code = REGREP_MN_FAILED_AUTH_FA;		} else {			/* actually this is FA-FA auth. failure, but there is			 * not currently any error code for it */			error_text = "invalid ff_auth";			error_code = REGREP_REASON_UNSPEC_FA;		}	} else if (ext->double_auth_ext > 0) {		error_text = "duplicate authentication extension";		if (ext->double_auth_ext & DOUBLE_MF_AUTH)			error_code = REGREP_MN_FAILED_AUTH_FA;		else			error_code = REGREP_BAD_REQUEST_FA;	} else if (ext->sk_auth && ext->fa_nai &&		   (char*) ext->sk_auth < (char*) ext->fa_nai) {		error_text = "SK_AUTH before FA_NAI";		error_code = REGREP_REASON_UNSPEC_FA;	} else if (ext->sk_auth && ext->prev_fa_nai &&		   (char*) ext->sk_auth < (char*) ext->prev_fa_nai) {		error_text = "SK_AUTH before PREV_FA_NAI";		error_code = REGREP_REASON_UNSPEC_FA;	} else if (ext->ff_auth == NULL && ext->fa_nai &&		   (GET_NAI_LEN(ext->fa_nai) != config->fa_nai_len ||		    memcmp(MSG_NAI_DATA(ext->fa_nai), config->fa_nai,			   config->fa_nai_len) != 0))	{		/* lowest FA, but the FA NAI does not match */		error_text = "unknown FA NAI";		error_code = REGREP_REASON_UNSPEC_FA;	} else if (ntohs(ext->req->lifetime) >		   config->fa_default_tunnel_lifetime) {		snprintf(error_buf, sizeof(error_buf),			 "requested lifetime too long (%i > %i)",			 ntohs(ext->req->lifetime),			 config->fa_default_tunnel_lifetime);		error_text = error_buf;		error_code = REGREP_LONG_LIFETIME_FA;	} else if (ext->req->home_addr.s_addr == 0) {		error_text = "non-zero homeaddr required";		error_code = REGREP_NONZERO_HOMEADDR_REQD_FA;	} else if (config->enable_challenge_response &&		   ext->challenge == NULL &&		   (config->require_challenge || ext->mf_auth == NULL)) {		/* FIX: check only in the lowest FA (?) */		error_text = "missing challenge";		error_code = REGREP_MISSING_CHALLENGE_FA;	}	if (error_code != 0) {		char mn[30], coa[30], ha[30];		dynamics_strlcpy(mn, inet_ntoa(ext->req->home_addr), 30);		dynamics_strlcpy(coa, inet_ntoa(ext->req->co_addr), 30);		dynamics_strlcpy(ha, inet_ntoa(ext->req->ha_addr), 30);		if (error_text != NULL) {			LOG2(LOG_WARNING, "SRC=%s, MN=%s, HA=%s, COA=%s - "			     "request denied: %s\n",			     inet_ntoa(info->src.sin_addr), mn,			     ha, coa, error_text);			report_discarded_msg(ext->start, ext->len, &info->src,					     error_text);		}		if (!discard_silently)			send_failure_reply(error_code, ext, info, NULL, 0);		else			DEBUG(DEBUG_FLAG, "Discarding reg.req. silently\n");		return 1;	}	return 0;}static intadd_key_request(struct fa_spi_entry *fa_spi, struct msg_extensions *ext,		int *len, char *msg){	struct msg_key *key;	/* request the session key	 * use shared secret with highest mobility agent if one exists or	 * public key cryptography if no security association is available */	if (fa_spi != NULL) {		if (*len + sizeof(struct msg_key) > MAXMSG)			return 1;		key = (struct msg_key *) (msg + *len);		init_key_extension(key, VENDOR_EXT_DYNAMICS_FA_KEYREQ,				   htonl(fa_spi->spi), 0);		*len += GET_KEY_EXT_LEN(key);		DEBUG(DEBUG_FLAG, " * adding fa_keyreq (len ==> %i)\n", *len);	} else {		/* add own public key after the copied parts */		if (*len + GET_KEY_EXT_LEN(fa_public_key) > MAXMSG)			return 1;		memcpy(msg + *len, fa_public_key,		       GET_KEY_EXT_LEN(fa_public_key));		*len += GET_KEY_EXT_LEN(fa_public_key);		DEBUG(DEBUG_FLAG, " * adding fa_public_key (len ==> %i)\n",		      *len);	}	return 0;}intadd_fa_auth_ext(struct in_addr lower_addr, struct in_addr home_addr,		unsigned char *data, unsigned char *pos){	struct fa_spi_entry *fa_spi;	/* Add the FA->FA or FA->MN authentication extension if a security	 * association is configured */	fa_spi = get_fa_spi(0, lower_addr, SPI_AGENT_FA);	if (fa_spi != NULL) {		return auth_add_vendor(			AUTH_ALG_MD5, fa_spi->shared_secret,			fa_spi->shared_secret_len, data,			(struct vendor_msg_auth *) pos,			VENDOR_EXT_DYNAMICS_FF_AUTH,			htonl(fa_spi->spi));	} else {		fa_spi = get_fa_spi(0, home_addr, SPI_AGENT_MN);		if (fa_spi != NULL) {			return auth_add(				fa_spi->alg, fa_spi->shared_secret,				fa_spi->shared_secret_len, data,				(struct msg_auth *) pos,				MF_AUTH, htonl(fa_spi->spi));		}	}	return 0;}#ifdef USE_TEARDOWN/* Send tear down message to lower FA.   returns:       0 if succeeded sending       1 if not successful*/static intsend_tear_down(struct bindingentry *binding, struct in_addr lower_addr,	       unsigned short lower_port, struct interface_entry *iface){	unsigned char msg[MAXMSG];	unsigned char *msgpos;	struct reg_rep *reply;	int msglen, result;	struct tunnel_data *t_data;	struct registration_ext_dynamics *dyn_ext;	struct fa_spi_entry *fa_spi;	t_data = binding->data;	msgpos = msg;	msglen = 0;	result = 0;	/* create the reply extension */	reply = (struct reg_rep *) msg;	memset(reply, 0, sizeof(struct reg_rep));	reply->lifetime = htons(0);	reply->type = REG_REP;	reply->code = REGREP_ACCEPTED;	memcpy(&reply->home_addr, &binding->mn_addr, sizeof(struct in_addr));	memcpy(&reply->ha_addr, &binding->ha_addr, sizeof(struct in_addr));	reply->id[0] = htonl(binding->id[0]);	reply->id[1] = htonl(binding->id[1]);	msgpos += sizeof(struct reg_rep);	/* add Dynamics options extension */	dyn_ext = (struct registration_ext_dynamics *) msgpos;	dyn_ext->type = VENDOR_EXT_TYPE2;	dyn_ext->length = sizeof(struct registration_ext_dynamics) - 2;	dyn_ext->reserved = 0;	dyn_ext->vendor_id = htonl(VENDOR_ID_DYNAMICS);	dyn_ext->sub_type = htons(VENDOR_EXT_DYNAMICS_OPTIONS);	dyn_ext->version = VENDOR_EXT_VERSION;	dyn_ext->opts = REG_EXT_OWN_TEAR_DOWN;	dyn_ext->seq = 0;	msgpos += sizeof(struct registration_ext_dynamics);	/* add sk_auth for authentication between FAs */	msgpos += auth_add_vendor(AUTH_ALG_MD5, binding->key, binding->keylen,				  msg, (struct vendor_msg_auth *) msgpos,				  VENDOR_EXT_DYNAMICS_SK_AUTH,				  htonl(binding->spi));	/* Add tha FA->FA auth. ext. if a security association is	 * configured */	fa_spi = get_fa_spi(0, lower_addr, SPI_AGENT_FA);	if (fa_spi != NULL) {		msgpos += auth_add_vendor(			AUTH_ALG_MD5, fa_spi->shared_secret,			fa_spi->shared_secret_len, msg,			(struct vendor_msg_auth *) msgpos,

⌨️ 快捷键说明

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