Network Working Group Craig Metz Internet Draft The Inner Net draft-metz-net-security-api-00.txt 1 August 1997 Network Security API for Sockets Status of this Memo This document is an Internet Draft. Internet Drafts are working documents. Internet Drafts are draft documents valid for a maximum of 6 months. Internet Drafts may be updated, replaced, or obsoleted by other documents at any time. It is not appropriate to use Internet Drafts as reference material or to cite them other than as "work in progress". A future version of this draft will be submitted to the RFC Editor for publication as an Informational document. Abstract This API is a means for sockets applications to request network security services from an operating system. It is designed to move most of the work and intelligence of security policy processing into the operating system so that the burden on application authors is light enough to encourage the use of network security. It is documented here for the benefit of others who might also adopt and use the API, thus providing increased portability of applications that use network security services (e.g., the IP Security ESP and AH protocols). 1. Introduction Many network protocols now provide security services such as encryption and authentication at the network layer. For example, IPv4 supports and IPv6 requires the IP Security protocols, ESP and AH. While various flow-based policy schemes can frequently identify the security requirements of a particular packet, applications and the end user should be able to provide input to the policy process and Metz Expires in 6 months [Page 1] Internet Draft Network Security API for Sockets 1 August 1997 request security services from the system. That is the main goal of this application programming interface: to provide a means for applications (and, through them, the end user) to request security services and properties from the system. Secondary goals of this API include moving most of the burden to the system, thus making it easier for the application programmer to use security services, supporting complex policy decisions with reasonable performance, and giving the application more input to and feedback from the policy process than is provided for in similar APIs. This API is built as an extension to the POSIX p1003.1g sockets interface. That interface is REQUIRED for this API. This API assumes that network security services follow a conceptual model similar to that of IP Security. This interface may need to be changed in the future to support protocol families that differ radically from that model. 1.1. Terminology Even though this document is not intended to be a standard, the words that are used to define the significance of particular features of this interface are usually capitalized. These words are: - MUST This word or the adjective "REQUIRED" means that the item is an absolute requirement of the specification. - SHOULD This word or the adjective "RECOMMENDED" means that there might exist valid reasons in particular circumstances to ignore this item, but the full implications should be understood and the case carefully weighed before taking a different course. - MAY This word or the adjective "OPTIONAL" means that this item is truly optional. One vendor might choose to include the item because a particular marketplace requires it or because it enhances the product, for example; another vendor may omit the same item. - CONFORMANCE and COMPLIANCE Conformance to this specification has the same meaning as compliance to this specification. In either case, the mandatory-to- Metz Expires in 6 months [Page 2] Internet Draft Network Security API for Sockets 1 August 1997 implement, or MUST, items MUST be fully implemented as specified here. If any mandatory item is not implemented as specified here, that implementation is not conforming and not compliant with this specification. - IMPLEMENTORS Those who are building a software implementation that uses this API. If not otherwise specified, this term refers both to application implementors and to system implementors. Many of the concepts and caveats of this API need to be carefully noted by both. - ULP An upper-layer protocol (ULP) is an opaque payload for purposes of security processing. This can be transport protocol (e.g., TCP or UDP), a control protocol (e.g., ICMP or IGMP), or another network protocol (e.g., IP or IPv6). 1.2. Conceptual Model This section describes the conceptual model of a system that implements this API. It is intended to provide background material useful to understand the rest of this document. Presentation of this conceptual model does not constrain an implementation to strictly adhere to the conceptual components discussed in this section. Systems implementing this API are expected to have a "policy engine". This term is used to refer to whatever components of a system that have programmed with rules that control what security operations and parameters are allowed and which are preferred for given requirements. In many cases, flow information determined from the contents of network packets and the rules in this policy engine will completely satisfy the security needs of an application without the need for this API. For example, if a policy engine is programmed with a rule that tells it to require that all TCP packets with a foreign port of 23 be encrypted, outbound telnet connections will be encrypted without the need for the telnet client itself to request that encryption. The problem with this example is that all outbound telnet connections are encrypted whether or not the user wants it. In order to make the choice of whether or not to encrypt available to the user, the telnet client needs to specify an input to the policy engine that reflects the user's desire to encrypt or not. That is one of the things that this API does. This API is built on a model where the policy engine makes the decisions for the system. It has complete and final control over what, if any, security processing is done on a packet and the Metz Expires in 6 months [Page 3] Internet Draft Network Security API for Sockets 1 August 1997 parameters for that processing. The application makes requests (presumably representing the needs of some user) to the policy engine that reflect what it would like the policy engine to do with its packets. The policy engine can, if so programmed, completely or selectively ignore this request. In some environments, ignoring some or all of an application's request is critical to maintaining system security; in others, it is inappropriate and frustrating. This API is not concerned with the programming of the policy engine and how the policy engine acts on an application's request, only how the application makes that request and receives feedback from the policy engine on what actually happened. A complete network security implementation requires many components beyond those just described, but these are all hidden from the application behind the system's policy engine. Figure 1 illustrates a possible system organization to show where this API applies. User | Network Application Key Management Daemon | | | | ====Sockets Security API=====PF_INET Sockets=======PF_KEY Socket==== | | TCP/UDP | | | Policy Engine-----------------SADB | | IPsec | \ / IP Figure 1 - A Possible System Organization This API uses abstract security properties instead of specific values. That is, an application might request encryption and ask that it be "stronger," but it does not specify the exact security transforms or cryptographic algorithms to be used. This design choice was made for several reasons. First, this allows applications to take advantage of network security services with the least amount of involvement in the inner workings of the system. Security associations, policy rules, available transforms, and available algorithms may change during an application's lifetime. These changes could make an application's request invalid or less desirable. Using abstract values, the policy engine can simply remap the abstract values to a new set of actual operations and parameters without the intervention of the application. Other approaches would place a more significant burden Metz Expires in 6 months [Page 4] Internet Draft Network Security API for Sockets 1 August 1997 on the authors of applications that wish to use network security services. Second, this allows the policy engine greater flexibility in combining the user's request with system policy rules. A request for a specific algorithm or transform does not tell the policy engine what the application's and/or user's requirements are or what properties are expected of that specific choice. Third, some applications will come in binary-only form and will try to select their security properties without user intervention. By abstracting the algorithms in use, a system administrator has the ability to change what actual algorithms and parameters are in use without the need for changing every such binary on the system. [cmetz-more text probably is needed here] 2. Requests The model chosen for the network security requests themselves could be compared to a set of recipes. Each recipe is a step-by-step listing of the steps that should be taken to achieve the result, but those steps might not get executed exactly as requested if the executor "knows better". Many similar recipes might be grouped together, but only one can be executed at a time. Typically, only one will be chosen and executed, but there are situations in which the ability to execute one of several quickly (and cache preparatory steps) is desirable. 2.1. Recipes Each "recipe" is a list of operations that specifies how an application would like its packets to be "cooked" by the system. There are four currently defined operations: Authenticate (A): Verify that the sender is as claimed and that the packet has not been changed in transit. This operation provides the properties of authentication and integrity. Encrypt (E): Protect the data from receipt by unauthorized parties. This operation provides the property of confidentiality. Encapsulate (N): Prepend a new network header to the packet. This allows applications to create half- tunnels "on-the-fly". Metz Expires in 6 months [Page 5] Internet Draft Network Security API for Sockets 1 August 1997 Magic Cookie (M): Provide a value to the policy engine with some pre-arranged meaning. This would be used as an escape mechanism for when a system administrator cannot arrange for a system to provide a certain set of needed properties through normal methods. This is a means of last resort only. Implementations MUST restrict the number of operations in a recipe to a reasonable number and define a preprocessor symbol named NET_SECURITY_OPERATION_MAX with the maximum number allowed. The suggested limit is 16. For example, an application might make a request of: A N E And the system policy engine might translate that and build a packet that looks like: IP ESP [ IP AH ULP ] But the system policy engine could also build a packet that looks like: IP ESP [ ULP ] On the surface, this looks like the policy engine is being unreasonable or denying service. But consider the "optimization" policy rules that could turn that request into that packet: 1. Combine A and E into an ESP combined encryption/authentication transform and put the combination in the place of E. 2. Combine N with adjacent network headers to prevent encapsulation with nothing between the two network headers. Implementors must always remember that requests are just that. The policy engine controls what services are delivered. Requests are always ordered such that the first operation is the one the application would like to be performed closest to the upper- layer protocol. Another way to look at this is that the first operation in the request is the one the application would like to be the first operation performed in output security processing and the last operation performed in input security processing. For example, a mapping scheme that used the application's ordering might map: A E to IP ESP [ AH ULP ] Metz Expires in 6 months [Page 6] Internet Draft Network Security API for Sockets 1 August 1997 E A to IP AH ESP [ ULP ] A N E to IP ESP [ IP AH ULP ] 2.2. Preferences Associated with each operation is a value that specifies the application's preference towards that operation actually taking place. There are four currently defined preferences: Default (d): The application has no preference about this operation being performed or not. The operation is included to specify properties of the operation should it take place and/or as a place-holder. In absence of any other policy information suggesting otherwise, a system SHOULD default to not performing the operation. Use (u): The application prefers, but does not require, that the operation take place. Require (r): The application requires that the operation take place and requests that processing of the recipe halt if the operation cannot be performed. Never (n): The application requires that the operation not take place and requests that processing of the recipe halt if the operation cannot be performed. For example, key management applications would need to use this request to prevent the system from attempting to provide security services for them and creating a catch-22. Policy engines SHOULD grant the application's request to cause processing of the recipe to halt if require or never preferences cannot be satisfied. For input processing, this would result in the recipe not being matched and, if the recipe is the last in the group, the packet being dropped. For output processing, this would result in the packet being dropped and an error being returned to the application. It is a serious security problem for processing to not fail if the application has requested it. For example, confidential data could then be sent out as cleartext if key management fails. Consider as an example the request: Au Er Suppose that the system's policy engine mapped this into an attempt to use AH and ESP. If key management failed to obtain a SA for AH but was able to obtain a SA for ESP, communication could continue and the actual packet would look like: Metz Expires in 6 months [Page 7] Internet Draft Network Security API for Sockets 1 August 1997 IP ESP [ ULP ] However, if the ESP SA could not be obtained, regardless of whether key management could obtain the AH SA, the packet SHOULD be dropped and an error returned to the application. 2.3. Barriers Barriers (b) are the most difficult concept in this API. They are a flag on some operations that asks the policy engine to maintain a separation located to the right of that operator. The policy engine SHOULD NOT re-order or combine operations across or through this barrier. Thus, barriers ask the policy engine to prevent certain kinds of optimizations from taking place. For example, consider the case of an application that deliberately wants to superencrypt its packets. A policy engine might have a rule that combines consecutive encryption operations. A request of: E E Would map to: IP ESP [ ULP ] But a request of Eb E Would map to: IP ESP [ ESP [ ULP ] ] If that policy engine is aggressive in its attempts to optimize security operations (because fewer operations performed means better performance), it might try to combine encryption operations even across an encapsulation operation. This would lead to internal steps like: E N E (Re-order: move the second E right) N E E (Combine: E + E = E) N E (Combine: remove leading N since there's a header immediately preceding it) E This results in something that probably isn't quite what the application expected when it made the original request. Insertion of a barrier solves this problem: Metz Expires in 6 months [Page 8] Internet Draft Network Security API for Sockets 1 August 1997 E Nb E The barrier is "located" between the N and E requests, though the actual flag is on the N request. Now the two E requests cannot be moved and/or combined, so the desired behavior is delivered. As a general rule of thumb, most encapsulation requests SHOULD be flagged as barriers and most other requests SHOULD NOT be flagged as barriers. Except as prevented by barriers, implementations SHOULD perform optimization steps such as re-ordering and combining compatible operations to attempt to decrease the amount of processing necessary for a packet. 2.4. Multiple Recipes A recipe specifies one possible arrangement of operations to protect an application's packet. An application's request can contain multiple recipes. This is used differently for output and input security processing. For output, providing multiple recipes allows an application to quickly flip between a small set of them and therefore change the security properties it desires for its packets. This could also be done using multiple requests, but providing multiple recipes to the kernel has less overhead (instead of having to specify the entire recipe when the application wishes to change, it only has to specify an index) and it allows the system to cache policy state information associated with each recipe. Note that only one recipe may be used with any given network packet on output. For input, providing multiple recipes allows an application to provide several possible acceptable input policies (in preference order) to try matching an incoming packet against. This can be used in applications that might allow communication with different security properties but might behave differently based on what properties are present. For example, one might use this capability to connect an incoming connection to a different telnet daemon depending on whether or not their packets were encrypted. Also, this can be used in conjunction with output switching to build datagram servers that can "match" the properties of incoming packets -- packets that were received encrypted could then be sent encrypted responses, while packets that were received as cleartext would be sent cleartext responses. Implementations MUST restrict the number of recipes to a reasonable number and define a preprocessor symbol named NET_SECURITY_RECIPE_MAX with the maximum number allowed. The suggested limit is 16, resulting in 15 usable recipes. Metz Expires in 6 months [Page 9] Internet Draft Network Security API for Sockets 1 August 1997 Consider as an example a UDP datagram server. It might make the following request: 1. Au Nr Er 2. Ar Er 3. Er 4. Ed A packet comes in: IP ESP [ IP ULP ] The application receives the packet and a notification that recipe one was matched. It then sends its reply and notifies the kernel that it wishes to use recipe one for that packet. All SAs are successful, so the reply looks like: IP ESP [ IP AH ULP ] Note that the reply doesn't look exactly the same as the original packet. This is a feature of using the "use" preference. If exact matching of the input and output specifications is required, the use and default preferences MUST NOT be used. 2.5. Latching Stream sockets present a special problem because there is generally not a correlation between output boundaries at the application layer and at the network layer. Consider this sequence of events: * Open a stream socket. * Load a request of: 1. Er 2. En * Select recipe 1. * connect() to a remote end. * write() a byte of secret data. * Select recipe 2. * write() a byte of non-secret data. Typically, the two bytes written would be combined by a stream transport protocol into one packet. But should that packet be encrypted or not? Either encrypting or not encrypting that packet violates one of the requests. Stream protocols like TCP can also retransmit packets and slice/combine packets while retransmitting, which complicates things more. Some might try to modify the implementations of stream protocols to "tag" ranges of data with security properties and prevent incompatible combinations and ensure Metz Expires in 6 months [Page 10] Internet Draft Network Security API for Sockets 1 August 1997 that the correct properties are present on retransmitted packets. This is complex and still leaves the application open to some kinds of attacks. Therefore, all implementations of this API MUST implement a "latching" behavior for stream protocols that "latches in" the first recipe that is used to successfully process a packet for a connection and does not allow any other recipe to be used for the lifetime of that connection. Consider this example: Both client and server open a TCP stream socket. Both client and server load a request of: 1. Er Ar 2. Er 3. En Client selects recipe 2 and issues a connect(). The first packet in the handshake "latches in" recipe 2 for the lifetime of the TCP connection. Server receives the first packet in the handshake from the client. It first tries to match recipe 1, fails, and then tries to match recipe 2, which succeeds. The server then creates its connection state for the new connection and "latches in" recipe 2 for that new connection. Note that the accepting socket is "latched", but NOT the listening socket. The handshake completes and data flows. All packets beyond the initial exchange are required to meet the criteria in recipe 2. 3. Detailed Interface This section discusses the actual symbols, structures, and function calls used with this API. These are all based on the concepts discussed in the previous section. 3.1. Name Space This network security API defines preprocessor symbols that start with the prefix "NET_SECURITY" and other names that start with the prefixes "net_security" and "__net_security". These are all defined as a result of including the header file . Inclusion of the file MUST NOT define symbols or structures in this name space that are not described in this document without the explicit prior permission of the author. An implementation that fails to obey this rule IS NOT COMPLIANT WITH THIS SPECIFICATION and MUST NOT make any claim to be. This rule also applies to any files that might be included as a result of including Metz Expires in 6 months [Page 11] Internet Draft Network Security API for Sockets 1 August 1997 the file . This rule provides implementors with some assurance that they will not encounter name space-related surprises. 3.2. Request Format A request consists of one request header followed by zero or more operations. The header looks like: #define NET_SECURITY_RECIPE_MAX 16 #define NET_SECURITY_OPERATION_MAX 16 #define NET_SECURITY_VERSION 1 struct net_security_request { uint8_t net_security_request_operations[NET_SECURITY_RECIPE_MAX]; }; #define net_security_request_version \ net_security_request_operations[0] net_security_request_version Identifies the version of this API in use. This value MUST be set to NET_SECURITY_VERSION. net_security_request_operations The number of operations in the recipe whose number is the same as the array index. That is, index one contains the number of operations for recipe number one and so on. Recipe number zero has special meaning and does not identify an actual recipe. Followed by the header is zero or more recipes, in order. Each recipe consists of zero or more operations, in order. So, for example, the recipes: 1. E N A 2. A N Would result in: struct net_security_request(operations[1]=3, operations[2]=2); struct net_security_operation(type=E); struct net_security_operation(type=N); struct net_security_operation(type=A); struct net_security_operation(type=A); struct net_security_operation(type=N); Each operation looks like: Metz Expires in 6 months [Page 12] Internet Draft Network Security API for Sockets 1 August 1997 struct net_security_sockaddr_union { struct sockaddr sa; #if AF_INET struct sockaddr_in sin; #endif /* AF_INET */ #if AF_INET6 struct sockaddr_in6 sin6; #endif /* AF_INET6 */ #if defined(AF_LOCAL) || defined(AF_UNIX) struct sockaddr_un sun; #endif /* defined(AF_LOCAL) || defined(AF_UNIX) */ }; struct net_security_operation { uint8_t net_security_operation_type; uint8_t net_security_operation_preference; uint8_t net_security_operation_barrier; uint8_t net_security_operation_reserved; /* compiler-inserted pad if 64 bit */ union { struct { uint8_t __alloctype; uint8_t __identtype; uint8_t __hints; uint8_t __algid; } __forsa; union net_security_sockaddr_union __sockaddr; uint32_t __cookie; } __union; }; #define net_security_operation_alloctype __union.__forsa.__alloctype #define net_security_operation_identtype __union.__forsa.__identtype #define net_security_operation_hints __union.__forsa.__hints #define net_security_operation_algid __union.__forsa.__algid #define net_security_operation_sockaddr __union.__sockaddr.sa #define net_security_operation_cookie __union.__cookie type The type of operation to be executed. Defined operations are described in section 2.1. preference The preference of the application toward this operation being executed. Defined preferences are described in section 2.2. barrier If set to one, indicates that a barrier should be placed after this operation. If set to zero, no barrier is placed there. All other values are reserved. reserved MUST be set to zero. alloctype For E and A requests, indicates the allocation type Metz Expires in 6 months [Page 13] Internet Draft Network Security API for Sockets 1 August 1997 requested for SAs obtained for this operation. Defined values for this field are described in section 3.3. identity For E and A requests, indicates the identity type request for SAs obtained for this operation. Defined values for this field are described in section 3.4. hints For E and A requests, a set of bit-mapped values that give the policy engine hints as to what algorithm and parameters should be used for this operation. Defined values for this field are described in section 3.5. algid For E and A requests, if nonzero, an algorithm identifier that requests that a specific cryptographic algorithm be used. Values for this field are defined in [MMP97]. This MUST be used as a means of last resort only. The use of this field is a privileged operation and subject to system policy; if it is nonzero and the application is not privileged, the system MUST return EPERM when the request is loaded. If an system's policy rejects the use of the algorithm specified in this field, the recipe SHOULD fail. Applications MUST NOT require this capability for normal operation. Systems MAY universally refuse to honor this field. [cmetz: This field is a concept-breaking blemish, but it's here by popular demand.] sockaddr For N requests, if sa_family is nonzero, the destination address of the requested encapsulation. This MAY be an address in a protocol family other than that of the socket. Specification of a destination MAY be a privileged operation, the details of which are specific to a particular system implementation. If sa_family is zero, the destination is the same as the destination address of the inside packet. cookie For M requests, the magic cookie value. Its meaning is not defined here. net_security_sockaddr_union is defined as being large enough to hold any sockaddr on the system that can be used with a socket protocol family that supports this API. Implementations SHOULD make this large enough to hold any sockaddr available on the system; this prevents possible buffer overrun problems. 3.3. Allocation Types This API gives applications the ability to request the granularity with which the system shares (or doesn't share) its SAs. The different granularities are called allocation types because they control the SA database's allocation functions. Six allocation types are currently defined: Metz Expires in 6 months [Page 14] Internet Draft Network Security API for Sockets 1 August 1997 System: The application requests that SAs allocated to this socket be shared with any other socket on the system. GID: The application requests that SAs allocated to this socket be shared only with other sockets with the same group ID. UID: The application requests that SAs allocated to this socket be shared only with other sockets with the same user ID. PGID: The application requests that SAs allocated to this socket be shared only with other sockets with the same process group (sometimes called session) ID. Family: The application requests that SAs allocated to this socket be allocated only to this socket and its descendants. Descendants are sockets created by through calls such as accept() as well as those copies of a socket created for child processes. Socket: The application requests that SAs allocated to this socket be allocated only to this socket. In the case of a passively created stream socket, control of the SAs created for connection setup will be transferred to the child socket returned at accept() time. After that, the listening socket MUST NOT have access to those SAs. Note that the GID, UID, and PGID MUST for a socket MUST be recorded at the time of socket creation and that stored copy is the GID, UID, and/or PGID used for SA allocation. This means that, if a program changes any of these after a socket has been opened, the ID used for allocation of SAs to a socket does not change. Also note that the actual UID used is the REAL UID. Application programmers should note that this behavior may not be what they would expect. For example, if an application opens a socket, requests an allocation type of PGID, then calls setpgid(), fork(), and exec()s a new process that also opens a socket and requests an allocation type of PGID, the SAs WILL NOT be shared between the two sockets. 3.4. Identity Types This API gives applications the ability to request the type of identity information sent to remote key management. The following identity types are currently defined: Address: The application requests that no identity information beyond the addresses present on a SA be specified. Metz Expires in 6 months [Page 15] Internet Draft Network Security API for Sockets 1 August 1997 Prefix: The application requests that additional identity information for the system's prefix be specified. (For IP systems, a prefix is the same thing as a subnet) FQDN: The application requests that additional identity information for the system's fully qualified domain name be specified. UserFQDN: The application requests that additional identity information in the form of a user's name and a system's fully qualified domain name be specified. Please note that some combinations of identity type and allocation type may or may not make sense for a given system. For example, most systems will probably not want to allow system or GID allocation with UserFQDN identities. System implementations SHOULD make the allowable combinations a policy control available to system administrators. More information on identity types may be found in the IP Security DOI specification [Piper97]. 3.5. Hints This API gives applications the ability to give certain hints to the policy engine about its expected security needs. These hints SHOULD affect the selection of specific transforms and algorithms by the policy engine. There are three parameters that an application can give hints about: the sensitivity of its data, the expected volume of data, and the latency needs of the application. Note that these parameters are not quite independent or dependent. How these parameters affect algorithm selection SHOULD be a policy decision that is configurable by the system administrator. The following sensitivity levels are currently defined. Note that there are sixteen numeric values currently available but only five named values; these extra intermediate values MAY be used when extra granularity is needed. Unknown: The application does not know in advance how sensitive its data will be. Lowest: The application expects its data to have the lowest sensitivity of any on the system and requires the weakest security. Low: The application expects its data to have low sensitivity; a weak algorithm is acceptable. Medium: The application expects its data to have medium Metz Expires in 6 months [Page 16] Internet Draft Network Security API for Sockets 1 August 1997 sensitivity. High: The application expects its data to have high sensitivity; a strong algorithm should be used. Highest: The application expects its data to have the highest sensitivity of any on the system and requires the strongest security available. Applications MUST NOT use this level unless absolutely necessary. The following volume levels are currently defined: Unknown: The application does not know in advance what volume of data it will communicate. Low: The application expects to communicate a low volume of data. For example, diagnostic applications like ping(8) might use this. Medium: The application expects to communicate a moderate volume of data. High: The application expects to communicate a high volume of data. For example, bulk data transfers such as FTP might use this. The following latency levels are currently defined: Unknown: The application does not know in advance what latency requirements it has for its data. Low: The application expects its data to need low latencies. For example, certain real-time traffic might need this. Medium: The application expects its data to tolerate moderate latencies. High: The application expects its data to tolerate high latencies. For example, bulk data transfers such as FTP might use this. Note that this API DOES NOT give the application the ability to directly select which cryptographic algorithms and parameters are used. This is a deliberate and useful feature, though some may consider this a bug. 3.6. Defined Values The following values have been defined for various fields. All other values are reserved. Operation types (net_security_operation_type): /* Authenticate (A) */ #define NET_SECURITY_TYPE_AUTHENTICATE 1 Metz Expires in 6 months [Page 17] Internet Draft Network Security API for Sockets 1 August 1997 /* Encrypt (E) */ #define NET_SECURITY_TYPE_ENCRYPT 2 /* Encapsulate (N) */ #define NET_SECURITY_TYPE_ENCAPSULATE 3 /* Magic Cookie (M) */ #define NET_SECURITY_TYPE_MAGICCOOKIE 4 Operation preferences (net_security_operation_preference): /* Default (d) */ #define NET_SECURITY_PREFERENCE_DEFAULT 0 /* Use (u) */ #define NET_SECURITY_PREFERENCE_USE 1 /* Require (r) */ #define NET_SECURITY_PREFERENCE_REQUIRE 2 /* Never (n) */ #define NET_SECURITY_PREFERENCE_NEVER 3 Operation SA allocation types (net_security_operation_alloctype): /* System */ #define NET_SECURITY_ALLOCTYPE_SYSTEM 1 /* GID */ #define NET_SECURITY_ALLOCTYPE_GID 2 /* UID */ #define NET_SECURITY_ALLOCTYPE_UID 3 /* PGID */ #define NET_SECURITY_ALLOCTYPE_PGID 4 /* Family */ #define NET_SECURITY_ALLOCTYPE_FAMILY 5 /* Socket */ #define NET_SECURITY_ALLOCTYPE_SOCKET 6 Operation SA identity types (net_security_operation_identtype): /* Address */ #define NET_SECURITY_IDENTTYPE_ADDRESS 1 /* Prefix */ #define NET_SECURITY_IDENTTYPE_PREFIX 2 /* FQDN */ #define NET_SECURITY_IDENTTYPE_FQDN 3 /* USERFQDN */ #define NET_SECURITY_IDENTTYPE_USERFQDN 4 Operation SA hints (net_security_operation_hints): /* Mask for sensitivity hints */ #define NET_SECURITY_HINTS_SENSITIVITY 0x0f Metz Expires in 6 months [Page 18] Internet Draft Network Security API for Sockets 1 August 1997 /* Mask for volume hints */ #define NET_SECURITY_HINTS_VOLUME 0x30 /* Mask for latency hints */ #define NET_SECURITY_HINTS_LATENCY 0xc0 /* Unknown sensitivity */ #define NET_SECURITY_SENSITIVITY_UNKNOWN 0x00 /* Lowest sensitivity */ #define NET_SECURITY_SENSITIVITY_LOWEST 0x01 /* Low sensitivity */ #define NET_SECURITY_SENSITIVITY_LOW 0x04 /* Medium sensitivity */ #define NET_SECURITY_SENSITIVTTY_MEDIUM 0x07 /* High sensitivity */ #define NET_SECURITY_SENSITIVITY_HIGH 0x0c /* Highest sensitivity */ #define NET_SECURITY_SENSITIVITY_HIGHEST 0x0f /* Unknown volume */ #define NET_SECURITY_SENSITIVITY_UNKNOWN 0x00 /* Low volume */ #define NET_SECURITY_VOLUME_LOW 0x10 /* Medium volume */ #define NET_SECURITY_VOLUME_MEDIUM 0x20 /* High volume */ #define NET_SECURITY_VOLUME_HIGH 0x30 /* Unknown latency */ #define NET_SECURITY_LATENCY_UNKOWN 0x00 /* Low latency */ #define NET_SECURITY_LATENCY_LOW 0x40 /* Medium latency */ #define NET_SECURITY_LATENCY_MEDIUM 0x80 /* High latency */ #define NET_SECURITY_LATENCY_HIGH 0xc0 3.7. System Calls Requests are sent to the kernel by an application through this setsockopt call: if (setsockopt(fd, SOL_SOCKET, NET_SECURITY_REQUEST, &request, requestlen)) { /* handle error */ }; If the socket is a stream socket and a recipe has been latched in, this setsockopt() call MUST fail with errno=EPERM. Metz Expires in 6 months [Page 19] Internet Draft Network Security API for Sockets 1 August 1997 The system engine MUST verify that the request is correctly formed and that all values are within range. If this is not the case, the setsockopt() call MUST fail with errno=EINVAL. If the setsockopt() call fails for any reason, the current request MUST remain unchanged. System implementors must be careful about attempting to check the request against system policy at setsockopt() time. Values that might be acceptable to the policy at setsockopt() time might not be acceptable when it's time to send or receive data, and the converse is also true. Therefore, the system MUST NOT check the request against any part of system policy that could change during the life of the socket. Requests are read back from the kernel by an application through this getsockopt call: if (getsockopt(fd, SOL_SOCKET, NET_SECURITY_REQUEST, &request, &requestlen)) { /* handle error */ }; The latter call is useful because it allows applications that receive an existing socket from a parent, such as children of inetd(8), to determine what security properties were originally requested. The recipe to be used for input and output is selected through this setsockopt call: if (setsockopt(fd, SOL_SOCKET, NET_SECURITY_RECIPE, &request, requestlen)) { /* handle error */ }; If the socket is a stream socket and a recipe has been latched in, this setsockopt() call MUST fail with errno=EPERM and the current request MUST remain unchanged. If a nonzero value less than NET_SECURITY_RECIPE_MAX is specified, that recipe alone will be used for all inputs and outputs (failure to match that recipe results in failure of security processing for that packet). If a value of zero is specified, output operations will fail. Input operations will attempt to match recipes starting at one until a recipe succeeds. If the socket is a stream socket, the index of the succeeding recipe will then be latched in and will replace the value specified in this request. Thus, subsequent outputs will Metz Expires in 6 months [Page 20] Internet Draft Network Security API for Sockets 1 August 1997 succeed. If the socket is a datagram or raw socket, the index will be returned in a control message if the system call used to receive the packet supports them. The cmsg_level will be SOL_SOCKET, cmsg_type will be NET_SECURITY_RECIPE, and cmsg_data will be a single int containing the index of the recipe that matched. This same control message is also valid for datagram sends. The identical format makes it easy for an application to "reflect" security properties. The recipe selected for use in input and output operations can be read from the kernel through this getsockopt call: if (getsockopt(fd, SOL_SOCKET, NET_SECURITY_RECIPE, &request, &requestlen)) { /* handle error */ }; This API defines a new errno value, EPOLICY. This value shall have the string definition (for functions like strerror()) of "Operation failed by policy". Output operations that fail as a result of a request and/or the system policy (for example, if require or never preferences are involved) MUST return this value. Input operations that result in a condition where the system would never receive packets for a socket (due to the interaction between the system's policy and the application's request) MUST fail and return this value. [cmetz: I know that I should avoid defining a new errno value because it's painful for people, but I think that this is an error condition that needs to be handled separately.] System implementations MUST make security operations either blocking or non-blocking depending on the application's I/O style request. That is, if the application has requested non-blocking I/O (e.g., via fcntl(F_SETFL, ...)), then security operations MUST also be non-blocking, and vice versa. For blocking I/O, the application SHOULD block while key management operations are taking place and while security processing (including policy processing and cryptographic operations) is performed. For non-blocking I/O, the application SHOULD be allowed to be execute while key management operations are taking place and MAY be allowed to execute while security processing (including policy processing and cryptographic operations) is performed. In the case of use and default preference levels, if SA negotiation is in progress and the system's policy configuration would allow the packet to be transmitted without security processing (e.g., as cleartext), the system MAY do so until a SA has been successfully negotiated. Metz Expires in 6 months [Page 21] Internet Draft Network Security API for Sockets 1 August 1997 [cmetz: An interface to obtain the identity strings used will be added as soon as can I figure out what exact form it should take. The problem is that you can have multiple identity strings, possibly one for each SA. This raises a higher issue of when identities for a string of SAs all used for the same flow can be different and when they must be the same. For example, if I have a packet: IP AH ESP [ ULP ] It doesn't make much sense for the ESP SA to have an identity of "bb@ministry-of-war.inner.net" and the AH SA to have an identity of "julia@ministry-of-love.inner.net"; they should be compatible. I believe that more thought needs to be given to this problem before it is appropriate to plumb the API for obtaining identities.] 4. Discussion Applications that use the loopback interface SHOULD request that security services NOT be provided for that communication (i.e., preference=never). An application has no choice but to trust that its OS is doing the right thing. Therefore, encryption and authentication of data over the loopback interface is usually nothing more than a waste of system resources. There are some cases where it's useful to have the system provide security services on loopback traffic, but implementations typically blindly request encryption and authentication without checking for loopback and end up just wasting cycles. [cmetz: more stuff will go here] Future Work This document needs lots of examples and discussion of border cases. This will be coming in a future revision. A companion document describing one possible design and implementation of a policy engine is in progress. Acknowledgments Randall Atkinson, Ron Lee, Daniel L. McDonald, and Chris Winters provided useful feedback on earlier versions of this document. This work was done at the Center for High Assurance Computer Systems at the U.S. Naval Research Laboratory. This work was sponsored by the Information Security Program Office (PMW-161), U.S. Space and Naval Warfare Systems Command (SPAWAR) and the Computing Systems Technology Office, Defense Advanced Research Projects Agency Metz Expires in 6 months [Page 22] Internet Draft Network Security API for Sockets 1 August 1997 (DARPA/CSTO). The author and his co-workers really appreciates their sponsorship of NRL's network security efforts and their continued support of IPsec development. Without that support, this document, among many others, would not exist. The "CONFORMANCE and COMPLIANCE" wording was taken from [MSST97]. The author has created a mailing list for discussion of this specification and implementations of it. If you would like to be added to this list, send a note to . References [Atk95a] Randall J. Atkinson, "IP Security Architecture", RFC 1825, August 1995. [Atk95b] Randall J. Atkinson, "IP Authentication Header", RFC 1826, August 1995. [Atk95c] Randall J. Atkinson, "IP Encapsulating Security Payload", RFC 1827, August 1995. [MMP97] D. L. McDonald, C. W. Metz, B. G. Phan, "PF_KEY Key Management API, Version 2", Internet Draft, July 1997. [MSST97] Douglas Maughan, Mark Schertler, Mark Schneider, Jeff Turner, "Internet Security Association and Key Management Protocol (ISAKMP)", Internet Draft, February 1997. [Piper97] Derrel Piper, "The Internet IP Security Domain of Interpretation for ISAKMP", Internet Draft, February 1997. Disclaimer The views and specification here are those of the author and are not necessarily those of his employer. His employer has not passed judgment on the merits, if any, of this work. The author and his employer specifically disclaim responsibility for any problems arising from correct or incorrect implementation or use of this specification. Author's Address Craig Metz The Inner Net Box 10314-1933 Blacksburg, VA 24062-0314 Metz Expires in 6 months [Page 23] Internet Draft Network Security API for Sockets 1 August 1997 PSTN: +1 202 404 8590 DSN: 354-8590 E-mail: cmetz@inner.net Metz Expires in 6 months [Page 24]