diff options
Diffstat (limited to 'src/pluto/connections.h')
-rw-r--r-- | src/pluto/connections.h | 367 |
1 files changed, 367 insertions, 0 deletions
diff --git a/src/pluto/connections.h b/src/pluto/connections.h new file mode 100644 index 000000000..df3af9dd4 --- /dev/null +++ b/src/pluto/connections.h @@ -0,0 +1,367 @@ +/* information about connections between hosts and clients + * 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: connections.h,v 1.18 2006/04/22 21:59:20 as Exp $ + */ + +#ifndef _CONNECTIONS_H +#define _CONNECTIONS_H + +#include <sys/queue.h> + +#include "id.h" +#include "certs.h" +#include "ac.h" +#include "smartcard.h" +#include "whack.h" + +/* There are two kinds of connections: + * - ISAKMP connections, between hosts (for IKE communication) + * - IPsec connections, between clients (for secure IP communication) + * + * An ISAKMP connection looks like: + * host<--->host + * + * An IPsec connection looks like: + * client-subnet<-->host<->nexthop<--->nexthop<->host<-->client-subnet + * + * For the connection to be relevant to this instance of Pluto, + * exactly one of the hosts must be a public interface of our machine + * known to this instance. + * + * The client subnet might simply be the host -- this is a + * representation of "host mode". + * + * Each nexthop defaults to the neighbouring host's IP address. + * The nexthop is a property of the pair of hosts, not each + * individually. It is only needed for IPsec because of the + * way IPsec is mixed into the kernel routing logic. Furthermore, + * only this end's nexthop is actually used. Eventually, nexthop + * will be unnecessary. + * + * Other information represented: + * - each connection has a name: a chunk of uninterpreted text + * that is unique for each connection. + * - security requirements (currently just the "policy" flags from + * the whack command to initiate the connection, but eventually + * much more. Different for ISAKMP and IPsec connections. + * - rekeying parameters: + * + time an SA may live + * + time before SA death that a rekeying should be attempted + * (only by the initiator) + * + number of times to attempt rekeying + * - With the current KLIPS, we must route packets for a client + * subnet through the ipsec interface (ipsec0). Only one + * gateway can get traffic for a specific (client) subnet. + * Furthermore, if the routing isn't in place, packets will + * be sent in the clear. + * "routing" indicates whether the routing has been done for + * this connection. Note that several connections may claim + * the same routing, as long as they agree about where the + * packets are to be sent. + * - With the current KLIPS, only one outbound IPsec SA bundle can be + * used for a particular client. This is due to a limitation + * of using only routing for selection. So only one IPsec state (SA) + * may "own" the eroute. "eroute_owner" is the serial number of + * this state, SOS_NOBODY if there is none. "routing" indicates + * what kind of erouting has been done for this connection, if any. + * + * Details on routing is in constants.h + * + * Operations on Connections: + * + * - add a new connection (with all details) [whack command] + * - delete a connection (by name) [whack command] + * - initiate a connection (by name) [whack command] + * - find a connection (by IP addresses of hosts) + * [response to peer request; finding ISAKMP connection for IPsec connection] + * + * Some connections are templates, missing the address of the peer + * (represented by INADDR_ANY). These are always arranged so that the + * missing end is "that" (there can only be one missing end). These can + * be instantiated (turned into real connections) by Pluto in one of two + * different ways: Road Warrior Instantiation or Opportunistic + * Instantiation. A template connection is marked for Opportunistic + * Instantiation by specifying the peer client as 0.0.0.0/32 (or the IPV6 + * equivalent). Otherwise, it is suitable for Road Warrior Instantiation. + * + * Instantiation creates a new temporary connection, with the missing + * details filled in. The resulting template lasts only as long as there + * is a state that uses it. + */ + +/* connection policy priority: how important this policy is + * - used to implement eroute-like precedence (augmented by a small + * bonus for a routed connection). + * - a whole number + * - larger is more important + * - three subcomponents. In order of decreasing significance: + * + length of source subnet mask (8 bits) + * + length of destination subnet mask (8 bits) + * + bias (8 bit) + * - a bias of 1 is added to allow prio BOTTOM_PRIO to be less than all + * normal priorities + * - other bias values are created on the fly to give mild preference + * to certaion conditions (eg. routedness) + * - priority is inherited -- an instance of a policy has the same priority + * as the original policy, even though its subnets might be smaller. + * - display format: n,m + */ +typedef unsigned long policy_prio_t; +#define BOTTOM_PRIO ((policy_prio_t)0) /* smaller than any real prio */ +#define set_policy_prio(c) { (c)->prio = \ + ((policy_prio_t)(c)->spd.this.client.maskbits << 16) \ + | ((policy_prio_t)(c)->spd.that.client.maskbits << 8) \ + | (policy_prio_t)1; } +#define POLICY_PRIO_BUF (3+1+3+1) +extern void fmt_policy_prio(policy_prio_t pp, char buf[POLICY_PRIO_BUF]); + +struct virtual_t; + +struct end { + struct id id; + ip_address + host_addr, + host_nexthop, + host_srcip; + ip_subnet client; + + bool key_from_DNS_on_demand; + bool has_client; + bool has_client_wildcard; + bool has_port_wildcard; + bool has_id_wildcards; + bool has_natip; + char *updown; + u_int16_t host_port; /* host order */ + u_int16_t port; /* host order */ + u_int8_t protocol; + cert_t cert; /* end certificate */ + chunk_t ca; /* CA distinguished name */ + struct ietfAttrList *groups;/* access control groups */ + smartcard_t *sc; /* smartcard reader and key info */ + struct virtual_t *virt; + bool modecfg; /* this end: request local address from server */ + /* that end: give local addresses to clients */ + bool hostaccess; /* allow access to host via iptables INPUT/OUTPUT */ + /* rules if client behind host is a subnet */ + certpolicy_t sendcert; /* whether or not to send the certificate */ +}; + +struct spd_route { + struct spd_route *next; + struct end this; + struct end that; + so_serial_t eroute_owner; + enum routing_t routing; /* level of routing in place */ + uint32_t reqid; +}; + +struct connection { + char *name; + bool ikev1; + + lset_t policy; + time_t sa_ike_life_seconds; + time_t sa_ipsec_life_seconds; + time_t sa_rekey_margin; + unsigned long sa_rekey_fuzz; + unsigned long sa_keying_tries; + + /* RFC 3706 DPD */ + time_t dpd_delay; + time_t dpd_timeout; + dpd_action_t dpd_action; + + char *log_file_name; /* name of log file */ + FILE *log_file; /* possibly open FILE */ + CIRCLEQ_ENTRY(connection) log_link; /* linked list of open conns */ + bool log_file_err; /* only bitch once */ + + struct spd_route spd; + + /* internal fields: */ + + unsigned long instance_serial; + policy_prio_t prio; + bool instance_initiation_ok; /* this is an instance of a policy that mandates initiate */ + enum connection_kind kind; + const struct iface *interface; /* filled in iff oriented */ + + so_serial_t /* state object serial number */ + newest_isakmp_sa, + newest_ipsec_sa; + + +#ifdef DEBUG + lset_t extra_debugging; +#endif + + /* note: if the client is the gateway, the following must be equal */ + sa_family_t addr_family; /* between gateways */ + sa_family_t tunnel_addr_family; /* between clients */ + + struct connection *policy_next; /* if multiple policies, + next one to apply */ + + struct gw_info *gw_info; + struct alg_info_esp *alg_info_esp; + struct alg_info_ike *alg_info_ike; + + struct host_pair *host_pair; + struct connection *hp_next; /* host pair list link */ + + struct connection *ac_next; /* all connections list link */ + + generalName_t *requested_ca; /* collected certificate requests */ + bool got_certrequest; +}; + +#define oriented(c) ((c).interface != NULL) +extern bool orient(struct connection *c); + +extern bool same_peer_ids(const struct connection *c + , const struct connection *d, const struct id *his_id); + +/* Format the topology of a connection end, leaving out defaults. + * Largest left end looks like: client === host : port [ host_id ] --- hop + * Note: if that==NULL, skip nexthop + */ +#define END_BUF (SUBNETTOT_BUF + ADDRTOT_BUF + IDTOA_BUF + ADDRTOT_BUF + 10) +extern size_t format_end(char *buf, size_t buf_len + , const struct end *this, const struct end *that + , bool is_left, lset_t policy); + +extern void add_connection(const whack_message_t *wm); +extern void initiate_connection(const char *name, int whackfd); +extern void initiate_opportunistic(const ip_address *our_client + , const ip_address *peer_client, int transport_proto, bool held, int whackfd); +extern void terminate_connection(const char *nm); +extern void release_connection(struct connection *c, bool relations); +extern void delete_connection(struct connection *c, bool relations); +extern void delete_connections_by_name(const char *name, bool strict); +extern void delete_every_connection(void); +extern char *add_group_instance(struct connection *group, const ip_subnet *target); +extern void remove_group_instance(const struct connection *group, const char *name); +extern void release_dead_interfaces(void); +extern void check_orientations(void); +extern struct connection *route_owner(struct connection *c + , struct spd_route **srp + , struct connection **erop + , struct spd_route **esrp); +extern struct connection *shunt_owner(const ip_subnet *ours + , const ip_subnet *his); + +extern bool uniqueIDs; /* --uniqueids? */ +extern void ISAKMP_SA_established(struct connection *c, so_serial_t serial); + +#define his_id_was_instantiated(c) ((c)->kind == CK_INSTANCE \ + && (id_is_ipaddr(&(c)->spd.that.id)? \ + sameaddr(&(c)->spd.that.id.ip_addr, &(c)->spd.that.host_addr) : TRUE)) + +struct state; /* forward declaration of tag (defined in state.h) */ +extern struct connection + *con_by_name(const char *nm, bool strict), + *find_host_connection(const ip_address *me, u_int16_t my_port + , const ip_address *him, u_int16_t his_port, lset_t policy), + *refine_host_connection(const struct state *st, const struct id *id + , chunk_t peer_ca), + *find_client_connection(struct connection *c + , const ip_subnet *our_net + , const ip_subnet *peer_net + , const u_int8_t our_protocol + , const u_int16_t out_port + , const u_int8_t peer_protocol + , const u_int16_t peer_port), + *find_connection_by_reqid(uint32_t reqid); + +extern struct connection * +find_connection_for_clients(struct spd_route **srp + , const ip_address *our_client + , const ip_address *peer_client + , int transport_proto); + +extern chunk_t get_peer_ca_and_groups(struct connection *c + , const ietfAttrList_t **peer_list); + +/* instantiating routines + * Note: connection_discard() is in state.h because all its work + * is looking through state objects. + */ +struct gw_info; /* forward declaration of tag (defined in dnskey.h) */ +struct alg_info; /* forward declaration of tag (defined in alg_info.h) */ +extern struct connection *rw_instantiate(struct connection *c + , const ip_address *him + , u_int16_t his_port + , const ip_subnet *his_net + , const struct id *his_id); + +extern struct connection *oppo_instantiate(struct connection *c + , const ip_address *him + , const struct id *his_id + , struct gw_info *gw + , const ip_address *our_client + , const ip_address *peer_client); + +extern struct connection + *build_outgoing_opportunistic_connection(struct gw_info *gw + , const ip_address *our_client + , const ip_address *peer_client); + +/* worst case: "[" serial "] " myclient "=== ..." peer "===" hisclient '\0' */ +#define CONN_INST_BUF \ + (2 + 10 + 1 + SUBNETTOT_BUF + 7 + ADDRTOT_BUF + 3 + SUBNETTOT_BUF + 1) + +extern void fmt_conn_instance(const struct connection *c + , char buf[CONN_INST_BUF]); + +/* operations on "pending", the structure representing Quick Mode + * negotiations delayed until a Keying Channel has been negotiated. + */ + +struct pending; /* forward declaration (opaque outside connections.c) */ + +extern void add_pending(int whack_sock + , struct state *isakmp_sa + , struct connection *c + , lset_t policy + , unsigned long try + , so_serial_t replacing); + +extern void release_pending_whacks(struct state *st, err_t story); +extern void unpend(struct state *st); +extern void update_pending(struct state *os, struct state *ns); +extern void flush_pending_by_state(struct state *st); +extern void show_pending_phase2(const struct host_pair *hp, const struct state *st); + +extern void connection_discard(struct connection *c); + +/* A template connection's eroute can be eclipsed by + * either a %hold or an eroute for an instance iff + * the template is a /32 -> /32. This requires some special casing. + */ +#define eclipsable(sr) (subnetishost(&(sr)->this.client) && subnetishost(&(sr)->that.client)) +extern long eclipse_count; +extern struct connection *eclipsed(struct connection *c, struct spd_route **); + + +/* print connection status */ + +extern void show_connections_status(bool all, const char *name); +extern int connection_compare(const struct connection *ca + , const struct connection *cb); +extern void update_host_pair(const char *why, struct connection *c + , const ip_address *myaddr, u_int16_t myport + , const ip_address *hisaddr, u_int16_t hisport); + +#endif /* _CONNECTIONS_H */ |