📄 rfc2367.txt
字号:
| Interface |
+-----------+
Figure 1: Relationship of Key Mgmt to PF_KEY
For performance reasons, some security protocols (e.g. IP Security)
are usually implemented inside the operating system kernel. Other
security protocols (e.g. OSPFv2 Cryptographic Authentication) are
implemented in trusted privileged applications outside the kernel.
Figure 2 shows a trusted, privileged routing daemon using PF_INET to
communicate routing information with a remote routing daemon and
using PF_KEY to request, obtain, and delete Security Associations
used with a routing protocol.
McDonald, et. al. Informational [Page 6]
RFC 2367 PF_KEY Key Management API July 1998
+---------------+
|Routing Daemon|
+---------------+
| |
| |
| | Applications
======[PF_KEY]====[PF_INET]==========================
| | OS Kernel
+------------+ +---------+
| Key Engine | | TCP/IP |
| or SADB |---| |
+------------+ +---------+
|
+-----------+
| Network |
| Interface |
+-----------+
Figure 2: Relationship of Trusted Application to PF_KEY
When a trusted privileged application is using the Key Engine but
implements the security protocol within itself, then operation varies
slightly. In this case, the application needing an SA sends a PF_KEY
SADB_ACQUIRE message down to the Key Engine, which then either
returns an error or sends a similar SADB_ACQUIRE message up to one or
more key management applications capable of creating such SAs. As
before, the key management daemon stores the SA into the Key Engine.
Then, the trusted privileged application uses an SADB_GET message to
obtain the SA from the Key Engine.
In some implementations, policy may be implemented in user-space,
even though the actual cryptographic processing takes place in the
kernel. Such policy communication between the kernel mechanisms and
the user-space policy MAY be implemented by PF_KEY extensions, or
other such mechanism. This document does not specify such
extensions. A PF_KEY implementation specified by the memo does NOT
have to support configuring systemwide policy using PF_KEY.
Untrusted clients, for example a user's web browser or telnet client,
do not need to use PF_KEY. Mechanisms not specified here are used by
such untrusted client applications to request security services (e.g.
IPsec) from an operating system. For security reasons, only trusted,
privileged applications are permitted to open a PF_KEY socket.
McDonald, et. al. Informational [Page 7]
RFC 2367 PF_KEY Key Management API July 1998
1.3 PF_KEY Socket Definition
The PF_KEY protocol family (PF_KEY) symbol is defined in
<sys/socket.h> in the same manner that other protocol families are
defined. PF_KEY does not use any socket addresses. Applications
using PF_KEY MUST NOT depend on the availability of a symbol named
AF_KEY, but kernel implementations are encouraged to define that
symbol for completeness.
The key management socket is created as follows:
#include <sys/types.h>
#include <sys/socket.h>
#include <net/pfkeyv2.h>
int s;
s = socket(PF_KEY, SOCK_RAW, PF_KEY_V2);
The PF_KEY domain currently supports only the SOCK_RAW socket type.
The protocol field MUST be set to PF_KEY_V2, or else EPROTONOSUPPORT
will be returned. Only a trusted, privileged process can create a
PF_KEY socket. On conventional UNIX systems, a privileged process is
a process with an effective userid of zero. On non-MLS proprietary
operating systems, the notion of a "privileged process" is
implementation-defined. On Compartmented Mode Workstations (CMWs) or
other systems that claim to provide Multi-Level Security (MLS), a
process MUST have the "key management privilege" in order to open a
PF_KEY socket[DIA]. MLS systems that don't currently have such a
specific privilege MUST add that special privilege and enforce it
with PF_KEY in order to comply and conform with this specification.
Some systems, most notably some popular personal computers, do not
have the concept of an unprivileged user. These systems SHOULD take
steps to restrict the programs allowed to access the PF_KEY API.
1.4 Overview of PF_KEY Messaging Behavior
A process interacts with the key engine by sending and receiving
messages using the PF_KEY socket. Security association information
can be inserted into and retrieved from the kernel's security
association table using a set of predefined messages. In the normal
case, all properly-formed messages sent to the kernel are returned to
all open PF_KEY sockets, including the sender. Improperly formed
messages will result in errors, and an implementation MUST check for
a properly formed message before returning it to the appropriate
listeners. Unlike the routing socket, most errors are sent in reply
messages, not the errno field when write() or send() fails. PF_KEY
message delivery is not guaranteed, especially in cases where kernel
or socket buffers are exhausted and messages are dropped.
McDonald, et. al. Informational [Page 8]
RFC 2367 PF_KEY Key Management API July 1998
Some messages are generated by the operating system to indicate that
actions need to be taken, and are not necessarily in response to any
message sent down by the user. Such messages are not received by all
PF_KEY sockets, but by sockets which have indicated that kernel-
originated messages are to be received. These messages are special
because of the expected frequency at which they will occur. Also, an
implementation may further wish to restrict return messages from the
kernel, in cases where not all PF_KEY sockets are in the same trust
domain.
Many of the normal BSD socket calls have undefined behavior on PF_KEY
sockets. These include: bind(), connect(), socketpair(), accept(),
getpeername(), getsockname(), ioctl(), and listen().
1.5 Common PF_KEY Operations
There are two basic ways to add a new Security Association into the
kernel. The simplest is to send a single SADB_ADD message,
containing all of the SA information, from the application into the
kernel's Key Engine. This approach works particularly well with
manual key management, which is required for IPsec, and other
security protocols.
The second approach to add a new Security Association into the kernel
is for the application to first request a Security Parameters Index
(SPI) value from the kernel using the SADB_GETSPI message and then
send an SADB_UPDATE message with the complete Security Association
data. This second approach works well with key management daemons
when the SPI values need to be known before the entire Security
Association data is known (e.g. so the SPI value can be indicated to
the remote end of the key management session).
An individual Security Association can be deleted using the
SADB_DELETE message. Categories of SAs or the entire kernel SA table
can be deleted using the SADB_FLUSH message.
The SADB_GET message is used by a trusted application-layer process
(e.g. routed(8) or gated(8)) to retrieve an SA (e.g. RIP SA or OSPF
SA) from the kernel's Key Engine.
The kernel or an application-layer can use the SADB_ACQUIRE message
to request that a Security Association be created by some
application-layer key management process that has registered with the
kernel via an SADB_REGISTER message. This ACQUIRE message will have
a sequence number associated with it. This sequence number MUST be
used by followup SADB_GETSPI, SADB_UPDATE, and SADB_ADD messages, in
order to keep track of which request gets its keying material. The
sequence number (described below) is similar to a transaction ID in a
McDonald, et. al. Informational [Page 9]
RFC 2367 PF_KEY Key Management API July 1998
remote procedure call.
The SADB_EXPIRE message is sent from the kernel to key management
applications when the "soft lifetime" or "hard lifetime" of a
Security Association has expired. Key management applications should
use receipt of a soft lifetime SADB_EXPIRE message as a hint to
negotiate a replacement SA so the replacement SA will be ready and in
the kernel before it is needed.
A SADB_DUMP message is also defined, but this is primarily intended
for PF_KEY implementor debugging and is not used in ordinary
operation of PF_KEY.
1.6 Differences Between PF_KEY and PF_ROUTE
The following bullets are points of difference between the routing
socket and PF_KEY. Programmers who are used to the routing socket
semantics will find some differences in PF_KEY.
* PF_KEY message errors are usually returned in PF_KEY messages
instead of causing write() operations to fail and returning the
error number in errno. This means that other listeners on a PF_KEY
socket can be aware that requests from another process failed,
which can be useful for auditing purposes. This also means that
applications that fail to read PF_KEY messages cannot do error
checking.
An implementation MAY return the errors EINVAL, ENOMEM, and ENOBUFS
by causing write() operations to fail and returning the error
number in errno. This is an optimization for common error cases in
which it does not make sense for any other process to receive the
error. An application MUST NOT depend on such errors being set by
the write() call, but it SHOULD check for such errors, and handle
them in an appropriate manner.
* The entire message isn't always reflected in the reply. A SADB_ADD
message is an example of this.
* The PID is not set by the kernel. The process that originates the
message MUST set the sadb_msg_pid to its own PID. If the kernel
ORIGINATES a message, it MUST set the sadb_msg_pid to 0. A reply
to an original message SHOULD have the pid of the original message.
(E.g. the kernel's response to an SADB_ADD SHOULD have its pid set
to the pid value of the original SADB_ADD message.)
McDonald, et. al. Informational [Page 10]
RFC 2367 PF_KEY Key Management API July 1998
1.7 Name Space
All PF_KEYv2 preprocessor symbols and structure definitions are
defined as a result of including the header file <net/pfkeyv2.h>.
There is exactly one exception to this rule: the symbol "PF_KEY" (two
exceptions if "AF_KEY" is also counted), which is defined as a result
of including the header file <sys/socket.h>. All PF_KEYv2
preprocessor symbols start with the prefix "SADB_" and all structure
names start with "sadb_". There are exactly two exceptions to this
rule: the symbol "PF_KEY_V2" and the symbol "PFKEYV2_REVISION".
The symbol "PFKEYV2_REVISION" is a date-encoded value not unlike
certain values defined by POSIX and X/Open. The current value for
PFKEYV2_REVISION is 199806L, where 1998 is the year and 06 is the
month.
Inclusion of the file <net/pfkeyv2.h> MUST NOT define symbols or
structures in the PF_KEYv2 name space that are not described in this
document without the explicit prior permission of the authors. Any
symbols or structures in the PF_KEYv2 name space that are not
described in this document MUST start with "SADB_X_" or "sadb_x_". An
implementation that fails to obey these rules IS NOT COMPLIANT WITH
THIS SPECIFICATION and MUST NOT make any claim to be. These rules
also apply to any files that might be included as a result of
including the file <net/pfkeyv2.h>. This rule provides implementors
with some assurance that they will not encounter namespace-related
surprises.
1.8 On Manual Keying
Not unlike the 4.4-Lite BSD PF_ROUTE socket, this interface allows an
application full-reign over the security associations in a kernel
that implements PF_KEY. A PF_KEY implementation MUST have some sort
of manual interface to PF_KEY, which SHOULD allow all of the
functionality of the programmatic interface described here.
2. PF_KEY Message Format
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -