RFC 2222
Simple Authentication and Security Layer (SASL)
RFC 2222: Simple Authentication and Security Layer (SASL) โจ
Okay bestie, this is the RFC for SASL, the auth glow-up for connection-based protocols ๐ It's written by J. Myers at Netscape Communications, it's on the Standards Track, and it's dated October 1997 ๐
Status of This Memo ๐
This doc is an Internet standards track protocol for the Internet community, and it's literally asking for discussion and suggestions ๐ซถ For the standardization state and status of this protocol, check the current "Internet Official Protocol Standards" (STD 1). Distribution of this memo is unlimited ๐
Copyright Notice ๐
Copyright (C) The Internet Society (1997). All Rights Reserved.
Table of Contents ๐ง
1. Abstract .............................................. 2
2. Organization of this Document ......................... 2
2.1. How to Read This Document ............................. 2
2.2. Conventions Used in this Document ..................... 2
2.3. Examples .............................................. 3
3. Introduction and Overview ............................. 3
4. Profiling requirements ................................ 4
5. Specific issues ....................................... 5
5.1. Client sends data first ............................... 5
5.2. Server returns success with additional data ........... 5
5.3. Multiple authentications .............................. 5
6. Registration procedures ............................... 6
6.1. Comments on SASL mechanism registrations .............. 6
6.2. Location of Registered SASL Mechanism List ............ 6
6.3. Change Control ........................................ 7
6.4. Registration Template ................................. 7
7. Mechanism definitions ................................. 8
7.1. Kerberos version 4 mechanism .......................... 8
7.2. GSSAPI mechanism ...................................... 9
7.2.1 Client side of authentication protocol exchange ....... 9
7.2.2 Server side of authentication protocol exchange ....... 10
7.2.3 Security layer ........................................ 11
7.3. S/Key mechanism ....................................... 11
7.4. External mechanism .................................... 12
8. References ............................................ 13
9. Security Considerations ............................... 13
10. Author's Address ...................................... 14
Appendix A. Relation of SASL to Transport Security .......... 15
Full Copyright Statement .................................... 16
1. Abstract ๐ธ
So this spec is all about adding authentication to connection-based protocols ๐ The vibe: a protocol gets a command that identifies and authenticates a user to a server, and it can optionally negotiate protection for everything after that. If that protection gets negotiated, a security layer slides in between the protocol and the connection โจ This doc explains how a protocol specifies that command, defines a few mechanisms the command can use, and defines the protocol for carrying a negotiated security layer over the connection. Iconic ๐
2. Organization of this Document ๐ฆ
2.1. How to Read This Document ๐
This doc is written for two audiences, and it's giving "for everyone who needs it" ๐ The first is protocol designers who want to use this spec to add authentication to their protocol. The second is implementors of clients or servers for those protocols.
The sections "Introduction and Overview", "Profiling requirements", and "Security Considerations" cover the stuff protocol designers need to understand and handle when they profile this spec for a specific protocol ๐ง
If you're implementing a protocol that uses this spec, you need the protocol-specific profiling info on top of what's in this document ๐ซถ
2.2. Conventions Used in this Document ๐
In examples, C: and S: mark lines sent by the client and the server, respectively.
The key words "MUST", "MUST NOT", "SHOULD", "SHOULD NOT", and "MAY" in this document are to be interpreted as defined in "Key words for use in RFCs to Indicate Requirement Levels" [RFC 2119]. Yes, these are the official requirement words, so they're in caps on purpose ๐ฅ
2.3. Examples ๐
The examples in this document are for the IMAP profile [RFC 2060] of this spec. The base64 encoding of challenges and responses, plus the + that comes before the responses, are part of the IMAP4 profile, not the SASL spec itself. Keep those separate in your head, bestie ๐ง
3. Introduction and Overview ๐
SASL is a method for adding authentication support to connection-based protocols โจ To use this spec, a protocol includes a command for identifying and authenticating a user to a server, and for optionally negotiating a security layer for the protocol interactions that come after.
The command has a required argument that identifies a SASL mechanism. SASL mechanisms are named by strings that are 1 to 20 characters long and made of upper-case letters, digits, hyphens, and/or underscores. SASL mechanism names must be registered with the IANA. The procedures for registering new SASL mechanisms are in the section "Registration procedures" ๐
If the server supports the requested mechanism, it starts an authentication protocol exchange ๐ค That's a series of server challenges and client responses that are specific to the requested mechanism. The mechanisms define the challenges and responses as binary tokens of arbitrary length, and the protocol's profile then specifies how those binary tokens get encoded for transfer over the connection.
After receiving the authentication command or any client response, the server can issue a challenge, indicate failure, or indicate completion. The protocol's profile says how the server signals which one it's doing ๐ฆ
After receiving a challenge, the client can issue a response or abort the exchange. The protocol's profile says how the client signals which one it's doing ๐ โโ๏ธ
During the authentication exchange, the mechanism does the authentication, sends an authorization identity (usually called a userid) from the client to the server, and negotiates the use of a mechanism-specific security layer ๐ If a security layer gets agreed on, the mechanism must also define or negotiate the maximum cipher-text buffer size that each side can receive ๐ง
The authorization identity that gets sent can be different from the identity in the client's authentication credentials. This lets agents like proxy servers authenticate with their own credentials and still ask for the access privileges of the identity they're proxying for ๐ With any mechanism, sending an authorization identity of the empty string tells the server to derive an authorization identity from the client's authentication credentials ๐ซถ
If a security layer is negotiated, it gets applied to all the data sent over the connection after that. The security layer takes effect right after the last response of the authentication exchange for data the client sends, and right after the completion indication for data the server sends. Once the security layer is active, the protocol stream gets processed by the security layer into buffers of cipher-text. Each buffer goes over the connection as a stream of octets, prefixed by a four octet field in network byte order that gives the length of the buffer that follows. The length of the cipher-text buffer must be no larger than the maximum size that was defined or negotiated by the other side ๐
4. Profiling requirements ๐
To use this spec, a protocol definition has to supply the following info:
- A service name, picked from the IANA registry of "service" elements for the GSSAPI host-based service name form [RFC 2078] ๐ง
- A definition of the command that starts the authentication protocol exchange. This command must have a parameter for the mechanism name the client selects.
The command SHOULD have an optional parameter giving an initial response ๐ That lets the client skip a round trip when using a mechanism that's defined to have the client send data first. If the client sends this initial response and the selected mechanism is defined to have the server start with an initial challenge, the command fails. See section 5.1 of this document for more info ๐
- A definition of how the authentication protocol exchange is carried out. That covers how challenges and responses are encoded, how the server indicates completion or failure of the exchange, how the client aborts an exchange, and how the exchange method interacts with any line length limits in the protocol ๐
- Identification of the octet where any negotiated security layer starts to take effect, in both directions ๐
- A specification of how the authorization identity passed from the client to the server is to be interpreted ๐
5. Specific issues ๐ฅ
5.1. Client sends data first ๐ซ
Some mechanisms say the first data sent in the authentication protocol exchange comes from the client to the server ๐ค
If a protocol's profile lets the command that starts an authentication exchange contain an initial client response, this parameter SHOULD be used with those mechanisms โจ
If the initial client response parameter isn't given, or if a protocol's profile doesn't let the command that starts an authentication exchange contain an initial client response, then the server issues a challenge with no data ๐ซ The client's response to that challenge then gets used as the initial client response. (After that, the server goes on to send the next challenge, indicates completion, or indicates failure.)
5.2. Server returns success with additional data ๐ง
Some mechanisms may say that server challenge data gets sent to the client along with an indication of successful completion of the exchange ๐ That data could, for example, authenticate the server to the client ๐ก๏ธ
If a protocol's profile doesn't allow this server challenge to come back with a success indication, then the server issues the server challenge without an indication of successful completion. The client then responds with no data. After it gets that empty response, the server indicates successful completion ๐
5.3. Multiple authentications โจ
Okay so, unless the protocol's profile says otherwise, only one successful SASL negotiation MAY occur in a protocol session. Once an authentication exchange has finished successfully, any later attempt to start another one just fails ๐
If a profile explicitly allows several successful SASL negotiations, there's still a hard rule: multiple security layers MUST NOT be in effect at the same time ๐ If a security layer is already on and a later negotiation picks no security layer, the original one stays on ๐ซถ If a later negotiation picks a second security layer, that new one replaces the first one โจ
6. Registration procedures ๐
Registering a SASL mechanism is done by filling in the template in section 6.4 and sending it to iana@isi.edu ๐ IANA can reject registrations that are obviously bogus, but they won't review any claims made on the registration form ๐
There's no naming convention for SASL mechanisms. Any name that follows the syntax of a SASL mechanism name can be registered ๐
Registration doesn't require it, but authors are encouraged to get community review and comment whenever that's doable ๐ฆ To ask for review, authors can post their mechanism spec as an internet-draft. If a mechanism is meant for widespread use, it SHOULD be standardized through the normal IETF process when that makes sense ๐
6.1. Comments on SASL mechanism registrations ๐ฌ
Comments on a registered SASL mechanism SHOULD go to the mechanism's "owner" first ๐ If you've tried reaching the owner and it didn't work out, commenters MAY ask IANA to attach their comment to the registration itself. If IANA says yes, the comment becomes accessible alongside the registration ๐
6.2. Location of Registered SASL Mechanism List ๐
Registrations get posted in the anonymous FTP directory ftp://ftp.isi.edu/in-notes/iana/assignments/sasl-mechanisms/, and every registered mechanism is listed in the periodically issued "Assigned Numbers" RFC [currently STD 2, RFC 1700] ๐ง The mechanism description and any other supporting material MAY also be published as an Informational RFC, by sending it to rfc-editor@isi.edu (please follow the instructions to RFC authors [RFC 2223]) ๐ธ
6.3. Change Control ๐
Once IANA has published a SASL mechanism registration, the author can ask for a change to its definition. That change request follows the same procedure as the original registration request ๐
The owner of a mechanism can hand responsibility over to another person or agency by telling IANA. No discussion or review needed for that ๐ซถ
The IESG MAY reassign responsibility for a SASL mechanism. The most common reason is when the registration's author has died, dropped out of contact, or otherwise can't make changes the community really needs ๐ญ
Registrations MUST NOT be deleted ๐ซ Mechanisms that are no longer considered appropriate can be declared OBSOLETE by changing their "intended use" field, and IANA's published lists will clearly mark them ๐ชฆ
The IESG is considered the owner of every SASL mechanism that's on the IETF standards track ๐
6.4. Registration Template ๐
Here's the template you fill in. Copy it exactly, babe:
To: iana@iana.org
Subject: Registration of SASL mechanism X
SASL mechanism name:
Security considerations:
Published specification (optional, recommended):
Person & email address to contact for further information:
Intended usage:
(One of COMMON, LIMITED USE or OBSOLETE)
Author/Change controller:
(Any other information that the author deems interesting may be
added below this line.)
7. Mechanism definitions ๐
The following mechanisms are hereby defined ๐
7.1. Kerberos version 4 mechanism ๐๏ธ
The mechanism name for Kerberos version 4 is KERBEROS_V4 ๐
The first challenge is a random 32-bit number in network byte order โจ The client answers with a Kerberos ticket and an authenticator for the principal service.hostname@realm. Here, service is the service name from the protocol's profile, hostname is the first component of the server's host name in all lower case, and realm is the server's Kerberos realm ๐ธ The encrypted checksum field inside the Kerberos authenticator holds the server's challenge, in network byte order ๐
Once the server decrypts and verifies the ticket and authenticator, it checks that the checksum field equals the random 32-bit number it originally sent. If that check passes, the server MUST add one to the checksum and build 8 octets of data ๐ง The first four octets hold the incremented checksum in network byte order. The fifth octet holds a bit-mask listing the security layers the server supports. The sixth through eighth octets hold, in network byte order, the largest cipher-text buffer the server can receive. The server MUST encrypt those 8 octets using DES ECB mode with the session key, and send the encrypted data as a second challenge ๐ The client treats the server as authenticated if the first four octets of the unencrypted data equal one plus the checksum it sent earlier ๐ซถ
The client MUST build data whose first four octets hold the original server-issued checksum in network byte order. The fifth octet holds the bit-mask for the selected security layer. The sixth through eighth octets hold, in network byte order, the largest cipher-text buffer the client can receive. The octets after that hold the authorization identity ๐ The client MUST then append from one to eight zero-valued octets so the data length is a multiple of eight octets. Then the client MUST encrypt the data with the session key using DES PCBC mode and reply with the encrypted data ๐ The server decrypts the data and verifies the checksum inside it. The server MUST verify that the principal named in the Kerberos ticket is authorized to connect as that authorization identity ๐ฅ After that check, the authentication process is complete ๐
The security layers and their bit-masks are:
1 No security layer
2 Integrity (krb_mk_safe) protection
4 Privacy (krb_mk_priv) protection
Other bit-masks MAY be defined in the future, and any bits that aren't understood MUST be negotiated off ๐ธ
Here are two Kerberos version 4 login scenarios for the IMAP4 protocol ๐ The line breaks in the sample authenticators are just there for editorial clarity. They aren't in real authenticators, so don't worry about them ๐
Successful login:
S: * OK IMAP4 Server
C: A001 AUTHENTICATE KERBEROS_V4
S: + AmFYig==
C: BAcAQU5EUkVXLkNNVS5FRFUAOCAsho84kLN3/IJmrMG+25a4DT
+nZImJjnTNHJUtxAA+o0KPKfHEcAFs9a3CL5Oebe/ydHJUwYFd
WwuQ1MWiy6IesKvjL5rL9WjXUb9MwT9bpObYLGOKi1Qh
S: + or//EoAADZI=
C: DiAF5A4gA+oOIALuBkAAmw==
S: A001 OK Kerberos V4 authentication successful
Failed login:
S: * OK IMAP4 Server
C: A001 AUTHENTICATE KERBEROS_V4
S: + gcfgCA==
C: BAcAQU5EUkVXLkNNVS5FRFUAOCAsho84kLN3/IJmrMG+25a4DT
+nZImJjnTNHJUtxAA+o0KPKfHEcAFs9a3CL5Oebe/ydHJUwYFd
WwuQ1MWiy6IesKvjL5rL9WjXUb9MwT9bpObYLGOKi1Qh
S: A001 NO Kerberos V4 authentication failed
7.2. GSSAPI mechanism ๐ท
Every mechanism that uses the GSSAPI [RFC 2078] is named GSSAPI ๐ง
7.2.1 Client side of authentication protocol exchange ๐ป
The client calls GSS_Init_sec_context, passing 0 for input_context_handle (at the start) and a targ_name equal to the output_name from GSS_Import_Name. That call uses an input_name_type of GSS_C_NT_HOSTBASED_SERVICE and an input_name_string of service@hostname. Here, service is the service name from the protocol's profile, and hostname is the server's fully qualified host name โจ The client then replies with the resulting output_token. If GSS_Init_sec_context returns GSS_S_CONTINUE_NEEDED, the client SHOULD expect the server to send a token in a later challenge. The client MUST pass that token into another call to GSS_Init_sec_context, repeating what this paragraph describes ๐
When GSS_Init_sec_context returns GSS_S_COMPLETE, the client does the following. If the last call to GSS_Init_sec_context returned an output_token, the client replies with that output_token. Otherwise it replies with no data. After that, the client SHOULD expect the server to send a token in a later challenge ๐ The client passes that token to GSS_Unwrap. The first octet of the cleartext is a bit-mask for the security layers the server supports, and the second through fourth octets give the largest output_message the server can receive ๐ Next, the client builds data. The first octet holds the bit-mask for the selected security layer. The second through fourth octets hold, in network byte order, the largest output_message the client can receive. The remaining octets hold the authorization identity ๐
The client passes that data to GSS_Wrap with conf_flag set to FALSE, and replies with the generated output_message. Then the client can consider the server authenticated ๐
7.2.2 Server side of authentication protocol exchange ๐ฅ๏ธ
The server passes the initial client response to GSS_Accept_sec_context as input_token, with input_context_handle set to 0 at the start. If GSS_Accept_sec_context returns GSS_S_CONTINUE_NEEDED, the server sends the generated output_token to the client in a challenge, and passes the resulting response into another call to GSS_Accept_sec_context, repeating what this paragraph describes ๐
When GSS_Accept_sec_context returns GSS_S_COMPLETE, the client does the following. If the last call to GSS_Accept_sec_context returned an output_token, the server sends it to the client in a challenge and expects a reply from the client with no data ๐ซง Whether or not an output_token was returned (and after any response to such a token has been received), the server builds 4 octets of data. The first octet holds a bit-mask for the security layers the server supports, and the second through fourth octets hold, in network byte order, the largest output_token the server can receive ๐ธ The server MUST then pass that plaintext to GSS_Wrap with conf_flag set to FALSE, and send the generated output_message to the client in a challenge ๐ The server MUST then pass the resulting response to GSS_Unwrap and read the first octet of the cleartext as the bit-mask for the selected security layer. The second through fourth octets are the largest output_message to send to the client, and the remaining octets are the authorization identity ๐๏ธ The server MUST verify that src_name is authorized to authenticate as that authorization identity. After these checks, the authentication process is complete โ
7.2.3 Security layer โจ
Okay so the security layers and their bit-masks go like this, and the number tells you what you get ๐:
1 No security layer
2 Integrity protection.
Sender calls GSS_Wrap with conf_flag set to FALSE
4 Privacy protection.
Sender calls GSS_Wrap with conf_flag set to TRUE
Other bit-masks MAY be defined in the future ๐ฎ, and bits which are not understood MUST be negotiated off. Not optional, bestie ๐ .
7.3. S/Key mechanism ๐
Okay, the mechanism name for S/Key [RFC 1760] using the MD4 digest algorithm is "SKEY" โจ.
The client kicks things off with an initial response that carries the authorization identity ๐.
Then the server sends a challenge with the decimal sequence number, a single space, and the seed string for that authorization identity. The client answers with the one-time-password, either as a 64-bit value in network byte order or in the "six English words" format ๐ง.
The server MUST verify the one-time-password. Once that's checked, the authentication process is complete ๐.
S/Key authentication does not provide any security layers, so no extras here ๐.
EXAMPLE: Here are two S/Key login scenarios in the IMAP4 protocol ๐ฆ.
S: * OK IMAP4 Server
C: A001 AUTHENTICATE SKEY
S: +
C: bW9yZ2Fu
S: + OTUgUWE1ODMwOA==
C: Rk9VUiBNQU5OIFNPT04gRklSIFZBUlkgTUFTSA==
S: A001 OK S/Key authentication successful
S: * OK IMAP4 Server
C: A001 AUTHENTICATE SKEY
S: +
C: c21pdGg=
S: + OTUgUWE1ODMwOA==
C: BsAY3g4gBNo=
S: A001 NO S/Key authentication failed
And here's an S/Key login in an IMAP4-like protocol that has an optional "initial response" argument on the AUTHENTICATE command. Super clean ๐ธ.
S: * OK IMAP4-Like Server
C: A001 AUTHENTICATE SKEY bW9yZ2Fu
S: + OTUgUWE1ODMwOA==
C: Rk9VUiBNQU5OIFNPT04gRklSIFZBUlkgTUFTSA==
S: A001 OK S/Key authentication successful
7.4. External mechanism ๐
The mechanism name for external authentication is "EXTERNAL" ๐.
The client sends an initial response with the authorization identity โจ.
The server uses information from outside SASL to decide whether the client is allowed to authenticate as that authorization identity. If the client is authorized, the server says the authentication exchange succeeded. If not, the server says it failed ๐ .
The system giving this external information MAY be, for example, IPsec or TLS ๐.
If the client sends the empty string as the authorization identity (basically asking for the authorization identity to be pulled from the client's own authentication credentials), then that identity is derived from the credentials that exist in the system providing the external authentication ๐ซถ.
8. References ๐
[RFC 2060] Crispin, M., "Internet Message Access Protocol - Version 4rev1", RFC 2060, December 1996.
[RFC 2078] Linn, J., "Generic Security Service Application Program Interface, Version 2", RFC 2078, January 1997.
[RFC 2119] Bradner, S., "Key words for use in RFCs to Indicate Requirement Levels", RFC 2119, March 1997.
[RFC 2223] Postel, J., and J. Reynolds, "Instructions to RFC Authors", RFC 2223, October 1997.
[RFC 1760] Haller, N., "The S/Key One-Time Password System", RFC 1760, February 1995.
[RFC 1700] Reynolds, J., and J. Postel, "Assigned Numbers", STD 2, RFC 1700, October 1994.
9. Security Considerations ๐จ
Okay, this is the serious part, bestie ๐. Security issues are discussed throughout this memo.
The mechanisms that support integrity protection are designed so that negotiating the security layer and authorization identity is itself integrity protected ๐. When the client selects a security layer with at least integrity protection, that protects against an active attacker who hijacks the connection and changes the authentication exchange to negotiate a plaintext connection. Not it ๐ โโ๏ธ.
When a server or client supports multiple authentication mechanisms, and each one has a different security strength, an active attacker can make a party use the least secure mechanism it supports. To protect against this, a client or server that supports mechanisms of different strengths SHOULD have a configurable minimum strength that it will use โ ๏ธ. It is not enough for this minimum strength check to exist only on the server, because an active attacker can change which mechanisms the client sees as supported, and then the client sends credentials for its weakest supported mechanism ๐.
The client's choice of a SASL mechanism happens in the clear and can be modified by an active attacker ๐. It's really important that any new SASL mechanisms are designed so that an active attacker can't get authentication with weaker security properties by changing the SASL mechanism name and/or the challenges and responses ๐ก๏ธ.
Any protocol interactions before authentication happen in the clear and can be modified by an active attacker ๐ฑ. If a client selects integrity protection, it's important that any security-sensitive protocol negotiations happen after authentication is complete. Protocols SHOULD be designed so that negotiations performed prior to authentication SHOULD be either ignored or revalidated once authentication is complete ๐.
10. Author's Address ๐๏ธ
John G. Myers
Netscape Communications
501 E. Middlefield Road
Mail Stop MV-029
Mountain View, CA 94043-4042
EMail: jgmyers@netscape.com
Appendix A. Relation of SASL to Transport Security ๐ฆ
Questions have come up about how SASL relates to services like IPsec and TLS, which give you a secured connection ๐ค.
Two of the key features of SASL are:
- Separating the authorization identity from the identity in the client's credentials. This lets agents such as proxy servers authenticate with their own credentials while requesting the access privileges of the identity they're proxying for ๐ง.
- Once an authentication exchange finishes successfully, the server knows the authorization identity the client wants to use. This lets servers move to a "user is authenticated" state in the protocol โจ.
These features are super important to some application protocols, but Transport Security services don't always provide them ๐ . Defining SASL mechanisms based on those services would be a very messy job, since the framing of those services would be redundant with the framing of SASL, and some way of providing these important SASL features would have to be invented ๐ญ.
Sometimes you want to turn on a security service inside an existing connection that doesn't fit the SASL model. (TLS is an example of that.) You can do this by adding a command, for example "STARTTLS", to the protocol. That command is outside the scope of SASL, and it SHOULD be different from the command that starts a SASL authentication protocol exchange ๐.
In certain situations, it makes sense to use SASL underneath one of these Transport Security services. The transport service secures the connection, either service authenticates the client, and SASL negotiates the authorization identity. The SASL negotiation is what moves the protocol from "unauthenticated" to "authenticated" state ๐. The "EXTERNAL" SASL mechanism is explicitly intended for the case where the transport service secures the connection and authenticates the client, and SASL negotiates the authorization identity ๐.
When you use SASL underneath a sufficiently strong Transport Security service, a SASL security layer would most likely be redundant. So the client and server would probably want to negotiate off the use of a SASL security layer ๐.
Full Copyright Statement ยฉ๏ธ
Copyright (C) The Internet Society (1997). All Rights Reserved.
This document and translations of it MAY be copied and furnished to others, and derivative works that comment on or otherwise explain it or assist in its implementation MAY be prepared, copied, published and distributed, in whole or in part, without restriction of any kind, provided that the above copyright notice and this paragraph are included on all such copies and derivative works. However, this document itself may not be modified in any way, such as by removing the copyright notice or references to the Internet Society or other Internet organizations, except as needed for the purpose of developing Internet standards, in which case the procedures for copyrights defined in the Internet Standards process MUST be followed, or as required to translate it into languages other than English.
The limited permissions granted above are perpetual and will not be revoked by the Internet Society or its successors or assigns.
This document and the information contained herein is provided on an "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING TASK FORCE DISCLAIMS 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. ๐ซถ
๐ฆ where this page comes from
- ietf: rfc2222 1997-10
- ๐ girlified by claude-haiku-5-5 on : a language model's rewrite of the original, under its terms