diff --git a/ChangeLog.adoc b/ChangeLog.adoc index 97b6bde74..0470390c4 100644 --- a/ChangeLog.adoc +++ b/ChangeLog.adoc @@ -21,6 +21,7 @@ https://weechat.org/files/releasenotes/ReleaseNotes-devel.html[release notes] New features:: * buflist: evaluate option buflist.look.sort so that sort can be customized for each of the three buflist bar items (issue #1465) + * relay: add command "handshake" in weechat relay protocol and nonce to prevent replay attacks, add options relay.network.auth_password, relay.network.hash_iterations, relay.network.nonce_size (issue #1474) * relay: add option relay.network.auth_timeout * relay: update default colors for client status * relay: add status "waiting_auth" in irc and weechat protocols (issue #1358) diff --git a/ReleaseNotes.adoc b/ReleaseNotes.adoc index 9859c7c51..fbe88a3ba 100644 --- a/ReleaseNotes.adoc +++ b/ReleaseNotes.adoc @@ -20,6 +20,36 @@ https://weechat.org/files/changelog/ChangeLog-devel.html[ChangeLog] [[v2.9]] == Version 2.9 (under dev) +[[v2.9_relay_weechat_protocol_handshake_nonce]] +=== Add of handshake and nonce in weechat relay protocol + +==== Handshake + +A _handshake_ command has been added in weechat relay protocol. + +The client should send this command before the _init_ to negotiate the way to +authenticate with the relay server. + +See the link:weechat_relay_protocol.en.html#command_handshake[handshake command] +in Relay protocol doc for more information. + +==== Server "nonce" + +Furthermore, a "nonce" is now generated for each client connecting and must be +used by the client in case of hashed password in the _init_ command. + +The goal is to prevent replay attacks in case someone manages to read exchanges +between the client and relay. + +When hashing the password, the client must use salt composed by this nonce +as binary (it is hexadecimal and must be base16-decoded), concatenated with +a client nonce after this one. + +So the hash is computed on: (`server nonce` + `client nonce` + `password`). + +This salt is now mandatory even for algorithms `SHA256` and `SHA512`; this is +a breaking change in protocol, needed for security reasons. + +See the link:weechat_relay_protocol.en.html#command_init[init command] +in Relay protocol doc for more information. + [[v2.9_trigger_command_eval]] === Evaluation of trigger command arguments diff --git a/doc/de/autogen/user/relay_options.adoc b/doc/de/autogen/user/relay_options.adoc index 5c6405f48..c47456060 100644 --- a/doc/de/autogen/user/relay_options.adoc +++ b/doc/de/autogen/user/relay_options.adoc @@ -116,6 +116,12 @@ ** Werte: beliebige Zeichenkette ** Standardwert: `+""+` +* [[option_relay.network.auth_password]] *relay.network.auth_password* +** Beschreibung: pass:none[comma separated list of hash algorithms used for password authentication in weechat protocol, among these values: "plain" (password in plain text, not hashed), "sha256", "sha512", "pbkdf2+sha256", "pbkdf2+sha512"), "*" means all algorithms, a name beginning with "!" is a negative value to prevent an algorithm from being used, wildcard "*" is allowed in names (examples: "*", "pbkdf2*", "*,!plain")] +** Typ: Zeichenkette +** Werte: beliebige Zeichenkette +** Standardwert: `+"*"+` + * [[option_relay.network.auth_timeout]] *relay.network.auth_timeout* ** Beschreibung: pass:none[timeout (in seconds) for client authentication: connection is closed if the client is still not authenticated after this delay and the client status is set to "authentication failed" (0 = wait forever)] ** Typ: integer @@ -140,6 +146,12 @@ ** Werte: 0 .. 9 ** Standardwert: `+6+` +* [[option_relay.network.hash_iterations]] *relay.network.hash_iterations* +** Beschreibung: pass:none[number of iterations asked to the client in weechat protocol when a hashed password with algorithm PBKDF2 is used for authentication; more iterations is better in term of security but is slower to compute; this number should not be too high if your CPU is slow] +** Typ: integer +** Werte: 1 .. 1000000 +** Standardwert: `+100000+` + * [[option_relay.network.ipv6]] *relay.network.ipv6* ** Beschreibung: pass:none[lauscht standardmäßig am IPv6 Socket (zusätzlich zu IPv4, welches als Standardprotokoll genutzt wird); mittels des Protokollnamens kann das IPv4 und IPv6 Protokoll, einzeln oder gemeinsam, erzwungen werden (siehe /help relay)] ** Typ: boolesch @@ -152,6 +164,12 @@ ** Werte: 0 .. 2147483647 ** Standardwert: `+5+` +* [[option_relay.network.nonce_size]] *relay.network.nonce_size* +** Beschreibung: pass:none[size of nonce (in bytes), generated when a client connects; the client must use this nonce, concatenated to the client nonce and the password when hashing the password in the "init" command of the weechat protocol] +** Typ: integer +** Werte: 8 .. 128 +** Standardwert: `+16+` + * [[option_relay.network.password]] *relay.network.password* ** Beschreibung: pass:none[Passwort wird von Clients benötigt um Zugriff auf dieses Relay zu erhalten (kein Eintrag bedeutet, dass kein Passwort benötigt wird, siehe Option relay.network.allow_empty_password) (Hinweis: Inhalt wird evaluiert, siehe /help eval)] ** Typ: Zeichenkette diff --git a/doc/en/autogen/user/relay_options.adoc b/doc/en/autogen/user/relay_options.adoc index ad86251b0..e80012a79 100644 --- a/doc/en/autogen/user/relay_options.adoc +++ b/doc/en/autogen/user/relay_options.adoc @@ -116,6 +116,12 @@ ** values: any string ** default value: `+""+` +* [[option_relay.network.auth_password]] *relay.network.auth_password* +** description: pass:none[comma separated list of hash algorithms used for password authentication in weechat protocol, among these values: "plain" (password in plain text, not hashed), "sha256", "sha512", "pbkdf2+sha256", "pbkdf2+sha512"), "*" means all algorithms, a name beginning with "!" is a negative value to prevent an algorithm from being used, wildcard "*" is allowed in names (examples: "*", "pbkdf2*", "*,!plain")] +** type: string +** values: any string +** default value: `+"*"+` + * [[option_relay.network.auth_timeout]] *relay.network.auth_timeout* ** description: pass:none[timeout (in seconds) for client authentication: connection is closed if the client is still not authenticated after this delay and the client status is set to "authentication failed" (0 = wait forever)] ** type: integer @@ -140,6 +146,12 @@ ** values: 0 .. 9 ** default value: `+6+` +* [[option_relay.network.hash_iterations]] *relay.network.hash_iterations* +** description: pass:none[number of iterations asked to the client in weechat protocol when a hashed password with algorithm PBKDF2 is used for authentication; more iterations is better in term of security but is slower to compute; this number should not be too high if your CPU is slow] +** type: integer +** values: 1 .. 1000000 +** default value: `+100000+` + * [[option_relay.network.ipv6]] *relay.network.ipv6* ** description: pass:none[listen on IPv6 socket by default (in addition to IPv4 which is default); protocols IPv4 and IPv6 can be forced (individually or together) in the protocol name (see /help relay)] ** type: boolean @@ -152,6 +164,12 @@ ** values: 0 .. 2147483647 ** default value: `+5+` +* [[option_relay.network.nonce_size]] *relay.network.nonce_size* +** description: pass:none[size of nonce (in bytes), generated when a client connects; the client must use this nonce, concatenated to the client nonce and the password when hashing the password in the "init" command of the weechat protocol] +** type: integer +** values: 8 .. 128 +** default value: `+16+` + * [[option_relay.network.password]] *relay.network.password* ** description: pass:none[password required by clients to access this relay (empty value means no password required, see option relay.network.allow_empty_password) (note: content is evaluated, see /help eval)] ** type: string diff --git a/doc/en/weechat_dev.en.adoc b/doc/en/weechat_dev.en.adoc index a3f1faef5..539b4d2ce 100644 --- a/doc/en/weechat_dev.en.adoc +++ b/doc/en/weechat_dev.en.adoc @@ -318,6 +318,7 @@ WeeChat "core" is located in following directories: |       weechat-python-api.c | Python scripting API functions. |    relay/ | Relay plugin (IRC proxy and relay for remote interfaces). |       relay.c | Main relay functions. +|       relay-auth.c | Clients authentication. |       relay-buffer.c | Relay buffer. |       relay-client.c | Clients of relay. |       relay-command.c | Relay commands. @@ -378,48 +379,47 @@ WeeChat "core" is located in following directories: [width="100%",cols="1m,2",options="header"] |=== -| Path/file | Description -| tests/ | Root of tests. -|    tests.cpp | Program used to run all tests. -|    scripts/ | Root of scripting API tests. -|       test-scripts.cpp | Program used to run the scripting API tests. -|       python/ | Python scripts to generate and run the scripting API tests. -|          testapigen.py | Python script generating scripts in all languages to test the scripting API. -|          testapi.py | Python script with scripting API tests, used by script testapigen.py. -|          unparse.py | Convert Python code to other languages, used by script testapigen.py. -|    unit/ | Root of unit tests. -|       test-plugins.cpp | Tests: plugins. -|       core/ | Root of unit tests for core. -|          test-core-arraylist.cpp | Tests: arraylists. -|          test-core-calc.cpp | Tests: calculation of expressions. -|          test-core-crypto.cpp | Tests: cryptographic functions. -|          test-core-eval.cpp | Tests: evaluation of expressions. -|          test-core-hashtble.cpp | Tests: hashtables. -|          test-core-hdata.cpp | Tests: hdata. -|          test-core-hook.cpp | Tests: hooks. -|          test-core-infolist.cpp | Tests: infolists. -|          test-core-list.cpp | Tests: lists. -|          test-core-secure.cpp | Tests: secured data. -|          test-core-string.cpp | Tests: strings. -|          test-core-url.cpp | Tests: URLs. -|          test-core-utf8.cpp | Tests: UTF-8. -|          test-core-util.cpp | Tests: utility functions. -|       gui/ | Root of unit tests for interfaces. -|          test-gui-color.cpp | Tests: colors. -|          test-gui-line.cpp | Tests: lines. -|          test-gui-nick.cpp | Tests: nicks. -|       plugins/ | Root of unit tests for plugins. -|          irc/ | Root of unit tests for IRC plugin. -|             test-irc-color.cpp | Tests: IRC colors. -|             test-irc-config.cpp | Tests: IRC configuration. -|             test-irc-ignore.cpp | Tests: IRC ignores. -|             test-irc-message.cpp | Tests: IRC messages. -|             test-irc-mode.cpp | Tests: IRC modes. -|             test-irc-nick.cpp | Tests: IRC nicks. -|             test-irc-protocol.cpp | Tests: IRC protocol. -|          relay/ | Root of unit tests for Relay plugin. -|             weechat/ | Root of unit tests for weechat protocol. -|                test-relay-weechat-protocol.cpp | Tests: weechat protocol. +| Path/file | Description +| tests/ | Root of tests. +|    tests.cpp | Program used to run all tests. +|    scripts/ | Root of scripting API tests. +|       test-scripts.cpp | Program used to run the scripting API tests. +|       python/ | Python scripts to generate and run the scripting API tests. +|          testapigen.py | Python script generating scripts in all languages to test the scripting API. +|          testapi.py | Python script with scripting API tests, used by script testapigen.py. +|          unparse.py | Convert Python code to other languages, used by script testapigen.py. +|    unit/ | Root of unit tests. +|       test-plugins.cpp | Tests: plugins. +|       core/ | Root of unit tests for core. +|          test-core-arraylist.cpp | Tests: arraylists. +|          test-core-calc.cpp | Tests: calculation of expressions. +|          test-core-crypto.cpp | Tests: cryptographic functions. +|          test-core-eval.cpp | Tests: evaluation of expressions. +|          test-core-hashtble.cpp | Tests: hashtables. +|          test-core-hdata.cpp | Tests: hdata. +|          test-core-hook.cpp | Tests: hooks. +|          test-core-infolist.cpp | Tests: infolists. +|          test-core-list.cpp | Tests: lists. +|          test-core-secure.cpp | Tests: secured data. +|          test-core-string.cpp | Tests: strings. +|          test-core-url.cpp | Tests: URLs. +|          test-core-utf8.cpp | Tests: UTF-8. +|          test-core-util.cpp | Tests: utility functions. +|       gui/ | Root of unit tests for interfaces. +|          test-gui-color.cpp | Tests: colors. +|          test-gui-line.cpp | Tests: lines. +|          test-gui-nick.cpp | Tests: nicks. +|       plugins/ | Root of unit tests for plugins. +|          irc/ | Root of unit tests for IRC plugin. +|             test-irc-color.cpp | Tests: IRC colors. +|             test-irc-config.cpp | Tests: IRC configuration. +|             test-irc-ignore.cpp | Tests: IRC ignores. +|             test-irc-message.cpp | Tests: IRC messages. +|             test-irc-mode.cpp | Tests: IRC modes. +|             test-irc-nick.cpp | Tests: IRC nicks. +|             test-irc-protocol.cpp | Tests: IRC protocol. +|          relay/ | Root of unit tests for Relay plugin. +|             test-relay-auth.cpp | Tests: clients authentication. |=== diff --git a/doc/en/weechat_relay_protocol.en.adoc b/doc/en/weechat_relay_protocol.en.adoc index 3ff6bc116..a2c9ca0b9 100644 --- a/doc/en/weechat_relay_protocol.en.adoc +++ b/doc/en/weechat_relay_protocol.en.adoc @@ -32,11 +32,11 @@ The _clients_ are connected to _relay_ like shown in this diagram: .... ┌──────────┐ Workstation ┌────────┐ ┌───┤ client 1 │ (Linux, Windows, - │ irc │◄──┐ ╔═══════════╤═══════╗ │ └──────────┘ BSD, macOS ...) - └────────┘ └──╢ │ ║◄───┘ ┌──────────┐ - ...... ║ WeeChat │ Relay ║◄───────┤ client 2 │ Mobile device - ┌────────┐ ┌──╢ │ ║◄───┐ └──────────┘ (Android, iPhone ...) - │ jabber │◄──┘ ╚═══════════╧═══════╝ │ ...... + │ irc │◀──┐ ╔═══════════╤═══════╗ │ └──────────┘ BSD, macOS ...) + └────────┘ └──╢ │ ║◀───┘ ┌──────────┐ + ...... ║ WeeChat │ Relay ║◀───────┤ client 2 │ Mobile device + ┌────────┐ ┌──╢ │ ║◀───┐ └──────────┘ (Android, iPhone ...) + │ jabber │◀──┘ ╚═══════════╧═══════╝ │ ...... └────────┘ │ ┌──────────┐ ...... └───┤ client N │ Other devices └──────────┘ @@ -86,24 +86,129 @@ List of available commands (detail in next chapters): [width="80%",cols="^3m,14",options="header"] |=== -| Command | Description -| init | Initialize connection with _relay_. -| hdata | Request a _hdata_. -| info | Request an _info_. -| infolist | Request an _infolist_. -| nicklist | Request a _nicklist_. -| input | Send data to a buffer (text or command). -| sync | Synchronize buffer(s): get updates for buffer(s). -| desync | Desynchronize buffer(s): stop updates for buffer(s). -| quit | Disconnect from _relay_. +| Command | Description +| handshake | Handshake: prepare client authentication and set options, before _init_ command. +| init | Authenticate with _relay_. +| hdata | Request a _hdata_. +| info | Request an _info_. +| infolist | Request an _infolist_. +| nicklist | Request a _nicklist_. +| input | Send data to a buffer (text or command). +| sync | Synchronize buffer(s): get updates for buffer(s). +| desync | Desynchronize buffer(s): stop updates for buffer(s). +| quit | Disconnect from _relay_. |=== +[[command_handshake]] +=== handshake + +_WeeChat ≥ 2.9._ + +Perform an handshake between the client and WeeChat: this is required in most +cases to know the session settings and prepare the authentication with the +_init_ command. + +The handshake can be performed multiple times before the _init_ command, +although it is rarely needed. + +Syntax: + +---- +handshake [