draft-ietf-sasl-gs2-14.txt   draft-ietf-sasl-gs2-15.txt 
Network Working Group S. Josefsson Network Working Group S. Josefsson
Internet-Draft SJD AB Internet-Draft SJD AB
Intended status: Standards Track N. Williams Intended status: Standards Track N. Williams
Expires: December 29, 2009 Sun Microsystems Expires: February 1, 2010 Sun Microsystems
June 27, 2009 July 31, 2009
Using GSS-API Mechanisms in SASL: The GS2 Mechanism Family Using GSS-API Mechanisms in SASL: The GS2 Mechanism Family
draft-ietf-sasl-gs2-14 draft-ietf-sasl-gs2-15
Status of this Memo Status of this Memo
This Internet-Draft is submitted to IETF in full conformance with the This Internet-Draft is submitted to IETF in full conformance with the
provisions of BCP 78 and BCP 79. This document may contain material provisions of BCP 78 and BCP 79. This document may contain material
from IETF Documents or IETF Contributions published or made publicly from IETF Documents or IETF Contributions published or made publicly
available before November 10, 2008. The person(s) controlling the available before November 10, 2008. The person(s) controlling the
copyright in some of this material may not have granted the IETF copyright in some of this material may not have granted the IETF
Trust the right to allow modifications of such material outside the Trust the right to allow modifications of such material outside the
IETF Standards Process. Without obtaining an adequate license from IETF Standards Process. Without obtaining an adequate license from
skipping to change at page 1, line 43 skipping to change at page 1, line 43
and may be updated, replaced, or obsoleted by other documents at any and may be updated, replaced, or obsoleted by other documents at any
time. It is inappropriate to use Internet-Drafts as reference time. It is inappropriate to use Internet-Drafts as reference
material or to cite them other than as "work in progress." material or to cite them other than as "work in progress."
The list of current Internet-Drafts can be accessed at The list of current Internet-Drafts can be accessed at
http://www.ietf.org/ietf/1id-abstracts.txt. http://www.ietf.org/ietf/1id-abstracts.txt.
The list of Internet-Draft Shadow Directories can be accessed at The list of Internet-Draft Shadow Directories can be accessed at
http://www.ietf.org/shadow.html. http://www.ietf.org/shadow.html.
This Internet-Draft will expire on December 29, 2009. This Internet-Draft will expire on February 1, 2010.
Copyright Notice Copyright Notice
Copyright (c) 2009 IETF Trust and the persons identified as the Copyright (c) 2009 IETF Trust and the persons identified as the
document authors. All rights reserved. document authors. All rights reserved.
This document is subject to BCP 78 and the IETF Trust's Legal This document is subject to BCP 78 and the IETF Trust's Legal
Provisions Relating to IETF Documents in effect on the date of Provisions Relating to IETF Documents in effect on the date of
publication of this document (http://trustee.ietf.org/license-info). publication of this document (http://trustee.ietf.org/license-info).
Please review these documents carefully, as they describe your rights Please review these documents carefully, as they describe your rights
skipping to change at page 3, line 14 skipping to change at page 3, line 14
Table of Contents Table of Contents
1. Introduction . . . . . . . . . . . . . . . . . . . . . . . . . 4 1. Introduction . . . . . . . . . . . . . . . . . . . . . . . . . 4
2. Conventions used in this document . . . . . . . . . . . . . . 5 2. Conventions used in this document . . . . . . . . . . . . . . 5
3. Mechanism name . . . . . . . . . . . . . . . . . . . . . . . . 5 3. Mechanism name . . . . . . . . . . . . . . . . . . . . . . . . 5
3.1. Generating SASL mechanism names from GSS-API OIDs . . . . 5 3.1. Generating SASL mechanism names from GSS-API OIDs . . . . 5
3.2. Computing mechanism names manually . . . . . . . . . . . . 6 3.2. Computing mechanism names manually . . . . . . . . . . . . 6
3.3. Examples . . . . . . . . . . . . . . . . . . . . . . . . . 6 3.3. Examples . . . . . . . . . . . . . . . . . . . . . . . . . 6
3.4. Grandfathered mechanism names . . . . . . . . . . . . . . 7 3.4. Grandfathered mechanism names . . . . . . . . . . . . . . 7
3.5. Which mechanism names to advertise and select . . . . . . 7 4. SASL Authentication Exchange Message Format . . . . . . . . . 7
4. SASL Authentication Exchange Message Format . . . . . . . . . 8 5. Channel Bindings . . . . . . . . . . . . . . . . . . . . . . . 9
5. Channel Bindings . . . . . . . . . . . . . . . . . . . . . . . 10
5.1. Content of GSS-CHANNEL-BINDINGS structure . . . . . . . . 10 5.1. Content of GSS-CHANNEL-BINDINGS structure . . . . . . . . 10
5.2. Default Channel Binding . . . . . . . . . . . . . . . . . 10 5.2. Default Channel Binding . . . . . . . . . . . . . . . . . 10
6. Examples . . . . . . . . . . . . . . . . . . . . . . . . . . . 11 6. Examples . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
7. Authentication Conditions . . . . . . . . . . . . . . . . . . 13 7. Authentication Conditions . . . . . . . . . . . . . . . . . . 12
8. GSS-API Parameters . . . . . . . . . . . . . . . . . . . . . . 13 8. GSS-API Parameters . . . . . . . . . . . . . . . . . . . . . . 13
9. Naming . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14 9. Naming . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
10. GSS_Inquire_SASLname_for_mech call . . . . . . . . . . . . . . 14 10. GSS_Inquire_SASLname_for_mech call . . . . . . . . . . . . . . 13
10.1. gss_inquire_saslname_for_mech . . . . . . . . . . . . . . 15 10.1. gss_inquire_saslname_for_mech . . . . . . . . . . . . . . 15
11. GSS_Inquire_mech_for_SASLname call . . . . . . . . . . . . . . 15 11. GSS_Inquire_mech_for_SASLname call . . . . . . . . . . . . . . 15
11.1. gss_inquire_mech_for_saslname . . . . . . . . . . . . . . 17 11.1. gss_inquire_mech_for_saslname . . . . . . . . . . . . . . 17
12. Security Layers . . . . . . . . . . . . . . . . . . . . . . . 17 12. Security Layers . . . . . . . . . . . . . . . . . . . . . . . 17
13. Interoperability with the SASL GSSAPI mechanism . . . . . . . 17 13. Interoperability with the SASL GSSAPI mechanism . . . . . . . 17
13.1. The interoperability problem . . . . . . . . . . . . . . . 17 13.1. The interoperability problem . . . . . . . . . . . . . . . 17
13.2. Resolving the problem . . . . . . . . . . . . . . . . . . 18 13.2. Resolving the problem . . . . . . . . . . . . . . . . . . 18
13.3. Additional Recommendations . . . . . . . . . . . . . . . . 18 13.3. Additional Recommendations . . . . . . . . . . . . . . . . 18
14. GSS-API Mechanisms that negotiate other mechanisms . . . . . . 18 14. GSS-API Mechanisms that negotiate other mechanisms . . . . . . 18
14.1. The interoperability problem . . . . . . . . . . . . . . . 18 14.1. The interoperability problem . . . . . . . . . . . . . . . 18
skipping to change at page 7, line 37 skipping to change at page 7, line 37
mechanism name. mechanism name.
3.4. Grandfathered mechanism names 3.4. Grandfathered mechanism names
Some older GSS-API mechanisms were not specified with a SASL GS2 Some older GSS-API mechanisms were not specified with a SASL GS2
mechanism name. Using a shorter name can be useful nonetheless. We mechanism name. Using a shorter name can be useful nonetheless. We
specify the names "GS2-KRB5" and "GS2-KRB5-PLUS" for the Kerberos V5 specify the names "GS2-KRB5" and "GS2-KRB5-PLUS" for the Kerberos V5
mechanism, to be used as if the original specification documented it. mechanism, to be used as if the original specification documented it.
See Section 15. See Section 15.
3.5. Which mechanism names to advertise and select
Servers SHOULD advertise both non-PLUS and the PLUS-variant of a GS2
mechanism name. If the server cannot support channel binding, it MAY
advertise only the non-PLUS variant. If the server would never
succeed authentication of the non-PLUS variant due to policy reasons,
it MAY advertise only the PLUS-variant.
If the client negotiates mechanisms then clients MUST select the
PLUS-variant if offered by the server. Otherwise, if the client does
not negotiate mechanisms then it MUST use the non-PLUS variant.
4. SASL Authentication Exchange Message Format 4. SASL Authentication Exchange Message Format
During the SASL authentication exchange for GS2, a number of messages During the SASL authentication exchange for GS2, a number of messages
following the following format is sent between the client and server. following the following format is sent between the client and server.
On success, this number is the same as the number of context tokens On success, this number is the same as the number of context tokens
that the GSS-API mechanism would normally require in order to that the GSS-API mechanism would normally require in order to
establish a security context. On failures, the exchange can be establish a security context. On failures, the exchange can be
terminated early by any party. terminated early by any party.
When using a GS2 mechanism the SASL client is always a GSS-API When using a GS2 mechanism the SASL client is always a GSS-API
skipping to change at page 10, line 4 skipping to change at page 9, line 22
means the client supports channel binding, but believes the server means the client supports channel binding, but believes the server
does not support it, so it did not use a channel binding. See the does not support it, so it did not use a channel binding. See the
next section for more details. next section for more details.
The "gs2-authzid" holds the SASL authorization identity. It is The "gs2-authzid" holds the SASL authorization identity. It is
encoded using UTF-8 [RFC3629] with three exceptions: encoded using UTF-8 [RFC3629] with three exceptions:
o The NUL characters is forbidden as required by section 3.4.1 of o The NUL characters is forbidden as required by section 3.4.1 of
[RFC4422]. [RFC4422].
o The server MUST replace any "," (comma) in the string with "=2C". o The server MUST replace any "," (comma) in the string with "=2C".
o The server MUST replace any "=" (equals) in the string with "=3D". o The server MUST replace any "=" (equals) in the string with "=3D".
Upon the receipt of this value the server verifies its correctness
according to the used SASL protocol profile. Failed verification
results in failed authentication exchange.
5. Channel Bindings 5. Channel Bindings
If the client does not support channel binding then it MUST use a "n" GS2 supports channel binding to external secure channels, such as
gs2-cb-flag. TLS. Clients and servers may or may not support channel binding,
therefore the use of channel binding is negotiable. GS2 does not
If the client supports channel binding and the server does not appear provide security layers, however, therefore it is imperative that GS2
to (i.e., the client did not see a -PLUS name) then the client MUST provide integrity protection for the negotiation of channel binding.
either fail authentication or it MUST chose the non-PLUS mechanism
name and use a "y" gs2-cb-flag.
If the client supports channel binding and the server appears to
support it (i.e., the client see a -PLUS name) then the client MUST
use a "p" gs2-cb-flag to indicate the channel binding type it is
using.
The client generate the chan_bindings input parameter for Use of channel binding is negotiated as follows:
o Servers SHOULD advertise both non-PLUS and the PLUS-variant of
each GS2 mechanism name. If the server cannot support channel
binding, it MAY advertise only the non-PLUS variant. If the
server would never succeed authentication of the non-PLUS variant
due to policy reasons, it MAY advertise only the PLUS-variant.
o If the client negotiates mechanisms then clients MUST select the
PLUS-variant if offered by the server. Otherwise (the client does
not negotiate mechanisms), if the client has no prior knowledge
about mechanisms supported by the server and wasn't explicitly
configured to use a particular variant of the GS2 mechanism, then
it MUST select only non-PLUS version of the GS2 mechanism.
o If the client does not support channel binding then it MUST use a
"n" gs2-cb-flag.
o If the client supports channel binding and the server does not
appear to (i.e., the client did not see the -PLUS name) then the
client MUST either fail authentication or it MUST chose the non-
PLUS mechanism name and use a "y" gs2-cb-flag.
o If the client supports channel binding and the server appears to
support it (i.e., the client see the -PLUS name), or if the client
wishes to use channel binding but the client does not negotiate
mechanisms, then the client MUST use a "p" gs2-cb-flag to indicate
the channel binding type it is using.
o The client generate the chan_bindings input parameter for
GSS_Init_sec_context as described below. GSS_Init_sec_context as described below.
o Upon receipt of the initial authentication message the server
Upon receipt of the initial authentication message the server checks checks the gs2-cb-flag in the GS2 header and constructs a
the gs2-cb-flag in the GS2 header and constructs a chan_bindings chan_bindings parameter for GSS_Accept_sec_context as described
parameter for GSS_Accept_sec_context as described below. If the below. If the client channel binding flag was "y" and the server
client channel binding flag was "y" and the server did advertise did advertise support for channel bindings then the server MUST
support for channel bindings then the server MUST fail fail authentication. If the client channel binding flag was "p"
authentication. If the client channel binding flag was "p" and the and the server does not support the indicated channel binding type
server does not support the indicated channel binding type then the then the server MUST fail authentication.
server MUST fail authentication.
For more discussions of channel bindings, and the syntax of the For more discussions of channel bindings, and the syntax of the
channel binding data for various security protocols, see [RFC5056]. channel binding data for various security protocols, see [RFC5056].
5.1. Content of GSS-CHANNEL-BINDINGS structure 5.1. Content of GSS-CHANNEL-BINDINGS structure
The calls to GSS_Init_sec_context and GSS_Accept_sec_context takes a The calls to GSS_Init_sec_context and GSS_Accept_sec_context takes a
chan_bindings parameter. The value is a GSS-CHANNEL-BINDINGS chan_bindings parameter. The value is a GSS-CHANNEL-BINDINGS
structure [RFC5554]. structure [RFC5554].
The initiator-address-type and acceptor-address-type fields of the The initiator-address-type and acceptor-address-type fields of the
GSS-CHANNEL-BINDINGS structure MUST be set to 0. The initiator- GSS-CHANNEL-BINDINGS structure MUST be set to 0. The initiator-
address and acceptor-address fields MUST be the empty string. address and acceptor-address fields MUST be the empty string.
The application-data field MUST be set to the gs2-header concatenated The application-data field MUST be set to the gs2-header concatenated
with, when a gs2-cb-flag of "p" is used, the application's channel with, when a gs2-cb-flag of "p" is used, the application's channel
binding data (if any). binding data.
5.2. Default Channel Binding 5.2. Default Channel Binding
A default channel binding type agreement process for all SASL A default channel binding type agreement process for all SASL
application protocols that do not provide their own channel binding application protocols that do not provide their own channel binding
type agreement is provided as follows. type agreement is provided as follows.
Clients and servers MUST implement the "tls-unique" [tls-unique] Clients and servers MUST implement the "tls-unique" [tls-unique]
channel binding type. Clients and servers SHOULD choose the highest- [I-D.altman-tls-channel-bindings] channel binding type. Clients and
layer/innermost end-to-end TLS channel as the channel to bind to. servers SHOULD choose the highest-layer/innermost end-to-end TLS
channel as the channel to bind to.
Clients SHOULD choose the tls-unique channel binding type. Clients SHOULD choose the tls-unique channel binding type.
Conversely, clients MAY choose a different channel binding type based Conversely, clients MAY choose a different channel binding type based
on user input, configuration, or a future, as-yet undefined channel on user input, configuration, or a future, as-yet undefined channel
binding type negotiation protocol. Servers MUST choose the channel binding type negotiation protocol. Servers MUST choose the channel
binding type indicated by the client, if they support it. binding type indicated by the client, if they support it.
6. Examples 6. Examples
Example #1: a one round-trip GSS-API context token exchange, no Example #1: a one round-trip GSS-API context token exchange, no
skipping to change at page 11, line 34 skipping to change at page 11, line 25
header removed> header removed>
S: Send reply context token as is S: Send reply context token as is
C: Empty message C: Empty message
S: Outcome of authentication exchange S: Outcome of authentication exchange
Example #2: a one and one half round-trip GSS-API context token Example #2: a one and one half round-trip GSS-API context token
exchange, no channel binding. exchange, no channel binding.
C: Request authentication exchange C: Request authentication exchange
S: Empty Challenge S: Empty Challenge
C: n,<initial context token with standard C: n,,<initial context token with standard
header removed> header removed>
S: Send reply context token as is S: Send reply context token as is
C: Send reply context token as is C: Send reply context token as is
S: Outcome of authentication exchange S: Outcome of authentication exchange
Example #3: a two round-trip GSS-API context token exchange, no Example #3: a two round-trip GSS-API context token exchange, no
channel binding, no standard token header. channel binding, no standard token header.
C: Request authentication exchange C: Request authentication exchange
S: Empty Challenge S: Empty Challenge
C: F,n,<initial context token without C: F,n,,<initial context token without
standard header> standard header>
S: Send reply context token as is S: Send reply context token as is
C: Send reply context token as is C: Send reply context token as is
S: Send reply context token as is S: Send reply context token as is
C: Empty message C: Empty message
S: Outcome of authentication exchange S: Outcome of authentication exchange
Example #4: using channel binding, optional authzid given. Example #4: using channel binding, optional authzid given.
C: Request authentication exchange C: Request authentication exchange
S: Empty Challenge S: Empty Challenge
C: p=tls-unique,a=someuser,<initial context token with standard C: p=tls-unique,a=someuser,<initial context token with standard
header removed> header removed>
S: Send reply context token as is S: Send reply context token as is
... ...
Example #5: using channel binding. Example #5: using channel binding.
skipping to change at page 12, line 30 skipping to change at page 12, line 17
S: Empty Challenge S: Empty Challenge
C: p=tls-unique,a=someuser,<initial context token with standard C: p=tls-unique,a=someuser,<initial context token with standard
header removed> header removed>
S: Send reply context token as is S: Send reply context token as is
... ...
Example #5: using channel binding. Example #5: using channel binding.
C: Request authentication exchange C: Request authentication exchange
S: Empty Challenge S: Empty Challenge
C: p=tls-unique,<initial context token with standard C: p=tls-unique,,<initial context token with standard
header removed> header removed>
S: Send reply context token as is S: Send reply context token as is
... ...
Example #6: using non-standard channel binding (requires out-of-band Example #6: using non-standard channel binding (requires out-of-band
negotiation). negotiation).
C: Request authentication exchange C: Request authentication exchange
S: Empty Challenge S: Empty Challenge
C: p=tls-server-end-point,<initial context token with standard C: p=tls-server-end-point,,<initial context token with standard
header removed> header removed>
S: Send reply context token as is S: Send reply context token as is
... ...
Example #7: client supports channel bindings but server does not, Example #7: client supports channel bindings but server does not,
optional authzid given. optional authzid given.
C: Request authentication exchange C: Request authentication exchange
S: Empty Challenge S: Empty Challenge
C: y,a=someuser,<initial C: y,a=someuser,<initial
skipping to change at page 14, line 11 skipping to change at page 13, line 34
GS2 does not use any GSS-API per-message tokens. Therefore the GS2 does not use any GSS-API per-message tokens. Therefore the
setting of req_flags related to per-message tokens is irrelevant. setting of req_flags related to per-message tokens is irrelevant.
9. Naming 9. Naming
There's no requirement that any particular GSS-API name-types be There's no requirement that any particular GSS-API name-types be
used. However, typically SASL servers will have host-based acceptor used. However, typically SASL servers will have host-based acceptor
principal names (see [RFC2743] section 4.1) and clients will principal names (see [RFC2743] section 4.1) and clients will
typically have username initiator principal names (see [RFC2743] typically have username initiator principal names (see [RFC2743]
section 4.2). section 4.2). When a host-based acceptor principal name is used
("service@hostname"), "service" is the service name specified in the
protocol's profile, and "hostname" is the fully qualified host name
of the server.
10. GSS_Inquire_SASLname_for_mech call 10. GSS_Inquire_SASLname_for_mech call
To allow SASL implementations to query for the SASL mechanism name of To allow SASL implementations to query for the SASL mechanism name of
a GSS-API mechanism, we specify a new GSS-API function for this a GSS-API mechanism, we specify a new GSS-API function for this
purpose. purpose.
Inputs: Inputs:
o desired_mech OBJECT IDENTIFIER o desired_mech OBJECT IDENTIFIER
Outputs: Outputs:
o sasl_mech_name UTF-8 STRING -- SASL name for this mechanism o sasl_mech_name UTF-8 STRING -- SASL name for this
mechanism; caller must release with
GSS_Release_buffer()
o mech_name UTF-8 STRING -- name of this mechanism, possibly o mech_name UTF-8 STRING -- name of this mechanism, possibly
localized localized; caller must release with GSS_Release_buffer()
o mech_description UTF-8 STRING -- possibly localized o mech_description UTF-8 STRING -- possibly localized
description of this mechanism. description of this mechanism; caller must release with
GSS_Release_buffer()
Return major_status codes: Return major_status codes:
o GSS_S_COMPLETE indicates successful completion, and that output o GSS_S_COMPLETE indicates successful completion, and that
parameters holds correct information. output parameters holds correct information.
o GSS_S_BAD_MECH indicates that a desired_mech was unsupported by o GSS_S_BAD_MECH indicates that a desired_mech was unsupported
the GSS-API implementation. by the GSS-API implementation.
The GSS_Inquire_SASLname_for_mech call is used to get the SASL The GSS_Inquire_SASLname_for_mech call is used to get the SASL
mechanism name for a GSS-API mechanism. It also returns a name mechanism name for a GSS-API mechanism. It also returns a name
and description of the mechanism in a human readable form. and description of the mechanism in a human readable form.
The output variable sasl_mech_name will hold the IANA registered The output variable sasl_mech_name will hold the IANA registered
mechanism name for the GSS-API mechanism, or if none is mechanism name for the GSS-API mechanism, or if none is
registered, a mechanism named computed from the OID as registered, a mechanism name computed from the OID as described
described in section 3.1 of this document. in section 3.1 of this document.
10.1. gss_inquire_saslname_for_mech 10.1. gss_inquire_saslname_for_mech
The C binding for the GSS_Inquire_SASLname_for_mech call is as The C binding for the GSS_Inquire_SASLname_for_mech call is as
follows. follows.
OM_uint32 gss_inquire_saslname_for_mech( OM_uint32 gss_inquire_saslname_for_mech(
OM_uint32 *minor_status, OM_uint32 *minor_status,
const gss_OID desired_mech, const gss_OID desired_mech,
gss_buffer_t sasl_mech_name, gss_buffer_t sasl_mech_name,
skipping to change at page 23, line 18 skipping to change at page 23, line 18
[RFC4752] Melnikov, A., "The Kerberos V5 ("GSSAPI") Simple [RFC4752] Melnikov, A., "The Kerberos V5 ("GSSAPI") Simple
Authentication and Security Layer (SASL) Mechanism", Authentication and Security Layer (SASL) Mechanism",
RFC 4752, November 2006. RFC 4752, November 2006.
[RFC5246] Dierks, T. and E. Rescorla, "The Transport Layer Security [RFC5246] Dierks, T. and E. Rescorla, "The Transport Layer Security
(TLS) Protocol Version 1.2", RFC 5246, August 2008. (TLS) Protocol Version 1.2", RFC 5246, August 2008.
[I-D.ietf-sasl-scram] [I-D.ietf-sasl-scram]
Menon-Sen, A., Melnikov, A., Newman, C., and N. Williams, Menon-Sen, A., Melnikov, A., Newman, C., and N. Williams,
"Salted Challenge Response (SCRAM) SASL Mechanism", "Salted Challenge Response (SCRAM) SASL Mechanism",
draft-ietf-sasl-scram-01 (work in progress), May 2009. draft-ietf-sasl-scram-02 (work in progress), July 2009.
[I-D.altman-tls-channel-bindings]
Altman, J., Williams, N., and L. Zhu, "Channel Bindings
for TLS", draft-altman-tls-channel-bindings-05 (work in
progress), June 2009.
[I-D.ietf-kitten-extended-mech-inquiry] [I-D.ietf-kitten-extended-mech-inquiry]
Williams, N., "Extended Generic Security Service Mechanism Williams, N., "Extended Generic Security Service Mechanism
Inquiry APIs", draft-ietf-kitten-extended-mech-inquiry-06 Inquiry APIs", draft-ietf-kitten-extended-mech-inquiry-06
(work in progress), April 2009. (work in progress), April 2009.
[mitm] Asokan, N., Niemi, V., and K. Nyberg, "Man-in-the-Middle [mitm] Asokan, N., Niemi, V., and K. Nyberg, "Man-in-the-Middle
in Tunneled Authentication", in Tunneled Authentication",
WWW http://www.saunalahti.fi/~asokan/research/mitm.html. WWW http://www.saunalahti.fi/~asokan/research/mitm.html.
 End of changes. 27 change blocks. 
63 lines changed or deleted 80 lines changed or added

This html diff was produced by rfcdiff 1.29, available from http://www.levkowetz.com/ietf/tools/rfcdiff/