ADDED spec/nimtas.ct Index: spec/nimtas.ct ================================================================== --- spec/nimtas.ct +++ spec/nimtas.ct @@ -0,0 +1,59 @@ +# nimtas protocol +the nimtas protocol is a very simple authentication/identification protocol suitable for embedding in other protocols. + +## definitions +an italicized form indicates a formally specified sequence of bytes. parameters (e.g. the length of an integer form) are placed in angle brackets after the identifier. if the form is bound to a name in context, it is followed by a [`:] and a name in variable notation. +* [*byte], [*byte<1>] ==> one octet +* [*byte<[$N]>] ==> [!byte] [!byte<[=N-1]>] +* [*int<[$N]>] ==> [!byte<[=N / 8]>] interpreted as a little-endian unsigned integer (e.g. [!int<32>] represents an unsigned little-endian 32-bit integer) +* [*byte-sequence<[$L]>] ==> [!int<[$L]>:[$N]] [!byte<[$N]>], with no specific semantics. that is, a variable-length byte sequence whose size prefix is [$L] bits long + +##overview +nimtas is composed of two procedures, the [>proc-id] and the authentication procedure. the identity procedure is a [*strict subset] of the authentication procedure and for some clients may be sufficient. formally, the [>proc-auth] is the protocol entry point. + +the initial connection handshake is the responsibility of the containing protocol. + +###proc-auth authentication procedure +: to authenticate by identity alone, client immediately follows the [>proc-id] +: to authenticate by challenge: +:: client transmits: +::: [`0x10] indicating challenge auth +::: a [!byte] naming a supported type of challenge +:::: [`0x00] = passphrase/prompt +:::: [`0x01] = SHA3 nonce hash +:::: [`0x02] = libsodium asymmetric signature +:::: [`0x03] = SCRAM +:::: [`0x04] = U2F +:::: [`0xFF] [!int<32>:[$method-number]] = private challenge method +::: client follows the [>proc-id] +:: if the server does not support the selected challenge type, it sends {m.n status-fail} and closes the connection. +:: otherwise, the following steps are repeated until authentication is complete: +::: if authentication is complete, exit loop and jump to ["[report]] +::: otherwise, server sends {m.n status-data} followed by [!byte-sequence<16>:[$challenge-blob]], the meaning of which depends on the selected challenge method +::: client sends [!byte-sequence<16>:[$challenge-response]] +: ["[report]] server reports authentication status +:: if the authentication failed, xmit {m.n status-fail} and close the connection +:: if the authentication succeeded, xmit {m.n status-ok} + +! other authentication methods may be defined later. a server that encounters an unknown authentication method must transmit {m.n status-fail} and close the connection, as it cannot know how to interpret any further communications from the client + +###proc-id identity procedure +! the identity procedure is a [*strict subset] of the [>proc-auth] + +: to identify anonymously, client transmits byte [`0x00]. +: to identify externally, client transmits byte [`0x01]. this method indicates that identity is already coded by the connection or challenge context, similar to the SASL EXTERNAL method. possible uses cases include connection over UNIX domain socket, over TLS, or when authenticating via a type of challenge that also supplies identification data. +: to identify by shortname, client transmits byte [`0x02] followed by a [!byte-sequence<8>]. this may be a PSK, a URI, a literal text name, an OID, or anything else depending on what the server is configured to recognize. +: to identify by longname, client transmits byte [`0x03] followed by a [!byte-sequence<16>]. this is identical to the above but allows longer values. technically these are different forms of the "name" authentication method; the difference is relevant only at the byte-level +: to identify by private method, client transmits byte [`0x0f] followed by +:: [!int<32>:[$method-number]] +:: [!byte-sequence<16>:[$auth-blob]] + +! note that bytes [`0x04]~[`0x0e] are reserved for potential future identification methods. a server that encounters a method it doesn't understand must immediately send {m.n stats-fail} and close the connection. + +##m magic numbers + n: ‹[*[#1]]› + ++ ID + value + +| status-ok | [`0xFF] | +| status-data | [`0xF0] | +| status-fail | [`0x00] | Index: spec/rasuir.ct ================================================================== --- spec/rasuir.ct +++ spec/rasuir.ct @@ -19,46 +19,41 @@ * [*string] ==> [!byte-sequence<8>] interpreted as a UTF-8 string * [*text] ==> [!byte-sequence<16>] interpreted as a UTF-8 string * [*bitmap] ==> [!int<16>:[$pxl-width]] [!byte-sequence<8>:[$map]] * [*state] ==> *: if on the root menu: [`0x00] -*: if on a menu with an ID between [`1]-[`127] and the opaque [$ref] value is [`0] ("null"): the menu number cast to [!int<8>] (e.g. [`0x00 4A] --> [`0x4A]) -*: if on a menu between [`128]-[`383] with a null [$ref] value: [`0x80] [!int<8>:[=mode - 128]] +*: if on a menu with an ID between [`1]~[`127] and the opaque [$ref] value is [`0] ("null"): the menu number cast to [!int<8>] (e.g. [`0x00 4A] --> [`0x4A]) +*: if on a menu between [`128]~[`383] with a null [$ref] value: [`0x80] [!int<8>:[=mode - 128]] *: if on a menu greater than [`383] with a null [$ref]: [`0x81] [!int<16>:[$mode]]. this form is also valid if the number is lower than [`383], and can be used where logical simplicity is more important than compact signalling *: otherwise: *:: let [$ref-len] be the length in bytes of the [$ref] value, maximum 8 (0 is valid, in which case no [$ref] sequence is sent) *:: let [$mode-range] be [`0] if [$mode] is between [`0] and [`255], [`1] otherwise -*:: let [$signal-byte] be [`([$ref-len] << 1) | [$mode]-[$range]] -*:: send [!int<8>:[$signal-byte]] [!int<[=8 + 8*mode-range]>:[$mode]] [!int<[$ref-len*8]>:[$ref]] +*:: let [$signal-byte] be [`([$ref-len] << 1) | [$mode-range]] +*:: send [!int<8>:[$signal-byte]] [!int<[`8 + 8*[$mode-range]]>:[$mode]] [!int<[`[$ref-len]*8]>:[$ref]] * [*link] ==> [!int<8>:[$role]] [!state:[$target]] ## outline - : client connects to server : client transmits {m.n con-ack} -: client authenticates by one of the following -:: to authenticate anonymously, client transmits byte [`0x00]. -:: to authenticate by shortname, client transmits byte [`0x01] followed by a [!byte-sequence<8>]. this may be a PSK, a URI, a literal text name, an OID, or anything else depending on what the server is configured to recognize. -:: to authenticate by longname, client transmits byte [`0x01] followed by a [!byte-sequence<16>]. this is identical to the above but allows to longer values. technically these are different forms of the "name" authentication method; the difference is relevant only at the byte-level -:: other authentication methods may be defined later. a server that encounters an unknown authentication method must transmit an error and close the connection, as it cannot know how to interpret any further communications from the client -: server reports authentication status -:: if the authentication failed, xmit {m.n status-fail} and close the connection -:: if the authentication succeeded, xmit {m.n status-ok} +: server responds {m.n status-ok} +: client and server authenticate using the [>nimtas authentication protocol]. for an anonymous connection, this is as simple as the dialogue “C: [`0x00] / S: {m.n status-ok}” : client transmits a command :: {m.n cmd-get} retrieves a menu. it takes the form [!state] [!action] :: {m.n cmd-hint} transmits a hint to the server. it takes the form [!int<8>:[$hint]] [!byte-sequence<16>] :: {m.n cmd-meta} requests metadata from the server. it takes the form [!int<16>] :: {m.n cmd-end} closes the connection. it takes no arguments : server issues [>rep reply] : while command was not {m.n cmd-end}, previous two steps repeat : peers disconnect + nimtas: file:nimtas.ct + ##rep server replies all replies begin with a one-byte status code. ### cmd-get reply -the hint reply code may be: +the get reply code may be: * {m.n status-ok}: the request was valid but the current display should not be changed * {m.n status-fail}: the request was not valid * {m.n status-ignore}: the action did nothing * {m.n status-data}: the request was valid and a form is being returned to display.