RFC 2244
ACAP -- Application Configuration Access Protocol
RFC 2244: ACAP -- Application Configuration Access Protocol ๐
Okay bestie, RFC 2244 is ACAP, the Application Configuration Access Protocol ๐ It came from the Network Working Group in November 1997 and is a Standards Track document. The authors are C. Newman (Innosoft) and J. G. Myers (Netscape) ๐ The title block doesn't list any RFCs that it obsoletes or updates, so there's no drama there โจ
Status of this Memo ๐ธ
This doc specifies an Internet standards track protocol for the Internet community, and it asks for discussion and suggestions for improvements ๐ For the standardization state and status of this protocol, check the current edition of the "Internet Official Protocol Standards" (STD 1). Distribution of this memo is unlimited ๐ฆ
Copyright Notice ๐
Copyright (C) The Internet Society 1997. All Rights Reserved.
Abstract โญ
ACAP, the Application Configuration Access Protocol, is built to support remote storage and access of program option, configuration and preference information ๐ง The data store model lets a client get at interesting data pretty simply, lets new information get added without a server reconfiguration, and promotes using both standardized data and custom or proprietary data ๐ซถ Two key features are "inheritance", which can manage default values for configuration settings, and access control lists, which let interesting personal information be shared while group information stays restricted ๐ฅ
Table of Contents ๐
Status of this Memo ............................................... i
Copyright Notice .................................................. i
Abstract .......................................................... i
ACAP Protocol Specification ....................................... 1
1. Introduction ............................................. 1
1.1. Conventions Used in this Document ........................ 1
1.2. ACAP Data Model .......................................... 1
1.3. ACAP Design Goals ........................................ 1
1.4. Validation ............................................... 2
1.5. Definitions .............................................. 2
1.6. ACAP Command Overview .................................... 4
2. Protocol Framework ....................................... 4
2.1. Link Level ............................................... 4
2.2. Commands and Responses ................................... 4
2.2.1. Client Protocol Sender and Server Protocol Receiver ...... 4
2.2.2. Server Protocol Sender and Client Protocol Receiver ...... 5
2.3. Server States ............................................ 6
2.3.1. Non-Authenticated State .................................. 6
2.3.2. Authenticated State ...................................... 6
2.3.3. Logout State ............................................. 6
2.4. Operational Considerations ............................... 7
2.4.1. Untagged Status Updates .................................. 7
2.4.2. Response when No Command in Progress ..................... 7
2.4.3. Auto-logout Timer ........................................ 7
2.4.4. Multiple Commands in Progress ............................ 8
2.5. Server Command Continuation Request ...................... 8
2.6. Data Formats ............................................. 8
2.6.1. Atom ..................................................... 9
2.6.2. Number ................................................... 9
2.6.3. String ................................................... 9
2.6.3.1. 8-bit and Binary Strings ................................. 10
2.6.4. Parenthesized List ....................................... 10
2.6.5. NIL ...................................................... 10
3. Protocol Elements ........................................ 10
3.1. Entries and Attributes ................................... 10
3.1.1. Predefined Attributes .................................... 11
3.1.2. Attribute Metadata ....................................... 12
3.2. ACAP URL scheme .......................................... 13
3.2.1. ACAP URL User Name and Authentication Mechanism .......... 13
3.2.2. Relative ACAP URLs ....................................... 14
3.3. Contexts ................................................. 14
3.4. Comparators .............................................. 15
3.5. Access Control Lists (ACLs) .............................. 17
3.6. Server Response Codes .................................... 18
4. Namespace Conventions .................................... 21
4.1. Dataset Namespace ........................................ 21
4.2. Attribute Namespace ...................................... 21
4.3. Formal Syntax for Dataset and Attribute Namespace ........ 22
5. Dataset Management ....................................... 23
5.1. Dataset Inheritance ...................................... 23
5.2. Dataset Attributes ....................................... 24
5.3. Dataset Creation ......................................... 25
5.4. Dataset Class Capabilities ............................... 25
5.5. Dataset Quotas ........................................... 26
6. Command and Response Specifications ...................... 26
6.1. Initial Connection ....................................... 26
6.1.1. ACAP Untagged Response ................................... 26
6.2. Any State ................................................ 27
6.2.1. NOOP Command ............................................. 27
6.2.2. LANG Command ............................................. 28
6.2.3. LANG Intermediate Response ............................... 28
6.2.4. LOGOUT Command ........................................... 29
6.2.5. OK Response .............................................. 29
6.2.6. NO Response .............................................. 29
6.2.7. BAD Response ............................................. 30
6.2.8. BYE Untagged Response .................................... 30
6.2.9. ALERT Untagged Response .................................. 31
6.3. Non-Authenticated State .................................. 31
6.3.1. AUTHENTICATE Command ..................................... 31
6.4. Searching ................................................ 33
6.4.1. SEARCH Command ........................................... 33
6.4.2. ENTRY Intermediate Response .............................. 37
6.4.3. MODTIME Intermediate Response ............................ 38
6.4.4. REFER Intermediate Response .............................. 38
6.4.5. Search Examples .......................................... 38
6.5. Contexts ................................................. 39
6.5.1. FREECONTEXT Command ...................................... 39
6.5.2. UPDATECONTEXT Command .................................... 40
6.5.3. ADDTO Untagged Response .................................. 40
6.5.4. REMOVEFROM Untagged Response ............................. 41
6.5.5. CHANGE Untagged Response ................................. 41
6.5.6. MODTIME Untagged Response ................................ 42
6.6. Dataset modification ..................................... 42
6.6.1. STORE Command ............................................ 42
6.6.2. DELETEDSINCE Command ..................................... 45
6.6.3. DELETED Intermediate Response ............................ 45
6.7. Access Control List Commands ............................. 45
6.7.1. SETACL Command ........................................... 46
6.7.2. DELETEACL Command ........................................ 46
6.7.3. MYRIGHTS Command ......................................... 47
6.7.4. MYRIGHTS Intermediate Response ........................... 47
6.7.5. LISTRIGHTS Command ....................................... 47
6.7.6. LISTRIGHTS Intermediate Response ......................... 48
6.8. Quotas ................................................... 48
6.8.1. GETQUOTA Command ......................................... 48
6.8.3. QUOTA Untagged Response .................................. 49
6.9. Extensions ............................................... 49
7. Registration Procedures .................................. 49
7.1. ACAP Capabilities ........................................ 50
7.2. ACAP Response Codes ...................................... 50
7.3. Dataset Classes .......................................... 51
7.4. Vendor Subtree ........................................... 51
8. Formal Syntax ............................................ 52
9. Multi-lingual Considerations ............................. 61
10. Security Considerations .................................. 62
11. Acknowledgments .......................................... 63
12. Authors' Addresses ....................................... 63
Appendices ........................................................ 64
A. References ............................................... 64
B. ACAP Keyword Index ....................................... 66
C. Full Copyright Statement
ACAP Protocol Specification ๐ฆ
1. Introduction โจ
1.1. Conventions Used in this Document ๐
In examples, "C:" and "S:" mark lines sent by the client and the server respectively. If such lines are wrapped without a new "C:" or "S:" label, the wrapping is for editorial clarity and isn't part of the command ๐
The key words "REQUIRED", "MUST", "MUST NOT", "SHOULD", "SHOULD NOT", and "MAY" in this document are to be interpreted as described in "Key words for use in RFCs to Indicate Requirement Levels" [KEYWORDS]. So those words in caps are the official requirement levels, not just vibes ๐
1.2. ACAP Data Model ๐งฉ
An ACAP server exports a hierarchical tree of entries ๐ณ Each level of the tree is called a dataset, and each dataset is made up of a list of entries. Every entry has a unique name and can hold any number of named attributes. Each attribute can be single valued or multi-valued, and it can have associated metadata to help with access and interpretation of the value ๐
The rules a client uses to interpret the data within a portion of ACAP's tree of entries are called a dataset class ๐
1.3. ACAP Design Goals ๐
ACAP's main job is to let users get at their configuration data from multiple network-connected computers. The vibe is that users can sit down in front of any network-connected computer, run any ACAP-enabled application, and still have access to their own configuration data ๐ Because lots of applications are hoped to become ACAP-enabled, client simplicity was preferred over server or protocol simplicity whenever that was reasonable ๐ฅ
ACAP is also meant to be easy to manage ๐ That's why it includes "inheritance", which lets one dataset inherit default attributes from another dataset. Access control lists are included too, so management can be delegated, and quotas are included to control storage ๐ง Finally, an ACAP server that conforms to this base specification should be able to support most dataset classes defined in the future without needing a server reconfiguration or upgrade โญ
ACAP is built for clients that only get sometimes connected to the server ๐ฑ, so every entry gets a server-maintained modification time that lets the client spot changes ๐. The client can also ask the server for a list of entries that were removed since it last checked in ๐๏ธ.
ACAP assumes a dataset could be huge and/or the client might be on a slow connection ๐, so it offers server sorting, selective fetching and change notification for entries in a dataset ๐ฅ.
Like most Internet protocols, security, scalability and internationalization were big priorities ๐๐.
With all that in mind, we kept ACAP as simple as possible โจ. It's a traditional text-based Internet protocol, which makes debugging SO much easier ๐. It's built on the super successful IMAP [IMAP4] framework, with a few upgrades ๐ .
1.4. Validation
By default, any value can be stored in any attribute the user has permission and quota for ๐. This is what lets people add new simple dataset classes without reconfiguring or upgrading the server ๐ง.
Sometimes, like when a value has special meaning to the server, it's super useful for the server to do the checking by returning the INVALID response code to a STORE command ๐ก๏ธ. These cases MUST be explicitly identified in the dataset class specification, which SHOULD include specific fixed rules for validation. Since a given ACAP server might not know about a particular dataset class specification, clients MUST NOT depend on enforced validation being there on the server ๐ญ.
1.5. Definitions
- access control list (ACL): A set of identifier, rights pairs associated with an object. An ACL is used to determine which operations a user is permitted to perform on that object. See section 3.5.
- attribute: A named value within an entry. See section 3.1.
- comparator: A named function which can be used to perform one or more of three comparison operations: ordering, equality and substring matching. See section 3.4.
- context: An ordered subset of entries in a dataset, created by a SEARCH command with a MAKECONTEXT modifier. See section 3.3.
- dataset: One level of hierarchy in ACAP's tree of entries.
- dataset class specification: The rules which allow a client to interpret the data within a portion of ACAP's tree of entries.
- entry: A set of attributes with a unique entry name. See section 3.1.
- metadata: Information describing an attribute, its value and any access controls associated with that attribute. See section 3.1.2.
- NIL: This represents the non-existence of a particular data item.
- NUL: A control character encoded as 0 in US-ASCII [US-ASCII].
- octet: An 8-bit value. On most modern computer systems, an octet is one byte.
- SASL: Simple Authentication and Security Layer [SASL].
- UTC: Universal Coordinated Time as maintained by the Bureau International des Poids et Mesures (BIPM).
- UTF-8: An 8-bit transformation format of the Universal Character Set [UTF8]. Note that an incompatible change was made to the coded character set referenced by [UTF8], so for the purpose of this document, UTF-8 refers to the UTF-8 encoding as defined by version 2.0 of Unicode [UNICODE-2], or ISO 10646 [ISO-10646] including amendments one through seven.
1.6. ACAP Command Overview
The AUTHENTICATE, NOOP, LANG and LOGOUT commands are the basic protocol services ๐ง. SEARCH is the one that selects, sorts, fetches and monitors changes to attribute values and metadata ๐. UPDATECONTEXT and FREECONTEXT help with monitoring those changes too ๐ฆ. STORE adds, modifies and deletes entries and attributes โ๏ธ. DELETEDSINCE helps a client re-synchronize a cache with the server ๐. And GETQUOTA, SETACL, DELETEACL, LISTRIGHTS and MYRIGHTS let you check storage quotas and examine or change access permissions ๐.
2. Protocol Framework โจ
2.1. Link Level
The ACAP protocol assumes a reliable data stream, such as the one TCP provides ๐งต. When TCP is used, an ACAP server listens on port 674 ๐.
2.2. Commands and Responses
An ACAP session has three parts: setting up the client/server connection, an initial greeting from the server, and then client/server interactions ๐ฌ. Each interaction is a client command, server data, and a server completion result.
ACAP is a text-based, line-oriented protocol ๐. Basically, what clients and servers send are lines, meaning sequences of characters that end with a CRLF ๐ธ. The protocol receiver of an ACAP client or server is either reading a line, or reading a sequence of octets with a known count (a literal) followed by a line ๐งฉ. Both clients and servers must be capable of handling lines of arbitrary length ๐ช.
2.2.1. Client Protocol Sender and Server Protocol Receiver
The client command begins an operation ๐. Each client command is prefixed with an identifier (an alphanumeric string of no more than 32 characters, e.g., A0001, A0002, etc.) called a "tag" ๐ท๏ธ. A different tag SHOULD be generated by the client for each command ๐.
There are two cases where a line from the client does not represent a complete command ๐. In one case, a command argument is quoted with an octet count (see the description of literal in section 2.6.3); in the other, the command arguments require server feedback (see the AUTHENTICATE command). In some of these cases, the server sends a command continuation request if it's ready for the next part of the command. This response is prefixed with the token "+" โ.
Note: If, instead, the server detected an error in a command, it sends a BAD completion response with tag matching the command (as described below) to reject the command and prevent the client from sending any more of the command. It is also possible for the server to send a completion or intermediate response for some other command (if multiple commands are in progress), or untagged data. In either case, the command continuation request is still pending; the client takes the appropriate action for the response, and reads another response from the server.
The ACAP server reads a command line from the client, parses the command and its arguments, and transmits server data and a server command completion result ๐ง .
2.2.2. Server Protocol Sender and Client Protocol Receiver
Data the server sends to the client comes in four forms: command continuation requests, command completion results, intermediate responses, and untagged responses ๐ฆ.
A command continuation request is prefixed with the token "+" โ.
A command completion result tells you whether the operation succeeded or failed ๐. It's tagged with the same tag as the client command that began the operation, so if more than one command is in progress, the tag tells you which command the response belongs to ๐. There are three possible server completion responses: OK (success), NO (failure), or BAD (protocol error, such as an unrecognized command or a command syntax error) โ
โ๐
.
An intermediate response returns data that only makes sense in the context of a command in progress ๐งฉ. It's tagged with the same tag as the client command that began the operation, so again, the tag is how you match it up. A tagged response other than OK, NO, or BAD is an intermediate response ๐.
An untagged response returns data or status messages that can be interpreted outside the context of a command in progress ๐. It's prefixed with the token "*" โญ. Untagged data may be sent as a result of a client command, or it may be sent unilaterally by the server. There's no syntactic difference between untagged data that resulted from a specific command and untagged data that were sent unilaterally ๐ซถ.
The protocol receiver of an ACAP client reads a response line from the server. It then takes action on the response based on the first token of the response, which may be a tag, a "*", or a "+" as described above ๐ฏ.
A client MUST be prepared to accept any server response at all times ๐จ. This includes untagged data that it may not have requested ๐.
This topic is discussed in greater detail in the Server Responses section ๐.
2.3. Server States
An ACAP server is in one of three states ๐ท. Most commands are only valid in certain states. It's a protocol error for the client to attempt a command while the server is in an inappropriate state for that command ๐ โโ๏ธ. In this case, the server responds with a BAD command completion result.
2.3.1. Non-Authenticated State
In non-authenticated state, the user must supply authentication credentials before most commands will be permitted ๐. This state is entered when a connection starts ๐ช.
2.3.2. Authenticated State
In authenticated state, the user is authenticated and most commands will be permitted ๐. This state is entered when acceptable authentication credentials have been provided ๐ .
2.3.3. Logout State
In logout state, the session is being terminated, and the server will close the connection ๐. This state can be entered because of a client request or a unilateral server decision ๐ฅ.
+--------------------------------------+
|initial connection and server greeting|
+--------------------------------------+
|| (1) || (2)
VV ||
+-----------------+ ||
|non-authenticated| ||
+-----------------+ ||
|| (4) || (3) ||
|| VV ||
|| +----------------+ ||
|| | authenticated | ||
|| +----------------+ ||
|| || (4) ||
VV VV VV
+--------------------------------------+
| logout and close connection |
+--------------------------------------+
(1) connection (ACAP greeting)
(2) rejected connection (BYE greeting)
(3) successful AUTHENTICATE command
(4) LOGOUT command, server shutdown, or connection closed
2.4. Operational Considerations
2.4.1. Untagged Status Updates
At any time, a server can send data that the client did not request ๐ฌ.
2.4.2. Response when No Command in Progress
Server implementations are permitted to send an untagged response while there's no command in progress ๐. Server implementations that send such responses MUST deal with flow control considerations ๐ฆ. Specifically, they must either (1) verify that the size of the data does not exceed the underlying transport's available window size, or (2) use non-blocking writes ๐.
2.4.3. Auto-logout Timer
If a server has an inactivity auto-logout timer, that timer MUST be of at least 30 minutes duration. Any command the server receives from the client during that interval MUST reset the auto-logout timer, and I mean ANY command ๐
2.4.4. Multiple Commands in Progress โณ
The client doesn't have to wait for a command to finish before sending the next one, as long as it stays within the flow control limits of the underlying data stream ๐ The server doesn't have to finish one command before starting the next either, UNLESS two commands would get tangled up because one changes the results of the other ๐ If that kind of mix-up could happen, the server runs the commands to completion in the order the client gave them. Order matters, bestie ๐
2.5. Server Command Continuation Request ๐
The command continuation request is marked with a "+" token instead of a tag. It basically means "I'm ready, keep going" โจ
The server uses this response in the AUTHENTICATE command to send server data to the client and ask for more client data. It also gets used when an argument to any command is a synchronizing literal (see section 2.6.3).
The client is not permitted to send the octets of a synchronizing literal unless the server says it's expecting them. This lets the server handle commands and reject errors one line at a time, assuming it checks for non-synchronizing literals at the end of each line ๐ง The rest of the command, including the CRLF that ends it, comes after the literal octets. If there are more command arguments, the literal octets are followed by a space and then those arguments.
Example:
C: A099 FREECONTEXT {10}
S: + "Ready for additional command text"
C: FRED
C: FOOB
S: A099 OK "FREECONTEXT completed"
C: A044 BLURDYBLOOP {102856}
S: A044 BAD "No such command as 'BLURDYBLOOP'"
2.6. Data Formats ๐
ACAP uses textual commands and responses. Data in ACAP can be one of five forms: atom, number, string, parenthesized list or NIL. Five options, so many vibes ๐
2.6.1. Atom ๐ธ
An atom is one to 1024 non-special characters. It has to begin with a letter ๐ค Atoms are used for protocol keywords.
2.6.2. Number ๐ข
A number is one or more digit characters, and it represents a numeric value. Numbers are limited to the range of an unsigned 32-bit integer: 0 < number < 4,294,967,296. Big number energy ๐ค
2.6.3. String ๐ฆ
A string comes in one of two forms: literal and quoted string. The literal form is the general one ๐ The quoted string form is the alternative. It skips the overhead of processing a literal, but it comes with restrictions on what can go inside it.
A literal is a sequence of zero or more octets (including CR and LF). It's prefixed with an octet count, written as an open brace ({), the number of octets, a close brace (}), and then CRLF. For literals sent from server to client, the octet data follows right after the CRLF ๐ง
There are two kinds of literals sent from client to server. The first one has an open brace ({) and the number of octets, immediately followed by a close brace (}) and CRLF. That's a synchronizing literal. When the client sends one, it must wait to receive a command continuation request before sending the octet data (and the rest of the command) ๐ The second one is the non-synchronizing literal, which lets the client send a string without waiting for a command continuation request. The difference is a plus (+) between the number of octets and the close brace (}), and the octet data sitting right after the CRLF. Quick and no waiting ๐โโ๏ธ
A quoted string is a sequence of zero to 1024 octets, excluding NUL, CR and LF, with double quote (<">) characters at each end ๐ฌ
The empty string can be written as "" (a quoted string with zero characters between the quotes), as {0} followed by CRLF (a synchronizing literal with an octet count of 0), or as {0+} followed by a CRLF (a non-synchronizing literal with an octet count of 0). Three ways to say nothing, iconic ๐ซถ
Note: Even if the octet count is 0, a client sending a synchronizing literal must wait to receive a command continuation request. Yes, even for zero ๐
2.6.3.1. 8-bit and Binary Strings ๐งฌ
Most strings in ACAP are restricted to UTF-8 characters, and they may not contain NUL octets. Attribute values MAY contain any octets, including NUL. Attribute values are the exception to the rule, and they're allowed to be wild ๐ฆ
2.6.4. Parenthesized List ๐งฉ
Data structures are shown as a "parenthesized list": a sequence of data items, separated by spaces, with parentheses at each end. A parenthesized list can hold other parenthesized lists, using multiple levels of parentheses to show nesting. Lists within lists, very layered ๐ช
The empty list is written as (), a parenthesized list with no members.
2.6.5. NIL ๐ซ
The special atom "NIL" means that a particular data item doesn't exist. It's represented as a string or a parenthesized list, and it's different from the empty string "" or the empty parenthesized list () ๐ NIL is not the same as nothing-but-empty, which is a whole vibe.
3. Protocol Elements โจ
This section defines the data formats and other protocol elements used throughout ACAP. Basically the building blocks ๐งฑ
3.1. Entries and Attributes ๐
Inside a dataset, each entry name is made up of zero or more UTF-8 characters, other than slash (/). A slash-separated list of entries, one at each level of the hierarchy, forms the full path to an entry ๐๏ธ
Each entry is made of a set of attributes. Each attribute has a hierarchical name in UTF-8, and each part of that name is separated by a period (.).
An attribute's value is either single or multi-valued. A single value is NIL (meaning it has no value), or a string of zero or more octets. A multi-value is a list of zero or more strings, and each of those strings has zero or more octets.
Attribute names are not allowed to contain asterisk (*) or percent (%). They MUST be valid UTF-8 strings that don't contain NUL. Invalid attribute names result in a BAD response. Entry names are not allowed to begin with . or contain slash (/). They MUST be valid UTF-8 strings that don't contain NUL. Invalid entry names in the entry field of a command result in a BAD response. Strict but fair ๐ค
Using non-visible UTF-8 characters in attribute and entry names is discouraged. Please don't be sneaky with invisible characters ๐
3.1.1. Predefined Attributes ๐
Attribute names that don't contain a dot (.) are reserved for standardized attributes, which have meaning in any dataset. The ACAP protocol defines the following attributes.
entry: Contains the name of the entry. It MUST be single valued. Illegal or multi-valued values for the entry attribute are protocol errors, and they MUST result in a BAD completion response. This one is a special case, so pay attention ๐จmodtime: Contains the date and time that any read-write metadata in the entry was last modified. This value MUST be in UTC, and MUST be automatically updated by the server โฐ
The value is 14 or more US-ASCII digits. The first four are the year, the next two are the month, the next two are the day of the month, the next two are the hour (0 - 23), the next two are the minute, and the next two are the second. Any further digits are fractions of a second ๐ข
The time, especially fractions of a second, doesn't need to be accurate. It is REQUIRED, though, that any two entries in a dataset changed by successive modifications have strictly ascending modtime values. Also, each STORE command within a dataset (including simultaneous stores from different connections) MUST use different modtime values. No two stores can share a timestamp, that's the rule ๐ โโ๏ธ
This attribute has enforced validation, so any attempt to STORE a value in it MAY result in a NO response with an INVALID response code.
subdataset: If this attribute is set, it shows that a sub-dataset of this entry exists ๐ณ
The value is a list of relative ACAP URLs (see section 3.2) that can be used to locate the sub-dataset. The base URL is the full path to the entry, followed by a slash (/). The value . means a subdataset is located directly under this one. Multiple values mean there are replicated copies of the subdataset ๐ฏ
For example, if the dataset /folder/site/ has an entry public-folder with a subdataset attribute of ., then the dataset /folder/site/public-folder/ exists. If the value of the subdataset attribute was instead //other.acap.domain//folder/site/public-folder/, that would mean the dataset is actually located on a different ACAP server ๐
A dataset can be created by storing a subdataset attribute that includes .. A sub-hierarchy of datasets is deleted by storing a NIL value to the subdataset attribute on the entry in the parent dataset ๐๏ธ
This attribute has enforced syntax validation. Specifically, if someone tries to STORE a non-list value (other than NIL), an empty list, or a value that doesn't follow the URL syntax rules [BASIC-URL, REL-URL], that results in a NO response with an INVALID response code. Rules are rules, babe ๐
3.1.2. Attribute Metadata ๐ท๏ธ
Each attribute is made up of metadata items that describe the attribute, its value, and any associated access controls. Metadata items are either read-only, in which case the client is never permitted to modify the item, or read-write, in which case the client may modify the item if the access control list (ACL) permits ๐
The following metadata items are defined in this specification:
acl: The access control list for the attribute, if one exists. If the attribute doesn't have an ACL, NIL is returned. Read-write. See section 3.5 for the contents of an ACL.attribute: The attribute name. Read-only.myrights: The set of rights that the client has to the attribute. Read-only. See section 3.5 for the possible rights.size: The length of the value. For a multi-value, this is a list of lengths, one for each of the values. Read-only.value: The value. For a multi-value, this is a list of single values. Read-write.
More metadata items may be defined in extensions to this protocol. Servers MUST respond to unrecognized metadata by returning a BAD command completion result. No mystery metadata gets a free pass ๐ต๏ธโโ๏ธ
3.2. ACAP URL scheme ๐
ACAP URLs are used within the ACAP protocol for the "subdataset" attribute, referrals and inheritance. They give you a convenient syntax for pointing at other ACAP datasets ๐บ๏ธ The ACAP URL follows the common Internet scheme syntax defined in [BASIC-URL], except that plaintext passwords are not permitted. If :<port> is omitted, the port defaults to 674.
An ACAP URL has the following general form:
url-acap = "acap://" url-server "/" url-enc-entry [url-filter]
[url-extension]
The <url-server> element includes the hostname, plus the optional user name, authentication mechanism and port number. The <url-enc-entry> element holds the name of an entry path, encoded according to the rules in [BASIC-URL] ๐ฆ
3.2. ACAP URL Continued ๐ธ
okay bestie, the <url-filter> is totally optional ๐
It's a list of the attribute names you're vibing with. If you leave it out, the URL points at all the attributes of the named entry ๐ซถ And <url-extension> is reserved for future extensions to this URL scheme, so hands off for now ๐
โโ๏ธ
Now the important part ๐จ unsafe or reserved characters like " " or "?" MUST be hex encoded, the way the URL spec [BASIC-URL] explains. Once they're hex encoded, the octets get read as UTF-8 [UTF8] โจ
3.2.1. ACAP URL User Name and Authentication Mechanism ๐
so you can include a user name and/or an authentication mechanism ๐ They get used in the AUTHENTICATE command once you've connected to the ACAP server. If you don't include either one, the default is SASL ANONYMOUS [SASL-ANON] ๐ซ If there's a mechanism but no user name, one SHOULD be obtained from that mechanism, or asked for from the user, whichever makes sense ๐ค If there's a user name but no mechanism, then ;AUTH=* is assumed ๐ท
The ;AUTH= parameter works the same way as in the IMAP URL Scheme [IMAP-URL] ๐ง
Also, if unsafe or reserved characters like " " or ";" show up in the user name or the authentication mechanism, they MUST be encoded the way the URL spec [BASIC-URL] describes ๐
3.2.2. Relative ACAP URLs ๐ฆ
Because ACAP uses / as the hierarchy separator for dataset paths, it plays super nicely with the relative URL rules in [REL-URL] ๐
The <aauth> grammar element counts as part of the user name when you're resolving relative ACAP URLs ๐
So the base URL for a relative URL stored in an attribute's value is built by taking the path to the dataset that holds that attribute, adding a /, then the entry name of the entry holding that attribute, and then one more / ๐ง
3.3. Contexts ๐
A context is a subset of entries from a dataset (or datasets), made with a SEARCH command using the MAKECONTEXT modifier โจ Context names are strings the client makes up itself, and they must not start with the slash (/) character ๐
When a client makes a context, it can ask for automatic notification of changes ๐ It can also ask for the entries inside a context to be enumerated. That's basically what makes a "virtual scrollbar" possible on the client side ๐๐
A context only lives inside the ACAP session it was created in. Close the connection and every context tied to it gets thrown out automatically ๐๏ธ A server is required to support at least 100 active contexts within a session. If it can handle a larger limit, it must advertise that in a CONTEXTLIMIT capability ๐ช
3.4. Comparators ๐
A comparator is a named function that takes two input values, and it can do one or more of four operations: ordering, equality, prefix matching and substring matching ๐
Ordering is used for the SORT search modifier and for the COMPARE and COMPARESTRICT search keys. Ordering comparators can tell you the ordinal precedence of any two values. When you use one for ordering, you can put a + or a - in front of its name to ask for normal or reversed order. No prefix means + ๐๐
A comparator can give certain values an undefined ordinal precedence. Those always collate with equal value after everything else, whether you're going normal or reversed ๐ซฅ Unless the comparator's definition says otherwise, multi-values and NIL values have an undefined ordinal precedence.
Equality is used for the EQUAL search modifier. It just checks whether two values count as equal under the comparator function. When you compare a single value to a multi-value, they're equal if any one of the multiple values matches the single value ๐ฏ
Prefix matching is for the PREFIX search modifier. It checks whether the search value is a prefix of the item being searched. For a prefix search on a multi-value, it's a match if the value is a prefix of any one of the multiple values ๐ท
Substring matching is for the SUBSTRING search modifier. It checks whether the search value is a substring of the item being searched. For a substring search on a multi-value, it's a match if the value is a substring of any one of the multiple values ๐ง
Rules for naming and registering comparators will show up in a future spec ๐ฎ Servers MUST respond to unknown or improperly used comparators with a BAD command completion result โ
These comparators are defined by this standard and MUST be implemented ๐
i;octet (Operations: Ordering, Equality, Prefix match, Substring match)
For collation, i;octet treats an attribute's value as a series of unsigned octets with ordinal values from 0 to 255. When ordering two strings, each octet pair gets compared in sequence until they're unequal or you hit the end of the string. If the shorter string is a prefix of the longer one, the shorter one counts as having a smaller ordinal value. The "i;octet" and "+i;octet" forms put smaller ordinal values first, and the "-i;octet" form puts larger ordinal values first ๐ข
For equality, two strings are equal if they're the same length and contain the same octets in the same order. NIL is equal only to itself ๐ซถ
For non-binary, non-nil single values, i;octet ordering is equivalent to the ANSI C [ISO-C] strcmp() function applied to the C string representations of the values. For those same values, i;octet substring match is equivalent to the ANSI C strstr() function applied to the C string representations ๐งท
i;ascii-casemap (Operations: Ordering, Equality, Prefix match, Substring match)
The i;ascii-casemap comparator first maps the attribute values so every US-ASCII letter becomes uppercase (octet values 0x61 to 0x7A become 0x41 to 0x5A respectively), then applies the i;octet comparator as described above. So "hello" and "HELLO" have the same ordinal value and count as equal ๐
i;ascii-numeric (Operations: Ordering, Equality)
The i;ascii-numeric comparator reads strings as decimal positive integers written with US-ASCII digits. Any value that doesn't begin with a US-ASCII digit counts as equal to the others, with an ordinal value higher than all non-NIL single-valued attributes ๐ Otherwise, all US-ASCII digits (octet values 0x30 to 0x39) are read from the start of the string up to the first non-digit or the end of the string ๐
3.5. Access Control Lists (ACLs) ๐
An access control list is a set of identifier and rights pairs, used to restrict access to a given dataset, attribute, or attribute within an entry ๐ก๏ธ An ACL is a multi-value, where each value holds an identifier, then a tab character, then the rights. The syntax is defined by the acl rule in the formal syntax in section 8 ๐
The identifier is a UTF-8 string. The identifier anyone is reserved to refer to the universal identity (all authentications, including anonymous) ๐ All user name strings accepted by the AUTHENTICATE command are reserved as identifiers for the corresponding user ๐ค Identifiers starting with a slash (/) are reserved for authorization groups, which will be defined in a future spec ๐ฎ Identifiers MAY be prefixed with a dash (-) to show a revocation of rights ๐ซ All other identifiers have implementation-defined meanings ๐คทโโ๏ธ
Rights is a string listing a (possibly empty) set of alphanumeric characters. Each character lists a set of operations being controlled. Letters are reserved for "standard" rights, listed below. The set of standard rights may only be extended by a standards-track or IESG approved experimental RFC ๐ Digits are reserved for implementation or site defined rights ๐ข The currently defined standard rights are:
x - search (use EQUAL search key with i;octet comparator)
r - read (access with SEARCH command)
w - write (modify with STORE command)
i - insert (perform STORE on a previously NIL value)
a - administer (perform SETACL or STORE on ACL attribute/metadata)
An implementation may force rights to always or never be granted. Implementations are expected to grant implicit read and administer rights to a user's personal dataset storage, in order to avoid denial of service problems ๐ซ Rights are never tied, unlike the IMAP ACL extension [IMAP-ACL] ๐ โโ๏ธ
It's possible for multiple identifiers in an access control list to apply to a given user (or other authentication identity). For example, an ACL may include rights granted to the identifier matching the user, one or more implementation-defined identifiers matching groups that include the user, and/or the identifier anyone. These get combined by taking the union of all positive rights that apply to a given user, then subtracting the union of all negative rights that apply to that user ๐งฎ A client MAY skip this calculation by using the MYRIGHTS command and metadata items โก
Each attribute of each entry of a dataset may potentially have an ACL. If an attribute in an entry doesn't have an ACL, access is controlled by a default ACL for that attribute in the dataset, if one exists. If there's no default ACL for that attribute in the dataset, access is controlled by a default ACL for that dataset. The default ACL for a dataset must exist ๐๏ธ
To do any access or manipulation on an entry in a dataset, the client must have 'r' rights on the entry attribute of that entry ๐ Implementations should take care not to reveal, through error messages, that an entry exists when the client lacks 'r' rights. A client does not need access to the subdataset attribute of the parent dataset to access the contents of a dataset ๐๏ธ
Many ACL commands and responses include an "acl object" parameter, which says what the ACL applies to. It's a parenthesized list. The list contains just the dataset name when referring to the default ACL for a dataset. It contains a dataset name and an attribute name when referring to the default ACL for an attribute in a dataset. And it contains a dataset name, an attribute name, and an entry name when referring to the ACL for an attribute of an entry of a dataset ๐ฏ
3.6. Server Response Codes โจ
Okay bestie, let's dig into the response codes! ๐ An OK, NO, BAD, ALERT or BYE response from the server MAY contain a response code, which is basically extra detail that describes what happened in a machine-parsable way ๐คโจ. A response code is data inside parentheses, shaped like an atom, which might be followed by a space and some arguments ๐. Response codes only exist when there's a specific action a client can take based on the extra info ๐ . To leave room for future extensions, each code is a slash-separated hierarchy, and every level adds more detail about the error ๐ฆ. Clients MUST tolerate the extra hierarchical detail they don't understand, no cap ๐ซถ.
The currently defined response codes are:
AUTH-TOO-WEAK: This one comes back on a tagged NO result from an AUTHENTICATE command ๐ โโ๏ธ. It means site security policy forbids the requested mechanism for that authentication identity ๐.ENCRYPT-NEEDED: Also on a tagged NO result from an AUTHENTICATE command ๐. It means site security policy requires a strong encryption mechanism for the specified authentication identity and mechanism ๐.INVALID: This shows up when a STORE command included data the server implementation doesn't allow ๐. It MUST NOT be used unless the dataset class specification for the attribute in question explicitly permits enforced server validation ๐ซ. The argument is the attribute that was invalid ๐.MODIFIED: A conditional store failed because the modtime on the entry is later than the modtime given with the STORE command's UNCHANGEDSINCE modifier โฐ. The argument is the entry that got modified ๐.NOEXIST: A search or NOCREATE store failed because a dataset didn't exist ๐ซฅ. The argument is the dataset that doesn't exist ๐.PERMISSION: A command failed due to insufficient permission, based on the access control list or implicit rights ๐ช. The argument is the acl-object that caused the failure ๐.QUOTA: A STORE or SETACL command that would have grown the dataset failed because there wasn't enough quota ๐ฆ.REFER: This can come back in a tagged NO response to any command that takes a dataset name as a parameter ๐. It has one or more arguments written as relative URLs, and it's a referral, meaning you should retry the command using one of those relative URLs ๐ง.SASL: This can show up in the tagged OK response to a successful AUTHENTICATE command ๐. It includes the optional final server response data from the server, as specified by SASL [SASL] โจ.TOOMANY: This may be returned in a tagged OK response to a SEARCH command that includes the LIMIT modifier ๐ธ. The argument gives the total number of matching entries ๐ข.TOOOLD: The modtime given in the DELETEDSINCE command is too old, so deletedsince info isn't available anymore ๐ฅ.TRANSITION-NEEDED: This occurs on a NO response to an AUTHENTICATE command ๐. It means the user name is valid, but the entry in the authentication database needs updating before that mechanism can be used to authenticate ๐ ๏ธ. This can happen when someone has an entry in a system authentication database like Unix /etc/passwd but lacks credentials suitable for the specified mechanism ๐.TRYLATER: A command failed because of a temporary server failure โณ. The client MAY continue using local information and try the command later ๐ซง.TRYFREECONTEXT: This may be returned in a tagged NO response to a SEARCH command that includes the MAKECONTEXT modifier ๐งฉ. It means a new context can't be created because the server has a limit on existing contexts ๐ง.WAYTOOMANY: This may be returned in a tagged NO response to a SEARCH command that includes a HARDLIMIT search modifier ๐ญ. It means the SEARCH would have returned more entries than HARDLIMIT allowed ๐ .
Additional response codes MUST be registered with IANA according to the proceedures in section 7.2 ๐. Client implementations MUST tolerate response codes that they do not recognize ๐ซถ.
4. Namespace Conventions โจ
4.1. Dataset Namespace
The dataset namespace is a slash-separated hierarchy ๐๏ธ. The first component is a dataset class. Dataset classes MUST have a vendor prefix (vendor.<vendor/product>) or be specified in a standards track or IESG approved experimental RFC ๐ . See section 7.3 for the registration template ๐.
The second component of the dataset name is "site", "group", "host", or "user", referring to server-wide data, administrative group data, per-host data and per-user data respectively ๐. For "group", "host", and "user" areas, the third component of the path is the group name, the fully qualified host domain name, or the user name ๐ . A path of the form "/<dataset-class>/~/" is a convenient abbreviation for "/<dataset-class>/user/<current-user>/" ๐.
Dataset names that begin with "/byowner/" are reserved as an alternate view of the namespace ๐. This gives you a way to see all the dataset classes a particular owner uses ๐ซฃ. For example, "/byowner/~/<dataset-class>/" is an alternate name for "/<dataset-class>/~/" ๐ฆ. Byowner lists the dataset classes owned by a given user, and you do this with the dataset "/byowner/user/<current-user>/" plus the NOINHERIT SEARCH modifier ๐.
The dataset "/" can be used to find all dataset classes visible to the current user ๐. A dataset of the form "/<dataset-class>/user/" can be used to find all users who have made a dataset or entry of that class visible to the current user ๐.
The formal syntax for a dataset name is defined by the "dataset-name" rule in section 4.3 ๐.
4.2. Attribute Namespace
Attribute names that don't contain a dot (".") are reserved for standardized attributes that have meaning in any dataset ๐ธ. To keep client implementations simple, the attribute namespace is meant to be unique across all datasets ๐ง . To get there, attribute names are prefixed with the dataset class name followed by a dot (".") ๐. Attributes that affect management of the dataset are prefixed with "dataset." ๐ ๏ธ. A subtree of the "vendor." attribute namespace may be registered with IANA according to the rules in section 7.4 ๐. ACAP implementors are encouraged to help define interoperable dataset class specifications rather than using the private attribute namespace ๐ซถ.
Some users or sites may want their own private attributes on certain dataset classes ๐. To allow that, the "user.<user-name>." and "site." subtrees are reserved for user-specific and site-specific attributes respectively, and they will not be standardized ๐. These attributes aren't interoperable, so they're discouraged in favor of defining standard attributes ๐ โโ๏ธ. A future extension is expected to permit discovery of syntax for user or site-specific attributes ๐ฎ. Clients that want to display user or site-specific attributes should display the value of any non-NIL single-valued "user.<user-name>." or "site." attribute that has valid UTF-8 syntax ๐ .
The formal syntax for an attribute name is defined by the "attribute-name" rule in the next section โจ.
4.3. Formal Syntax for Dataset and Attribute Namespace
The naming conventions for datasets and attributes are defined by the following ABNF ๐. Note that this grammar is not part of the ACAP protocol syntax in section 8, because dataset names and attribute names are encoded as strings within the ACAP protocol ๐.
attribute-dacl = "dataset.acl" *("." name-component)
attribute-dset = dataset-std 1*("." name-component)
;; MUST be defined in a dataset class specification
attribute-name = attribute-std / attr-site / attr-user / vendor-name
attribute-std = "entry" / "subdataset" / "modtime" /
"dataset.inherit" / attribute-dacl / attribute-dset
attr-site = "site" 1*("." name-component)
attr-user = "user." name-component 1*("." name-component)
byowner = "/byowner/" owner "/"
[dataset-class "/" dataset-sub]
dataset-class = dataset-std / vendor-name
dataset-normal = "/" [dataset-class "/"
(owner-prefix / dataset-tail)]
dataset-name = byowner / dataset-normal
dataset-std = name-component
;; MUST be registered with IANA and the spec MUST
;; be published as a standards track or
;; IESG-approved experimental RFC
dataset-sub = *(dname-component "/")
;; The rules for this portion of the namespace may
;; be further restricted by the dataset class
;; specification.
dataset-tail = owner "/" dataset-sub
dname-component = 1*UTF8-CHAR
;; MUST NOT begin with "." or contain "/"
name-component = 1*UTF8-CHAR
;; MUST NOT contain ".", "/", "%", or "*"
owner = "site" / owner-host / owner-group /
owner-user / "~"
owner-group = "group/" dname-component
owner-host = "host/" dname-component
owner-prefix = "group/" / "host/" / "user/"
owner-user = "user/" dname-component
vendor-name = vendor-token *("." name-component)
vendor-token = "vendor." name-component
;; MUST be registered with IANA
5. Dataset Management ๐
The entry with an empty name ("") in the dataset holds the management information for the dataset as a whole ๐.
5.1. Dataset Inheritance
A dataset can inherit data from another dataset ๐งฌ. The dataset that data is inherited from is called the base dataset ๐ฑ. Data in the base dataset appears in the inheriting dataset, unless it gets overridden by a STORE to the inheriting dataset ๐ซ.
The base dataset is usually a system-wide or group-wide set of defaults ๐ฐ. A system-wide dataset usually has one inheriting dataset per user, so each user can add to or tweak the defaults as needed ๐ .
An entry that exists in both the inheriting and base dataset inherits a modtime equal to the greater of the two modtimes โฐ. An attribute in such an entry is inherited from the base dataset if it was never modified by a STORE command in the inheriting dataset, or if DEFAULT was stored to that attribute ๐. This means default entries can be amended instead of replaced in the inheriting dataset, which is honestly so iconic ๐โจ.
So, the subdataset attribute does NOT just get copied down the chain ๐
โโ๏ธ ๐
. If the base dataset has a subdataset attribute and the inheriting dataset doesn't, the inheriting one gets a virtual value: a list containing a "." โจ. That subdataset becomes a "virtual" dataset, basically a virtual copy of the base dataset with every subdataset attribute swapped to a list containing "." ๐ฆ. Bestie, the big catch is that a virtual dataset is invisible if NOINHERIT is specified on the SEARCH command ๐.
Servers MUST support at least two levels of inheritance ๐. Picture this: a user's dataset like "/options/user/fred/common" inherits from a group dataset like "/options/group/dinosaur operators/common", which then inherits from a server-wide dataset like "/options/site/common" ๐ฆ. Iconic chain, no notes ๐ซถ.
5.2. Dataset Attributes
These attributes handle managing the dataset and live in the "" entry of a dataset ๐. The big deal here is that none of them get inherited ๐
โโ๏ธ.
dataset.acl: This holds the default access control list for the dataset ๐. It gets validated, so if you STORE an invalid access control list, you'll get a NO response with an INVALID response code ๐.dataset.acl.<attribute>: Same energy, but for one specific attribute inside the dataset ๐ธ. It's validated too, so an invalid access control list in a STORE command gets a NO response with an INVALID response code ๐ญ.dataset.inherit: This holds the name of the dataset to inherit from, following the rules from the previous section ๐ง. It MAY refer to a non-existent dataset, in which case nothing gets inherited ๐. It's validated as well, so illegal dataset syntax or trying to store a multi-value gets a NO response with an INVALID response code ๐.
5.3. Dataset Creation
Okay, so when a dataset is first made (by storing a "." in the subdataset attribute, or by storing an entry in a dataset that didn't exist before), its attributes get initialized from the values in the parent dataset under the /byowner/ hierarchy ๐. For dataset.inherit, the right hierarchy component gets added on top โจ. Quick note: \t means the US-ASCII horizontal tab character ๐.
Here's the example, with an entry like this:
entry path "/byowner/user/joe/"
dataset.acl ("joe\txrwia" "fred\txr")
dataset.inherit "/byowner/site"
If a new dataset class "/byowner/user/joe/new" gets created, it ends up with these dataset attributes ๐ฆ:
entry path "/byowner/user/joe/new/"
dataset.acl ("joe\txrwia" "fred\txr")
dataset.inherit "/byowner/site/new"
And yes, the dataset "/byowner/user/joe/new/" is equivalent to "/new/user/joe/" ๐
. Main character energy ๐.
5.4. Dataset Class Capabilities
Some dataset classes, or features of them, are only useful if there's an active updating client or the server has built-in support for the feature ๐. That's why the dataset class "capability" is reserved, so clients or servers can advertise these features ๐ฃ. The "entry" attribute in this class is the name of the dataset class whose features are being described ๐. The attributes are prefixed with capability.<dataset-class>. and get defined by that dataset class's own specification ๐ง.
Since any unprivileged user can run an active client for themselves, a per-user capability dataset is super useful ๐. The dataset /capability/~/ holds info about every feature available to the user (through inheritance), and /capability/site/ holds info about every feature the site supports ๐.
5.5. Dataset Quotas
Okay, quotas are implementation dependent, both how they're managed and what they cover ๐คทโโ๏ธ. Clients can check the applicable quota limit and usage (in bytes) with the GETQUOTA command ๐. Servers can warn the client about a low quota situation with the QUOTA untagged response ๐จ.
6. Command and Response Specifications
This section describes ACAP commands and responses ๐ . Commands are sorted first by the state they're allowed in, then by a general category of command type ๐๏ธ.
Command arguments, marked "Arguments:" in the command descriptions, are described by what they do, not by their syntax โจ. The exact syntax lives in the Formal Syntax section ๐. Some commands send back specific server data, marked "Data:" in the descriptions ๐. Check the Responses section for those, and the Formal Syntax section for the precise syntax. Any command CAN return server data, which is why commands that don't specifically need server data say "no specific data for this command" instead of "none" ๐.
Hmm, careful: "CAN" is not a keyword and I shouldn't capitalise it. Let me rewrite that sentence in the final, with no caps.
The "Result:" in each command description covers the possible tagged status responses, plus any special interpretation of them ๐ฏ.
6.1. Initial Connection
Upon session startup, the server sends one of two untagged responses: ACAP or BYE ๐ . The untagged BYE response is covered in section 6.2.8 ๐.
6.1.1. ACAP Untagged Response
Data: capability list
The untagged ACAP response says the session is ready for commands ๐. It also has a space-separated list of the capabilities the server supports ๐ง. Each capability is a list: the capability name, optionally followed by capability-specific string arguments ๐.
ACAP capability names MUST be registered with IANA, following the rules in section 7.1 ๐. Client implementations SHOULD NOT require any capability name beyond the ones defined in this specification ๐ โโ๏ธ, and they MUST tolerate any unknown capability names ๐ซถ. A client implementation MAY be configurable to require SASL mechanisms other than CRAM-MD5 [CRAM-MD5] for site security policy reasons ๐.
The following initial capabilities are defined ๐:
CONTEXTLIMIT: This has one argument, a number for the maximum number of contexts the server supports per connection ๐ข. The number 0 means the server has no limit. Otherwise, this number MUST be greater than 100 ๐ฏ.IMPLEMENTATION: This has one argument, a string describing the server implementation ๐ ๏ธ. ACAP clients MUST NOT alter their behavior based on this value ๐ซ. It's mainly for debugging ๐.SASL: This includes a list of the authentication mechanisms the server supports ๐. See section 6.3.1 ๐.
Example:
S: * ACAP (IMPLEMENTATION "ACME v3.5")
(SASL "CRAM-MD5") (CONTEXTLIMIT "200")
6.2. Any State
These commands and responses are valid in any state ๐.
6.2.1. NOOP Command
Arguments: none
Data: no specific data for this command (but see below)
Result: OK - noop completed
BAD - command unknown or arguments invalid
NOOP always succeeds, and it does nothing ๐ด. It can be used to reset any inactivity auto-logout timer on the server โฐ.
Example:
C: a002 NOOP
S: a002 OK "NOOP completed"
6.2.2. LANG Command
Arguments: list of language preferences
Data: intermediate response: LANG
Result: OK - lang completed
NO - no matching language available
BAD - command unknown or arguments invalid
You can send one or more arguments to tell the server which languages you'd like for error messages ๐. The server checks each of your preferences in order against its table of available error string languages ๐. For a match, the client's language tag MUST be a prefix of the server's tag, and it has to match up to a "-" or the end of the string ๐งฉ. If there's a match, the server sends an intermediate LANG response and then an OK response ๐. The LANG response shows the language it actually picked, plus the right comparators to use with the languages listed in the LANG command ๐ฆ.
If no LANG command is issued, all error text strings MUST be in the registered language "i-default" [CHARSET-LANG-POLICY], which is meant for an international audience ๐.
Example:
C: A003 LANG "fr-ca" "fr" "en-ca" "en-uk"
S: A003 LANG "fr-ca" "i;octet" "i;ascii-numeric"
"i;ascii-casemap" "en;primary" "fr;primary"
S: A003 OK "Bonjour"
6.2.3. LANG Intermediate Response
Data: language for error responses
appropriate comparators
The LANG response tells you which language will be used for error responses, plus the comparators that suit the languages listed in the LANG command ๐ฃ๏ธ. The comparators SHOULD go in approximate order, from most efficient (usually "i;octet") to most appropriate for human text in the preferred language ๐.
6.2.4. LOGOUT Command
Arguments: none
Data: mandatory untagged response: BYE
Result: OK - logout completed
BAD - command unknown or arguments invalid
LOGOUT tells the server the client is done with the session ๐. The server must send a BYE untagged response before the (tagged) OK response, and then close the network connection ๐ช.
Example:
C: A023 LOGOUT
S: * BYE "ACAP Server logging out"
S: A023 OK "LOGOUT completed"
(Server and client then close the connection)
6.2.5. OK Response
Data: optional response code
human-readable text
The OK response is an information message from the server โ . When it's tagged, it means the associated command finished successfully ๐ฅณ. The human-readable text can be shown to the user as an information message ๐ฌ. The untagged form is information-only, and the nature of that information MAY be indicated by a response code ๐.
Example:
S: * OK "Master ACAP server is back up"
6.2.6. NO Response
Data: optional response code
human-readable text
The NO response is an operational error message from the server ๐ฌ. When it's tagged, the associated command didn't complete successfully ๐. The untagged form is a warning, and the command may still complete successfully ๐ซ . The human-readable text describes the situation ๐ฃ.
Example:
C: A010 SEARCH "/addressbook/" DEPTH 3 RETURN ("*")
EQUAL "entry" "+i;octet" "bozo"
S: * NO "Master ACAP server is down, your data may
be out of date."
S: A010 OK "search done"
...
C: A222 STORE ("/folder/site/comp.mail.misc"
"folder.creation-time" "19951206103412")
S: A222 NO (PERMISSION ("/folder/site/")) "Permission
denied"
6.2.7. BAD Response
Data: optional response code
human-readable text
Pull the Data block above into the final output exactly as written.
The BAD response is the server's way of saying "something went wrong" ๐ โโ๏ธ. When it's tagged, it's a protocol-level error in the client's command, and the tag tells you which command caused it. The untagged form is a protocol-level error where the server can't figure out which command it belongs to, and it can also mean an internal server failure. Either way, the human-readable text explains what happened ๐ฌ.
Example:
C: ...empty line...
S: * BAD "Empty command line"
C: A443 BLURDYBLOOP
S: A443 BAD "Unknown command"
C: A444 NOOP Hello
S: A444 BAD "invalid arguments"
6.2.8. BYE Untagged Response ๐
Data:
optional response code
human-readable text
The untagged BYE response means the server is about to close the connection ๐ช. The client can show the human-readable text to the user in a status report. BYE can show up as part of a normal logout sequence, or as a panic shutdown announcement from the server ๐ฑ. Some server implementations also use it to announce an inactivity auto-logout ๐ค.
BYE is also one of two possible greetings at session startup ๐ . When it shows up there, it means the server isn't willing to accept a session from this client ๐ซ.
Example:
S: * BYE "Auto-logout; idle for too long"
6.2.9. ALERT Untagged Response ๐จ
Data:
optional response code
human-readable text
The human-readable text carries a special, human-generated alert, and it MUST be presented to the user in a way that grabs their attention ๐ฃ. This is meant for vital messages from the server administrator, like a heads-up that the server is going down for maintenance soon ๐ ๏ธ.
Example:
S: * ALERT "This ACAP server will be shut down in
10 minutes for system maintenance."
6.3. Non-Authenticated State ๐
In non-authenticated state, the AUTHENTICATE command sets up authentication and moves you into authenticated state ๐ชโจ. It's a general mechanism that works for a whole range of authentication techniques.
Server implementations may allow non-authenticated access to certain information by supporting the SASL ANONYMOUS [SASL-ANON] mechanism ๐ต๏ธโโ๏ธ.
Once you're authenticated (including as anonymous), you can't go back to non-authenticated state. No re-entry, bestie ๐ซ.
Only the any-state commands (NOOP, LANG and LOGOUT) and the AUTHENTICATE command are valid in non-authenticated state ๐ .
6.3.1. AUTHENTICATE Command ๐ชช
Arguments/Data/Result:
Arguments: SASL mechanism name
optional initial response
Data: continuation data may be requested
Result: OK - authenticate completed, now in authenticated state
NO - authenticate failure: unsupported authentication
mechanism, credentials rejected
BAD - command unknown or arguments invalid,
authentication exchange cancelled
The AUTHENTICATE command tells the server which SASL [SASL] authentication mechanism you want to use ๐. If the server supports it, the two sides run an authentication exchange to authenticate and identify the user. Optionally, they can also negotiate a security layer for the rest of the protocol interactions ๐ก๏ธ. If the server doesn't support the requested mechanism, it turns down the AUTHENTICATE command with a tagged NO response ๐ โโ๏ธ.
The authentication exchange is a back-and-forth of server challenges and client answers, and the details depend on the mechanism. A server challenge is a command continuation request with the "+" token, followed by a string ๐. The client answer is a line containing a string. If the client wants to cancel the exchange, it should send a line with a single unquoted "*" ๐. If the server gets that answer, it must reject the AUTHENTICATE command with a tagged BAD response ๐.
The optional initial-response argument saves a round trip ๐. It's for mechanisms that send no data in the initial challenge. When you use it with one of those mechanisms, the server doesn't send the empty initial challenge to the client. Instead, it treats the initial-response data as if it had been sent in reply to that empty challenge โจ. If you use the initial-response argument with a mechanism that does send data in the initial challenge, the server rejects the AUTHENTICATE command with a tagged NO response ๐.
The service name for this protocol's profile of SASL is "acap" ๐ท๏ธ.
If a security layer gets negotiated through the SASL exchange, it takes effect right after the CRLF that concludes the authentication exchange for the client, and after the CRLF of the tagged OK response from the server ๐.
All ACAP implementations MUST implement the CRAM-MD5 SASL mechanism [CRAM-MD5], although they MAY offer a configuration option to disable it if site security policy dictates ๐ง. The example below is the same one described in the CRAM-MD5 specification.
Example:
S: * ACAP (IMPLEMENTATION "Blorfysoft v3.5")
(SASL "CRAM-MD5" "KERBEROS_V4")
C: A001 AUTHENTICATE "CRAM-MD5"
S: + "<1896.697170952@postoffice.reston.mci.net>"
C: "tim b913a602c7eda7a495b4e6e7334d3890"
S: A001 OK "CRAM-MD5 authentication successful"
If an AUTHENTICATE command fails with a NO response, the client may try another mechanism by sending another AUTHENTICATE command ๐. In other words, the client can go through the authentication types in decreasing order of preference ๐ฅ๐ฅ๐ฅ.
6.4. Searching ๐
This section covers the SEARCH command, which is how you grab data from datasets ๐.
6.4.1. SEARCH Command ๐
Arguments/Data/Result:
Arguments: dataset or context name
optional list of modifiers
search criteria
Data: intermediate responses: ENTRY, MODTIME, REFER
untagged responses: ADDTO, REMOVEFROM, CHANGE, MODTIME
Result: OK - search completed
NO - search failure: can't perform search
BAD - command unknown or arguments invalid
The SEARCH command finds a subset of entries in a dataset and sends that subset's info back to the client ๐ฏ. Inherited entries and attributes are included in the search, unless the NOINHERIT search modifier is used or the user doesn't have permission to read the attributes in the base dataset ๐งฌ.
The first argument to SEARCH says what gets searched ๐๏ธ. If the string starts with a slash ("/"), it's the name of a dataset. Otherwise, it's the name of a context that an earlier SEARCH command in the session created ๐งญ.
A successful SEARCH command MAY result in intermediate ENTRY responses, and it MUST result in a MODTIME intermediate response โฐ.
After the first argument come zero or more modifiers. Each modifier can only be specified once ๐ซ. Here are the defined modifiers:
DEPTH number Tells SEARCH how far to traverse the dataset tree ๐ณ. ENTRY responses include the full path to the entry. A value of "0" means traverse the entire tree, and "1" is the default, which only searches the specified dataset. If a dataset gets traversed that isn't on the current server, a REFER intermediate response is returned for that subtree, and the search keeps going ๐ช.
HARDLIMIT number If the SEARCH command would return more than number entries, the SEARCH fails with a NO completion result and a WAYTOOMANY response code ๐.
LIMIT number number Caps how many intermediate ENTRY responses the search can generate ๐งข. The first numeric argument is the limit, and the second is how many entries to return if the matches go over the limit. If the limit gets exceeded, SEARCH still succeeds, and the total number of matches comes back in a TOOMANY response code in the tagged OK response ๐ข.
MAKECONTEXT [ENUMERATE] [NOTIFY] context Makes SEARCH create a context with the name given in the argument, which refers to the matching entries ๐๏ธ. If the SEARCH succeeds, that context name can be given to later SEARCH commands to search within the matching entries. If a context with that name already exists, it gets freed first. If a new context can't be created because the server has hit its limit on existing contexts, the command fails and returns a TRYFREECONTEXT response code in the NO completion response ๐งน.
The optional "ENUMERATE" and "NOTIFY" arguments can be included to ask for enumeration of the context (for virtual scroll bars) or for change notifications on the context ๐. If "NOTIFY" isn't requested, the context is a snapshot of the entries at the time the SEARCH was issued ๐ธ.
ENUMERATE asks that the contents of the context be ordered according to the SORT modifier, and that sequential numbers, starting with one, get assigned to the entries in the context ๐ข. That lets the RANGE modifier fetch portions of the ordered context ๐ฐ.
NOTIFY asks the server to send untagged ADDTO, REMOVEFROM, CHANGE, and MODTIME responses while the context created by this SEARCH command exists ๐. The server MAY issue untagged ADDTO, REMOVEFROM, CHANGE and MODTIME notifications for a context at any time between the SEARCH command with MAKECONTEXT NOTIFY and the completion of a FREECONTEXT command for that context โณ. Notifications only cover changes that happen after the server receives the SEARCH command that created the context ๐ฌ. After it sends a sequence of ADDTO, REMOVEFROM or CHANGE notifications, the server MUST send an untagged MODTIME notification, which says the client has all updates to the entries in the context up to and including the given modtime value ๐. Servers are allowed a reasonable delay to batch change notifications before sending them to the client ๐ฆ.
The position arguments of the ADDTO, REMOVEFROM and CHANGE notifications are 0 if ENUMERATE isn't requested 0๏ธโฃ.
NOINHERIT Makes the SEARCH command operate without inheritance ๐ โโ๏ธ. It can be used to tell which values are explicit overrides. If MAKECONTEXT is also specified, the created context isn't affected by inheritance either ๐งฌ.
RETURN (metadata...) Says what should come back in intermediate ENTRY responses ๐. If this modifier isn't specified, no intermediate ENTRY responses get returned ๐ค.
Okay so the RETURN modifier is where it gets fun ๐. Inside the parentheses you can list an optional set of attributes, and each one can optionally be followed by its own parenthesized list of metadata. If you leave off that metadata list, it defaults to (value) ๐.
You can also use a trailing * on an attribute name to ask for every attribute that starts with that prefix, and a * all by itself asks for everything ๐. If you do that with a trailing * and skip the metadata list, it defaults to (attribute value), and the matching results get grouped in parentheses so they're easy to spot โจ.
Once the last intermediate ENTRY response comes back, the server sends one intermediate MODTIME response to close things out ๐ฆ.
SORT (attribute comparator ...) ๐
This one decides what order your ENTRY replies come back in. It takes a parenthesized list of one or more attribute/comparator pairs. The attribute says what to sort on, and the comparator names the collation rule used on that attribute's values. The next pair only gets used to order two entries when all the pairs before it said those two entries collate the same, so it's like a tiebreaker chain ๐.
If you use SORT together with MAKECONTEXT, then SORT sets the order of entries in the context that gets created ๐ง.
If you don't include SORT, or none of the attribute/comparator pairs can tell two entries apart, the server just uses whatever order the entries already have in the context or dataset being searched ๐ซถ.
Next up are the search criteria. These are made of one or more search keys, and you can combine them with AND and OR. Check out this example, where the newline is only there so it's readable and isn't actually part of the criteria ๐:
AND COMPARE "modtime" "+i;octet" "19951206103400"
COMPARE "modtime" "-i;octet" "19960112000000"
That one finds every entry modified between 10:34 December 6 1995 and midnight January 12, 1996 UTC ๐ฅน.
Here are the search keys we've got right now ๐ฅ:
ALL: matches every entry ๐.AND search-key1 search-key2: entries that match both search keys โจ.COMPARE attribute comparator value: entries where the attribute's value collates with the given comparator the same as or later than the given value ๐ธ.COMPARESTRICT attribute comparator value: same idea, but strictly later than the given value, so ties don't count ๐.EQUAL attribute comparator value: entries where the attribute's value is equal to the given value under that comparator ๐.NOT search-key: entries that do NOT match the search key you gave ๐.OR search-key1 search-key2: entries that match either one ๐ฆ.PREFIX attribute comparator value: entries that begin with the given value under that comparator. If the comparator can't do substring matching, the server sends back a BAD response ๐ง.RANGE start end time: entries inside a range of the enumerated context's ordering. The lowest-ordered entry gets number one, the next one gets number two, and so on. The two numbers say the lowest and highest numbers to match. The time tells the server the client has processed notifications for that context up to that point. If the context has changed since then, the server MUST either return a NO with a MODIFIED response code, or return the same results SEARCH would have returned if none of those changes had happened ๐ญ.
RANGE only works on enumerated contexts. If you use RANGE with a dataset or a non-enumerated context, the server MUST return a BAD response ๐ซ.
SUBSTRING attribute comparator value: entries that contain the given value under that comparator. If the comparator can't do substring matching, you get a BAD response ๐ .
6.4.2. ENTRY Intermediate Response
Data: entry name and entry data ๐ท
The ENTRY intermediate response shows up as a result of a SEARCH or STORE command. This is how dataset entries actually make it back to the client ๐.
The ENTRY response starts with the entry name if you sent a SEARCH command without the DEPTH modifier. In every other case it starts with the entry path. After that comes a set of zero or more items, one for each metadata item in the RETURN search modifier. Results that match an attribute pattern, or that return several metadata items, get wrapped in parentheses โจ.
6.4.3. MODTIME Intermediate Response
Data: modtime value โฐ
The MODTIME intermediate response shows up as a result of a SEARCH command. It tells the client that the context that was just created, or the ENTRY responses returned earlier, include every update to those entries up to and including the modtime value in the argument ๐ซถ.
6.4.4. REFER Intermediate Response
Data: dataset path and relative ACAP URLs ๐บ๏ธ
The REFER intermediate response shows up during a multi-level SEARCH where one of the levels lives on a different server. It names the dataset that isn't on the current server, plus one or more relative ACAP URLs that say where that dataset might be found ๐ง.
6.4.5. Search Examples
Here are some SEARCH command exchanges between the client and server ๐:
C: A046 SEARCH "/addressbook/" DEPTH 3 RETURN ("addressbook.Alias"
"addressbook.Email" "addressbook.List") OR NOT EQUAL
"addressbook.Email" "i;octet" NIL NOT EQUAL
"addressbook.List" "i;octet" NIL
S: A046 ENTRY "/addressbook/user/joe/A0345" "fred"
"fred@stone.org" NIL
S: A046 ENTRY "/addressbook/user/fred/A0537" "joe" "joe@stone.org"
NIL
S: A046 ENTRY "/addressbook/group/Dinosaur Operators/A423"
"saurians" NIL "1"
S: A046 MODTIME "19970728105252"
S: A046 OK "SEARCH completed"
C: A047 SEARCH "/addressbook/user/fred/" RETURN ("*") EQUAL "entry"
"i;octet" "A0345"
S: A047 ENTRY "A0345" (("modtime" "19970728102226")
("addressbook.Alias" "fred") ("addressbook.Email"
"fred@stone.org") ("addressbook.CommonName"
"Fred Flintstone") ("addressbook.Surname" "Flintstone")
("addressbook.GivenName" "Fred"))
S: A047 MODTIME "19970728105258"
S: A047 OK "SEARCH completed"
C: A048 SEARCH "/options/~/vendor.example/" RETURN
("option.value"("size" "value" "myrights"))
SORT ("entry" "i;octet") COMPARE "modtime" "i;octet"
"19970727123225"
S: A048 ENTRY "blurdybloop" (5 "ghoti" "rwia")
S: A048 ENTRY "buckybits" (2 "10" "rwia")
S: A048 ENTRY "windowSize" (7 "100x100" "rwia")
S: A048 MODTIME "19970728105304"
S: A048 OK "SEARCH completed"
C: A049 SEARCH "/addressbook/~/public" RETURN ("addressbook.Alias"
"addressbook.Email") MAKECONTEXT ENUMERATE "blob" LIMIT 100 1
SORT ("addressbook.Alias" "i;octet") NOT EQUAL
"addressbook.Email" NIL
S: A049 ENTRY "A437" "aaguy" "aaguy@stone.org"
S: A049 MODTIME "19970728105308"
S: A049 OK (TOOMANY 347) "Context 'blob' created"
C: A050 SEARCH "blob" RANGE 2 2 "19970728105308" ALL
S: A050 ENTRY "A238" "abguy" "abguy@stone.org"
S: A050 MODTIME "19970728105310"
S: A050 OK "SEARCH Completed"
6.5. Contexts
The following commands use contexts that were created by a SEARCH command with a MAKECONTEXT modifier ๐งฉ.
6.5.1. FREECONTEXT Command
Arguments: context name Data: no specific data for this command Result:
OK: freecontext completed ๐NO: freecontext failure, no such context ๐ โโ๏ธBAD: command unknown or arguments invalid ๐
The FREECONTEXT command tells the server to free all the state tied to the named context. After that, the context can't be searched anymore, and the server stops sending untagged responses for it. It also stops counting against the server's limit on how many contexts it can hold ๐ซง.
C: A683 FREECONTEXT "blurdybloop"
S: A683 OK "Freecontext completed"
6.5.2. UPDATECONTEXT Command
Arguments: list of context names Data: untagged responses: ADDTO REMOVEFROM CHANGE MODTIME Result:
OK: updatecontext completed, all updates are done ๐ฅณNO: updatecontext failed, no such context or not a notify context ๐ฌBAD: command unknown or arguments invalid ๐ซ
The UPDATECONTEXT command makes sure the client gets notified of every change the server knows about for the contexts listed as arguments, up to the current time ๐ฌ. The contexts you list have to have already been handed to a successful SEARCH command with a MAKECONTEXT NOTIFY modifier. If any read-write metadata in the context changed since the last MODTIME for that context, a MODTIME untagged response MUST be returned. That still applies to metadata that isn't in the context's RETURN modifier ๐.
The server can send untagged ADDTO, REMOVEFROM, CHANGE, and MODTIME at any time. UPDATECONTEXT is basically the way to "prod" the server into sending any notifications it hasn't sent yet ๐.
The UPDATECONTEXT command SHOULD NOT be used to poll for updates. Don't be that person ๐ โโ๏ธ๐ .
C: Z4S9 UPDATECONTEXT "blurdybloop" "blarfl"
S: Z4S9 OK "client has been notified of all changes"
6.5.3. ADDTO Untagged Response
Data: context name entry name position metadata list
The untagged ADDTO response tells the client that an entry got added to a context ๐ฑ. It includes the position number of the new entry (the first entry in the context is numbered 1), plus any metadata in the entry that matches the RETURN statement from when the context was created โจ.
For enumerated contexts, ADDTO also bumps the position of every member whose position was greater than or equal to the ADDTO position number, adding one to each. For non-enumerated contexts, the position field is always 0 ๐ง.
S: * ADDTO "blurdybloop" "fred" 15
("addressbook.Email" "fred@stone.org")
6.5.4. REMOVEFROM Untagged Response
Data: context name entry name old position
The untagged REMOVEFROM response tells the client that an entry got removed from a context ๐๏ธ. It includes the position number the removed entry used to have (the first entry in the context is numbered 1).
For enumerated contexts, REMOVEFROM subtracts one from the position numbers of every member whose position was greater than the REMOVEFROM position number. For non-enumerated contexts, the position field is always 0 ๐ธ.
S: * REMOVEFROM "blurdybloop" "fred" 15 is the last example from the previous bit, so here it is:
S: * REMOVEFROM "blurdybloop" "fred" 15
6.5.5. CHANGE Untagged Response โจ
Data:
- context name
- entry name
- old position
- new position
- metadata list
The untagged CHANGE response tells the client that an entry in a context either moved to a new position in that context, or had the values of one or more attributes from the RETURN modifier change (the RETURN modifier that was set when the context was created). ๐
The response includes the entry's previous and current position numbers (these are 0 if ENUMERATE wasn't specified on the context), plus the attribute metadata requested in the RETURN modifier when the context was created. ๐ฆ
For enumerated contexts, the CHANGE response quietly shifts the position numbers of every entry that sat between the old and new positions. If old position is less than new position, then one is subtracted from all entries with position numbers in that range. Otherwise, one is added to all entries with position numbers in that range. If old position and new position are the same, no implicit renumbering happens at all. ๐ข
CHANGE responses are not sent for entries whose positions shifted implicitly because of another ADDTO, REMOVEFROM or CHANGE response. Those shifts already come with their own updates, so no need to double up. ๐
Example:
S: * CHANGE "blurdybloop" "fred" 15 10
("addressbook.Email" "fred@stone.org")
6.5.6. MODTIME Untagged Response ๐ฐ๏ธ
Data:
- context name
- modtime value
The untagged MODTIME response tells the client that it has received every update to entries in the context whose modtime values are less than or equal to the modtime value in the argument. Basically a "you're caught up to here" message. ๐ซถ
Example:
S: * MODTIME mycontext "19970320162338"
6.6. Dataset modification ๐ธ
These commands and responses handle changing datasets. Let's go! ๐
6.6.1. STORE Command ๐พ
Arguments: entry store list
Data: intermediate responses: ENTRY
Result:
OK- store completedNO- store failure: can't store that name, orUNCHANGEDSINCEspecified and entry changedBAD- command unknown or arguments invalid, or invalid UTF-8 syntax in attribute name
STORE creates, modifies, or deletes the named entries in the named datasets. Any metadata that isn't specified in the command stays exactly as it was. ๐
Setting the "value" metadata of an attribute to NIL removes that attribute from the entry. Setting the "value" of the "entry" attribute to NIL removes the whole entry from the dataset and cancels inheritance for the entire entry. Setting the "value" of the "entry" attribute to DEFAULT removes that entry from the inheriting dataset and reverts the entry and its attributes to inherited values, if there are any. And changing the value of the "entry" attribute renames the entry. โ๏ธ
Storing DEFAULT to the "value" metadata of an attribute is the same as storing NIL, except that inheritance is turned on for that attribute. If a non-NIL value gets inherited, then an ENTRY intermediate response is sent to tell the client about the change. That ENTRY response includes the entry-path, plus the attribute name and value metadata for each attribute that reverted to a non-NIL inherited setting. ๐
Storing NIL to the "value" metadata of an attribute MAY be treated the same as storing DEFAULT to that "value", if there is a NIL value in the base dataset. ๐ค
The STORE command is followed by one or more entry store lists. Each entry store list starts with an entry path, followed by STORE modifiers, followed by zero or more attribute store items. Each attribute store item is made up of the attribute name followed by NIL (to remove the attribute's value), DEFAULT (to revert the item to any inherited value), a single value (to set the attribute's single value), or a list of metadata items to modify. These STORE modifiers are allowed:
NOCREATE: By default, the server MUST create any datasets needed to store the entry, including multiple hierarchy levels. IfNOCREATEis specified, theSTOREcommand fails with aNOEXISTerror unless the parent dataset already exists. ๐๏ธUNCHANGEDSINCE: If the"modtime"of the entry is later than the unchangedsince time, then the store fails with aMODIFIEDresponse code. UsingUNCHANGEDSINCEwith a time of"00000101000000"will always fail if the entry exists. Clients writing to a shared dataset are encouraged to useUNCHANGEDSINCEwhen modifying an existing entry. ๐
The server MUST either make all the changes specified in a single STORE command, or make none of them. If it succeeds, the server MUST update the "modtime" attribute for every entry that was changed. โฐ
It's illegal to list any metadata item within an attribute twice, any attribute within an entry twice, or any entry path twice. The server MUST return a BAD response if this happens. ๐ซ
The server MAY re-order the strings in a multi-value on STORE and MAY remove duplicate strings. However, SEARCH MUST return multi-values and the associated size list metadata in a consistent order. ๐
Example:
C: A342 STORE ("/addressbook/user/fred/ABC547"
"addressbook.TelephoneNumber" "555-1234"
"addressbook.CommonName" "Barney Rubble"
"addressbook.AlternateNames" ("value"
("Barnacus Rubble" "Coco Puffs Thief"))
"addressbook.Email" NIL)
S: A342 OK "Store completed"
C: A343 STORE ("/addressbook/user/joe/ABD42"
UNCHANGEDSINCE "19970320162338"
"user.joe.hair-length" "10 inches")
S: A343 NO (MODIFIED) "'ABD42' has been changed
by somebody else."
C: A344 STORE ("/addressbook/group/Developers/ACD54"
"entry" NIL)
S: A344 OK "Store completed"
C: A345 STORE ("/option/~/common/SMTPserver"
"option.value" DEFAULT)
S: A345 ENTRY "/option/~/common/SMTPserver"
"option.value" "smtp.server.do.main"
S: A345 OK "Store completed"
C: A347 STORE ("/addressbook/~/" "dataset.inherit"
"/addressbook/group/Developers")
S: A347 OK "Store completed"
6.6.2. DELETEDSINCE Command ๐๏ธ
Arguments:
- dataset name
- time
Data: intermediate response: DELETED
Result:
OK- DELETEDSINCE completedNO- DELETEDSINCE failure: can't read dataset, or date too far in the pastBAD- command unknown or arguments invalid
DELETEDSINCE sends back, in intermediate DELETED replies, the names of entries that were deleted from the named dataset since the given time. Little trip down memory lane! ๐ฐ๏ธ
Servers may impose a limit on the number or age of deleted entry names they keep track of. If the server doesn't have information going back to the specified time, the command fails and returns a TOOOLD response code in the tagged NO response. ๐ฌ
Example:
C: Z4S9 DELETEDSINCE "/folder/site/" 19951205103412
S: Z4S9 DELETED "blurdybloop"
S: Z4S9 DELETED "anteaters"
S: Z4S9 OK "DELETEDSINCE completed"
C: Z4U3 DELETEDSINCE "/folder/site/" 19951009040854
S: Z4U3 NO (TOOOLD) "Don't have that information"
6.6.3. DELETED Intermediate Response ๐
Data: entry name
The intermediate DELETED response shows up as a result of a DELETEDSINCE command. It returns an entry that was deleted from the dataset named in that DELETEDSINCE command. Gone but not forgotten! ๐ฅ
6.7. Access Control List Commands ๐
The commands in this section manage access control lists (ACLs). Permissions are serious business, bestie. ๐
6.7.1. SETACL Command ๐
Arguments:
- acl object
- authentication identifier
- access rights
Data: no specific data for this command
Result:
OK- setacl completedNO- setacl failure: can't set aclBAD- command unknown or arguments invalid
The SETACL command changes the access control list on the specified object so that the specified identifier is granted the permissions listed in rights. If the object didn't already have an access control list, one gets created. โจ
Example:
C: A123 SETACL ("/addressbook/~/public/") "anyone" "r"
S: A123 OK "Setacl complete"
C: A124 SETACL ("/folder/site/") "B1FF" "rwa"
S: A124 NO (PERMISSION ("/folder/site/")) "'B1FF' not
permitted to modify access rights
for '/folder/site/'"
6.7.2. DELETEACL Command ๐งน
Arguments:
- acl object
- optional authentication identifier
Data: no specific data for this command
Result:
OK- deleteacl completedNO- deleteacl failure: can't delete aclBAD- command unknown or arguments invalid
If you give the optional identifier argument, the DELETEACL command removes any part of the access control list on the specified object for that identifier. ๐ฏ
If you leave out the optional identifier argument, the DELETEACL command removes the ACL from the object entirely, so access gets controlled by a higher-level default ACL instead. This form of the DELETEACL command is not permitted on the default ACL for a dataset, and servers MUST return a BAD in that case. ๐ท
Example:
C: A223 DELETEACL ("/addressbook/~/public") "anyone"
S: A223 OK "Deleteacl complete"
C: A224 DELETEACL ("/folder/site")
S: A224 BAD "Can't delete ACL from dataset"
C: A225 DELETEACL ("/addressbook/user/fred"
"addressbook.Email" "barney")
S: A225 OK "Deleteacl complete"
6.7.3. MYRIGHTS Command ๐
Arguments: acl object
Data: intermediate responses: MYRIGHTS
Result:
OK- myrights completedNO- myrights failure: can't get rightsBAD- command unknown or arguments invalid
The MYRIGHTS command returns the set of rights the client has for the given dataset or dataset attribute. Checking your own vibes, basically. ๐ช
Example:
C: A003 MYRIGHTS ("/folder/site")
S: A003 MYRIGHTS "r"
S: A003 OK "Myrights complete"
6.7.4. MYRIGHTS Intermediate Response ๐จ
Data: rights
The MYRIGHTS response shows up as a result of a MYRIGHTS command. Its argument is the set of rights the client has for the object referred to in that command. ๐
6.7.5. LISTRIGHTS Command ๐
Arguments:
- acl object
- authentication identifier
Data: untagged responses: LISTRIGHTS
Result:
OK- listrights completedNO- listrights failure: can't get rights listBAD- command unknown or arguments invalid
The LISTRIGHTS command takes an object and an identifier, and returns info about which rights the current user may revoke or grant to that identifier in the ACL for that object. Power moves only! ๐
Example: C: a001 LISTRIGHTS ("/folder/~/") "smith"
S: a001 LISTRIGHTS "xra" "w" "i"
S: a001 OK Listrights completed
C: a005 LISTRIGHTS ("/folder/site/archive/imap") "anyone"
S: a005 LISTRIGHTS "" "x" "r" "w" "i"
S: a005 OK Listrights completed
6.7.6. LISTRIGHTS Intermediate Response ๐ฆ
Data:
- required rights
- list of optional rights
okay so the LISTRIGHTS response shows up because of a LISTRIGHTS command ๐
The first argument is a string holding the set of rights the identifier will always be granted on the dataset or attribute. That set can be empty, so don't panic if it's "" ๐ซถ
After that come zero or more strings, and each one has a single right that the current user is allowed to revoke or grant to the identifier in that dataset or attribute โจ
The same right MUST NOT be listed more than once in the LISTRIGHTS response. no doubles, bestie ๐
6.8. Quotas ๐ธ
This section defines the commands and responses that relate to quotas. it's giving storage limits, lowkey ๐
6.8.1. GETQUOTA Command ๐
Arguments: dataset
Data: untagged responses: QUOTA
Result:
OK- Quota information returnedNO- Quota failure: can't access resource limit, or no resource limitBAD- command unknown or arguments invalid
the GETQUOTA command takes the name of a dataset and gives you back an untagged QUOTA response ๐ฌ That response has the dataset name, the quota limit in bytes that applies to that dataset, and the quota usage within that limit. The scope of a quota limit is implementation dependent, so it can look different depending on who built it ๐คทโโ๏ธ
Example: C: A043 GETQUOTA "/option/user/fred/common"
S: * QUOTA "/option/user/fred/common" 1048576 2475
S: A043 OK "Getquota completed"
6.8.3. QUOTA Untagged Response ๐ง
Data:
- dataset
- quota limit in bytes
- amount of quota limit used
- extension data
the QUOTA untagged response is generated as a result of a GETQUOTA command. It MAY be generated by the server in response to a SEARCH or STORE command too, to warn you about high usage of a quota โ ๏ธ It includes the name of the applicable dataset, the quota limit in bytes, the quota usage, and some optional extension data.
Clients MUST tolerate the extension data, because its use is reserved for a future extension ๐ฎ
6.9. Extensions ๐
so the protocol can grow without breaking everything, clients MUST tolerate unknown server responses that meet the syntax of response-extend. Clients MUST also tolerate unknown server response codes that meet the syntax of resp-code-ext. New commands MUST be announced through a capability on the initial greeting line, and those commands SHOULD meet the syntax of command-extend ๐
Servers MUST respond to unknown commands with a BAD command completion result. Servers MUST also skip over non-synchronizing literals contained in an unknown command. A server can do this by assuming the unknown command matches the command-extend syntax, or by reading a line at a time and checking for the non-synchronizing literal syntax at the end of the line ๐
7. Registration Procedures ๐
ACAP's whole vibe is providing a structured storage model for all sorts of configuration data ๐ For that potential to actually happen, the Internet community needs to work toward these goals:
- (1) Standardization. It is very important to standardize dataset classes. The authors hope ACAP gets the same success SNMP has seen with the definition of numerous standards track MIBs ๐
- (2) Community Review. In the absence of standardization, it's important to get community review on a proposal so its engineering quality improves ๐ Community review is strongly recommended prior to registration. The ACAP implementors mailing list
<ietf-acap@andrew.cmu.edu>should be used for this purpose ๐ฎ - (3) Registration. Registration serves a two-fold purpose. First, it prevents use of the same name for different purposes. Second, it provides a one-stop list that can be used to locate existing extensions or dataset classes, so nobody duplicates work ๐ฆ
The following registration templates may be used to register ACAP protocol elements with the Internet Assigned Numbers Authority (IANA) ๐งพ
7.1. ACAP Capabilities ๐
New ACAP capabilities MUST be registered prior to use. no skipping this step, bestie ๐ โโ๏ธ Careful consideration should be made before extending the protocol, because it can lead to complexity or interoperability problems. Review of proposals on the acap implementors mailing list is strongly encouraged prior to registration.
To: iana@iana.org
Subject: Registration of ACAP capability
Capability name:
Capability keyword:
Capability arguments:
Published Specification(s):
(Optional, but strongly encouraged)
Person and email address to contact for further information:
7.2. ACAP Response Codes ๐
ACAP response codes are registered on a first come, first served basis. Review of proposals on the acap implementors mailing list is strongly encouraged prior to registration ๐
To: iana@iana.org
Subject: Registration of ACAP response code
Response Code:
Arguments (use ABNF to specify syntax):
Purpose:
Published Specification(s):
(Optional, but strongly encouraged)
Person and email address to contact for further information:
7.3. Dataset Classes ๐
A dataset class provides a core set of attributes for use in a specified hierarchy. It may also define rules for the dataset hierarchy underneath that class. Dataset class specifications must be standards track or IESG approved experimental RFCs ๐
To: iana@iana.org
Subject: Registration of ACAP dataset class
Dataset class name/attribute prefix:
Purpose:
Published Specification(s):
(Standards track or IESG approved experimental RFC)
Person and email address to contact for further information:
7.4. Vendor Subtree ๐ข
Vendors may reserve a portion of the ACAP namespace for private use. Dataset class names beginning with "vendor.<company/product name>." are reserved for use by that company or product. Also, all attribute names beginning with "vendor.<company/product name>." are reserved for use by that company or product once registered. Registration is first come, first served. Whenever possible, private attributes and dataset classes should be avoided in favor of improving interoperable dataset class definitions ๐ซถ
To: iana@iana.org
Subject: Registration of ACAP vendor subtree
Private Prefix: vendor.<company/product name>.
Person and email address to contact for further information:
(company names and addresses should be included when appropriate)
8. Formal Syntax ๐ง
The following syntax specification uses the augmented Backus-Naur Form (BNF) notation as specified in [ABNF]. It uses the ABNF core rules as specified in Appendix A of the ABNF specification [ABNF] โจ
Except as noted otherwise, all alphabetic characters are case-insensitive. Using upper or lower case characters to define token strings is only for editorial clarity. Implementations MUST accept these strings in a case-insensitive fashion ๐
The initial-greeting rule defines the initial ACAP greeting from the server. The command rule defines the syntax for commands sent by the client. The response rule defines the syntax for responses sent by the server ๐
ATOM-CHAR = "!" / %x23-27 / %x2A-5B / %x5D-7A / %x7C-7E
;; Any CHAR except ATOM-SPECIALS
ATOM-SPECIALS = "(" / ")" / "{" / SP / CTL / QUOTED-SPECIALS
CHAR = %x01-7F
DIGIT-NZ = %x31-39
; non-zero digits ("1" - "9")
QUOTED-CHAR = SAFE-UTF8-CHAR / "\" QUOTED-SPECIALS
QUOTED-SPECIALS = <"> / "\"
SAFE-CHAR = %x01-09 / %x0B-0C / %x0E-21 /
%x23-5B / %x5D-7F
;; any TEXT-CHAR except QUOTED-SPECIALS
SAFE-UTF8-CHAR = SAFE-CHAR / UTF8-2 / UTF8-3 / UTF8-4 /
UTF8-5 / UTF8-6
TAG-CHAR = %x21 / %x23-27 / %x2C-5B / %x5D-7A / %x7C-7E
;; Any ATOM-CHAR except "*" or "+"
TEXT-CHAR = %x01-09 / %x0B-0C / %x0E-7F
;; any CHAR except CR and LF
TEXT-UTF8-CHAR = SAFE-UTF8-CHAR / QUOTED-SPECIALS
UTF8-1 = %x80-BF
UTF8-2 = %xC0-DF UTF8-1
UTF8-3 = %xE0-EF 2UTF8-1
UTF8-4 = %xF0-F7 3UTF8-1
UTF8-5 = %xF8-FB 4UTF8-1
UTF8-6 = %xFC-FD 5UTF8-1
UTF8-CHAR = TEXT-UTF8-CHAR / CR / LF
acl = "(" [acl-identrights *(SP acl-identrights)] ")"
*(SPACE acl-identrights)] ")"
acl-identifier = string-utf8
;; MUST NOT contain HTAB
acl-identrights = string-utf8
;; The identifier followed by a HTAB,
;; followed by the rights.
acl-delobject = "(" dataset SP attribute [SP entry-name] ")"
acl-object = "(" dataset [SP attribute [SP entry-name]] ")"
acl-rights = quoted
atom = ALPHA *1023ATOM-CHAR
attribute = string-utf8
;; dot-separated attribute name
;; MUST NOT contain "*" or "%"
attribute-store = attribute SP (value-nildef /
"(" 1*(metadata-write-q SP value-store) ")")
;; MUST NOT include the same metadata twice
auth-type = <"> auth-type-name <">
auth-type-name = iana-token
;; as defined in SASL [SASL]
command = tag SP (command-any / command-auth /
command-nonauth) CRLF
;; Modal based on state
command-authent = "AUTHENTICATE" SP auth-type
[SP string] *(CRLF string)
command-any = "NOOP" / command-lang / "LOGOUT" /
command-extend
command-auth = command-delacl / command-dsince /
command-freectx / command-getquota /
command-lrights / command-myrights /
command-search / command-setacl /
command-store
;; only valid in authenticated state
command-delacl = "DELETEACL" SP acl-delobject [SP acl-identifier]
command-dsince = "DELETEDSINCE" SP dataset SP time
command-extend = extend-token [SP extension-data]
command-freectx = "FREECONTEXT" SP context
command-getquota = "GETQUOTA" SP dataset
command-lang = "LANG" *(SP lang-tag)
command-lrights = "LISTRIGHTS" SP acl-object
command-myrights = "MYRIGHTS" SP acl-object
command-nonauth = command-authent
;; only valid in non-authenticated state
command-search = "SEARCH" SP (dataset / context)
*(SP search-modifier) SP search-criteria
;; MUST NOT include same search-modifier twice
command-setacl = "SETACL" SP acl-object SP acl-identifier
SP acl-rights
command-store = "STORE" SP store-entry-list
comparator = <"> comparator-name <">
comparator-name = ["+" / "-"] iana-token
context = string-utf8
;; MUST NOT begin with slash ("/")
dataset = string-utf8
;; slash-separated dataset name
;; begins with slash
entry = entry-name / entry-path
entry-name = string-utf8
;; entry name MUST NOT contain slash
;; MUST NOT begin with "."
entry-path = string-utf8
;; slash-separated path to entry
;; begins with slash
entry-relative = string-utf8
;; potentially relative path to entry
extend-token = atom
;; MUST be defined by a standards track or
;; IESG approved experimental protocol extension
extension-data = extension-item *(SP extension-item)
extension-item = extend-token / string / number /
"(" [extension-data] ")"
iana-token = atom
;; MUST be registered with IANA
initial-greeting = "*" SP "ACAP" *(SP "(" init-capability ")") CRLF
init-capability = init-cap-context / init-cap-extend /
init-cap-implem / init-cap-sasl
init-cap-context = "CONTEXTLIMIT" SP string
init-cap-extend = iana-token [SP string-list]
init-cap-implem = "IMPLEMENTATION" SP string
init-cap-sasl = "SASL" SP string-list
lang-tag = <"> Language-Tag <">
;; Language-Tag rule is defined in [LANG-TAGS]
literal = "{" number [ "+" ] "}" CRLF *OCTET
;; The number represents the number of octets
;; MUST be literal-utf8 except for values
literal-utf8 = "{" number [ "+" ] "}" CRLF *UTF8-CHAR
;; The number represents the number of octets
;; not the number of characters
metadata = attribute [ "(" metadata-type-list ")" ]
;; attribute MAY end in "*" as wildcard.
metadata-list = metadata *(SP metadata)
metadata-type = "attribute" / "myrights" / "size" /
"count" / metadata-write
metadata-type-q = <"> metadata-type <">
metadata-type-list = metadata-type-q *(SP metadata-type-q)
metadata-write = "value" / "acl"
metadata-write-q = <"> metadata-write <">
nil = "NIL"
number = *DIGIT
;; A 32-bit unsigned number.
;; (0 <= n < 4,294,967,296)
nz-number = DIGIT-NZ *DIGIT
;; A 32-bit unsigned non-zero number.
;; (0 < n < 4,294,967,296)
position = number
;; "0" if context is not enumerated
;; otherwise this is non-zero
quota-limit = number
quota-usage = number
quoted = <"> *QUOTED-CHAR <">
;; limited to 1024 octets between the <">s
response = response-addto / response-alert / response-bye /
response-change / response-cont /
response-deleted / response-done /
response-entry / response-extend /
response-listr / response-lang /
response-mtimei / response-mtimeu /
response-myright / response-quota /
response-refer / response-remove / response-stat
response-addto = "*" SP "ADDTO" SP context SP entry-name
SP position SP return-data-list
response-alert = "*" SP "ALERT" SP resp-body CRLF
;; Client MUST display alert text to user
response-bye = "*" SP "BYE" SP resp-body CRLF
;; Server will disconnect condition
response-change = "*" SP "CHANGE" SP context SP entry-name
SP position SP position SP return-data-list
response-cont = "+" SP string
response-deleted = tag SP "DELETED" SP entry-name
response-done = tag SP resp-cond-state CRLF
response-entry = tag SP "ENTRY" SP entry SP return-data-list
response-extend = (tag / "*") SP extend-token [SP extension-data]
response-lang = "*" SP "LANG" SP lang-tag 1*(SP comparator)
response-listr = tag SP "LISTRIGHTS" SP acl-rights
*(SP acl-rights)
response-mtimei = tag SP "MODTIME" SP time
response-mtimeu = "*" SP "MODTIME" SP context SP time
response-myright = tag SP "MYRIGHTS" SP acl-rights
response-quota = "*" SP "QUOTA" SP dataset SP quota-limit
SP quota-usage [SP extension-data]
response-refer = tag SP "REFER" SP dataset
1*(SP <"> url-relative <">)
response-remove = "*" SP "REMOVEFROM" SP context SP
entry-name SP position
response-stat = "*" SP resp-cond-state CRLF
resp-body = ["(" resp-code ")" SP] quoted
resp-code = "AUTH-TOO-WEAK" / "ENCRYPT-NEEDED" /
resp-code-inval / resp-code-mod /
resp-code-noexist / resp-code-perm / "QUOTA" /
resp-code-refer / resp-code-sasl /
resp-code-toomany / "TOOOLD" /
"TRANSITION-NEEDED" / "TRYFREECONTEXT" /
"TRYLATER" / "WAYTOOMANY" / resp-code-ext
resp-code-ext = iana-token [SP extension-data]
;; unknown codes MUST be tolerated by the client
resp-code-inval = "INVALID" 1*(SP entry-path SP attribute)
resp-code-mod = "MODIFIED" SP entry-path
resp-code-noexist = "NOEXIST" SP dataset
resp-code-perm = "PERMISSION" SP acl-object
resp-code-refer = "REFER" 1*(SP <"> url-relative <">)
resp-code-sasl = "SASL" SP string
resp-code-toomany = "TOOMANY" SP nz-number
resp-cond-state = ("OK" / "NO" / "BAD") SP resp-body
;; Status condition
return-attr-list = "(" return-metalist *(SP return-metalist) ")"
;; occurs when "*" in RETURN pattern on SEARCH
return-data = return-metadata / return-metalist /
return-attr-list
return-data-list = return-data *(SP return-data)
return-metalist = "(" return-metadata *(SP return-metadata) ")"
;; occurs when multiple metadata items requested
return-metadata = nil / string / value-list / acl
searchkey-equal = "EQUAL" SP attribute SP comparator SP value-nil
searchkey-comp = "COMPARE" SP attribute SP comparator SP value
searchkey-prefix = "PREFIX" SP attribute SP comparator SP value
searchkey-range = "RANGE" SP nz-number SP nz-number SP time
searchkey-strict = "COMPARESTRICT" SP attribute SP comparator
SP value
searchkey-substr = "SUBSTRING" SP attribute SP comparator SP value
searchmod-depth = "DEPTH" SP number
searchmod-hard = "HARDLIMIT" SP nz-number
searchmod-limit = "LIMIT" SP number SP number
searchmod-make = "MAKECONTEXT" [SP "ENUMERATE"]
[SP "NOTIFY"] SP context
searchmod-ninh = "NOINHERIT"
searchmod-return = "RETURN" SP "(" [metadata-list] ")"
searchmod-sort = "SORT" SP "(" sort-list ")"
search-criteria = "ALL" / searchkey-equal / searchkey-comp /
searchkey-strict / searchkey-range /
searchkey-prefix / searchkey-substr /
"NOT" SP search-criteria /
"OR" SP search-criteria SP search-criteria /
"AND" SP search-criteria SP search-criteria
search-modifier = searchmod-depth / searchmod-hard /
searchmod-limit / searchmod-make /
searchmod-ninh / searchmod-return /
searchmod-sort
sort-list = sort-item *(SP sort-item)
sort-item = attribute SP comparator
store-entry = "(" entry-path *(SP store-modifier)
*(SP attribute-store) ")"
;; MUST NOT include same store-modifier twice
;; MUST NOT include same attribute twice
store-entry-list = store-entry *(SP store-entry)
;; MUST NOT include same entry twice
store-modifier = store-mod-unchang / store-mod-nocreate
store-mod-nocreate = "NOCREATE"
store-mod-unchang = "UNCHANGEDSINCE" SP time
string = quoted / literal
string-list = string *(SP string)
string-utf8 = quoted / literal-utf8
tag = 1*32TAG-CHAR
time = <"> time-year time-month time-day time-hour
time-minute time-second time-subsecond <">
;; Timestamp in UTC
time-day = 2DIGIT ;; 01-31
time-hour = 2DIGIT ;; 00-23
time-minute = 2DIGIT ;; 00-59
time-month = 2DIGIT ;; 01-12
time-second = 2DIGIT ;; 00-60
time-subsecond = *DIGIT
time-year = 4DIGIT
value = string
value-list = "(" [value *(SP value)] ")"
value-nil = value / nil
value-nildef = value-nil / "DEFAULT"
value-store = value-nildef / value-list / acl
url-acap = "acap://" url-server "/" url-enc-entry
[url-filter] [url-extension]
;; url-enc-entry interpreted relative to "/"
url-attr-list = url-enc-attr *("&" url-enc-attr)
url-auth = ";AUTH=" ("*" / url-enc-auth)
url-achar = uchar / "&" / "=" / "~"
;; See RFC 1738 for definition of "uchar"
url-char = uchar / "=" / "~" / ":" / "@" / "/"
;; See RFC 1738 for definition of "uchar"
url-enc-attr = 1*url-char
;; encoded version of attribute name
url-enc-auth = 1*url-achar
;; encoded version of auth-type-name above
url-enc-entry = 1*url-char
;; encoded version of entry-relative above
url-enc-user = *url-achar
;; encoded version of login userid
url-extension = *("?" 1*url-char)
url-filter = "?" url-attr-list
url-relative = url-acap / [url-enc-entry] [url-filter]
;; url-enc-entry is relative to base URL
url-server = [url-enc-user [url-auth] "@"] hostport
;; See RFC 1738 for definition of "hostport"
9. Multi-lingual Considerations โจ
Okay so this bit is about languages ๐ธ The IAB charset workshop [IAB-CHARSET] reached a bunch of conclusions that shaped how ACAP got designed ๐
. The big one is that UTF-8 was picked as the character encoding, and that choice came straight out of that workshop work ๐. There's also the LANG command, which lets you negotiate a language for error messages ๐ซถ.
Now here's the tea ๐ต Section 3.4.5 of the IAB charset workshop report says there should be a way to identify the natural language of human readable strings ๐ง. The thing is, ACAP has several promising proposals on the table, but right now nobody has landed on one clear winner ๐ญ. So the spec isn't locking anything in yet โจ.
That said, the plan is that these rules will probably let multi-lingual support get added later ๐ฆ:
okay so bestie, these notes are basically "heads up for the future" vibes ๐ฎ
(1) there's this work in progress called Multi-Lingual String Format (MLSF) ๐ and it wants to sit on top of UTF-8 and use byte sequences that are normally illegal to stash language tags ๐ณ๏ธโ๐. So that it can be added to a future version of this standard, client-side UTF-8 interpreters MUST be able to silently ignore illegal multi-byte UTF-8 characters, and treat illegal single-byte UTF-8 characters as end of string markers ๐. Servers, for now, MUST be able to silently accept illegal UTF-8 characters, except in attribute names and entry names ๐. Clients MUST NOT send illegal UTF-8 characters to the server unless a future standard changes this rule ๐ซ.
(2) there's a proposal to add language tags to Unicode ๐. To make that work, servers MUST be able to store UTF-8 characters of up to 20 bits of data ๐พ.
(3) the metadata item "language" is reserved for future use ๐ง.
10. Security Considerations ๐
okay this section is serious, so read it with your whole brain, no cap ๐ญ
The AUTHENTICATE command uses SASL [SASL] to give you basic authentication, authorization, integrity and privacy services. This is described in section 6.3.1 ๐ก๏ธ.
When the CRAM-MD5 mechanism is used, the security considerations for the CRAM-MD5 SASL mechanism [CRAM-MD5] apply. CRAM-MD5 is also susceptible to passive dictionary attacks ๐. That means if a passive observer records an authentication session, they can try common passwords through the CRAM-MD5 mechanism and see if the results match. Hard-to-guess passwords make this attack weaker ๐. Sites are encouraged to educate users and to have the password change service test candidate passwords against a dictionary ๐. ACAP implementations of CRAM-MD5 SHOULD permit passwords of at least 64 characters in length ๐.
ACAP protocol transactions are open to passive observers or man in the middle attacks that alter the data ๐ฑ, unless the optional encryption and integrity services of the AUTHENTICATE command are enabled, or an external security mechanism is used for protection. It may be useful to let both clients and servers be configured to refuse to transfer sensitive information when strong encryption is absent ๐.
ACAP access control lists give fine grained authorization for access to attributes ๐. A number of related security issues are described in section 3.5 ๐ง.
ACAP URLs have the same security considerations as IMAP URLs [IMAP-URL] ๐.
ACAP clients are encouraged to think about the security problems of a shared lab computer situation ๐ฅ๏ธ. Specifically, a client cache of ACAP configuration information MUST NOT allow access by an unauthorized user. One way to make sure of this is for an ACAP client to be able to completely flush any non-public cached configuration data when a user leaves ๐งน.
Laptops can be easily stolen, and a cache of configuration data may contain sensitive information ๐ป. So a disconnected mode ACAP client may wish to encrypt and password protect cached configuration information ๐.
11. Acknowledgments ๐
Many thanks to the following people who have contributed to ACAP over the past four years ๐ซถ: Wallace Colyer, Mark Crispin, Jack DeWinter, Rob Earhart, Ned Freed, Randy Gellens, Terry Gray, J. S. Greenfield, Steve Dorner, Steve Hole, Steve Hubert, Dave Roberts, Bart Schaefer, Matt Wall and other participants of the IETF ACAP working group โจ.
12. Authors' Addresses ๐
here are the brilliant minds behind it ๐ง
Chris Newman
Innosoft International, Inc.
1050 Lakes Drive
West Covina, CA 91790 USA
Email: chris.newman@innosoft.com
John Gardiner Myers
Netscape Communications
501 East Middlefield Road
Mail Stop MV-029
Mountain View, CA 94043
Email: jgmyers@netscape.com
A. References โจ
okay bestie, the references are where all the good stuff lives ๐๐ซถ every single one is kept exactly as written, so you can chase down any source you need.
- [ABNF] Crocker, Overell, "Augmented BNF for Syntax Specifications: ABNF", RFC 2234, Internet Mail Consortium, Demon Internet Ltd, November 1997.
ftp://ds.internic.net/rfc/rfc2234.txt
- [BASIC-URL] Berners-Lee, Masinter, McCahill, "Uniform Resource Locators (URL)", RFC 1738, CERN, Xerox Coproration, University of Minnesota, December 1994.
ftp://ds.internic.net/rfc/rfc1738.txt
- [CHARSET-LANG-POLICY] Alvestrand, "IETF Policy on Character Sets and Languages", work in progress.
- [CRAM-MD5] Klensin, Catoe, Krumviede, "IMAP/POP AUTHorize Extension for Simple Challenge/Response", RFC 2195, MCI, September 1997.
ftp://ds.internic.net/rfc/rfc2195.txt
- [IAB-CHARSET] Weider, Preston, Simonsen, Alvestrand, Atkinson, Crispin, Svanberg, "The Report of the IAB Character Set Workshop held 29 February - 1 March, 1996", RFC 2130, April 1997.
ftp://ds.internic.net/rfc/rfc2130.txt
- [IMAP4] Crispin, M., "Internet Message Access Protocol - Version 4rev1", RFC 2060, University of Washington, December 1996.
ftp://ds.internic.net/rfc/rfc2060.txt
- [IMAP-ACL] Myers, J., "IMAP4 ACL extension", RFC 2086, Carnegie Mellon, January 1997.
ftp://ds.internic.net/rfc/rfc2086.txt
- [IMAP-URL] Newman, "IMAP URL Scheme", RFC 2192, Innosoft, July 1997.
ftp://ds.internic.net/rfc/rfc2192.txt
- [ISO-10646] ISO/IEC 10646-1:1993(E) "Information Technology-- Universal Multiple-octet Coded Character Set (UCS)." See also amendments 1 through 7, plus editorial corrections.
- [ISO-C] "Programming languages -- C", ISO/IEC 9899:1990, International Organization for Standardization. This is effectively the same as ANSI C standard X3.159-1989.
- [KEYWORDS] Bradner, "Key words for use in RFCs to Indicate Requirement Levels", RFC 2119, Harvard University, March 1997.
ftp://ds.internic.net/rfc/rfc2119.txt
- [LANG-TAGS] Alvestrand, H., "Tags for the Identification of Languages", RFC 1766.
ftp://ds.internic.net/rfc/rfc1766.txt
- [REL-URL] Fielding, "Relative Uniform Resource Locators", RFC 1808, UC Irvine, June 1995.
ftp://ds.internic.net/rfc/rfc1808.txt
- [SASL] Myers, J., "Simple Authentication and Security Layer (SASL)", RFC 2222, Netscape Communications, October 1997.
ftp://ds.internic.net/rfc/rfc2222.txt
- [SASL-ANON] Newman, C., "Anonymous SASL Mechanism", RFC 2245, November 1997.
- [UNICODE-2] The Unicode Consortium, "The Unicode Standard, Version 2.0", Addison-Wesley, 1996. ISBN 0-201-48345-9.
- [US-ASCII] "USA Standard Code for Information Interchange," X3.4. American National Standards Institute: New York (1968).
- [UTF8] Yergeau, F. "UTF-8, a transformation format of Unicode and ISO 10646", RFC 2044, Alis Technologies, October 1996.
ftp://ds.internic.net/rfc/rfc2044.txt
B. ACAP Keyword Index ๐๏ธ
this index is basically your cheat sheet for finding every ACAP keyword, command, response and attribute, with the page where each one shows up ๐ every entry is copied exactly as it appears.
ACAP (untagged response) ................................... 26
ADDTO (untagged response) .................................. 40
ALERT (untagged response) .................................. 31
ALL (search keyword) ....................................... 36
AND (search keyword) ....................................... 36
AUTH-TOO-WEAK (response code) .............................. 19
AUTHENTICATE (command) ..................................... 31
BAD (response) ............................................. 30
BYE (untagged response) .................................... 30
CHANGE (untagged response) ................................. 41
COMPARE (search keyword) ................................... 36
COMPARESTRICT (search keyword) ............................. 36
CONTEXTLIMIT (ACAP capability) ............................. 27
DELETEACL (command) ........................................ 46
DELETED (intermediate response) ............................ 45
DELETEDSINCE (command) ..................................... 45
DEPTH (search modifier) .................................... 34
ENCRYPT-NEEDED (response code) ............................. 19
ENTRY (intermediate response) .............................. 37
EQUAL (search keyword) ..................................... 37
FREECONTEXT (command) ...................................... 39
GETQUOTA (command) ......................................... 48
HARDLIMIT (search modifier) ................................ 34
IMPLEMENTATION (ACAP capability) ........................... 27
INVALID (response code) .................................... 19
LANG (command) ............................................. 28
LANG (intermediate response) ............................... 28
LIMIT (search modifier) .................................... 34
LISTRIGHTS (command) ....................................... 47
LISTRIGHTS (intermediate response) ......................... 48
LOGOUT (command) ........................................... 29
MAKECONTEXT (search modifier) .............................. 34
MODIFIED (response code) ................................... 19
MODTIME (intermediate response) ............................ 38
MODTIME (untagged response) ................................ 42
MYRIGHTS (command) ......................................... 47
MYRIGHTS (intermediate response) ........................... 47
NO (response) .............................................. 29
NOCREATE (store modifier) .................................. 44
NOEXIST (response code) .................................... 19
NOINHERIT (search modifier) ................................ 35
NOOP (command) ............................................. 27
NOT (search keyword) ....................................... 37
OK (response) .............................................. 29
OR (search keyword) ........................................ 37
PERMISSION (response code) ................................. 19
PREFIX (search keyword) .................................... 37
QUOTA (response code) ...................................... 19
QUOTA (untagged response) .................................. 49
RANGE (search keyword) ..................................... 37
REFER (intermediate response) .............................. 38
REFER (response code) ...................................... 19
REMOVEFROM (untagged response) ............................. 41
RETURN (search modifier) ................................... 35
SASL (ACAP capability) ..................................... 27
SASL (response code) ....................................... 20
SEARCH (command) ........................................... 33
SETACL (command) ........................................... 46
SORT (search modifier) ..................................... 36
STORE (command) ............................................ 42
SUBSTRING (search keyword) ................................. 37
TOOMANY (response code) .................................... 20
TOOOLD (response code) ..................................... 20
TRANSITION-NEEDED (response code) .......................... 20
TRYFREECONTEXT (response code) ............................. 20
TRYLATER (response code) ................................... 20
UNCHANGEDSINCE (store modifier) ............................ 44
UPDATECONTEXT (command) .................................... 40
WAYTOOMANY (response code) ................................. 20
acl (attribute metadata) ................................... 12
anyone (ACL identifier) .................................... 17
attribute (attribute metadata) ............................. 12
dataset.acl (dataset attribute) ............................ 24
dataset.acl.<attribute> (dataset attribute) ................ 24
dataset.inherit (dataset attribute) ........................ 24
entry (predefined attribute) ............................... 11
i;ascii-casemap (comparator) ............................... 16
i;ascii-numeric (comparator) ............................... 16
i;octet (comparator) ....................................... 16
modtime (predefined attribute) ............................. 11
myrights (attribute metadata) .............................. 12
size (attribute metadata) .................................. 13
subdataset (predefined attribute) .......................... 11
value (attribute metadata) ................................. 13
C. Full Copyright Statement ๐
okay this is the legal bit, and I'm keeping every word so nothing gets lost ๐
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 implmentation 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: rfc2244 1997-11
- ๐ girlified by claude-haiku-5-5 on : a language model's rewrite of the original, under its terms