naim recognizes several flavours of CTCPs, including the 1994 revision of the IRC Client to Client Protocol, the 2002 revision (previously undocumented) to the AIM Extra Client Transaction specification, and the 2002 adaptation (previously undocumented) to ECT to operate under Lily. This document will document any revisions that are naim-specific, or have previously been undocumented.
ECT under AIM currently uses HTML FONT tags to hide messages from non-participating clients. A participating client searches message text for the string
"<font ECT=\"" followed by a block of characters that make up the request terminated with the string "\"></font>". A complete ECT request
might therefore be: <font ECT="VERSION"></font>
. ECT replies are sent the same way, with the "auto" flag set. A complete ECT
reply might therefore be: <font ECT="VERSION naim:0.11.5.8:Linux 2.4.20"></font>
.
ECT under Lily currently uses normal messages, but the protocol driver transparently drops messages destined for clients that haven't advertized
themselves as participating. Currently, clients advertize participation by joining the special (invulnerable) discussion "-ctcpmagic" and remaining
there for as long as the user is connected. A participating client will scan incoming messages for the string "CTCP REQ " and treat the remainder of the
message as the request. A complete ECT request might therefore be: CTCP REQ VERSION
. ECT replies are sent the same way using the string
"CTCP REP " instead of "CTCP REQ ". A complete ECT reply might therefore be: CTCP REP naim:0.11.5.8:Linux 2.4.20
.
The original implementations of CTCP-aware clients were designed around the use of CTCP as a "user to client" protocol, rather than strictly a "client to client" protocol. The most common application of CTCP is the ACTION request, used to simulate the EMOTE command popular on MUDs. The IRC protocol only provides for two types of private messages, a PRIVMSG and a NOTICE, the former to be taken as something spoken aloud, and the latter to be taken as some sort of automatic reply to the former. The CTCP ACTION routine describes actions a user is taking in the artificial environment created within IRC, and is tied directly into the /ME or /ACTION commands. After ACTION, the second most common application of CTCP is the PING request, which is simply a remote echo service. A user will issue the /PING command against another user's name, and his client will send a CTCP PING request enclosed with a representation of the current time. Participating clients will respond with a CTCP PING reply and the same time string. Upon receipt of the reply, the originating client can compare the time stamp with the current time, and compute the round-trip time.
naim adds a new CTCP request type, AUTOPEER, to be used exclusively for client to client capabilities exchange. naim uses an AUTOPEER CTCP request to identify other clients that support it, then uses it to identify client capabilities and synchronize features. At the time of writing, the two client capabilities that make use of AUTOPEER are AUTOZONE and AUTOCRYPT.
Participating clients will encode or otherwise transmit a CTCP AUTOPEER request without user intervention the first time a user contacts another one for
a given session. A session in terms of AUTOPEER is ended when either client disconnects, or otherwise becomes untrackable (such as when one peer leaves
all channels the other peer is in on IRC). A CTCP AUTOPEER synchronization request is formatted as CTCP "AUTOPEER +AUTOPEER:version" where version is a
positive number representing the revision of the AUTOPEER spec the client participates in, currently "3". A complete AUTOPEER synchronization request
might therefore be: (in IRC) PRIVMSG victim :\001AUTOPEER +AUTOPEER:3\001
, (in AIM) toc_send_im victim "<font ECT=\"AUTOPEER
+AUTOPEER:3\"></font>"
, (in Lily) victim:CTCP REQ AUTOPEER +AUTOPEER:3
. Participating clients will immediately respond with
an additional CTCP AUTOPEER request of the same format, with the addition of a token for every AUTOPEER capability the client supports. A complete
AUTOPEER reply might therefre be: (in IRC) PRIVMSG victim :\001AUTOPEER +AUTOPEER:3 +AUTOCRYPT +AUTOZONE:EDT-0400\001
, (in AIM)
toc_send_im victim "<font ECT=\"AUTOPEER +AUTOPEER:3 +AUTOZONE:EST-0500\"></font>"
, (in Lily) victim:CTCP REQ AUTOPEER
+AUTOPEER:3 +AUTOCRYPT
. The originating client then may reply with any additional synchronization messages needed, such as an AUTOCRYPT key or a
response to the AUTOZONE message.
The AUTOCRYPT token, if present without an argument, is to be taken as a proclamation that the client handles automatic encryption using the scheme
described by the version of AUTOPEER it supports. For AUTOPEER:3, this scheme is simple XOR, and uses clear key exchange, so is vulnerable to man in the
middle during key exchange (at the beginning of a conversation). For AUTOPEER:3, if an argument is provided to the AUTOPEER token, it is to be taken as
the literal key. Hence, the key is restricted to characters that can be literally transmitted through the medium in question, another source of weakness
in the encryption scheme. Upon receipt of an AUTOCRYPT token with key, participating clients should immediately begin encoding and deencoding messages
sent and received from the other client, without user intervention. Therefore, a complete exchange to enable encryption with a key of "testkey" might
be: (in IRC)
--> PRIVMSG victim :Hello, victim\001AUTOPEER +AUTOPEER:3\001
<-- :victim!vic@example.net PRIVMSG actor :\001AUTOPEER +AUTOPEER:3 +AUTOCRYPT\001
--> PRIVMSG victim :\001AUTOPEER +AUTOCRYPT:testkey\001
Every character sent between the two clients once AUTOCRYPT has been negotiated will be XORd with the string "testkey" repeated as necessary before
transmission and after receipt. This is the same mechanism used to "roast" your login password while signing on to AIM (the TOC protocol uses the static
string "Tic/Toc" as the key, whereas AUTOCRYPT negotiates the key dynamically).
The AUTOZONE token doesn't make any sense when specified without an argument, as no client to client changes should occur based on negotiation (or failure during negotiation) of AUTOZONE. The argument is a free-form string specifying the user's time zone, and is merely meant to be used as an advisory message sent to the user. naim uses the format SSS-HHMM where SSS is the three-letter code made available as struct tm.tm_zone or extern char *tzname[0], and HHMM is the four-digit offset from UTC ("GMT") time zone. My AUTOZONE argument is "EST-0500" during the Winter and "EDT-0400" during the summer.
Sometimes a character typed by a user, generated through AUTOCRYPT, etc. can not be adequately expressed in the underlying communication medium. For
Lily and many IRC servers, this includes any character that does not meet the ctype.h's isprint()
definition. For AIM, characters that are
between integer value 160 and 254 are carryable in addition to those that meet isprint()
. Each protocol may have unique and interesting
provisions for encoding unrepresentable characters, but naim uses its own mechanism that is guaranteed to work universally. Whenever a message to be
sent contains a character that can not be represented by the underlying protocol, the entire message is wrapped up inside a CTCP "HEXTEXT" request. The
argument to HEXTEXT is a set of two-characters per character of input text that represents the hexadecimal value of the original character. Therefore,
in the above example for AUTOCRYPT, if the encryption key was "testkey" and a message of "hello there" was to be sent, the resulting message would be
sent as a HEXTEXT request simply because the second character of the plaintext matches the second character of the key, and 'e' XORd with 'e' yields the
integer value 0, which can not be represented in any communication medium. Therefore, the message might be sent as: (in IRC) PRIVMSG victim
:\001HEXTEXT ..00..................\001
.
For client authours who merely want to enable naim-compatible end-to-end encryption in AIM, here is the executive summary of client behaviours needed.
<font ECT="
] and followed with ["></font>
]. Messages that only
contain an ECT message should be treated as special cases, and are not to be passed on to the user as private messages.<font ECT="AUTOPEER +AUTOPEER:3"></font>
] message, your client should respond with a message of
[<font ECT="AUTOPEER +AUTOPEER:3 +AUTOCRYPT"></font>
].<font ECT="AUTOPEER *"></font>
] message where * contains "+AUTOCRYPT:xxx", begin or continue tracking
the online status of the sender, and associate an encryption key (the "xxx" after the colon) with that user. Keys can not contain whitespace, so a
message of [<font ECT="AUTOPEER xyz +AUTOCRYPT:abc def"></font>
] is treated as an AUTOPEER +xyz followed by an AUTOPEER
+AUTOCRYPT:abc followed by an AUTOPEER +def, and the key for encryption is simply "abc" not "abc def".<font ECT="
] and ending with ["></font>
] from a user
with an encryption key associated with them, XOR each character in their message with the corresponding character in their key. That is, if the key was
"abc", then the first character of their message is to be XORd with "a", the second character XORd with "b", the third with "c", the fourth with "a",
the fifth with "b", etc.<font ECT="HEXTEXT
], treat the remainder of the ECT message as the hexadecimal
representation of a message that should be re-processed as a private message. That is, a message of [<font ECT="HEXTEXT
68656C6C6F207468657265"></font>
] should be treated as a private message sent as "hello there". Private messages discovered in this way
should be un-encoded using that user's encryption key if one exists after being de-hextexted.For client authours who merely want to enable naim-compatible end-to-end encryption in IRC, here is the executive summary of client behaviours needed.
\001AUTOPEER +AUTOPEER:3\001
" message, your client should respond with a message of "\001AUTOPEER +AUTOPEER:3
+AUTOCRYPT\001
".\001AUTOPEER *\001
" message where * contains "+AUTOCRYPT:xxx", begin or continue tracking the online status of the
sender, and associate an encryption key (the "xxx" after the colon) with that user. Keys can not contain whitespace, so a message of "\001AUTOPEER
xyz +AUTOCRYPT:abc def\001
" is treated as an AUTOPEER +xyz followed by an AUTOPEER +AUTOCRYPT:abc followed by an AUTOPEER +def, and the key for
encryption is simply "abc" not "abc def".\001
" and ending with "\001
" from a user with an encryption key
associated with them, XOR each character in their message with the corresponding character in their key. That is, if the key was "abc", then the first
character of their message is to be XORd with "a", the second character XORd with "b", the third with "c", the fourth with "a", the fifth with "b",
etc.\001HEXTEXT
", treat the remainder of the ECT message as the hexadecimal
representation of a message that should be re-processed as a private message. That is, a message of "\001HEXTEXT
68656C6C6F207468657265\001
" should be treated as a private message sent as "hello there". Private messages discovered in this way should be
un-encoded using that user's encryption key if one exists after being de-hextexted.For client authours who merely want to enable naim-compatible end-to-end encryption in Lily, here is the executive summary of client behaviours needed.