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 <net/security.h>.
Inclusion of the file <net/security.h> 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 <net/security.h>. 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 <net-security-api-
request@inner.net>.
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]