idnits 2.17.1 draft-sayre-http-hmac-digest-01.txt: Checking boilerplate required by RFC 5378 and the IETF Trust (see https://trustee.ietf.org/license-info): ---------------------------------------------------------------------------- ** It looks like you're using RFC 3978 boilerplate. You should update this to the boilerplate described in the IETF Trust License Policy document (see https://trustee.ietf.org/license-info), which is required now. -- Found old boilerplate from RFC 3978, Section 5.1 on line 19. -- Found old boilerplate from RFC 3978, Section 5.5 on line 606. -- Found old boilerplate from RFC 3979, Section 5, paragraph 1 on line 583. -- Found old boilerplate from RFC 3979, Section 5, paragraph 2 on line 590. -- Found old boilerplate from RFC 3979, Section 5, paragraph 3 on line 596. ** This document has an original RFC 3978 Section 5.4 Copyright Line, instead of the newer IETF Trust Copyright according to RFC 4748. ** This document has an original RFC 3978 Section 5.5 Disclaimer, instead of the newer disclaimer which includes the IETF Trust according to RFC 4748. Checking nits according to https://www.ietf.org/id-info/1id-guidelines.txt: ---------------------------------------------------------------------------- == No 'Intended status' indicated for this document; assuming Proposed Standard Checking nits according to https://www.ietf.org/id-info/checklist : ---------------------------------------------------------------------------- ** The abstract seems to contain references ([1]), which it shouldn't. Please replace those with straight textual mentions of the documents in question. Miscellaneous warnings: ---------------------------------------------------------------------------- The document has an RFC 3978 Section 5.2(a) Derivative Works Limitation clause. == The copyright year in the RFC 3978 Section 5.4 Copyright Line does not match the current year -- The document seems to lack a disclaimer for pre-RFC5378 work, but may have content which was first submitted before 10 November 2008. If you have contacted all the original authors and they are all willing to grant the BCP78 rights to the IETF Trust, then this is fine, and you can ignore this comment. If not, you may need to add the pre-RFC5378 disclaimer. (See the Legal Provisions document at https://trustee.ietf.org/license-info for more information.) -- The document date (April 6, 2006) is 6594 days in the past. Is this intentional? -- Found something which looks like a code comment -- if you have code sections in the document, please surround them with '' and '' lines. Checking references for intended status: Proposed Standard ---------------------------------------------------------------------------- (See RFCs 3967 and 4897 for information about using normative references to lower-maturity documents in RFCs) ** Downref: Normative reference to an Informational RFC: RFC 2104 ** Obsolete normative reference: RFC 2616 (Obsoleted by RFC 7230, RFC 7231, RFC 7232, RFC 7233, RFC 7234, RFC 7235) ** Obsolete normative reference: RFC 2617 (Obsoleted by RFC 7235, RFC 7615, RFC 7616, RFC 7617) -- Possible downref: Non-RFC (?) normative reference: ref. '1' -- Possible downref: Non-RFC (?) normative reference: ref. '2' Summary: 7 errors (**), 0 flaws (~~), 2 warnings (==), 10 comments (--). Run idnits with the --verbose option for more detailed information about the items above. -------------------------------------------------------------------------------- 2 Network Working Group R. Sayre 3 Internet-Draft 4 Expires: October 8, 2006 A. Melnikov 5 Isode Ltd. 6 April 6, 2006 8 HMAC Digest Access Authentication for HTTP 9 draft-sayre-http-hmac-digest-01.txt 11 Status of this Memo 13 By submitting this Internet-Draft, each author represents that any 14 applicable patent or other IPR claims of which he or she is aware 15 have been or will be disclosed, and any of which he or she becomes 16 aware will be disclosed, in accordance with Section 6 of BCP 79. 17 This document may not be modified, and derivative works of it may not 18 be created, except to publish it as an RFC and to translate it into 19 languages other than English. 21 Internet-Drafts are working documents of the Internet Engineering 22 Task Force (IETF), its areas, and its working groups. Note that 23 other groups may also distribute working documents as Internet- 24 Drafts. 26 Internet-Drafts are draft documents valid for a maximum of six months 27 and may be updated, replaced, or obsoleted by other documents at any 28 time. It is inappropriate to use Internet-Drafts as reference 29 material or to cite them other than as "work in progress." 31 The list of current Internet-Drafts can be accessed at 32 http://www.ietf.org/ietf/1id-abstracts.txt. 34 The list of Internet-Draft Shadow Directories can be accessed at 35 http://www.ietf.org/shadow.html. 37 This Internet-Draft will expire on October 8, 2006. 39 Copyright Notice 41 Copyright (C) The Internet Society (2006). 43 Abstract 45 This document specifies an HTTP authentication scheme based on 46 cryptographic hashes. 48 Editor's Note 49 To discuss this draft, please join the ietf-http-auth mailing 50 list [1]. Membership is open to all. 52 Table of Contents 54 1. Introduction . . . . . . . . . . . . . . . . . . . . . . . . . 3 55 2. WWW-Authenticate . . . . . . . . . . . . . . . . . . . . . . . 3 56 3. Authorization . . . . . . . . . . . . . . . . . . . . . . . . 5 57 4. The Request Digest . . . . . . . . . . . . . . . . . . . . . . 6 58 5. Header Handling . . . . . . . . . . . . . . . . . . . . . . . 7 59 6. Acknowledgements . . . . . . . . . . . . . . . . . . . . . . . 8 60 7. IANA Considerations . . . . . . . . . . . . . . . . . . . . . 8 61 8. Security Considerations . . . . . . . . . . . . . . . . . . . 8 62 9. Normative References . . . . . . . . . . . . . . . . . . . . . 8 63 Appendix A. Example Implementations . . . . . . . . . . . . . . . 9 64 A.1. Example Server . . . . . . . . . . . . . . . . . . . . . . 9 65 A.2. Example Client . . . . . . . . . . . . . . . . . . . . . . 11 66 Appendix B. Change Log . . . . . . . . . . . . . . . . . . . . . 13 67 Authors' Addresses . . . . . . . . . . . . . . . . . . . . . . . . 14 68 Intellectual Property and Copyright Statements . . . . . . . . . . 15 70 1. Introduction 72 This document specifies an HTTP authentication scheme similar to the 73 Digest scheme [RFC2617]. It borrows heavily from that scheme's 74 specifcation, but there are substantive differences. Most 75 importantly, the algorithm is based on a hash of the user password, 76 rather than the password itself. In addition, the scheme defined in 77 this document allows for additional message integrity checks on HTTP 78 request headers. It omits quality-of-protection options and 79 Authentication-Info headers from the server. Like Digest 80 authentication, the scheme specified in this document suffers from 81 many known weaknesses, and is only intended to improve on Basic 82 authentication [RFC2617]. 84 This specification is a companion to the HTTP/1.1 specification 85 [RFC2616]. It uses the augmented BNF section 2.1 of that document, 86 and relies on both the non-terminals defined in that document and 87 other aspects of the HTTP/1.1 specification. 89 The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", 90 "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this 91 document are to be interpreted as described in RFC 2119 [RFC2119]. 93 2. WWW-Authenticate 95 When a server a recieves a request for an access-protected object 96 without an acceptable Authorization header, it responds with a "401 97 Unauthorized" status code, and a WWW-Authenticate header [RFC2617]. 98 For the HMAC Digest scheme, the value of the header is as follows: 100 challenge = "HMACDigest" digest-challenge 101 digest-challenge = 1#( realm | snonce | [domain] | [reason] | 102 [algorithm] | [pw-algorithm] | 103 [salt] | [auth-param] ) 104 realm = "realm" "=" quoted-string 105 snonce = "snonce" "=" quoted-string 106 domain = "domain" "=" <"> URI *( 1*SP URI ) <"> 107 URI = absoluteURI | abs_path 108 reason = "reason" "=" ("unauthorized" | "integrity" | 109 token) 110 algorithm = "algorithm" "=" ( "HMAC-SHA-1" | "HMAC-MD5" | 111 token ) 112 pw-algorithm = "pw-algorithm" "=" ( "SHA-1" | "MD5" | 113 token ) 114 salt = "salt" "=" quoted-string 116 realm: A string to be displayed to users so they know which username 117 and password to use. This string should contain at least the name 118 of the host performing the authentication and might additionally 119 indicate the collection of users who might have access. An 120 example might be "registered_users@gotham.news.com". 122 snonce: A server-specified data string which should be uniquely 123 generated each time a 401 response is made. It is recommended 124 that this string be base64 or hexadecimal data. Specifically, 125 since the string is passed in the header lines as a quoted string, 126 the double-quote character is not allowed. 128 The contents of the snonce are implementation dependent and opaque 129 to the client. The quality of the implementation depends on a 130 good choice. An snonce might, for example, be constructed as the 131 base64 encoding of 133 time-stamp hash(time-stamp ":" ETag ":" private-key) 135 where time-stamp is a server-generated time or other non-repeating 136 value, ETag is the value of the HTTP ETag header associated with 137 the requested entity, and private-key is data known only to the 138 server. With an snonce of this form, a server would recalculate 139 the hash portion after receiving the client authentication header 140 and reject the request if it did not match the snonce from that 141 header or if the time-stamp value is not recent enough. In this 142 way, the server can limit the time of the snonce's validity.[@ 143 Eliminate replay text?] The inclusion of the ETag prevents a 144 replay request for an updated version of the resource. (Note: 145 including the IP address of the client in the snonce would appear 146 to offer the server the ability to limit the reuse of the snonce 147 to the same client that originally got it. However, that would 148 break proxy farms, where requests from a single user often go 149 through different proxies in the farm. Also, IP address spoofing 150 is not that hard.) 152 domain: A quoted, space-separated list of URI references [RFC3986] 153 that define the protection space. If a URI is an abs_path, it is 154 relative to the canonical root URL [RFC2617] of the server being 155 accessed. An absoluteURI in this list may refer to a different 156 server than the one being accessed. The client can use this list 157 to determine the set of URIs for which the same authentication 158 information may be sent: any URI that has a URI in this list as a 159 prefix (after both have been made absolute) may be assumed to be 160 in the same protection space. If this directive is omitted or its 161 value is empty, the client should assume that the protection space 162 consists of all URIs on the responding server. 164 reason: The value of this directive indicates the reason for the 165 rejection of the previous client request. "unauthorized" indicates 166 that the request did not contain a valid digest. "stale" indicates 167 that the previous request from the client was rejected because the 168 snonce value was stale. The client may wish to simply retry the 169 request with a new encrypted response, without reprompting the 170 user for a new username and password. "integrity" indicates that 171 the request contained unverified content that the server requires 172 be included in the calculation of the digest. If the directive is 173 not present, or a value other than "integrity" or "stale", the 174 client should behave as though its value were "unauthorized". 176 algorithm: This directive indicates the HMAC construction to be used 177 [RFC2104]. If not present, it is assumed to be "HMAC-SHA-1". 179 pw-algorithm: This directive indicates the algorithm to be used when 180 preparing an HMAC key. If not present, it is assumed to be 181 "SHA-1". 183 salt: If present, this directive indicates a value that is appended 184 to the password before the initial hash function is applied. 186 3. Authorization 188 The Authorization request header contains client credentials 189 generated according to the directives recieved in a WWW-Authenticate 190 response header. 192 credentials = "HMACDigest" digest-response 193 digest-response = 1#( username | realm | cnonce | snonce | 194 digest-uri | created | response | [headers] | 195 [auth-param] ) 196 username = "username" "=" quoted-string 197 cnonce = "cnonce" "=" quoted-string 198 digest-uri = "uri" "=" request-uri 199 response = "response" "=" request-digest 200 request-digest = <"> *LHEX <"> 201 LHEX = "0" | "1" | "2" | "3" | 202 "4" | "5" | "6" | "7" | 203 "8" | "9" | "a" | "b" | 204 "c" | "d" | "e" | "f" 205 headers = "headers" "=" header-list 206 header-list = <"> field-name *( 1*SP field-name ) <"> 208 username: The user's name in the specified realm. 210 cnonce: The cnonce value is an opaque quoted string value provided by 211 the client and used by both client and server to avoid chosen 212 plaintext attacks, to provide mutual authentication, and to 213 provide some message integrity protection. 215 digest-uri: The URI from Request-URI of the Request-Line; duplicated 216 here because proxies are allowed to change the Request-Line in 217 transit. 219 response: The response value is a string containing hexadecimal data. 220 The two HMAC constructions listed by this specification will 221 produce strings of 32 or 40 characters in length. 223 created: The created value is an RFC3339 timestamp [RFC3339]. 225 headers: The headers value is a space-separated list of HTTP headers 226 used to calculate the request-digest. 228 4. The Request Digest 230 This section describes the process a client uses to calculate the 231 request digest, and how the server can verify it. 233 1. The client applies the algorithm specified by the pw-algorithm 234 directive to the user password. If present, the value of the 235 salt directive is appended to the password prior to calculation. 237 2. The client applies the algorithm specified by the pw-algorithm 238 directive to the concatenation of the username, a colon, the 239 lowercased hexadecimal digest of the result of step 1, a colon, 240 and the value of the realm directive. The lowercased hexadecimal 241 digest of the result serves as the HMAC key. 243 3. The client generates a cnonce, a data string which should be 244 uniquely generated each time a request is made. It is 245 recommended that this string be base64 or hexadecimal data. 246 Specifically, since the string is passed in the header lines as a 247 quoted string, the double-quote character is not allowed. A 248 combination of a timestamp and a random number is sufficient for 249 many purposes. 251 4. The client forms a list of request headers it wishes to include 252 in the digest calculation. The most useful headers to include 253 are entity headers such as Content-Type, Content-Length, and 254 Content-MD5 (see Section 5). 256 5. The client generates a timestamp using the current time. 258 6. The client concatenates the request method, a colon, the request 259 URI, a colon, the cnonce, a colon, the snonce, a colon, and the 260 value of each applicable header in the header list (see 261 Section 5). This value is the message data. 263 7. The client applies the HMAC construction specified by the 264 algorithm directive to the key and the message data. The 265 lowercased hexadecimal digest of this calculation is the value of 266 the response directive. 268 8. The client then uses the relevant values to compose an 269 Authorization header, and sends the request. 271 When the server receives a request containing an Authorization header 272 using the HMAC Digest scheme, it can validate it value using the 273 procedure listed below. 275 1. The server should already have the hash of the user's password 276 available, using the algorithm it instructed the client to use in 277 the WWW-Authenticate header. 279 2. The server uses the realm and username directives supplied in the 280 Authorization header to check for a candidate key. 282 3. The server concatenates the request method, a colon, the value of 283 the uri directive, a colon, the value of the nonce directive, a 284 colon, the value of the created directive, a colon, and the value 285 of each header in the headers directive (see Section 5). This 286 value is the message data. 288 4. The server uses the key to calculate the HMAC for the message 289 data. If the hexadecimal digest of this calculation matches the 290 value provided in the response directive, the request is valid. 292 5. Header Handling 294 When selecting headers for inclusion in the Digest calculation, 295 clients SHOULD NOT include hop-by-hop headers. HTTP 1.1 [RFC2616] 296 defines eight hop-by-hop headers: Connection, Keep-Alive, Proxy- 297 Authenticate, Proxy-Authorization, TE, Trailers, Transfer-Encoding, 298 and Upgrade. HTTP 1.1 also requires that extension hop-by-hop 299 headers are listed in the Connection header. 301 When creating or verifying a digest, leading whitespace in the header 302 values MUST be stripped and header unfolding MUST NOT be done. If a 303 header in the header list appears multiple times, those values are be 304 combined in order. For example, if a client specifies headers="A B", 305 and the request contains A,B,A headers (in that order), both sides 306 MUST calculate the digest using header values in the order A,A,B. 308 6. Acknowledgements 310 This document is largely based on the Digest section of "HTTP 311 Authentication: Basic and Digest Access Authentication" [RFC2617], 312 and includes some sections of that document verbatim. 314 The technique of including header values in the digest calculation 315 was originally proposed by James Undery for the SIP protocol. 317 7. IANA Considerations 319 This memo includes no request to IANA. 321 8. Security Considerations 323 [TBD... depends on how much needs to be repeated from RFC2617.] 325 9. Normative References 327 [RFC2104] Krawczyk, H., Bellare, M., and R. Canetti, "HMAC: Keyed- 328 Hashing for Message Authentication", RFC 2104, 329 February 1997. 331 [RFC2119] Bradner, S., "Key words for use in RFCs to Indicate 332 Requirement Levels", BCP 14, RFC 2119, March 1997. 334 [RFC2616] Fielding, R., Gettys, J., Mogul, J., Frystyk, H., 335 Masinter, L., Leach, P., and T. Berners-Lee, "Hypertext 336 Transfer Protocol -- HTTP/1.1", RFC 2616, June 1999. 338 [RFC2617] Franks, J., Hallam-Baker, P., Hostetler, J., Lawrence, S., 339 Leach, P., Luotonen, A., and L. Stewart, "HTTP 340 Authentication: Basic and Digest Access Authentication", 341 RFC 2617, June 1999. 343 [RFC3339] Klyne, G. and C. Newman, "Date and Time on the Internet: 344 Timestamps", RFC 3339, July 2002. 346 [RFC3986] Berners-Lee, T., Fielding, R., and L. Masinter, "Uniform 347 Resource Identifier (URI): Generic Syntax", STD 66, 348 RFC 3986, January 2005. 350 [1] 353 [2] 355 Appendix A. Example Implementations 357 This section provides example implementations in the Python [2] 358 programming language, version 2.4. 360 A.1. Example Server 362 The example server program responds to all request URIs with the same 363 response, and knows of only one user. If the server program is saved 364 in the file "hmac-digest-server.py", it can be started by typing 365 "python hmac-digest-server.py". 367 import BaseHTTPServer, cgi, urllib2 368 import time 369 import hmac, sha, md5, base64 371 PORT = 8888 372 user = "user" 373 password = "password" 374 salt = 'xyzzy' 375 realm = "HMACDigest Sample" 376 algo = "HMAC-SHA-1" 377 pw_algo = "MD5" 378 key_str = "%s:%s:%s" % (user, 379 md5.new(password+salt).hexdigest(), 380 realm) 381 key = md5.new(key_str).hexdigest() 383 secret_key = "moo" 384 digest_header = 'HMACDigest realm="%s", ' 385 digest_header += 'snonce="%s", ' 386 digest_header += 'reason="%s", ' 387 digest_header += 'domain="/ http://www.example.com/", ' 388 digest_header += 'algorithm="%s", ' 389 digest_header += 'pw-algorithm="%s", ' 390 digest_header += 'salt="%s"' 392 class HMACDigestHandler(BaseHTTPServer.BaseHTTPRequestHandler): 393 def do_GET(self): 395 auth = self.headers.getheader('authorization') 396 result = self.check(auth) 397 if result is False: 398 self.send_401() 399 elif result == 'stale': 400 self.send_401(reason='stale') 401 else: 402 self.send_response(200) 403 self.send_header('Content-type','text/plain') 404 self.end_headers() 405 self.wfile.write("\nAuthentication Successful!\n") 407 def check(self, auth): 408 if auth is None: 409 return False 410 token, fields = auth.split(' ', 1) 411 if token != 'HMACDigest': 412 return False 413 cred = urllib2.parse_http_list(fields) 414 cred = urllib2.parse_keqv_list(cred) 415 if cred['username'] != user or cred['realm'] != realm: 416 return False 417 snonce = cred['snonce'] 418 nonce_time,s_hash = base64.b64decode(snonce).split() 419 test_hash = md5.new(nonce_time + 420 ":fake_etag:" + secret_key).hexdigest() 421 if s_hash != test_hash: 422 return False 423 now = time.mktime(time.gmtime()) 424 # allow 10 minute old nonces... this is arbitrary 425 if now - float(nonce_time) > 600: 426 return "stale" 427 names = cred.get('headers','').split() 428 vals = ''.join([self.headers.getheader(h) for h in names]) 429 msg = "%s:%s:%s:%s:%s" % (self.command, self.path, 430 cred['cnonce'], snonce, 431 vals) 432 the_hmac = hmac.new(key, msg, sha).hexdigest() 433 if cred['response'] == the_hmac: 434 return True 435 else: 436 return False 438 def send_401(self, reason="unauthorized"): 439 auth_header = digest_header % (realm, self.snonce(), 440 reason, algo, pw_algo, salt) 441 self.send_response(401) 442 self.send_header('WWW-Authenticate', auth_header) 443 self.send_header('Content-type', 'text/plain') 444 self.end_headers() 445 self.wfile.write('\nUnauthorized\n') 447 def snonce(self): 448 now = str(time.mktime(time.gmtime())) 449 print now 450 h = md5.new(now+":fake_etag:"+secret_key).hexdigest() 451 return base64.b64encode(now + " " + h) 453 httpd = BaseHTTPServer.HTTPServer(("", PORT), HMACDigestHandler) 454 print "Serving at port", PORT 455 httpd.serve_forever() 457 A.2. Example Client 459 The example client program makes one request to the example server 460 without an authorization header, examines the WWW-Authenticate header 461 returned in the 401 response, and then creates an Authorization 462 header to make a second (successful) request. 464 import httplib, urllib2, md5, sha, hmac, time, random, os 466 PORT = 8888 467 username = "user" 468 password = "password" 469 params = {} 470 headers = {"accept": "text/X-Oh-Several-Things+xml, */*", 471 "user-agent": "libwww-perl/5.803", 472 "x-hopbyhop": "some proxy information", 473 "x-fooproxy": "some more proxy info", 474 "x-freedom-is-what-you-think-it-is": 475 "But there ain't no train to Stockholm", 476 "connection": "close, x-hopbyhop, x-fooproxy"} 478 # Make an initial request 479 conn = httplib.HTTPConnection("localhost",PORT) 480 conn.request("GET","",params,headers) 481 response = conn.getresponse() 482 data = response.read() 484 # Print the rejection letter 485 print "First request:",data 487 # Get the challenge 488 wa = response.getheader('WWW-Authenticate') 489 token, kv = wa.split(' ', 1) 490 challenge = urllib2.parse_keqv_list(urllib2.parse_http_list(kv)) 491 realm = challenge['realm'] 492 snonce = challenge['snonce'] 493 algorithm = challenge.get('algorithm', 'HMAC-SHA-1') 494 pw_algorithm = challenge.get('pw-algorithm', 'SHA-1') 495 salt = challenge.get('salt','') 497 # Choose our HMAC construct 498 if algorithm == 'HMAC-SHA-1': 499 hashmod = sha 500 elif algoritm == 'HMAC-MD5': 501 hashmod = md5 503 # Choose our password algorithm 504 if pw_algorithm == 'SHA-1': 505 pwhashmod = sha 506 elif pw_algorithm == 'MD5': 507 pwhashmod = md5 509 # Make the key 510 key = "%s:%s:%s" % (username, 511 pwhashmod.new(password+salt).hexdigest(), 512 realm) 513 key = pwhashmod.new(key).hexdigest() 515 # Put together the headers 516 keys = set(headers.keys()) 517 hop_by_hops = set(['connection', 'keep-alive', 'proxy-authenticate', 518 'proxy-authorization', 'te', 'trailers', 519 'transfer-encoding', 'upgrade']) 520 if 'connection' in keys: 521 ext_hop_heads = urllib2.parse_http_list(headers['connection']) 522 ext_hop_heads.remove('close') 523 hop_by_hops = hop_by_hops.union(ext_hop_heads) 524 keys = keys.difference(hop_by_hops) 525 keylist = ''.join(["%s " % k for k in keys]) 526 header_vals = ''.join([headers[k] for k in keys]) 528 # Make a cnonce 529 created = time.strftime('%Y-%m-%dT%H:%M%SZ',time.gmtime()) 530 cnonce = sha.new(str(random.getrandbits(512))+created).hexdigest() 532 # Calculate the HMAC 533 msg = "%s:%s:%s:%s:%s" % ("GET", "/", cnonce, snonce, header_vals) 534 response = hmac.new(key, msg, hashmod).hexdigest() 536 # Compose the Authorization header 537 auth = 'username="%s", realm="%s", cnonce="%s", uri="%s", ' \ 538 'snonce="%s", response="%s", headers="%s"' 539 auth = auth % (username, realm, cnonce, "/", 540 snonce, response, keylist) 541 headers['Authorization'] = "HMACDigest " + auth 543 # wait a few seconds 544 time.sleep(2) 545 conn.request("GET","/",params,headers) 546 response = conn.getresponse() 547 data = response.read() 549 # Print the successful response 550 print "Second request:",data 551 conn.close() 553 Appendix B. Change Log 555 01: Add server nonce, remove client timestamp. 557 Specify header handling more extensively. 559 Add RFC2119 terms for header handling. 561 Demo client excludes hop-by-hop headers. 563 Authors' Addresses 565 Robert Sayre 567 Email: rfsayre@boswijck.com 569 Alexey Melnikov 570 Isode Ltd. 572 Email: Alexey.Melnikov@isode.com 574 Intellectual Property Statement 576 The IETF takes no position regarding the validity or scope of any 577 Intellectual Property Rights or other rights that might be claimed to 578 pertain to the implementation or use of the technology described in 579 this document or the extent to which any license under such rights 580 might or might not be available; nor does it represent that it has 581 made any independent effort to identify any such rights. Information 582 on the procedures with respect to rights in RFC documents can be 583 found in BCP 78 and BCP 79. 585 Copies of IPR disclosures made to the IETF Secretariat and any 586 assurances of licenses to be made available, or the result of an 587 attempt made to obtain a general license or permission for the use of 588 such proprietary rights by implementers or users of this 589 specification can be obtained from the IETF on-line IPR repository at 590 http://www.ietf.org/ipr. 592 The IETF invites any interested party to bring to its attention any 593 copyrights, patents or patent applications, or other proprietary 594 rights that may cover technology that may be required to implement 595 this standard. Please address the information to the IETF at 596 ietf-ipr@ietf.org. 598 Disclaimer of Validity 600 This document and the information contained herein are provided on an 601 "AS IS" basis and THE CONTRIBUTOR, THE ORGANIZATION HE/SHE REPRESENTS 602 OR IS SPONSORED BY (IF ANY), THE INTERNET SOCIETY AND THE INTERNET 603 ENGINEERING TASK FORCE DISCLAIM ALL WARRANTIES, EXPRESS OR IMPLIED, 604 INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE 605 INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED 606 WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. 608 Copyright Statement 610 Copyright (C) The Internet Society (2006). This document is subject 611 to the rights, licenses and restrictions contained in BCP 78, and 612 except as set forth therein, the authors retain all their rights. 614 Acknowledgment 616 Funding for the RFC Editor function is currently provided by the 617 Internet Society.