tnet.c revision e899e59309fcb43081a58c5d5c252dca3071aaf6
127N/A * The contents of this file are subject to the terms of the 127N/A * Common Development and Distribution License (the "License"). 127N/A * You may not use this file except in compliance with the License. 127N/A * See the License for the specific language governing permissions 127N/A * and limitations under the License. 127N/A * When distributing Covered Code, include this CDDL HEADER in each 127N/A * If applicable, add the following below this CDDL HEADER, with the 127N/A * fields enclosed by brackets "[]" replaced with your own identifying 127N/A * information: Portions Copyright [yyyy] [name of copyright owner] 127N/A * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 5636N/A * Use is subject to license terms. /* tunable for strict error-reply behavior (TCP RST and ICMP Unreachable) */ * Some notes on the Trusted Solaris IRE gateway security attributes: * When running in Trusted mode, the routing subsystem determines whether or * not a packet can be delivered to an off-link host (not directly reachable * through an interface) based on the accreditation checks of the packet's * security attributes against those associated with the next-hop gateway. * The next-hop gateway's security attributes can be derived from two sources * (in order of preference): route-related and the host database. A Trusted * system must be configured with at least the host database containing an * entry for the next-hop gateway, or otherwise no accreditation checks can * be performed, which may result in the inability to send packets to any * off-link destination host. * The major differences between the two sources are the number and type of * security attributes used for accreditation checks. A host database entry * can contain at most one set of security attributes, specific only to the * next-hop gateway. On contrast, route-related security attributes are made * up of a collection of security attributes for the distant networks, and * are grouped together per next-hop gateway used to reach those networks. * This is the preferred method, and the routing subsystem will fallback to * the host database entry only if there are no route-related attributes * associated with the next-hop gateway. * INTERFACE type) are initialized to contain a placeholder to store this * information. The ire_gw_secattr structure gets allocated, initialized * and associated with the IRE during the time of the IRE creation. The * initialization process also includes resolving the host database entry * of the next-hop gateway for fallback purposes. It does not include any * route-related attribute setup, as that process comes separately as part * of the route requests (add/change) made to the routing subsystem. * The underlying logic which involves associating IREs with the gateway * security attributes are represented by the following data structures: * - This is a system-wide collection of records containing the * currently used route-related security attributes, which are fed * through the routing socket interface, e.g. "route add/change". * - This is the gateway credential structure, and it provides for the * only mechanism to access the contents of gcdb. More than one gc * entries may refer to the same gcdb record. gc's in the system are * grouped according to the next-hop gateway address. * tsol_gcgrp_t, or "gcgrp" * - Group of gateway credentials, and is unique per next-hop gateway * address. When the group is not empty, i.e. when gcgrp_count is * greater than zero, it contains one or more gc's, each pointing to * a gcdb record which indicates the gateway security attributes * associated with the next-hop gateway. * The fields of the tsol_ire_gw_secattr_t used from within the IRE are: * - Lock that protects all fields within tsol_ire_gw_secattr_t. * - Remote host cache database entry of next-hop gateway. This is * used in the case when there are no route-related attributes * configured for the IRE. * - A set of route-related attributes that only get set for prefix * IREs. If this is non-NULL, the prefix IRE has been associated * with a set of gateway security attributes by way of route add/ /* See comments in hash_bylabel in zone.c for details */ /* using 2^n + 1, 1 <= n <= 16 as source of many primes */ /* No match; not found */ /* Address family must match */ /* No match; not found */ #
define RTSAFLAGS "\20\11cipso\3doi\2max_sl\1min_sl" /* RTSA_CIPSO must be set, and DOI must not be zero */ "rtsa(1) lacks flag or has 0 doi.",
* SL range must be specified, and it must have its * upper bound dominating its lower bound. "rtsa(1) min_sl and max_sl not set or max_sl is " * A brief explanation of the reference counting scheme: * Apart from dynamic references due to to reference holds done * actively by threads, we have the following references: * - Every tsol_gc_t pointing to a tsol_gcdb_t contributes a reference * - A prefix IRE that points to an igsa_gc contributes a reference * - Every tsol_gc_t in the chain headed by tsol_gcgrp_t contributes * a reference to the gcgrp_refcnt. /* Find a copy in the cache; otherwise, create one and cache it */ "gcdb(1) inserted in gcdb_hash(global)",
"gcdb(1) removed from gcdb_hash(global)",
char *,
"found gc(1) in gcgrp(2)",
/* caller has incremented gcgrp reference for us */ /* drop lock before it's destroyed */ "removed inactive gc(1) from gcgrp(2)",
char *,
"inserted gcgrp(1) in hash(2)",
"removed inactive gcgrp(1) from hash(2)",
* Assign a sensitivity label to inbound traffic which arrived without * an explicit on-the-wire label. * In the case of CIPSO-type hosts, we assume packets arriving without * a label are at the most sensitive label known for the host, most * likely involving out-of-band key management traffic (such as IKE, * Converts CIPSO option to sensitivity label. * Validity checks based on restrictions defined in * COMMERCIAL IP SECURITY OPTION (CIPSO 2.2) (draft-ietf-cipso-ipsecurity) bsllow(
sl);
/* assumed: sets compartments to all zeroes */ * If present, parse the CIPSO label in the incoming packet and * construct a ts_label_t that reflects the CIPSO label and put it in * the ip_recv_attr_t. Later as the packet flows up through the stack any * code that needs to examine the packet label can inspect the label * from the ira_tsl. This function is * called right in ip_input for all packets, i.e. locally destined and * to be forwarded packets. The forwarding path needs to examine the label * to determine how to forward the packet. * This routine pulls all message text up into the first mblk. * For IPv4, only the first 20 bytes of the IP header are guaranteed * to exist. For IPv6, only the IPv6 header is guaranteed to exist. * Convert the CIPSO label to the internal format * and attach it to the dblk cred. * Validity checks based on restrictions defined in * COMMERCIAL IP SECURITY OPTION (CIPSO 2.2) * (draft-ietf-cipso-ipsecurity) * If the source was unlabeled, then flag as such, * (since CIPSO routers may add headers) * Handle special cases that may not be labeled, even * though the sending system may otherwise be configured as * - IPv4 ICMP Router Discovery * - IPv6 Neighbor Discovery * Look up the tnrhtp database and get the implicit label * that is associated with the sending host and attach * If peer is label-aware, mark as "implicit" rather than * "unlabeled" to cause appropriate mac-exempt processing "template(1) has unknown hosttype",
* Put the label in ira_tsl for convinience, while keeping * the cred in ira_cred for getpeerucred which is used to get * for IRA_FREE_CRED is sufficient for both. * This routine determines whether the given packet should be accepted locally. * It does a range/set check on the packet's label by looking up the given * address in the remote host database. * tsol_get_pkt_label intentionally avoids the labeling process for: * - IPv6 router and neighbor discovery as well as redirects. * - MLD packets. (Anything between ICMPv6 code 130 and 138.) * - IPv4 router discovery. * In those cases ira_cred is NULL. * If this packet is from the inside (not a remote host) and has the * same zoneid as the selected destination, then no checks are * necessary. Membership in the zone is enough proof. This is * intended to be a hot path through this function. * Note: Using crgetzone here is ok since the peer is local. * Implicitly labeled packets from label-aware sources * go only to privileged receivers "implicitly labeled packet mp(1) for conn(2) " "which isn't in implicit mac mode",
* MLPs are always validated using the range and set of the local * address, even when the remote host is unlabeled. /* LINTED: no consequent */ * If this is a packet from an unlabeled sender, then we must apply * different rules. If the label is equal to the zone's label, then * it's allowed. If it's not equal, but the zone is either the global * zone or the label is dominated by the zone's label, then allow it * as long as it's in the range configured for the destination. "unlabeled packet mp(1) fails mac for conn(2)",
* If this is a packet from a labeled sender, verify the * label on the packet matches the connection label. "packet mp(1) failed label match to SLP conn(2)",
* No further checks will be needed if this is a zone- * specific address because (1) The process for bringing up * the interface ensures the zone's label is within the zone- * specific address's valid label range; (2) For cases where * the conn is bound to the unspecified addresses, ip fanout * logic ensures conn's zoneid equals the dest addr's zoneid; * (3) Mac-exempt and mlp logic above already handle all * cases where the zone label may not be the same as the char *,
"dropping mp(1), host(2) lacks entry",
* The local host address should not be unlabeled at this point. The * only way this can happen is that the destination isn't unicast. We * assume that the packet should not have had a label, and thus should * have been handled by the TSLF_UNLABELED logic above. "mp(1) unlabeled source, but tp is not unlabeled.",
"delivering mp(1), found unrecognized tpc(2) type.",
"mp(1) could not be delievered to tp(2), doi mismatch",
"mp(1) could not be delievered to tp(2), bad mac",
/* We are bootstrapping or the internal template was never deleted */ * Check that the packet's label is in the correct range for labeled * sender, or is equal to the default label for unlabeled sender. * Until we have SL range in the Zone structure, pass it * when our own address lookup returned an internal entry. * This routine determines whether a response to a failed packet delivery or * connection should be sent back. By default, the policy is to allow such * messages to be sent at all times, as these messages reveal little useful * information and are healthy parts of TCP/IP networking. * If tsol_strict_error is set, then we do strict tests: if the packet label is * return B_FALSE, which causes the packet to be dropped silently. * Note that tsol_get_pkt_label will cause the packet to drop if the sender is * marked as labeled in the remote host database, but the packet lacks a label. * This means that we don't need to do a lookup on the source; the * TSLF_UNLABELED flag is sufficient. /* Caller must pull up at least the IP header */ /* We are bootstrapping or the internal template was never deleted */ "cannot send error report for packet mp(1) with " "unresolved security label sl(2)",
* If we're in the midst of forwarding, then the destination * address might not be labeled. In that case, allow unlabeled * packets through only if the default label is the same, and * labeled ones if they dominate. * Finds the zone associated with the receive attributes. Returns GLOBAL_ZONEID * if the zone cannot be located. * This is used by the classifier when the packet matches an ALL_ZONES IRE, and * there's no MLP defined. * Note that we assume that this is only invoked in the ALL_ZONES case. * Handling other cases would require handling exclusive IP zones where either * this routine or the callers would have to map from * the zoneid (zone->zone_id) to what IP uses in conn_zoneid etc. * If we don't have a label to compare with, or the IRE does not * contain any gateway security attributes, there's not much that * we can do. We let the former case pass, and the latter fail, * since the IRE doesn't qualify for a match due to the lack of "ire(1) lacks ire_gw_secattr when matching " * The possible lock order scenarios related to the tsol gateway * attribute locks are documented at the beginning of ip.c in the * lock order scenario section. * structure which contains all security credentials of the gateway. * An offline IRE is associated with at most one gateway credential. * If our cached entry has grown stale, then discard it so we /* Last attempt at loading the template had failed; try again */ /* We've found a gateway address to do the template lookup */ * Note that if the lookup above returned an * internal template, we'll use it for the * time being, and do another lookup next /* Another thread has loaded the template? */ /* reload, it could be different */ * Hold an extra reference just like we did * above prior to dropping the igsa_lock. /* Gateway template not found */ * If destination address is directly reachable through an * interface rather than through a learned route, pass it. "ire(1), label(2) off-link with no gw_rhc",
* In the case of IRE_CACHE we've got one or more gateway * security credentials to compare against the passed in label. * Perform label range comparison against each security * credential of the gateway. In the case of a prefix ire * we need to match against the security attributes of * just the route itself, so the loop is executed only once. char *,
"ire(1), tsl(2): all gc failed match",
* We didn't find any gateway credentials in the IRE * attributes; fall back to the gateway's template for * label range checks, if we are required to do so. char *,
"ire(1), tsl(2), gw_rhc(3) " "failed match (cipso gw)",
char *,
"ire(1), tsl(2), gw_rhc(3) " "failed match (unlabeled gw)",
* Performs label accreditation checks for packet forwarding. * Add or remove a CIPSO option as needed. * Returns a pointer to the modified mblk if allowed for forwarding, * or NULL if the packet must be dropped. * Note that the ire is the first one found, i.e., an IRE_OFFLINK if * the destination is offlink. /* malformed packet; drop it */ * off_link is TRUE if destination not directly reachable. "cannot forward packet mp(1) with unresolved " * Without a template we do not know if forwarding "mp(1) dropped, no template for destination ip4|6(2)",
* Gateway template must have existed for off-link destinations, * since tsol_ire_match_gwattr has ensured such condition. * Surya note: first check if we can get the gw_rhtp from * the ire_gw_secattr->igsa_rhc; if this is null, then * do a lookup based on the ire_addr (address of gw) "mp(1) dropped, no gateway in ire attributes(2)",
"mp(1) dropped, no gateway in ire attributes(2)",
* Check that the label for the packet is acceptable * by destination host; otherwise, drop it. "labeled packet mp(1) dropped, label(2) fails " "destination(3) accredation check",
"unlabeled packet mp(1) dropped, label(2) fails " "destination(3) accredation check",
* We keep the label on any of the following cases: * 2. The unlabeled destination is off-link, * and the next hop gateway is labeled. * Strip off the CIPSO option from the packet because: the * unlabeled destination host is directly reachable through * an interface (on-link); or, the unlabeled destination host * is not directly reachable (off-link), and the next hop * Note that caller adjusts ira_pktlen and * For AF_INET6 note that tsol_remove_secopt_v6 "mp(1) adjusted(2) for CIPSO option removal",
* We need to add CIPSO option if the destination or the next hop * gateway is labeled. Otherwise, pass the packet as is. * Since we are forwarding packets we use GLOBAL_ZONEID for * the IRE lookup in tsol_check_label. * Since mac_exempt is false the zoneid isn't used for anything * but the IRE lookup, hence we set zone_is_global to false. * The effective_tsl must never affect the routing decision, hence * Name: tsol_pmtu_adjust() * Returns the adjusted mtu after removing security option. * sender or if pkt_diff indicates this system enlarged the packet. * Note: label_adj is non-positive, indicating the number of * bytes removed by removing the security option from the * Make pkt_diff non-negative and the larger of the bytes * previously added (if any) or just removed, since label * addition + subtraction may not be completely idempotent. * Normal: Sanity checks on the route security attributes provided by * user. Convert it into a route security parameter list to * Output: EINVAL if bad security attributes in the routing message * ENOMEM if unable to allocate data structures * Note: On input, cp must point to the end of any addresses in * the rt_msghdr_t structure. * In theory, we could accept as many security attributes configured * per route destination. However, the current design is limited * such that at most only one set security attributes is allowed to * be associated with a prefix IRE. We therefore assert for now. * Trying to add route security attributes when system * labeling service is not available, or when user supllies * more than the maximum number of security attributes /* Ensure valid credentials */ * The only time that attrp can be NULL is when this routine is * of the corresponding IRE. It will only get cleared when the * References already held by caller and we keep them; * note that gc may be set to NULL to clear out igsa_gc. * Intialize the template for gateway; we use the gateway's * address found in either the passed in gateway credential * or group pointer, or the ire_gateway_addr{_v6} field. * Caller is holding a reference, and that we don't * need to hold any lock to access the address. * Lookup the gateway template; note that we could get an internal * template here, which we cache anyway. During IRE matching, we'll * try to update this gateway template cache and hopefully get a * This function figures the type of MLP that we'll be using based on the * address that the user is binding and the zone. If the address is * unspecified, then we're looking at both private and shared. If it's one * of the zone's private addresses, then it's private only. If it's one * of the global addresses, then it's shared only. Multicast addresses are * treated same as unspecified address. * If we can't figure out what it is, then return mlptSingle. That's actually * The callers are assumed to pass in zone->zone_id and not the zoneid that * is stored in a conn_t (since the latter will be GLOBAL_ZONEID in an * For exclusive stacks we set the zoneid to zero * to operate as if in the global zone for IRE and conn_t comparisons. /* Check whether the IRE_LOCAL (or ipif) is ALL_ZONES */ * If we can't find the IRE, then we have to behave exactly like * ip_laddr_verify_{v4,v6}. That means looking up the IPIF so that * users can bind to addresses on "down" interfaces. * If we can't find that either, then the bind is going to fail, so * just give up. Note that there's a miniscule chance that the address * is in transition, but we don't bother handling that. * Since we are configuring local interfaces, and we know trusted * extension CDE requires local interfaces to be cipso host type in * order to function correctly, we'll associate a cipso template * to each local interface and let the interface come up. Configuring * a local interface to be "unlabeled" host type is a configuration error. * We'll override that error and make the interface host type to be cipso * The code is optimized for the usual "success" case and unwinds things on * error. We don't want to go to the trouble and expense of formatting the * interface name for the usual case where everything is configured correctly. /* assumes that ALL_ZONES implies that there is no exclusive stack */ /* Exclusive stack case */ * If it's CIPSO and an all-zones address, then we're done. * If it's a CIPSO zone specific address, the zone's label * must be in the range or set specified in the template. * When the remote host entry is missing or the template * type is incorrect for this interface, we create a * CIPSO host entry in kernel and allow the interface to be * brought up as CIPSO type. /* The local-zone case */ * we've corrected a config error and let the interface * come up as cipso. Need to insert an rhent.