Better than Nothing Security M. Komu Internet-Draft Helsinki Institute for Information Expires: August 16, 2006 Technology February 12, 2006 IPsec Application Programming Interfaces draft-komu-btns-api-00.txt Status of this Memo By submitting this Internet-Draft, each author represents that any applicable patent or other IPR claims of which he or she is aware have been or will be disclosed, and any of which he or she becomes aware will be disclosed, in accordance with Section 6 of BCP 79. This document may not be modified, and derivative works of it may not be created, except to publish it as an RFC and to translate it into languages other than English. Internet-Drafts are working documents of the Internet Engineering Task Force (IETF), its areas, and its working groups. Note that other groups may also distribute working documents as Internet- Drafts. Internet-Drafts are draft documents valid for a maximum of six months and may be updated, replaced, or obsoleted by other documents at any time. It is inappropriate to use Internet-Drafts as reference material or to cite them other than as "work in progress." The list of current Internet-Drafts can be accessed at http://www.ietf.org/ietf/1id-abstracts.txt. The list of Internet-Draft Shadow Directories can be accessed at http://www.ietf.org/shadow.html. This Internet-Draft will expire on August 16, 2006. Copyright Notice Copyright (C) The Internet Society (2006). Abstract IPsec based security is usually transparent for applications and they may not be sure when network connections are protected. This document specifies an API that increases the visibility of IPsec to applications. The API allows applications to use the Stand-alone BTNS mode, control the channel bindigs and control also other network Komu Expires August 16, 2006 [Page 1] Internet-Draft IPsec APIs February 2006 security properties related to IPsec. Komu Expires August 16, 2006 [Page 2] Internet-Draft IPsec APIs February 2006 1. Introduction The network communications of applications are usually secured explicitly with TLS [6], or using even higher layer interfaces such as GSS [5] or SASL [7] APIs. However, such interfaces do not exist for IPsec because it operates on lower layers and is mostly transparent for applications. Applying of IPsec to existing applications is therefore easier than with e.g. TLS because IPsec does not require changes in the application. However, it is difficult for the application to detect when network connections are secured using IPsec. IPsec can be used as "all or nothing" security measure, which can be problematic in early deployments when the number of IPsec enabled machines is small. An alternative approach could be to use IPsec in "use when peer supports" fashion. However, the application or the user may not have any knowledge that the communications was actually protected in this case. In this document, we attempt to increase the visibility of the IPsec layer to the applications and to fulfil the BTNS requirements in [3]. The APIs defined in this document are based on sockets API [1] or similar APIs that provide socket descriptors for applications. The documents defines an explicit way of enabling IPsec in applications. This API allows the dual use of both IPsec and higher layer security mechanisms simultaneously. The security and performance related benefits of this are described in more detail in [4]. Komu Expires August 16, 2006 [Page 3] Internet-Draft IPsec APIs February 2006 +---------+---------+---------+---------+ | App # 1 | App # 2 | App # 3 | App #4 | +-----+---+-----+---+---+-----+----+----+ | | | | | +---v-------v--+ | | | TLS/GSS/SASL | | +-----v-----+-------+------+ | Appl. Layer | IPsec APIs | | | +-----+---------+---+ | | | | | | +-----v---------v-------v-----------v---+ Sockets Layer | IPv4 and IPv6 APIs | +-----------+--------------+------------+ Transport Layer | SCTP | TCP | UDP | +-----------+--------------+------------+ IPsec Layer | IPsec | +--------------------+------------------+ Network Layer | IPv4 | IPv6 | +--------------------+------------------+ Link Layer | Ethernet | Etc | +--------------------+------------------+ Figure 1: API Layering Figure Figure 1 illustrates four different applications. The first application is using only the IPsec APIs based on either IKE based authentication or Stand-alone BTNS. The second application is using both TLS (or other similar APIs) and IPsec APIs. In this case, TLS provides its own authentication credentials. The application reuses the credentials to the resulting IPsec channel when IKE based authentication is not possible or to avoid double authentication. Now, the application can bind the TLS authentication credentials to resulting IPsec channel. The channel binding is a local operation, i.e., it does not involve any extra communications with the peer application or host. The third application is using only TLS and the fourth one is using neither IPsec or TLS APIs. In the first three cases, the application is explicitly modified to use either TLS or IPsec. In contrast, the fourth application is not using either TLS or IPsec explicitly, but it may be using IPsec implicitly. This document covers the use of applications one and two. Komu Expires August 16, 2006 [Page 4] Internet-Draft IPsec APIs February 2006 2. IPsec APIs This section defines constants, data structures and functions for manipulating IPsec policies and channel bindings. The definitions are based on C-language. See Appendix A.1 for code examples on how to use the APIs in practise. 2.1. IPsec Policies This section defines functions that manage application policies. The policies are used to control the key management software or the IPsec module of a host. 2.1.1. Policy Creation The data structure that represents an application policy is contained in an opaque ipsec_policy structure. The application MUST not alter the data structure contents directly, but rather use the accessor functions introduced in the following sections. The application can use ipsec_policy_t typedef as a short hand for the policy structure. The typedef is shown in Figure 2. typedef ipsec_policy_t struct ipsec_policy; Figure 2 The size of a policy is variable and applications MUST NOT declare them directly. Instead, the application uses the constructor and destructor functions shown in Figure 3. ipsec_policy_t *ipsec_create_policy(uint32_t type); int ipsec_free_policy(ipsec_policy_t *policy); Figure 3 Table 1 +----------------------+-----------------+ | Policy Type | Purpose | +----------------------+-----------------+ | IPSEC_DEFAULT_POLICY | System defaults | +----------------------+-----------------+ Table 1 Komu Expires August 16, 2006 [Page 5] Internet-Draft IPsec APIs February 2006 2.1.2. Policy Attributes Policies are opaque data structures that MUST NOT be manipulated directly. Instead, the application uses the accessor functions shown in Figure 4. int ipsec_get_policy_attr(const ipsec_policy_t *policy, uint32_t attr_type, uint32_t *attr_len, void **attr_val); int ipsec_set_policy_attr(ipsec_policy_t *policy, uint32_t attr_type, uint32_t attr_len, const void *attr_val); Figure 4 Function ipsec_get_policy_attr searches for the given attribute type (attr_type) from the policy. It allocates memory into attr_val and copies the attribute into the allocated memory. On successful operation, it sets the attribute length in attr_len. Function ipsec_set_policy_attr writes the attribute (attr_val) to the policy. The type and length of the attribute must be set in attr_type and attr_len. The attribute types and their lengths are shown in Table 2. +----------------------------+----------+---------------------------+ | Attribute Type | Length | Purpose | +----------------------------+----------+---------------------------+ | IPSEC_BTNS_STANDALONE | 4 octets | Allow BTNS standalone | | | | mode | | | | | | IPSEC_BTNS_CHANNEL_BINDING | 4 octets | Require channel bindings | +----------------------------+----------+---------------------------+ Table 2 Both of the functions return zero for success and non-zero for failure. XX FIX list error values here. 2.1.3. Connection Oriented Communications Declaring a policy does not affect the networking communications of an application. For connection oriented communications, the application must first attach the policy to socket before the policy is effective. It is also possible to query for the policy attached Komu Expires August 16, 2006 [Page 6] Internet-Draft IPsec APIs February 2006 to a socket as shown in Figure 5. int ipsec_set_socket_policy(int fd, const ipsec_policy_t *policy); int ipsec_get_socket_policy(int fd, ipsec_policy_t **policy); Figure 5 Both functions input an socket descriptor as the first argument and a policy pointer as the second argument. Function ipsec_set_socket_policy attaches the given policy pointer to the socket descriptor fd. For ipsec_get_socket_policy, the policy is a double pointer because the function also allocates the memory for the queried policy. Both functions return zero upon success, and non-zero upon failure. XX FIX list error values here. 2.1.4. Datagram Oriented Communications The previous section covered the use of connected sockets. Datagram oriented communications based on sendmsg and recvmsg functions are supported in the API, but sendto and recvfrom are not supported. Datagram related functions are applicable both to incoming and outgoing packets. The functions are shown in Figure 6. int ipsec_set_msg_policy(const struct msghdr *msg, const ipsec_policy_t *policy); int ipsec_get_msg_policy(const struct msghdr *msg, ipsec_policy_t **policy); Figure 6 Function ipsec_set_msg_policy applies the given policy to the msg data structure. The policy of a msg can be queried using ipsec_get_msg_policy. It allocates the memory required for the policy and returns it to the caller in policy double pointer. Both functions return zero on success and non-zero on failure. XX FIX list error values here. 2.1.5. Other Policy Related Functions An application is not allowed to read or write to policies directly. The same restriction applies also to comparison and byte-wise copying of policies. Theses operations have their own accessor functions that are shown in Figure 7. Komu Expires August 16, 2006 [Page 7] Internet-Draft IPsec APIs February 2006 int ipsec_cmp_policy(ipsec_policy_t *p1, ipsec_policy_t *p2); int ipsec_dup_policy(ipsec_policy_t *p, ipsec_policy_t **p_dup); Figure 7 Function ipsec_cmp_policy inputs two policies, p1 and p2, and returns zero if they are equal. Otherwise it returns non-zero. Function ipsec_dup_policy duplicates given policy p and writes it to p_dup. The function allocates the memory for duplicated policy that the caller is responsible of freeing. Return value is zero on success and non-zero on failure. XX list error values here. 2.2. Channel Bindings Channel bindings are handled locally at the host, i.e., they are not communicated with a peer host. The channel bindings allow the application to replace network layer authentication with e.g. TLS certificates. In addition, application can store the channel binding information and use it to verify that it is still talking to the same host in subsequent communications. 2.2.1. Channel Creation Similarly to policies, also channel related information is stored in an opaque structure. An application MUST not read or write directly channel information data structures, but rather use the accessor functions introduce in the following sections. Typedef for channel information is shown in Figure 8. typedef ipsec_channel_info_t struct ipsec_channel_info; Figure 8 Channel information data structures are created and initialized using ipsec_create_channel_info function. Deallocation is handled through ipsec_free_channel_info function. The functions are shown in Figure 9. ipsec_channel_info_t *ipsec_create_channel_info(); int ipsec_free_channel_info(*ipsec_channel_info_t *ci); Figure 9 Function ipsec_create_channel_info allocated memory for the channel information and returns it to the caller. Upon failure, it returns Komu Expires August 16, 2006 [Page 8] Internet-Draft IPsec APIs February 2006 NULL. ipsec_free_channel_info deallocates the given channel information data structure ci. It returns zero on success and non-zero on failure. 2.2.2. Channel Attributes The details of the channel information can be queried and set using the functions shown in Figure 10. int ipsec_set_channel_attr(ipsec_channel_info_t *ci, uint32_t attr_type, uint32_t attr_len, const void *attr_val); int ipsec_get_channel_attr(const ipsec_channel_info_t *ci, uint32_t attr_type, uint32_t *attr_len, void **attr_val); Figure 10 Function ipsec_set_channel_attr writes the given channel attribute attr_val to the channel information ci. The length and type of the attribute are passed in attr_type and attr_len. Function ipsec_get_channel_attr reads the channel attribute from ci, allocates memory for the attribute and writes the queried attribute (attr_type) to attr_val. The function writes the length of the attribute to attr_len. Different attribute types along with lengths are shown in Table 3. +----+----+----+ | xx | xx | xx | +----+----+----+ | xx | xx | xx | +----+----+----+ Table 3 Both of the attribute functions return zero on success and non-zero on failure. The error values are listed in Table 4. Komu Expires August 16, 2006 [Page 9] Internet-Draft IPsec APIs February 2006 +----+----+ | xx | xx | +----+----+ | xx | xx | +----+----+ Table 4 2.2.3. Connection Oriented Communications With connection oriented sockets, an application can attach channel information to a socket with ipsec_set_socket_channel_info function. The channel information can be e.g. a TLS certificate. In turn, ipsec_get_socket_channel_info function can be used to query the channel information attached to a socket. The application can use this information to e.g. verify that it is talking to the same host as before. Figure Figure 11 shows the get and set functions. int ipsec_set_socket_channel_info(int fd, const ipsec_channel_info_t *ci); int ipsec_get_socket_channel_info(int fd, ipsec_channel_info_t **ci); Figure 11 Both of the functions input a socket descriptor fd. Function ipsec_set_socket_channel_info inputs the channel information to be set in ci. Function ipsec_get_socket_channel_info allocates memory for channel information and outputs it to ci. The functions return zero on success and non-zero on failure. XX fix list error values here. 2.2.4. Datagram Oriented Communications When an application uses sendmsg or recvmsg calls for datagram oriented communications, it can use the functions shown in Figure 12. Functions recvfrom and sendto are not supported. int ipsec_set_msg_channel_info(const struct *msg_hdr, const ipsec_channel_info_t *ci); int ipsec_get_msg_channel_info(const struct *msg_hdr, ipsec_channel_info_t **ci); Figure 12 Function ipsec_set_msg_channel_info attaches the channel information ci into the msg_hdr. Function ipsec_get_msg_channel_info reads Komu Expires August 16, 2006 [Page 10] Internet-Draft IPsec APIs February 2006 channel information from msg_hdr, allocates memory for it and returns it in ci. Both functions return zero on success and non-zero on failure. XX FIX list error values here. 2.2.5. Other Channel Related Function Channel information is opaque and must be operated through accessor functions. Channel information comparison, duplication and conversion functions are shown in Figure 13. int ipsec_cmp_channel_info(const ipsec_channel_info_t *ci1, const ipsec_channel_info_t *ci2); int ipsec_dup_channel_info(const ipsec_channel_info_t *ci, ipsec_channel_info_t **ci_dup); int ipsec_openssl_to_channel_info(const SSL *ssl, const ipsec_policy_t *policy, ipsec_channel_info_t **ci); Figure 13 Function ipsec_cmp_channel_info compares channel information ci1 and ci2. It returns zero when they are equal or non-zero when they are different. Channel information is duplicated using ipsec_dup_channel_info. It inputs channel information ci and outputs the duplicated ci_dup. The function reserves memory for the duplicated channel information. Return value is zero on success and non-zero on failure. XX FIX list error values here. Function ipsec_openssl_to_channel_info converts an OpenSSL data structure ssl to channel information ci according to the rules in the given policy. The function reserves memory for the created channel information. The function returns zero on success and non-zero on failure. XX FIX list error values here. Komu Expires August 16, 2006 [Page 11] Internet-Draft IPsec APIs February 2006 3. IANA Considerations TBD Komu Expires August 16, 2006 [Page 12] Internet-Draft IPsec APIs February 2006 4. Security Considerations TBD Komu Expires August 16, 2006 [Page 13] Internet-Draft IPsec APIs February 2006 5. Acknowledgements Thanks for Michael Richardson, Love Hoernquist Aestrand, Nicolas Williams and Julien Laganier for feedback, ideas and discussion on the topic. Komu Expires August 16, 2006 [Page 14] Internet-Draft IPsec APIs February 2006 Appendix A. Appendix Appendix A.1. Code Examples This section shows code examples that illustrate the use of the APIs. Error value handling is not very verbose to keep the code length smaller. In addition, the code snippets do not show e.g. address resolution at all. int hello_conn_client(int domain, int type, int family, const struct sockaddr *sockaddr, socklen_t sockaddr_len, ipsec_channel_info_t **old_channel) { int sockfd = 0, err = 0, hello_len; unint32_t on = 1; ipsec_channel_info_t *channel_info = NULL; ipsec_policy_t *policy = NULL; char *hello = "hello world"; ssize_t count; hello_len = strlen(hello); sockfd = socket(domain, type, family); if (sockfd < 0) { err = -1; goto out; } /* Set socket policy to allow btns in channel binding mode. This way, lower layer authentication can be omitted because we are using TLS with certificates for this connection */ policy = ipsec_new_policy(IPSEC_DEFAULT_POLICY); if (policy == 0) goto out_err; err = ipsec_set_policy_attr(policy, IPSEC_BTNS_STANDALONE, sizeof(on), &on); if (err) goto out; err = ipsec_set_socket_policy(sockfd, policy); if (err) goto out; Komu Expires August 16, 2006 [Page 15] Internet-Draft IPsec APIs February 2006 /* If we have contacted the peer before, we can ensure that the host is still the same by reusing the old channel binding */ if (*old_channel) { err = ipsec_set_socket_channel_info(sockfd, *old_channel); if (err) goto out; } /* In the case of TCP, connect() triggers a TCP handshake that is protected by IPsec according to the policy */ err = connect(sockfd, sockaddr, sockaddr_len); if (err) goto out; /* Store new channel bindings for subsequent communications */ if (*old_channel == NULL) { /* Store channel information to the old_channel_info to check that the peer host is the still the same. */ err = ipsec_dup_channel_info(channel_info, old_channel) } /* Send data protected using IPsec according to the policy. */ count = send(sockfd, hello, hello_len, 0); if (count != hello_len) { err = -1; goto out; } out: if (channel_info) ipsec_free_channel_info(channel_info); if (sockfd) close(sockfd); if (policy) ipsec_free_policy(policy); return err; } Figure 14: Connection Oriented Client Example int hello_tls_conn_client(char *hostname, Komu Expires August 16, 2006 [Page 16] Internet-Draft IPsec APIs February 2006 int domain, int type, int family, const struct sockaddr *sockaddr, socklen_t sockaddr_len, SSL_ctx *ctx, ipsec_channel_info_t **old_channel) { int sockfd = 0, err = 0, hello_len; unint32_t on = 1; ipsec_channel_info_t *channel_info = NULL; ipsec_policy_t *policy = NULL; char *hello = "hello world"; SSL *ssl = NULL; BIO *bio = NULL; ssize_t count; hello_len = strlen(hello); sockfd = socket(domain, type, family); if (sockfd < 0) { err = -1; goto out; } /* Set socket policy to allow btns in channel binding mode. This way, lower layer authentication can be omitted because we are using TLS with certificates for this connection */ policy = ipsec_new_policy(IPSEC_DEFAULT_POLICY); if (policy == 0) goto out_err; err = ipsec_set_policy_attr(policy, IPSEC_BTNS_CHANNEL_BINDING, sizeof(on), &on); if (err) goto out; err = ipsec_set_socket_policy(sockfd, policy); if (err) goto out; /* If we have contacted the peer before, we can ensure that the host is still the same by reusing the old channel binding */ if (*old_channel) { err = ipsec_set_socket_channel_info(sockfd, *old_channel); if (err) goto out; Komu Expires August 16, 2006 [Page 17] Internet-Draft IPsec APIs February 2006 } /* Do TCP handshake that is protected using IPsec according to the application's policy */ err = connect(sockfd, sockaddr, sockaddr_len); if (err) goto out; /* Create ssl structure and associate sockfd to it. Do TLS handshake and verify server certificate. */ ssl = SSL_new(ctx); if (ssl == NULL) goto out; bio = BIO_new_socket(sockfd, BIO_NOCLOSE); if (bio == NULL) goto out; SSL_set_bio(ssl, bio, bio); if (SSL_connect(ssl) &st;= 0) goto out; if (verify_server_cert(ssl, hostname)) goto out; /* First connection attempt to the peer host. Get channel binding info from ssl according to the policy rules (the policy selects e.g. the certificate). Store it to verify subsequent communications */ if (*old_channel == NULL) { err = ipsec_openssl_to_channel_info(ssl, policy, &channel_info); if (err) goto out; err = ipsec_dup_channel_info(channel_info, old_channel) if (err) goto out; } /* Encrypt and send the data. For simplicity, a for loop is omitted here that would ensure all bytes were sent */ count = SSL_write(ssl, hello, hello_len); if (count != hello_len) { err = -1; goto out; } Komu Expires August 16, 2006 [Page 18] Internet-Draft IPsec APIs February 2006 out: if (channel_info) ipsec_free_channel_info(channel_info); if (bio) BIO_free(bio) if (ssl) SSL_free(ssl); if (sockfd) close(sockfd); if (policy) ipsec_free_policy(policy); return err; } Figure 15: Connection Oriented TLS Client Example int hello_msg_client(int domain, int type, int family, const struct msg_hdr *hello_msg, ssize_t hello_len, socklen_t sockaddr_len, ipsec_channel_info_t **old_channel) { int sockfd = 0, err = 0, hello_len; unint32_t on = 1; ipsec_channel_info_t *channel_info = NULL; ipsec_policy_t *policy = NULL; ssize_t count; sockfd = socket(domain, type, family); if (sockfd < 0) { err = -1; goto out; } /* Set socket policy to allow btns in channel binding mode. This way, lower layer authentication can be omitted because we are using TLS with certificates for this connection */ policy = ipsec_new_policy(IPSEC_DEFAULT_POLICY); if (policy == 0) goto out_err; err = ipsec_set_policy_attr(policy, IPSEC_BTNS_STANDALONE, Komu Expires August 16, 2006 [Page 19] Internet-Draft IPsec APIs February 2006 sizeof(on), &on); if (err) goto out; /* Send data to the peer. Data and peer are both defined in the msg header. If a previous channel binding is provided, use it to ensure that we are still talking to the same host */ if (*old_channel != NULL ) { err = ipsec_set_msg_policy(hello_msg, policy); if (err) goto out_err; err = ipsec_set_msg_channel_info(hello_msg, *old_channel); if (err) goto out_err; } count = sendmsg(sockfd, hello_msg, 0); if (count != hello_len) { err = -1; goto out; } /* If we just communicated with the peer for the first time, let's query and store the channel info for subsequent communications */ if (*old_channel == NULL) { err = ipsec_get_msg_channel_info(hello_msg, &channel_info); if (err) goto out_err; err = ipsec_dup_channel_info(channel_info, old_channel); } /* Let's receive a message from the peer. Apply IPsec policy and reuse the previous channel binding to ensure that we are still talking to the same host. */ err = ipsec_set_msg_policy(hello_msg, policy); if (err) goto out_err; err = ipsec_set_msg_channel_info(hello_msg, channel_info); if (err) goto out_err; count = recvmsg(sockfd, hello_msg, 0); if (count != hello_len) { err = -1; Komu Expires August 16, 2006 [Page 20] Internet-Draft IPsec APIs February 2006 goto out; } out: if (channel_info) ipsec_free_channel_info(channel_info); if (sockfd) close(sockfd); if (policy) ipsec_free_policy(policy); return err; } Figure 16: Datagram Oriented Client Example Komu Expires August 16, 2006 [Page 21] Internet-Draft IPsec APIs February 2006 6. References 6.1. Normative References [1] Institute of Electrical and Electronics Engineers, "IEEE Std. 1003.1-2001 Standard for Information Technology - Portable Operating System Interface (POSIX)", Dec 2001. [2] Gilligan, R., Thomson, S., Bound, J., McCann, J., and W. Stevens, "Basic Socket Interface Extensions for IPv6", RFC 3493, February 2003. [3] Richardson, M. and B. Sommerfeld, "Requirements for an IPsec API", draft-ietf-btns-ipsec-apireq-00 (work in progress), April 2006. [4] Touch, J., "Problem and Applicability Statement for Better Than Nothing Security (BTNS)", draft-ietf-btns-prob-and-applic-04 (work in progress), September 2006. 6.2. Informative References [5] Wray, J., "Generic Security Service API Version 2 : C-bindings", RFC 2744, January 2000. [6] Dierks, T. and E. Rescorla, "The Transport Layer Security (TLS) Protocol Version 1.1", RFC 4346, April 2006. [7] Melnikov, A. and K. Zeilenga, "Simple Authentication and Security Layer (SASL)", RFC 4422, June 2006. Komu Expires August 16, 2006 [Page 22] Internet-Draft IPsec APIs February 2006 Author's Address Miika Komu Helsinki Institute for Information Technology Tammasaarenkatu 3 Helsinki Finland Phone: +358503841531 Fax: +35896949768 Email: miika@iki.fi URI: http://www.iki.fi/miika/ Komu Expires August 16, 2006 [Page 23] Internet-Draft IPsec APIs February 2006 Full Copyright Statement Copyright (C) The Internet Society (2006). This document is subject to the rights, licenses and restrictions contained in BCP 78, and except as set forth therein, the authors retain all their rights. This document and the information contained herein are provided on an "AS IS" basis and THE CONTRIBUTOR, THE ORGANIZATION HE/SHE REPRESENTS OR IS SPONSORED BY (IF ANY), THE INTERNET SOCIETY AND THE INTERNET ENGINEERING TASK FORCE DISCLAIM ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Intellectual Property The IETF takes no position regarding the validity or scope of any Intellectual Property Rights or other rights that might be claimed to pertain to the implementation or use of the technology described in this document or the extent to which any license under such rights might or might not be available; nor does it represent that it has made any independent effort to identify any such rights. Information on the procedures with respect to rights in RFC documents can be found in BCP 78 and BCP 79. Copies of IPR disclosures made to the IETF Secretariat and any assurances of licenses to be made available, or the result of an attempt made to obtain a general license or permission for the use of such proprietary rights by implementers or users of this specification can be obtained from the IETF on-line IPR repository at http://www.ietf.org/ipr. The IETF invites any interested party to bring to its attention any copyrights, patents or patent applications, or other proprietary rights that may cover technology that may be required to implement this standard. Please address the information to the IETF at ietf-ipr@ietf.org. Acknowledgment Funding for the RFC Editor function is currently provided by the Internet Society. Komu Expires August 16, 2006 [Page 24]