diff options
43 files changed, 2388 insertions, 469 deletions
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 [<option>=<value>,[<option>=<value>,...]] +---- + +Arguments: + +* _option_: one of following options: +** _password_: list of hash algorithms supported by the client (separated by colons), + allowed values are: +*** _plain_: plain text password (no hash) +*** _sha256_: password salted and hashed with SHA256 algorithm +*** _sha512_: password salted and hashed with SHA512 algorithm +*** _pbkdf2+sha256_: password salted and hashed with PBKDF2 algorithm (using SHA256 hash) +*** _pbkdf2+sha512_: password salted and hashed with PBKDF2 algorithm (using SHA512 hash) +** _compression_: compression type: +*** _zlib_: enable _zlib_ compression for messages sent by _relay_ + (enabled by default if _relay_ supports _zlib_ compression) +*** _off_: disable compression + +Notes about option _password_: + +* If the option is not given (of if the _handshake_ command is not sent by the + client), _relay_ uses automatically _plain_ authentication (if allowed on + _relay_ side). +* _Relay_ chooses the safest algorithm available on both client and _relay_, + by order of priority from first (safest) to last used: + . _pbkdf2+sha512_ + . _pbkdf2+sha256_ + . _sha512_ + . _sha256_ + . _plain_ + +WeeChat replies with a hashtable containing the following keys and values: + +* _auth_password_: the password authentication negotiated: supported by both + the client and _relay_: +** (empty value): negotiation failed, password authentication is *NOT* possible +** _plain_ +** _sha256_ +** _sha512_ +** _pbkdf2+sha256_ +** _pbkdf2+sha512_ +* _hash_iterations_: number of iterations for hash (for the PBKDF2 algorithm only) +* _totp_: +** _on_: Time-based One-Time Password (TOTP) is configured and expected + in the _init_ command +** _off_: Time-based One-Time Password (TOTP) is not enabled and not needed + in the _init_ command +* _nonce_: a buffer of unpredictable bytes, sent as hexadecimal, to prevent + replay attacks; if _auth_password_ is a hash algorithm, the client must compute + the hash of password on this nonce, concatenated with a client nonce and the + user password (the _relay_ nonce + the client nonce is the salt used in the + password hash algorithm) + +Examples: + +---- +# nothing offered by the client (or only "plain"), authentication password "plain" will be used if allowed on relay side +handshake +handshake password=plain + +# only plain, sha256 and pbkdf2+sha256 are supported by the client +handshake password=plain:sha256:pbkdf2+sha256 +---- + +Example of response: + +[source,python] +---- +id: 'handshake' +htb: {'auth_password': 'pbkdf2+sha256', 'hash_iterations': '100000', 'totp': 'on', 'nonce': '85B1EE00695A5B254E14F4885538DF0D'} +---- + +The client can authenticate with this command (see <<command_init,init command>>), +the salt is the _relay_ nonce + "ABCD" ("41424344" in hexadecimal): + +---- +init password_hash=pbkdf2+sha256:85b1ee00695a5b254e14f4885538df0d41424344:100000:01757d53157ca14a1419e3a8cc1563536520a60b76d2d48e7f9ac09afc945a1c +---- + +[TIP] +With WeeChat ≤ 2.8, the command _handshake_ is not implemented, WeeChat silently +ignores this command, even if it is sent before the _init_ command. + +So it is safe to send this command to any WeeChat version. + [[command_init]] === init -Initialize connection with _relay_. This must be first command sent to _relay_. -If not sent, _relay_ will close connection on first command received, without -warning. +_Updated in versions 2.4, 2.8, 2.9._ + +Authenticate with _relay_. + +This must be first command sent to _relay_ (only _handshake_ command can be sent +before _init_). + +If not sent, _relay_ will close connection on first command received (except +_handshake_), without warning. Syntax: @@ -123,7 +228,9 @@ Arguments: factor, in addition to the password (option _relay.network.totp_secret_ in WeeChat) _(WeeChat ≥ 2.4)_ -** _compression_: compression type: +** _compression_: compression type (*deprecated* since version 2.9, it is kept + for compatibility reasons but should be sent in the + <<command_handshake,handshake command>>): *** _zlib_: enable _zlib_ compression for messages sent by _relay_ (enabled by default if _relay_ supports _zlib_ compression) *** _off_: disable compression @@ -135,13 +242,27 @@ With WeeChat ≥ 1.6, commas can be escaped in the value, for example Format of hashed password is one of the following, where _hash_ is the hashed password as hexadecimal: -* `+sha256:hash+` -* `+sha512:hash+` -* `+pbkdf2:algorithm:salt:iterations:hash+` with: -** _algorithm_: _sha256_ or _sha512_ -** _salt_: salt (hexadecimal) +* `+sha256:salt:hash+` with: +** _salt_: salt (hexadecimal), which must start with the server nonce, + concatenated to the client nonce +** _hash_: the hashed salt + password (hexadecimal) +* `+sha512:salt:hash+` with: +** _salt_: salt (hexadecimal), which must start with the server nonce, + concatenated to the client nonce +** _hash_: the hashed salt + password (hexadecimal) +* `+pbkdf2+sha256:salt:iterations:hash+` with: +** _salt_: salt (hexadecimal), which must start with the server nonce, + concatenated to the client nonce +** _iterations_: number of iterations +** _hash_: the hashed salt + password with SHA256 algorithm (hexadecimal) +* `+pbkdf2+sha512:salt:iterations:hash+` with: +** _salt_: salt (hexadecimal), which must start with the server nonce, + concatenated to the client nonce ** _iterations_: number of iterations -** _hash_: the hashed password (hexadecimal) +** _hash_: the hashed salt + password with SHA512 algorithm (hexadecimal) + +[NOTE] +Hexadecimal strings can be lower or upper case, _relay_ can decode both. Examples: @@ -158,14 +279,14 @@ init password=mypass,totp=123456 # initialize and disable compression init password=mypass,compression=off -# initialize with hashed password (SHA256) (WeeChat ≥ 2.8) -init password_hash=sha256:b9a4c3393dfac4330736684510378851e581c68add8eca84110c31a33e694676 +# initialize with hashed password (SHA256: salt="nonce:cnonce") (WeeChat ≥ 2.9) +init password_hash=sha256:6e6f6e63653a636e6f6e6365:b9a4c3393dfac4330736684510378851e581c68add8eca84110c31a33e694676 -# initialize with hashed password (SHA512) (WeeChat ≥ 2.8) -init password_hash=sha512:4469190d4e0d1fdc0afb6f408d9873c89b8ce89cc4db79fe058255c55ad6821fa5e9bb068f9e578c8ae7cc825d85ff99c439d59e439bc589d95620a1e6b8ae6e +# initialize with hashed password (SHA512: salt="nonce:cnonce") (WeeChat ≥ 2.9) +init password_hash=sha512:6e6f6e63653a636e6f6e6365:4469190d4e0d1fdc0afb6f408d9873c89b8ce89cc4db79fe058255c55ad6821fa5e9bb068f9e578c8ae7cc825d85ff99c439d59e439bc589d95620a1e6b8ae6e -# initialize with hashed password (PBKDF2: SHA256, salt="ABCDEFGHIJKLMNOP", 100000 iterations) (WeeChat ≥ 2.8) -init password_hash=pbkdf2:sha256:4142434445464748494a4b4c4d4e4f50:100000:01757d53157ca14a1419e3a8cc1563536520a60b76d2d48e7f9ac09afc945a1c +# initialize with hashed password (PBKDF2: SHA256, salt="nonce:cnonce", 100000 iterations) (WeeChat ≥ 2.9) +init password_hash=pbkdf2+sha256:6e6f6e63653a636e6f6e6365:100000:01757d53157ca14a1419e3a8cc1563536520a60b76d2d48e7f9ac09afc945a1c ---- [[command_hdata]] @@ -1389,7 +1510,7 @@ Example: .... ┌────┐ -│ 41 │ ────► 65 (0x41: "A") +│ 41 │ ────▶ 65 (0x41: "A") └────┘ .... @@ -1405,11 +1526,11 @@ Examples: .... ┌────┬────┬────┬────┐ -│ 00 │ 01 │ E2 │ 40 │ ────► 123456 +│ 00 │ 01 │ E2 │ 40 │ ────▶ 123456 └────┴────┴────┴────┘ ┌────┬────┬────┬────┐ -│ FF │ FE │ 1D │ C0 │ ────► -123456 +│ FF │ FE │ 1D │ C0 │ ────▶ -123456 └────┴────┴────┴────┘ .... @@ -1424,13 +1545,13 @@ Examples: .... ┌────╥────┬────┬────┬────┬────┬────┬────┬────┬────┬────┐ -│ 0A ║ 31 │ 32 │ 33 │ 34 │ 35 │ 36 │ 37 │ 38 │ 39 │ 30 │ ────► 1234567890 +│ 0A ║ 31 │ 32 │ 33 │ 34 │ 35 │ 36 │ 37 │ 38 │ 39 │ 30 │ ────▶ 1234567890 └────╨────┴────┴────┴────┴────┴────┴────┴────┴────┴────┘ └──┘ └───────────────────────────────────────────────┘ length '1' '2' '3' '4' '5' '6' '7' '8' '9' '0' ┌────╥────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┐ -│ 0B ║ 2D │ 31 │ 32 │ 33 │ 34 │ 35 │ 36 │ 37 │ 38 │ 39 │ 30 │ ────► -1234567890 +│ 0B ║ 2D │ 31 │ 32 │ 33 │ 34 │ 35 │ 36 │ 37 │ 38 │ 39 │ 30 │ ────▶ -1234567890 └────╨────┴────┴────┴────┴────┴────┴────┴────┴────┴────┴────┘ └──┘ └────────────────────────────────────────────────────┘ length '-' '1' '2' '3' '4' '5' '6' '7' '8' '9' '0' @@ -1445,7 +1566,7 @@ Example: .... ┌────┬────┬────┬────╥────┬────┬────┬────┬────┐ -│ 00 │ 00 │ 00 │ 05 ║ 68 │ 65 │ 6C │ 6C │ 6F │ ────► "hello" +│ 00 │ 00 │ 00 │ 05 ║ 68 │ 65 │ 6C │ 6C │ 6F │ ────▶ "hello" └────┴────┴────┴────╨────┴────┴────┴────┴────┘ └─────────────────┘ └──────────────────────┘ length 'h' 'e' 'l' 'l' 'o' @@ -1455,7 +1576,7 @@ An empty string has a length of zero: .... ┌────┬────┬────┬────┐ -│ 00 │ 00 │ 00 │ 00 │ ────► "" +│ 00 │ 00 │ 00 │ 00 │ ────▶ "" └────┴────┴────┴────┘ └─────────────────┘ length @@ -1465,7 +1586,7 @@ A _NULL_ string (NULL pointer in C) has a length of -1: .... ┌────┬────┬────┬────┐ -│ FF │ FF │ FF │ FF │ ────► NULL +│ FF │ FF │ FF │ FF │ ────▶ NULL └────┴────┴────┴────┘ └─────────────────┘ length @@ -1485,7 +1606,7 @@ Example: .... ┌────╥────┬────┬────┬────┬────┬────┬────┬────┬────┐ -│ 09 ║ 31 │ 61 │ 32 │ 62 │ 33 │ 63 │ 34 │ 64 │ 35 │ ────► 0x1a2b3c4d5 +│ 09 ║ 31 │ 61 │ 32 │ 62 │ 33 │ 63 │ 34 │ 64 │ 35 │ ────▶ 0x1a2b3c4d5 └────╨────┴────┴────┴────┴────┴────┴────┴────┴────┘ └──┘ └──────────────────────────────────────────┘ length '1' 'a' '2' 'b' '3' 'c' '4' 'd' '5' @@ -1495,7 +1616,7 @@ A _NULL_ pointer has a length of 1 with value 0: .... ┌────╥────┐ -│ 01 ║ 00 │ ────► NULL (0x0) +│ 01 ║ 00 │ ────▶ NULL (0x0) └────╨────┘ └──┘ └──┘ length 0 @@ -1510,7 +1631,7 @@ Example: .... ┌────╥────┬────┬────┬────┬────┬────┬────┬────┬────┬────┐ -│ 0A ║ 31 │ 33 │ 32 │ 31 │ 39 │ 39 │ 33 │ 34 │ 35 │ 36 │ ────► 1321993456 +│ 0A ║ 31 │ 33 │ 32 │ 31 │ 39 │ 39 │ 33 │ 34 │ 35 │ 36 │ ────▶ 1321993456 └────╨────┴────┴────┴────┴────┴────┴────┴────┴────┴────┘ └──┘ └───────────────────────────────────────────────┘ length '1' '3' '2' '1' '9' '9' '3' '4' '5' '6' @@ -1532,7 +1653,7 @@ Example: .... ┌─────┬─────┬───╥──────┬─────╥──────┬─────┐ -│ str │ str │ 2 ║ key1 │ abc ║ key2 │ def │ ────► { 'key1' => 'abc', +│ str │ str │ 2 ║ key1 │ abc ║ key2 │ def │ ────▶ { 'key1' => 'abc', └─────┴─────┴───╨──────┴─────╨──────┴─────┘ 'key2' => 'def' } └───┘ └───┘ └─┘ └──────────┘ └──────────┘ type type count item 1 item 2 @@ -1759,7 +1880,7 @@ Example of array with two strings: type number of strings length ──╥────┬────┬────╥────┬────┬────┬────╥────┬────┐ - ... ║ 61 │ 62 │ 63 ║ 00 │ 00 │ 00 │ 02 ║ 64 │ 65 │ ────► [ "abc", "de" ] + ... ║ 61 │ 62 │ 63 ║ 00 │ 00 │ 00 │ 02 ║ 64 │ 65 │ ────▶ [ "abc", "de" ] ──╨────┴────┴────╨────┴────┴────┴────╨────┴────┘ └────────────┘ └─────────────────┘ └───────┘ 'a' 'b' 'c' length 'd' 'e' @@ -1775,7 +1896,7 @@ Example of array with three integers: type number of integers 123 (0x7B) ──╥────┬────┬────┬────╥────┬────┬────┬────┐ - ... ║ 00 │ 00 │ 01 │ C8 ║ 00 │ 00 │ 03 │ 15 │ ────► [ 123, 456, 789 ] + ... ║ 00 │ 00 │ 01 │ C8 ║ 00 │ 00 │ 03 │ 15 │ ────▶ [ 123, 456, 789 ] ──╨────┴────┴────┴────╨────┴────┴────┴────┘ └─────────────────┘ └─────────────────┘ 456 (0x1C8) 789 (0x315) @@ -1785,7 +1906,7 @@ A _NULL_ array: .... ┌─────╥────┬────┬────┬────┐ -│ str ║ 00 │ 00 │ 00 │ 00 │ ────► NULL +│ str ║ 00 │ 00 │ 00 │ 00 │ ────▶ NULL └─────╨────┴────┴────┴────┘ └───┘ └─────────────────┘ type number of strings @@ -1799,43 +1920,49 @@ A _NULL_ array: │ Client ├ ─ ─ ─ ─(network)─ ─ ─ ─ ┤ Relay ├────────────────┤ WeeChat │ └────────┘ └───────┘ └─────────┘ ║ ║ ║ - ╟───────────────────────────────► ║ ║ + ╟───────────────────────────────▶ ║ ║ ║ open socket ║ add client ║ ║ ║ ║ - ╟───────────────────────────────► ║ ║ - ║ cmd: init password=xxx,... ║ init/allow client ║ + ╟───────────────────────────────▶ ║ ║ + ║ cmd: handshake password=xxx,... ║ negotiate algos ║ + ║ ║ and options ║ + ║ ◀───────────────────────────────╢ ║ + ║ msg: id: "handshake" ... ║ ║ + ║ ║ ║ + ╟───────────────────────────────▶ ║ ║ + ║ cmd: init password=xxx,... ║ authenticate client ║ ║ ║ ║ - ╟───────────────────────────────► ║ ║ - ║ cmd: hdata buffer ... ╟───────────────────────► ║ + ╟───────────────────────────────▶ ║ ║ + ║ cmd: hdata buffer ... ╟───────────────────────▶ ║ ║ sync ... ║ request hdata ║ read hdata ║ ║ ║ values - ║ ║ ◄───────────────────────╢ - ║ ◄───────────────────────────────╢ hdata ║ + ║ ║ ◀───────────────────────╢ + ║ ◀───────────────────────────────╢ hdata ║ create ║ msg: hda buffer ║ ║ buffers ║ ║ ║ ║ ........ ║ ........ ║ ║ ║ ║ - ╟───────────────────────────────► ║ ║ - ║ cmd: input ... ╟───────────────────────► ║ + ╟───────────────────────────────▶ ║ ║ + ║ cmd: input ... ╟───────────────────────▶ ║ ║ ║ send data to buffer ║ send data ║ ║ ║ to buffer ║ ........ ║ ........ ║ ║ ║ ║ signal - ║ ║ ◄───────────────────────╢ received - ║ ◄───────────────────────────────╢ signal XXX ║ (hooked by + ║ ║ ◀───────────────────────╢ received + ║ ◀───────────────────────────────╢ signal XXX ║ (hooked by update ║ msg: id: "_buffer_..." ║ ║ relay) buffers ║ ║ ║ ║ ........ ║ ........ ║ ║ ║ ║ - ╟───────────────────────────────► ║ ║ + ╟───────────────────────────────▶ ║ ║ ║ cmd: ping ... ║ ║ ║ ║ ║ - ║ ◄───────────────────────────────╢ ║ + ║ ◀───────────────────────────────╢ ║ measure ║ msg: id: "_pong" ... ║ ║ response ║ ║ ║ time ║ ........ ║ ........ ║ ║ ║ ║ - ╟───────────────────────────────► ║ ║ + ╟───────────────────────────────▶ ║ ║ ║ cmd: quit ║ disconnect client ║ ║ ║ ║ .... diff --git a/doc/fr/autogen/user/relay_options.adoc b/doc/fr/autogen/user/relay_options.adoc index 7337a7b45..2ac16023b 100644 --- a/doc/fr/autogen/user/relay_options.adoc +++ b/doc/fr/autogen/user/relay_options.adoc @@ -116,6 +116,12 @@ ** valeurs: toute chaîne ** valeur par défaut: `+""+` +* [[option_relay.network.auth_password]] *relay.network.auth_password* +** description: pass:none[liste des algorithmes de hachage pour l'authentification par mot de passe dans le protocole relay, parmi ces valeurs : "plain" (mot de passe en clair, non haché), "sha256", "sha512", "pbkdf2+sha256", "pbkdf2+sha512" ; "*" signifie tous les algorithmes, un nom commençant par "!" est une valeur négative pour empêcher un algorithme d'être utilisé, le caractère joker "*" est autorisé dans les noms (exemples : "*", "pbkdf2*", "*,!plain")] +** type: chaîne +** valeurs: toute chaîne +** valeur par défaut: `+"*"+` + * [[option_relay.network.auth_timeout]] *relay.network.auth_timeout* ** description: pass:none[temps maximum (en secondes) pour l'authentification du client ; la connexion est fermée si le client n'est toujours pas authentifié après ce délai et le statut est positionné à "échec d'authentification" (0 = attendre sans fin)] ** type: entier @@ -140,6 +146,12 @@ ** valeurs: 0 .. 9 ** valeur par défaut: `+6+` +* [[option_relay.network.hash_iterations]] *relay.network.hash_iterations* +** description: pass:none[nombre d'itérations demandées au client dans le protocole weechat lorsqu'un mot de passe haché avec l'algorithme PBKDF2 est utilisé pour l'authentification ; plus d'itérations est mieux en terme de sécurité mais est plus lent à calculer ; ce nombre ne doit pas être trop élevé si votre micro-processeur est lent] +** type: entier +** valeurs: 1 .. 1000000 +** valeur par défaut: `+100000+` + * [[option_relay.network.ipv6]] *relay.network.ipv6* ** description: pass:none[écouter en IPv6 sur le socket par défaut (en plus de l'IPv4 qui est par défaut) ; les protocoles IPv4 et IPv6 peuvent être forcés (individuellement ou ensemble) dans le nom du protocole (voir /help relay)] ** type: booléen @@ -152,6 +164,12 @@ ** valeurs: 0 .. 2147483647 ** valeur par défaut: `+5+` +* [[option_relay.network.nonce_size]] *relay.network.nonce_size* +** description: pass:none[taille du nonce (en octets), généré lorsqu'un client se connecte ; le client doit utiliser ce nonce, concaténé au nonce client et au mot de passe pour hacher le mot de passe dans la commande "init" du protocole weechat] +** type: entier +** valeurs: 8 .. 128 +** valeur par défaut: `+16+` + * [[option_relay.network.password]] *relay.network.password* ** description: pass:none[mot de passe requis par les clients pour accéder à ce relai (une valeur vide indique que le mot de passe n'est pas nécessaire, voir l'option relay.network.allow_empty_password) (note : le contenu est évalué, voir /help eval)] ** type: chaîne diff --git a/doc/fr/weechat_dev.fr.adoc b/doc/fr/weechat_dev.fr.adoc index 40d0edb8b..3bff1e0fb 100644 --- a/doc/fr/weechat_dev.fr.adoc +++ b/doc/fr/weechat_dev.fr.adoc @@ -320,6 +320,7 @@ Le cœur de WeeChat est situé dans les répertoires suivants : | weechat-python-api.c | Fonctions de l'API script Python. | relay/ | Extension Relay (proxy IRC et relai pour des interfaces distantes). | relay.c | Fonctions principales de Relay. +| relay-auth.c | Authentification des clients. | relay-buffer.c | Tampon Relay. | relay-client.c | Clients du relai. | relay-command.c | Commandes de Relay. @@ -380,48 +381,47 @@ Le cœur de WeeChat est situé dans les répertoires suivants : [width="100%",cols="1m,2",options="header"] |=== -| Chemin/fichier | Description -| tests/ | Racine des tests. -| tests.cpp | Programme utilisé pour lancer tous les tests. -| scripts/ | Racine des tests de l'API script. -| test-scripts.cpp | Programme utilisé pour lancer les tests de l'API script. -| python/ | Scripts Python pour générer et lancer les tests de l'API script. -| testapigen.py | Script Python générant des scripts dans tous les languages pour tester l'API script. -| testapi.py | Script Python avec les tests API, utilisé par le script testapigen.py. -| unparse.py | Conversion de code Python vers d'autres langages, utilisé par le script testapigen.py. -| unit/ | Racine des tests unitaires. -| test-plugins.cpp | Tests : extensions. -| core/ | Racine des tests unitaires pour le cœur. -| test-core-arraylist.cpp | Tests : listes avec tableau (« arraylists »). -| test-core-calc.cpp | Tests : calcul d'expressions. -| test-core-crypto.cpp | Tests : fonctions cryptographiques. -| test-core-eval.cpp | Tests : évaluation d'expressions. -| test-core-hashtble.cpp | Tests : tables de hachage. -| test-core-hdata.cpp | Tests : hdata. -| test-core-hook.cpp | Tests : hooks. -| test-core-infolist.cpp | Tests : infolists. -| test-core-list.cpp | Tests : listes. -| test-core-secure.cpp | Tests : données sécurisées. -| test-core-string.cpp | Tests : chaînes. -| test-core-url.cpp | Tests : URLs. -| test-core-utf8.cpp | Tests : UTF-8. -| test-core-util.cpp | Tests : fonctions utiles. -| gui/ | Racine des tests unitaires pour les interfaces. -| test-gui-color.cpp | Tests : couleurs. -| test-gui-line.cpp | Tests : lignes. -| test-gui-nick.cpp | Tests : pseudos. -| plugins/ | Racine des tests unitaires pour les extensions. -| irc/ | Racine des tests unitaires pour l'extension IRC. -| test-irc-color.cpp | Tests : couleurs IRC. -| test-irc-config.cpp | Tests : configuration IRC. -| test-irc-ignore.cpp | Tests : ignores IRC. -| test-irc-message.cpp | Tests : messages IRC. -| test-irc-mode.cpp | Tests : modes IRC. -| test-irc-nick.cpp | Tests : pseudos IRC. -| test-irc-protocol.cpp | Tests : protocole IRC. -| relay/ | Racine des tests unitaires pour l'extension Relay. -| weechat/ | Racine des tests unitaires pour le protocole weechat. -| test-relay-weechat-protocol.cpp | Tests : protocole weechat. +| Chemin/fichier | Description +| tests/ | Racine des tests. +| tests.cpp | Programme utilisé pour lancer tous les tests. +| scripts/ | Racine des tests de l'API script. +| test-scripts.cpp | Programme utilisé pour lancer les tests de l'API script. +| python/ | Scripts Python pour générer et lancer les tests de l'API script. +| testapigen.py | Script Python générant des scripts dans tous les languages pour tester l'API script. +| testapi.py | Script Python avec les tests API, utilisé par le script testapigen.py. +| unparse.py | Conversion de code Python vers d'autres langages, utilisé par le script testapigen.py. +| unit/ | Racine des tests unitaires. +| test-plugins.cpp | Tests : extensions. +| core/ | Racine des tests unitaires pour le cœur. +| test-core-arraylist.cpp | Tests : listes avec tableau (« arraylists »). +| test-core-calc.cpp | Tests : calcul d'expressions. +| test-core-crypto.cpp | Tests : fonctions cryptographiques. +| test-core-eval.cpp | Tests : évaluation d'expressions. +| test-core-hashtble.cpp | Tests : tables de hachage. +| test-core-hdata.cpp | Tests : hdata. +| test-core-hook.cpp | Tests : hooks. +| test-core-infolist.cpp | Tests : infolists. +| test-core-list.cpp | Tests : listes. +| test-core-secure.cpp | Tests : données sécurisées. +| test-core-string.cpp | Tests : chaînes. +| test-core-url.cpp | Tests : URLs. +| test-core-utf8.cpp | Tests : UTF-8. +| test-core-util.cpp | Tests : fonctions utiles. +| gui/ | Racine des tests unitaires pour les interfaces. +| test-gui-color.cpp | Tests : couleurs. +| test-gui-line.cpp | Tests : lignes. +| test-gui-nick.cpp | Tests : pseudos. +| plugins/ | Racine des tests unitaires pour les extensions. +| irc/ | Racine des tests unitaires pour l'extension IRC. +| test-irc-color.cpp | Tests : couleurs IRC. +| test-irc-config.cpp | Tests : configuration IRC. +| test-irc-ignore.cpp | Tests : ignores IRC. +| test-irc-message.cpp | Tests : messages IRC. +| test-irc-mode.cpp | Tests : modes IRC. +| test-irc-nick.cpp | Tests : pseudos IRC. +| test-irc-protocol.cpp | Tests : protocole IRC. +| relay/ | Racine des tests unitaires pour l'extension Relay. +| test-relay-auth.cpp | Tests : authentification des clients. |=== [[documentation_translations]] diff --git a/doc/fr/weechat_relay_protocol.fr.adoc b/doc/fr/weechat_relay_protocol.fr.adoc index 67b976175..5bcb88e82 100644 --- a/doc/fr/weechat_relay_protocol.fr.adoc +++ b/doc/fr/weechat_relay_protocol.fr.adoc @@ -36,11 +36,11 @@ Les _clients_ sont connectés au _relay_ comme dans le diagramme ci-dessous : .... ┌──────────┐ Station de travail ┌────────┐ ┌───┤ client 1 │ (Linux, Windows, - │ irc │◄──┐ ╔═══════════╤═══════╗ │ └──────────┘ BSD, macOS ...) - └────────┘ └──╢ │ ║◄───┘ ┌──────────┐ - ...... ║ WeeChat │ Relay ║◄───────┤ client 2 │ Appareil mobile - ┌────────┐ ┌──╢ │ ║◄───┐ └──────────┘ (Android, iPhone ...) - │ jabber │◄──┘ ╚═══════════╧═══════╝ │ ...... + │ irc │◀──┐ ╔═══════════╤═══════╗ │ └──────────┘ BSD, macOS ...) + └────────┘ └──╢ │ ║◀───┘ ┌──────────┐ + ...... ║ WeeChat │ Relay ║◀───────┤ client 2 │ Appareil mobile + ┌────────┐ ┌──╢ │ ║◀───┐ └──────────┘ (Android, iPhone ...) + │ jabber │◀──┘ ╚═══════════╧═══════╝ │ ...... └────────┘ │ ┌──────────┐ ...... └───┤ client N │ Autres appareils └──────────┘ @@ -91,24 +91,139 @@ Liste des commandes disponibles (détail dans les chapitres suivants) : [width="80%",cols="^3m,14",options="header"] |=== -| Commande | Description -| init | Initialiser la connexion avec _relay_. -| hdata | Demander un _hdata_. -| info | Demander une _info_. -| infolist | Demander une _infolist_. -| nicklist | Demander une _nicklist_ (liste de pseudos). -| input | Envoyer des données à un tampon (texte ou commande). -| sync | Synchroniser un/des tampon(s) : recevoir les mises à jour pour le(s) tampon(s). -| desync | Désynchroniser un/des tampon(s) : stopper les mises à jour pour le(s) tampon(s). -| quit | Se déconnecter de _relay_. +| Commande | Description +| handshake | Poignée de main : préparer l'authentification du client et définir des options, avant la commande _init_. +| init | S'authentifier avec _relay_. +| hdata | Demander un _hdata_. +| info | Demander une _info_. +| infolist | Demander une _infolist_. +| nicklist | Demander une _nicklist_ (liste de pseudos). +| input | Envoyer des données à un tampon (texte ou commande). +| sync | Synchroniser un/des tampon(s) : recevoir les mises à jour pour le(s) tampon(s). +| desync | Désynchroniser un/des tampon(s) : stopper les mises à jour pour le(s) tampon(s). +| quit | Se déconnecter de _relay_. |=== +[[command_handshake]] +=== handshake + +_WeeChat ≥ 2.9._ + +Effectuer une poignée de main entre le client et WeeChat : cela est obligatoire +dans la plupart des cas pour connaître les paramètres de la session et préparer +l'authentification avec la commande _init_. + +La poignée de main peut être effectuée plusieurs fois avant la commande _init_, +même si cela est rarement nécessaire. + +Syntaxe : + +---- +handshake [<option>=<valeur>,[<option>=<valeur>,...]] +---- + +Paramètres : + +* _option_ : une des options suivantes : +** _password_ : liste d'algorithmes de hachage supportés par le client (séparés par + des deux-points), les valeurs autorisées sont : +*** _plain_ : mot de passe en clair (pas de hachage) +*** _sha256_ : mot de passe salé et haché avec l'algorithme SHA256 +*** _sha512_ : mot de passe salé et haché avec l'algorithme SHA512 +*** _pbkdf2+sha256_ : mot de passe salé et haché avec l'algorithme PBKDF2 + (avec un hachage SHA256) +*** _pbkdf2+sha512_ : mot de passe salé et haché avec l'algorithme PBKDF2 + (avec un hachage SHA512) +** _compression_ : type de compression : +*** _zlib_ : activer la compression _zlib_ pour les messages envoyés par _relay_ + (activée par défaut si _relay_ supporte la compression _zlib_) +*** _off_ : désactiver la compression + +Notes à propos de l'option _password_ : + +* Si l'option _password_ n'est pas donnée (ou si la commande _handshake_ n'est + pas envoyée par le client), _relay_ utilise automatiquement l'authentification + _plain_ (si elle est autorisée côté _relay_). +* _Relay_ choisit l'algorithme le plus sûr disponible à la fois côté client et + _relay_, par ordre de priorité du premier (plus sûr) au dernier utilisé : + . _pbkdf2+sha512_ + . _pbkdf2+sha256_ + . _sha512_ + . _sha256_ + . _plain_ + +[NOTE] +Si l'option _password_ n'est pas donnée, WeeChat utilise automatiquement +l'authentification _plain_ (si autorisée par _relay_). + +WeeChat répond avec une table de hachage qui contient les clés et valeurs +suivantes : + +* _auth_password_ : l'authentification mot de passe négociée : supportée par le + client et _relay_ : +** (valeur vide) : la négociation a échoué, l'authentification par mot de passe + n'est *PAS* possible +** _plain_ +** _sha256_ +** _sha512_ +** _pbkdf2+sha256_ +** _pbkdf2+sha512_ +* _hash_iterations_ : nombre d'itérations pour le hachage (pour l'algorithme + PBKDF2 seulement) +* _totp_: +** _on_ : le mot de passe à usage unique basé sur le temps (TOTP : Time-based + One-Time Password) est configuré et est attendu dans la commande _init_ +** _off_ : le mot de passe à usage unique basé sur le temps (TOTP : Time-based + One-Time Password) n'est pas activé et pas nécessaire dans la commande _init_ +* _nonce_ : un tampon d'octets non prédictibles, envoyé en hexadécimal, pour + empêcher les attaques par rejeu ; si _auth_password_ est un algorithme de + hachage, le client doit calculer le mot de passe haché avec ce nonce, + concaténé avec un nonce client et le mot de passe utilisateur (le nonce + _relay_ + le nonce client constituent le sel utilisé dans l'algorithme de + hachage du mot de passe) + +Exemples : + +---- +# rien d'offert par le client (ou seulement "plain"), l'authentification par mot de passe "plain" sera utilisée si autorisée côté relay +handshake +handshake password=plain + +# seulement plain, sha256 et pbkdf2+sha256 sont supportés par le client +handshake password=plain:sha256:pbkdf2+sha256 +---- + +Exemple de réponse : + +[source,python] +---- +id: 'handshake' +htb: {'auth_password': 'pbkdf2+sha256', 'hash_iterations': '100000', 'totp': 'on', 'nonce': '85B1EE00695A5B254E14F4885538DF0D'} +---- + +Le client peut s'authentifier avec cette commande (voir la <<command_init,commande init>>), +le sel est le nonce _relay_ + "ABCD" ("41424344" en hexadécimal) : + +---- +init password_hash=pbkdf2+sha256:85b1ee00695a5b254e14f4885538df0d41424344:100000:01757d53157ca14a1419e3a8cc1563536520a60b76d2d48e7f9ac09afc945a1c +---- + +[TIP] +Avec WeeChat ≤ 2.8, la commande _handshake_ n'est pas implémentée, WeeChat ignore +silencieusement cette commande, même si elle est envoyée avant la commande _init_. + +Il est donc sûr d'envoyer cette commande à n'importe quelle version de WeeChat. + [[command_init]] === init -Initialiser la connexion avec _relay_. Il doit s'agir de la première commande -envoyée à _relay_. Si elle n'est pas envoyée, _relay_ coupera la connexion à la -première commande reçue, sans avertissement. +_Mis à jour dans les versions 2.4, 2.8, 2.9._ + +S'authentifier avec _relay_. + +Il doit s'agir de la première commande envoyée à _relay_ (seule la commande +_handshake_ peut être envoyée avant _init_). + +Si elle n'est pas envoyée, _relay_ coupera la connexion à la première commande +reçue, sans avertissement. Syntaxe : @@ -128,7 +243,9 @@ Paramètres : One-Time Password) utilisé comme second facteur d'authentification, en plus du mot de passe (option _relay.network.totp_secret_ dans WeeChat) _(WeeChat ≥ 2.4)_ -** _compression_ : type de compression : +** _compression_ : type de compression (*obsolète* depuis la version 2.9, gardé + pour des raisons de compatibilité mais devrait être envoyé dans la + <<command_handshake,commande handshake>>) : *** _zlib_ : activer la compression _zlib_ pour les messages envoyés par _relay_ (activée par défaut si _relay_ supporte la compression _zlib_) *** _off_ : désactiver la compression @@ -140,13 +257,28 @@ par exemple `init password=foo\,bar` pour envoyer le mot de passe "foo,bar". Le format du mot de passe haché est l'un des suivants, où _hash_ est le mot de passe haché en hexadécimal : -* `+sha256:hash+` -* `+sha512:hash+` -* `+pbkdf2:algorithme:sel:itérations:hash+` avec : -** _algorithme_ : _sha256_ ou _sha512_ -** _sel_ : sel (hexadécimal) +* `+sha256:sel:hash+` avec : +** _sel_ : sel (hexadécimal), qui doit démarrer avec le nonce de _relay_, + concaténé au nonce client +** _hash_ : le sel et mot de passe haché (hexadécimal) +* `+sha512:sel:hash+` avec : +** _sel_ : sel (hexadécimal), qui doit démarrer avec le nonce de _relay_, + concaténé au nonce client +** _hash_ : le set et mot de passe haché (hexadécimal) +* `+pbkdf2+sha256:sel:itérations:hash+` avec : +** _sel_ : sel (hexadécimal), qui doit démarrer avec le nonce de _relay_, + concaténé au nonce client +** _iterations_ : nombre d'itérations +** _hash_ : le sel et mot de passe haché avec l'algorithme SHA256 (hexadécimal) +* `+pbkdf2+sha256:sel:itérations:hash+` avec : +** _sel_ : sel (hexadécimal), qui doit démarrer avec le nonce de _relay_, + concaténé au nonce client ** _iterations_ : nombre d'itérations -** _hash_ : le mot de passe haché (hexadécimal) +** _hash_ : le sel et mot de passe haché avec l'algorithme SHA512 (hexadécimal) + +[NOTE] +Les chaînes en hexadécimal peuvent être en minuscules ou majuscules, _relay_ +peut décoder les deux. Exemples : @@ -163,14 +295,14 @@ init password=mypass,totp=123456 # initialiser et désactiver la compression init password=mypass,compression=off -# initialiser avec un mot de passe haché (SHA256) (WeeChat ≥ 2.8) -init password_hash=sha256:b9a4c3393dfac4330736684510378851e581c68add8eca84110c31a33e694676 +# initialiser avec un mot de passe haché (SHA256 : sel="nonce:cnonce") (WeeChat ≥ 2.9) +init password_hash=sha256:6e6f6e63653a636e6f6e6365:b9a4c3393dfac4330736684510378851e581c68add8eca84110c31a33e694676 -# initialiser avec un mot de passe haché (SHA512) (WeeChat ≥ 2.8) -init password_hash=sha512:4469190d4e0d1fdc0afb6f408d9873c89b8ce89cc4db79fe058255c55ad6821fa5e9bb068f9e578c8ae7cc825d85ff99c439d59e439bc589d95620a1e6b8ae6e +# initialiser avec un mot de passe haché (SHA512 : sel="nonce:cnonce") (WeeChat ≥ 2.9) +init password_hash=sha512:6e6f6e63653a636e6f6e6365:4469190d4e0d1fdc0afb6f408d9873c89b8ce89cc4db79fe058255c55ad6821fa5e9bb068f9e578c8ae7cc825d85ff99c439d59e439bc589d95620a1e6b8ae6e -# initialiser avec un mot de passe haché (PBKDF2: SHA256, sel="ABCDEFGHIJKLMNOP", 100000 itérations) (WeeChat ≥ 2.8) -init password_hash=pbkdf2:sha256:4142434445464748494a4b4c4d4e4f50:100000:01757d53157ca14a1419e3a8cc1563536520a60b76d2d48e7f9ac09afc945a1c +# initialiser avec un mot de passe haché (PBKDF2 : SHA256, sel="nonce:cnonce", 100000 itérations) (WeeChat ≥ 2.9) +init password_hash=pbkdf2:sha256:6e6f6e63653a636e6f6e6365:100000:01757d53157ca14a1419e3a8cc1563536520a60b76d2d48e7f9ac09afc945a1c ---- [[command_hdata]] @@ -1415,7 +1547,7 @@ Exemple : .... ┌────┐ -│ 41 │ ────► 65 (0x41: "A") +│ 41 │ ────▶ 65 (0x41: "A") └────┘ .... @@ -1431,11 +1563,11 @@ Exemples : .... ┌────┬────┬────┬────┐ -│ 00 │ 01 │ E2 │ 40 │ ────► 123456 +│ 00 │ 01 │ E2 │ 40 │ ────▶ 123456 └────┴────┴────┴────┘ ┌────┬────┬────┬────┐ -│ FF │ FE │ 1D │ C0 │ ────► -123456 +│ FF │ FE │ 1D │ C0 │ ────▶ -123456 └────┴────┴────┴────┘ .... @@ -1451,13 +1583,13 @@ Exemples : .... ┌────╥────┬────┬────┬────┬────┬────┬────┬────┬────┬────┐ -│ 0A ║ 31 │ 32 │ 33 │ 34 │ 35 │ 36 │ 37 │ 38 │ 39 │ 30 │ ────► 1234567890 +│ 0A ║ 31 │ 32 │ 33 │ 34 │ 35 │ 36 │ 37 │ 38 │ 39 │ 30 │ ────▶ 1234567890 └────╨────┴────┴────┴────┴────┴────┴────┴────┴────┴────┘ └──┘ └───────────────────────────────────────────────┘ long. '1' '2' '3' '4' '5' '6' '7' '8' '9' '0' ┌────╥────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┐ -│ 0B ║ 2D │ 31 │ 32 │ 33 │ 34 │ 35 │ 36 │ 37 │ 38 │ 39 │ 30 │ ────► -1234567890 +│ 0B ║ 2D │ 31 │ 32 │ 33 │ 34 │ 35 │ 36 │ 37 │ 38 │ 39 │ 30 │ ────▶ -1234567890 └────╨────┴────┴────┴────┴────┴────┴────┴────┴────┴────┴────┘ └──┘ └────────────────────────────────────────────────────┘ long. '-' '1' '2' '3' '4' '5' '6' '7' '8' '9' '0' @@ -1473,7 +1605,7 @@ Exemple : .... ┌────┬────┬────┬────╥────┬────┬────┬────┬────┐ -│ 00 │ 00 │ 00 │ 05 ║ 68 │ 65 │ 6C │ 6C │ 6F │ ────► "hello" +│ 00 │ 00 │ 00 │ 05 ║ 68 │ 65 │ 6C │ 6C │ 6F │ ────▶ "hello" └────┴────┴────┴────╨────┴────┴────┴────┴────┘ └─────────────────┘ └──────────────────────┘ longueur 'h' 'e' 'l' 'l' 'o' @@ -1483,7 +1615,7 @@ Une chaîne vide a une longueur de zéro : .... ┌────┬────┬────┬────┐ -│ 00 │ 00 │ 00 │ 00 │ ────► "" +│ 00 │ 00 │ 00 │ 00 │ ────▶ "" └────┴────┴────┴────┘ └─────────────────┘ longueur @@ -1493,7 +1625,7 @@ Une chaîne _NULL_ (pointeur NULL en C) a une longueur de -1 : .... ┌────┬────┬────┬────┐ -│ FF │ FF │ FF │ FF │ ────► NULL +│ FF │ FF │ FF │ FF │ ────▶ NULL └────┴────┴────┴────┘ └─────────────────┘ longueur @@ -1515,7 +1647,7 @@ Exemple : .... ┌────╥────┬────┬────┬────┬────┬────┬────┬────┬────┐ -│ 09 ║ 31 │ 61 │ 32 │ 62 │ 33 │ 63 │ 34 │ 64 │ 35 │ ────► 0x1a2b3c4d5 +│ 09 ║ 31 │ 61 │ 32 │ 62 │ 33 │ 63 │ 34 │ 64 │ 35 │ ────▶ 0x1a2b3c4d5 └────╨────┴────┴────┴────┴────┴────┴────┴────┴────┘ └──┘ └──────────────────────────────────────────┘ long. '1' 'a' '2' 'b' '3' 'c' '4' 'd' '5' @@ -1525,7 +1657,7 @@ Un pointeur _NULL_ a une longueur de 1 avec la valeur 0 : .... ┌────╥────┐ -│ 01 ║ 00 │ ────► NULL (0x0) +│ 01 ║ 00 │ ────▶ NULL (0x0) └────╨────┘ └──┘ └──┘ long. 0 @@ -1541,7 +1673,7 @@ Exemple : .... ┌────╥────┬────┬────┬────┬────┬────┬────┬────┬────┬────┐ -│ 0A ║ 31 │ 33 │ 32 │ 31 │ 39 │ 39 │ 33 │ 34 │ 35 │ 36 │ ────► 1321993456 +│ 0A ║ 31 │ 33 │ 32 │ 31 │ 39 │ 39 │ 33 │ 34 │ 35 │ 36 │ ────▶ 1321993456 └────╨────┴────┴────┴────┴────┴────┴────┴────┴────┴────┘ └──┘ └───────────────────────────────────────────────┘ long. '1' '3' '2' '1' '9' '9' '3' '4' '5' '6' @@ -1564,7 +1696,7 @@ Exemple : .... ┌─────┬─────┬───╥──────┬─────╥──────┬─────┐ -│ str │ str │ 2 ║ key1 │ abc ║ key2 │ def │ ────► { 'key1' => 'abc', +│ str │ str │ 2 ║ key1 │ abc ║ key2 │ def │ ────▶ { 'key1' => 'abc', └─────┴─────┴───╨──────┴─────╨──────┴─────┘ 'key2' => 'def' } └───┘ └───┘ └─┘ └──────────┘ └──────────┘ type type nombre élément 1 élément 2 @@ -1796,7 +1928,7 @@ Exemple de tableau avec deux chaînes de caractères : type nombre de chaînes longueur ──╥────┬────┬────╥────┬────┬────┬────╥────┬────┐ - ... ║ 61 │ 62 │ 63 ║ 00 │ 00 │ 00 │ 02 ║ 64 │ 65 │ ────► [ "abc", "de" ] + ... ║ 61 │ 62 │ 63 ║ 00 │ 00 │ 00 │ 02 ║ 64 │ 65 │ ────▶ [ "abc", "de" ] ──╨────┴────┴────╨────┴────┴────┴────╨────┴────┘ └────────────┘ └─────────────────┘ └───────┘ 'a' 'b' 'c' longueur 'd' 'e' @@ -1812,7 +1944,7 @@ Exemple de tableau avec trois entiers : type nombre d'entiers 123 (0x7B) ──╥────┬────┬────┬────╥────┬────┬────┬────┐ - ... ║ 00 │ 00 │ 01 │ C8 ║ 00 │ 00 │ 03 │ 15 │ ────► [ 123, 456, 789 ] + ... ║ 00 │ 00 │ 01 │ C8 ║ 00 │ 00 │ 03 │ 15 │ ────▶ [ 123, 456, 789 ] ──╨────┴────┴────┴────╨────┴────┴────┴────┘ └─────────────────┘ └─────────────────┘ 456 (0x1C8) 789 (0x315) @@ -1822,7 +1954,7 @@ Un tableau _NULL_ : .... ┌─────╥────┬────┬────┬────┐ -│ str ║ 00 │ 00 │ 00 │ 00 │ ────► NULL +│ str ║ 00 │ 00 │ 00 │ 00 │ ────▶ NULL └─────╨────┴────┴────┴────┘ └───┘ └─────────────────┘ type nombre de chaînes @@ -1836,43 +1968,49 @@ Un tableau _NULL_ : │ Client ├ ─ ─ ─ ─ (réseau)─ ─ ─ ─ ┤ Relay ├────────────────┤ WeeChat │ └────────┘ └───────┘ └─────────┘ ║ ║ ║ - ╟───────────────────────────────► ║ ║ + ╟───────────────────────────────▶ ║ ║ ║ ouverture socket ║ ajout du client ║ ║ ║ ║ - ╟───────────────────────────────► ║ ║ - ║ cmd: init password=xxx,... ║ init/autoriser client ║ + ╟───────────────────────────────▶ ║ ║ + ║ cmd: handshake password=xxx,... ║ négociation algos ║ + ║ ║ et options ║ + ║ ◀───────────────────────────────╢ ║ + ║ msg: id: "handshake" ... ║ ║ ║ ║ ║ - ╟───────────────────────────────► ║ ║ - ║ cmd: hdata buffer ... ╟───────────────────────► ║ + ╟───────────────────────────────▶ ║ ║ + ║ cmd: init password=xxx,... ║ authentification ║ + ║ ║ client ║ + ╟───────────────────────────────▶ ║ ║ + ║ cmd: hdata buffer ... ╟───────────────────────▶ ║ ║ sync ... ║ demande de hdata ║ lecture ║ ║ ║ valeurs - ║ ║ ◄───────────────────────╢ hdata - ║ ◄───────────────────────────────╢ hdata ║ + ║ ║ ◀───────────────────────╢ hdata + ║ ◀───────────────────────────────╢ hdata ║ créat° ║ msg: hda buffer ║ ║ tampons ║ ║ ║ ║ ........ ║ ........ ║ ║ ║ ║ - ╟───────────────────────────────► ║ ║ - ║ cmd: input ... ╟───────────────────────► ║ + ╟───────────────────────────────▶ ║ ║ + ║ cmd: input ... ╟───────────────────────▶ ║ ║ ║ envoi données au tampon ║ envoi données ║ ║ ║ au tampon ║ ........ ║ ........ ║ ║ ║ ║ signal - ║ ║ ◄───────────────────────╢ reçu - ║ ◄───────────────────────────────╢ signal XXX ║ (accroché + ║ ║ ◀───────────────────────╢ reçu + ║ ◀───────────────────────────────╢ signal XXX ║ (accroché MAJ ║ msg: id: "_buffer_..." ║ ║ par relay) tampons ║ ║ ║ ║ ........ ║ ........ ║ ║ ║ ║ - ╟───────────────────────────────► ║ ║ + ╟───────────────────────────────▶ ║ ║ ║ cmd: ping ... ║ ║ ║ ║ ║ - ║ ◄───────────────────────────────╢ ║ + ║ ◀───────────────────────────────╢ ║ mesure ║ msg: id: "_pong" ... ║ ║ temps ║ ║ ║ réponse ║ ........ ║ ........ ║ ║ ║ ║ - ╟───────────────────────────────► ║ ║ + ╟───────────────────────────────▶ ║ ║ ║ cmd: quit ║ déconnexion du client ║ ║ ║ ║ .... diff --git a/doc/it/autogen/user/relay_options.adoc b/doc/it/autogen/user/relay_options.adoc index 5a58effc4..0baad687d 100644 --- a/doc/it/autogen/user/relay_options.adoc +++ b/doc/it/autogen/user/relay_options.adoc @@ -116,6 +116,12 @@ ** valori: qualsiasi stringa ** valore predefinito: `+""+` +* [[option_relay.network.auth_password]] *relay.network.auth_password* +** descrizione: 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")] +** tipo: stringa +** valori: qualsiasi stringa +** valore predefinito: `+"*"+` + * [[option_relay.network.auth_timeout]] *relay.network.auth_timeout* ** descrizione: 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)] ** tipo: intero @@ -140,6 +146,12 @@ ** valori: 0 .. 9 ** valore predefinito: `+6+` +* [[option_relay.network.hash_iterations]] *relay.network.hash_iterations* +** descrizione: 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] +** tipo: intero +** valori: 1 .. 1000000 +** valore predefinito: `+100000+` + * [[option_relay.network.ipv6]] *relay.network.ipv6* ** descrizione: 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)] ** tipo: bool @@ -152,6 +164,12 @@ ** valori: 0 .. 2147483647 ** valore predefinito: `+5+` +* [[option_relay.network.nonce_size]] *relay.network.nonce_size* +** descrizione: 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] +** tipo: intero +** valori: 8 .. 128 +** valore predefinito: `+16+` + * [[option_relay.network.password]] *relay.network.password* ** descrizione: 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)] ** tipo: stringa diff --git a/doc/ja/autogen/user/relay_options.adoc b/doc/ja/autogen/user/relay_options.adoc index d8b19979f..c923d24db 100644 --- a/doc/ja/autogen/user/relay_options.adoc +++ b/doc/ja/autogen/user/relay_options.adoc @@ -116,6 +116,12 @@ ** 値: 未制約文字列 ** デフォルト値: `+""+` +* [[option_relay.network.auth_password]] *relay.network.auth_password* +** 説明: 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")] +** タイプ: 文字列 +** 値: 未制約文字列 +** デフォルト値: `+"*"+` + * [[option_relay.network.auth_timeout]] *relay.network.auth_timeout* ** 説明: 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)] ** タイプ: 整数 @@ -140,6 +146,12 @@ ** 値: 0 .. 9 ** デフォルト値: `+6+` +* [[option_relay.network.hash_iterations]] *relay.network.hash_iterations* +** 説明: 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] +** タイプ: 整数 +** 値: 1 .. 1000000 +** デフォルト値: `+100000+` + * [[option_relay.network.ipv6]] *relay.network.ipv6* ** 説明: pass:none[デフォルトで IPv6 ソケットをリッスン (デフォルトの IPv4 に加えて); 特定のプロトコルでプロトコルに IPv4 と IPv6 (個別または両方) を強制 (/help relay を参照してください)] ** タイプ: ブール @@ -152,6 +164,12 @@ ** 値: 0 .. 2147483647 ** デフォルト値: `+5+` +* [[option_relay.network.nonce_size]] *relay.network.nonce_size* +** 説明: 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] +** タイプ: 整数 +** 値: 8 .. 128 +** デフォルト値: `+16+` + * [[option_relay.network.password]] *relay.network.password* ** 説明: pass:none[このリレーを利用するためにクライアントが必要なパスワード (空の場合パスワードなし、オプション relay.network.allow_empty_password を参照してください) (注意: 値は評価されます、/help eval を参照してください)] ** タイプ: 文字列 diff --git a/doc/ja/weechat_dev.ja.adoc b/doc/ja/weechat_dev.ja.adoc index 0e4170314..37325bda0 100644 --- a/doc/ja/weechat_dev.ja.adoc +++ b/doc/ja/weechat_dev.ja.adoc @@ -327,6 +327,8 @@ WeeChat "core" は以下のディレクトリに配置されています: | weechat-python-api.c | python スクリプト作成 API 関数 | relay/ | relay プラグイン (IRC プロキシとリモートインターフェースへの中継) | relay.c | relay の主要関数 +// TRANSLATION MISSING +| relay-auth.c | Clients authentification. | relay-buffer.c | relay バッファ | relay-client.c | relay クライアント | relay-command.c | relay コマンド @@ -387,60 +389,58 @@ WeeChat "core" は以下のディレクトリに配置されています: [width="100%",cols="1m,2",options="header"] |=== -| パス/ファイル名 | 説明 -| tests/ | テスト用のルートディレクトリ -| tests.cpp | 全テストの実行時に使われるプログラム -| scripts/ | スクリプト API テスト用のルートディレクトリ -| test-scripts.cpp | スクリプト API テストの実行時に使われるプログラム -| python/ | スクリプト API テストを生成、実行する Python スクリプト -| testapigen.py | スクリプト API のテスト時にすべての言語に関するスクリプトを生成する Python スクリプト -| testapi.py | スクリプト API テスト時に使われる Python スクリプト (スクリプト testapigen.py から使われます) -| unparse.py | Python コードを別の言語に変換 (スクリプト testapigen.py から使われます) -| unit/ | 単体テスト用のルートディレクトリ -| test-plugins.cpp | テスト: プラグイン -| core/ | core 向け単体テスト用のルートディレクトリ -| test-core-arraylist.cpp | テスト: 配列リスト -// TRANSLATION MISSING -| test-core-calc.cpp | Tests: calculation of expressions. +| パス/ファイル名 | 説明 +| tests/ | テスト用のルートディレクトリ +| tests.cpp | 全テストの実行時に使われるプログラム +| scripts/ | スクリプト API テスト用のルートディレクトリ +| test-scripts.cpp | スクリプト API テストの実行時に使われるプログラム +| python/ | スクリプト API テストを生成、実行する Python スクリプト +| testapigen.py | スクリプト API のテスト時にすべての言語に関するスクリプトを生成する Python スクリプト +| testapi.py | スクリプト API テスト時に使われる Python スクリプト (スクリプト testapigen.py から使われます) +| unparse.py | Python コードを別の言語に変換 (スクリプト testapigen.py から使われます) +| unit/ | 単体テスト用のルートディレクトリ +| test-plugins.cpp | テスト: プラグイン +| core/ | core 向け単体テスト用のルートディレクトリ +| test-core-arraylist.cpp | テスト: 配列リスト // TRANSLATION MISSING -| test-core-crypto.cpp | Tests: cryptographic functions. -| test-core-eval.cpp | テスト: 式の評価 -| test-core-hashtble.cpp | テスト: ハッシュテーブル -| test-core-hdata.cpp | テスト: hdata -| test-core-hook.cpp | テスト: フック -| test-core-infolist.cpp | テスト: インフォリスト -| test-core-list.cpp | テスト: リスト -| test-core-secure.cpp | テスト: データ保護 -| test-core-string.cpp | テスト: 文字列 -| test-core-url.cpp | テスト: URL -| test-core-utf8.cpp | テスト: UTF-8 -| test-core-util.cpp | テスト: ユーティリティ関数 -| gui/ | インターフェースの単体テストを収める最上位ディレクトリ +| test-core-calc.cpp | Tests: calculation of expressions. // TRANSLATION MISSING -| test-gui-color.cpp | Tests: colors. -| test-gui-line.cpp | テスト: 行 +| test-core-crypto.cpp | Tests: cryptographic functions. +| test-core-eval.cpp | テスト: 式の評価 +| test-core-hashtble.cpp | テスト: ハッシュテーブル +| test-core-hdata.cpp | テスト: hdata +| test-core-hook.cpp | テスト: フック +| test-core-infolist.cpp | テスト: インフォリスト +| test-core-list.cpp | テスト: リスト +| test-core-secure.cpp | テスト: データ保護 +| test-core-string.cpp | テスト: 文字列 +| test-core-url.cpp | テスト: URL +| test-core-utf8.cpp | テスト: UTF-8 +| test-core-util.cpp | テスト: ユーティリティ関数 +| gui/ | インターフェースの単体テストを収める最上位ディレクトリ // TRANSLATION MISSING -| test-gui-nick.cpp | テスト: nicks -| plugins/ | プラグインの単体テストを収める最上位ディレクトリ -| irc/ | IRC プラグインの単体テストを収める最上位ディレクトリ +| test-gui-color.cpp | Tests: colors. +| test-gui-line.cpp | テスト: 行 // TRANSLATION MISSING -| test-irc-color.cpp | Tests: IRC colors. -| test-irc-config.cpp | テスト: IRC 設定 +| test-gui-nick.cpp | テスト: nicks +| plugins/ | プラグインの単体テストを収める最上位ディレクトリ +| irc/ | IRC プラグインの単体テストを収める最上位ディレクトリ // TRANSLATION MISSING -| test-irc-ignore.cpp | Tests: IRC ignores. +| test-irc-color.cpp | Tests: IRC colors. +| test-irc-config.cpp | テスト: IRC 設定 // TRANSLATION MISSING -| test-irc-message.cpp | Tests: IRC messages. +| test-irc-ignore.cpp | Tests: IRC ignores. // TRANSLATION MISSING -| test-irc-mode.cpp | Tests: IRC modes. +| test-irc-message.cpp | Tests: IRC messages. // TRANSLATION MISSING -| test-irc-nick.cpp | Tests: IRC nicks. -| test-irc-protocol.cpp | テスト: IRC プロトコル +| test-irc-mode.cpp | Tests: IRC modes. // TRANSLATION MISSING -| relay/ | Root of unit tests for Relay plugin. +| test-irc-nick.cpp | Tests: IRC nicks. +| test-irc-protocol.cpp | テスト: IRC プロトコル // TRANSLATION MISSING -| weechat/ | Root of unit tests for weechat protocol. +| relay/ | Root of unit tests for Relay plugin. // TRANSLATION MISSING -| test-relay-weechat-protocol.cpp | Tests: weechat protocol. +| test-relay-auth.cpp | Tests: clients authentication. |=== [[documentation_translations]] diff --git a/doc/ja/weechat_relay_protocol.ja.adoc b/doc/ja/weechat_relay_protocol.ja.adoc index 1a10f5047..97ed97278 100644 --- a/doc/ja/weechat_relay_protocol.ja.adoc +++ b/doc/ja/weechat_relay_protocol.ja.adoc @@ -39,11 +39,11 @@ .... ┌────────────────┐ ワークステーション ┌────────┐ ┌───┤ クライアント 1 │ (Linux、Windows、 - │ irc │◄──┐ ╔═══════════╤════════╗ │ └────────────────┘ BSD、macOS ...) - └────────┘ └──╢ │ ║◄───┘ ┌────────────────┐ - ...... ║ WeeChat │ リレー ║◄───────┤ クライアント 2 │ 携帯デバイス - ┌────────┐ ┌──╢ │ ║◄───┐ └────────────────┘ (Android、iPhone ...) - │ jabber │◄──┘ ╚═══════════╧════════╝ │ ...... + │ irc │◀──┐ ╔═══════════╤════════╗ │ └────────────────┘ BSD、macOS ...) + └────────┘ └──╢ │ ║◀───┘ ┌────────────────┐ + ...... ║ WeeChat │ リレー ║◀───────┤ クライアント 2 │ 携帯デバイス + ┌────────┐ ┌──╢ │ ║◀───┐ └────────────────┘ (Android、iPhone ...) + │ jabber │◀──┘ ╚═══════════╧════════╝ │ ...... └────────┘ │ ┌────────────────┐ ...... └───┤ クライアント N │ その他のデバイス └────────────────┘ @@ -93,24 +93,134 @@ _リレー_ プラグインは _IRC プロキシ_ のように振舞います ( [width="80%",cols="^3m,14",options="header"] |=== -| コマンド | 説明 -| init | _リレー_ 接続を初期化 -| hdata | _hdata_ を要求 -| info | _インフォ_ を要求 -| infolist | _インフォリスト_ を要求 -| nicklist | _ニックネームリスト_ を要求 -| input | バッファにデータを送信 (テキストまたはコマンド) -| sync | バッファを同期: バッファの最新情報を取得 -| desync | バッファを非同期: バッファの更新を止める -| quit | _リレー_ から切断 +| コマンド | 説明 +// TRANSLATION MISSING +| handshake | Handshake: prepare client authentication and set options, before _init_ command. +| init | _リレー_ 接続を初期化 +| hdata | _hdata_ を要求 +| info | _インフォ_ を要求 +| infolist | _インフォリスト_ を要求 +| nicklist | _ニックネームリスト_ を要求 +| input | バッファにデータを送信 (テキストまたはコマンド) +| sync | バッファを同期: バッファの最新情報を取得 +| desync | バッファを非同期: バッファの更新を止める +| quit | _リレー_ から切断 |=== +// TRANSLATION MISSING +[[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 [<option>=<value>,[<option>=<value>,...]] +---- + +Arguments: + +* _option_: one of following options: +** _password_: list of hash algorithms supported by the client (separated by colons), + allowed values are: +*** _plain_: plain text password (no hash) +*** _sha256_: password salted and hashed with SHA256 algorithm +*** _sha512_: password salted and hashed with SHA512 algorithm +*** _pbkdf2+sha256_: password salted and hashed with PBKDF2 algorithm (using SHA256 hash) +*** _pbkdf2+sha512_: password salted and hashed with PBKDF2 algorithm (using SHA512 hash) +** _compression_: compression type: +*** _zlib_: enable _zlib_ compression for messages sent by _relay_ + (enabled by default if _relay_ supports _zlib_ compression) +*** _off_: disable compression + +Notes about option _password_: + +* If the option is not given (of if the _handshake_ command is not sent by the + client), _relay_ uses automatically _plain_ authentication (if allowed on + _relay_ side). +* _Relay_ chooses the safest algorithm available on both client and _relay_, + by order of priority from first (safest) to last used: + . _pbkdf2+sha512_ + . _pbkdf2+sha256_ + . _sha512_ + . _sha256_ + . _plain_ + +WeeChat replies with a hashtable containing the following keys and values: + +* _auth_password_: the password authentication negotiated: supported by both + the client and _relay_: +** (empty value): negotiation failed, password authentication is *NOT* possible +** _plain_ +** _sha256_ +** _sha512_ +** _pbkdf2+sha256_ +** _pbkdf2+sha512_ +* _hash_iterations_: number of iterations for hash (for the PBKDF2 algorithm only) +* _totp_: +** _on_: Time-based One-Time Password (TOTP) is configured and expected + in the _init_ command +** _off_: Time-based One-Time Password (TOTP) is not enabled and not needed + in the _init_ command +* _nonce_: a buffer of unpredictable bytes, sent as hexadecimal, to prevent + replay attacks; if _auth_password_ is a hash algorithm, the client must compute + the hash of password on this nonce, concatenated with a client nonce and the + user password (the _relay_ nonce + the client nonce is the salt used in the + password hash algorithm) + +Examples: + +---- +# nothing offered by the client (or only "plain"), authentication password "plain" will be used if allowed on relay side +handshake +handshake password=plain + +# only plain, sha256 and pbkdf2+sha256 are supported by the client +handshake password=plain:sha256:pbkdf2+sha256 +---- + +Example of response: + +[source,python] +---- +id: 'handshake' +htb: {'auth_password': 'pbkdf2+sha256', 'hash_iterations': '100000', 'totp': 'on', 'nonce': '85B1EE00695A5B254E14F4885538DF0D'} +---- + +The client can authenticate with this command (see <<command_init,init command>>), +the salt is the _relay_ nonce + "ABCD" ("41424344" in hexadecimal): + +---- +init password_hash=pbkdf2+sha256:85b1ee00695a5b254e14f4885538df0d41424344:100000:01757d53157ca14a1419e3a8cc1563536520a60b76d2d48e7f9ac09afc945a1c +---- + +[TIP] +With WeeChat ≤ 2.8, the command _handshake_ is not implemented, WeeChat silently +ignores this command, even if it is sent before the _init_ command. + +So it is safe to send this command to any WeeChat version. + [[command_init]] === init -_リレー_ 接続を初期化。_リレー_ に送るコマンドは必ずこのコマンドから始めてください。_リレー_ -がこのコマンドを受信していない場合、_リレー_ -は最初のコマンドを受け取った時点で警告無しに接続を閉じます。 +// TRANSLATION MISSING +_Updated in versions 2.4, 2.8, 2.9._ + +// TRANSLATION MISSING +Authenticate with _relay_. + +// TRANSLATION MISSING +This must be first command sent to _relay_ (only _handshake_ command can be sent +before _init_). + +If not sent, _relay_ will close connection on first command received (except +_handshake_), without warning. 構文: @@ -130,7 +240,10 @@ init [<option>=<value>,[<option>=<value>,...]] ** _totp_: パスワードに加えた二要素認証で利用する時間ベースのワンタイムパスワード (TOTP) (WeeChat の _relay.network.totp_secret_ オプション) _(WeeChat バージョン 2.4 で利用可能)_ -** _compression_: 圧縮タイプ: +// TRANSLATION MISSING +** _compression_: 圧縮タイプ (*deprecated* since version 2.9, it is kept + for compatibility reasons but should be sent in the + <<command_handshake,handshake command>>): *** _zlib_: _リレー_ から受信するメッセージに対して _zlib_ 圧縮を使う (_リレー_ が _zlib_ 圧縮をサポートしている場合、デフォルトで有効化されます) *** _off_: 圧縮を使わない @@ -143,13 +256,27 @@ WeeChat バージョン 1.6 以上の場合、コンマをエスケープする Format of hashed password is one of the following, where _hash_ is the hashed password as hexadecimal: -* `+sha256:hash+` -* `+sha512:hash+` -* `+pbkdf2:algorithm:salt:iterations:hash+` with: -** _algorithm_: _sha256_ or _sha512_ -** _salt_: salt (hexadecimal) +* `+sha256:salt:hash+` with: +** _salt_: salt (hexadecimal), which must start with the server nonce, + concatenated to the client nonce +** _hash_: the hashed salt + password (hexadecimal) +* `+sha512:salt:hash+` with: +** _salt_: salt (hexadecimal), which must start with the server nonce, + concatenated to the client nonce +** _hash_: the hashed salt + password (hexadecimal) +* `+pbkdf2+sha256:salt:iterations:hash+` with: +** _salt_: salt (hexadecimal), which must start with the server nonce, + concatenated to the client nonce ** _iterations_: number of iterations -** _hash_: the hashed password (hexadecimal) +** _hash_: the hashed salt + password with SHA256 algorithm (hexadecimal) +* `+pbkdf2+sha512:salt:iterations:hash+` with: +** _salt_: salt (hexadecimal), which must start with the server nonce, + concatenated to the client nonce +** _iterations_: number of iterations +** _hash_: the hashed salt + password with SHA512 algorithm (hexadecimal) + +[NOTE] +Hexadecimal strings can be lower or upper case, _relay_ can decode both. // TRANSLATION MISSING 例: @@ -167,14 +294,14 @@ init password=mypass,totp=123456 # 圧縮を使わない例 init password=mypass,compression=off -# initialize with hashed password (SHA256) (WeeChat バージョン 2.8 以上の場合) -init password_hash=sha256:b9a4c3393dfac4330736684510378851e581c68add8eca84110c31a33e694676 +# initialize with hashed password (SHA256: salt="nonce:cnonce") (WeeChat バージョン 2.9 以上の場合) +init password_hash=sha256:6e6f6e63653a636e6f6e6365:b9a4c3393dfac4330736684510378851e581c68add8eca84110c31a33e694676 -# initialize with hashed password (SHA512) (WeeChat バージョン 2.8 以上の場合) -init password_hash=sha512:4469190d4e0d1fdc0afb6f408d9873c89b8ce89cc4db79fe058255c55ad6821fa5e9bb068f9e578c8ae7cc825d85ff99c439d59e439bc589d95620a1e6b8ae6e +# initialize with hashed password (SHA512: salt="nonce:cnonce") (WeeChat バージョン 2.9 以上の場合) +init password_hash=sha512:6e6f6e63653a636e6f6e6365:4469190d4e0d1fdc0afb6f408d9873c89b8ce89cc4db79fe058255c55ad6821fa5e9bb068f9e578c8ae7cc825d85ff99c439d59e439bc589d95620a1e6b8ae6e -# initialize with hashed password (PBKDF2: SHA256, salt="ABCDEFGHIJKLMNOP", 100000 iterations) (WeeChat バージョン 2.8 以上の場合) -init password_hash=pbkdf2:sha256:4142434445464748494a4b4c4d4e4f50:100000:01757d53157ca14a1419e3a8cc1563536520a60b76d2d48e7f9ac09afc945a1c +# initialize with hashed password (PBKDF2: SHA256, salt="nonce:cnonce", 100000 iterations) (WeeChat バージョン 2.9 以上の場合) +init password_hash=pbkdf2+sha256:6e6f6e63653a636e6f6e6365:100000:01757d53157ca14a1419e3a8cc1563536520a60b76d2d48e7f9ac09afc945a1c ---- [[command_hdata]] @@ -1397,7 +1524,7 @@ _WeeChat バージョン 0.3.8 以上で利用可。_ .... ┌────┐ -│ 41 │ ────► 65 (0x41: "A") +│ 41 │ ────▶ 65 (0x41: "A") └────┘ .... @@ -1413,11 +1540,11 @@ _WeeChat バージョン 0.3.8 以上で利用可。_ .... ┌────┬────┬────┬────┐ -│ 00 │ 01 │ E2 │ 40 │ ────► 123456 +│ 00 │ 01 │ E2 │ 40 │ ────▶ 123456 └────┴────┴────┴────┘ ┌────┬────┬────┬────┐ -│ FF │ FE │ 1D │ C0 │ ────► -123456 +│ FF │ FE │ 1D │ C0 │ ────▶ -123456 └────┴────┴────┴────┘ .... @@ -1432,13 +1559,13 @@ _WeeChat バージョン 0.3.8 以上で利用可。_ .... ┌────╥────┬────┬────┬────┬────┬────┬────┬────┬────┬────┐ -│ 0A ║ 31 │ 32 │ 33 │ 34 │ 35 │ 36 │ 37 │ 38 │ 39 │ 30 │ ────► 1234567890 +│ 0A ║ 31 │ 32 │ 33 │ 34 │ 35 │ 36 │ 37 │ 38 │ 39 │ 30 │ ────▶ 1234567890 └────╨────┴────┴────┴────┴────┴────┴────┴────┴────┴────┘ └──┘ └───────────────────────────────────────────────┘ length '1' '2' '3' '4' '5' '6' '7' '8' '9' '0' ┌────╥────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┐ -│ 0B ║ 2D │ 31 │ 32 │ 33 │ 34 │ 35 │ 36 │ 37 │ 38 │ 39 │ 30 │ ────► -1234567890 +│ 0B ║ 2D │ 31 │ 32 │ 33 │ 34 │ 35 │ 36 │ 37 │ 38 │ 39 │ 30 │ ────▶ -1234567890 └────╨────┴────┴────┴────┴────┴────┴────┴────┴────┴────┴────┘ └──┘ └────────────────────────────────────────────────────┘ length '-' '1' '2' '3' '4' '5' '6' '7' '8' '9' '0' @@ -1453,7 +1580,7 @@ length '-' '1' '2' '3' '4' '5' '6' '7' '8' '9' '0' .... ┌────┬────┬────┬────╥────┬────┬────┬────┬────┐ -│ 00 │ 00 │ 00 │ 05 ║ 68 │ 65 │ 6C │ 6C │ 6F │ ────► "hello" +│ 00 │ 00 │ 00 │ 05 ║ 68 │ 65 │ 6C │ 6C │ 6F │ ────▶ "hello" └────┴────┴────┴────╨────┴────┴────┴────┴────┘ └─────────────────┘ └──────────────────────┘ length 'h' 'e' 'l' 'l' 'o' @@ -1463,7 +1590,7 @@ length '-' '1' '2' '3' '4' '5' '6' '7' '8' '9' '0' .... ┌────┬────┬────┬────┐ -│ 00 │ 00 │ 00 │ 00 │ ────► "" +│ 00 │ 00 │ 00 │ 00 │ ────▶ "" └────┴────┴────┴────┘ └─────────────────┘ length @@ -1473,7 +1600,7 @@ _NULL_ 文字列 (C 言語の NULL ポインタ) を表現するにはの長さ .... ┌────┬────┬────┬────┐ -│ FF │ FF │ FF │ FF │ ────► NULL +│ FF │ FF │ FF │ FF │ ────▶ NULL └────┴────┴────┴────┘ └─────────────────┘ length @@ -1493,7 +1620,7 @@ _NULL_ 文字列 (C 言語の NULL ポインタ) を表現するにはの長さ .... ┌────╥────┬────┬────┬────┬────┬────┬────┬────┬────┐ -│ 09 ║ 31 │ 61 │ 32 │ 62 │ 33 │ 63 │ 34 │ 64 │ 35 │ ────► 0x1a2b3c4d5 +│ 09 ║ 31 │ 61 │ 32 │ 62 │ 33 │ 63 │ 34 │ 64 │ 35 │ ────▶ 0x1a2b3c4d5 └────╨────┴────┴────┴────┴────┴────┴────┴────┴────┘ └──┘ └──────────────────────────────────────────┘ length '1' 'a' '2' 'b' '3' 'c' '4' 'd' '5' @@ -1503,7 +1630,7 @@ _NULL_ ポインタを表現するには長さを 1 で値を 0 にしてくだ .... ┌────╥────┐ -│ 01 ║ 00 │ ────► NULL (0x0) +│ 01 ║ 00 │ ────▶ NULL (0x0) └────╨────┘ └──┘ └──┘ length 0 @@ -1518,7 +1645,7 @@ length 0 .... ┌────╥────┬────┬────┬────┬────┬────┬────┬────┬────┬────┐ -│ 0A ║ 31 │ 33 │ 32 │ 31 │ 39 │ 39 │ 33 │ 34 │ 35 │ 36 │ ────► 1321993456 +│ 0A ║ 31 │ 33 │ 32 │ 31 │ 39 │ 39 │ 33 │ 34 │ 35 │ 36 │ ────▶ 1321993456 └────╨────┴────┴────┴────┴────┴────┴────┴────┴────┴────┘ └──┘ └───────────────────────────────────────────────┘ length '1' '3' '2' '1' '9' '9' '3' '4' '5' '6' @@ -1540,7 +1667,7 @@ length '1' '3' '2' '1' '9' '9' '3' '4' '5' '6' .... ┌─────┬─────┬───╥──────┬─────╥──────┬─────┐ -│ str │ str │ 2 ║ key1 │ abc ║ key2 │ def │ ────► { 'key1' => 'abc', +│ str │ str │ 2 ║ key1 │ abc ║ key2 │ def │ ────▶ { 'key1' => 'abc', └─────┴─────┴───╨──────┴─────╨──────┴─────┘ 'key2' => 'def' } └───┘ └───┘ └─┘ └──────────┘ └──────────┘ type type count item 1 item 2 @@ -1767,7 +1894,7 @@ infolist buffer type number of strings length ──╥────┬────┬────╥────┬────┬────┬────╥────┬────┐ - ... ║ 61 │ 62 │ 63 ║ 00 │ 00 │ 00 │ 02 ║ 64 │ 65 │ ────► [ "abc", "de" ] + ... ║ 61 │ 62 │ 63 ║ 00 │ 00 │ 00 │ 02 ║ 64 │ 65 │ ────▶ [ "abc", "de" ] ──╨────┴────┴────╨────┴────┴────┴────╨────┴────┘ └────────────┘ └─────────────────┘ └───────┘ 'a' 'b' 'c' length 'd' 'e' @@ -1783,7 +1910,7 @@ infolist buffer type number of integers 123 (0x7B) ──╥────┬────┬────┬────╥────┬────┬────┬────┐ - ... ║ 00 │ 00 │ 01 │ C8 ║ 00 │ 00 │ 03 │ 15 │ ────► [ 123, 456, 789 ] + ... ║ 00 │ 00 │ 01 │ C8 ║ 00 │ 00 │ 03 │ 15 │ ────▶ [ 123, 456, 789 ] ──╨────┴────┴────┴────╨────┴────┴────┴────┘ └─────────────────┘ └─────────────────┘ 456 (0x1C8) 789 (0x315) @@ -1793,7 +1920,7 @@ _NULL_ 配列: .... ┌─────╥────┬────┬────┬────┐ -│ str ║ 00 │ 00 │ 00 │ 00 │ ────► NULL +│ str ║ 00 │ 00 │ 00 │ 00 │ ────▶ NULL └─────╨────┴────┴────┴────┘ └───┘ └─────────────────┘ type number of strings @@ -1802,48 +1929,55 @@ _NULL_ 配列: [[typical_session]] == 典型的なセッション +// TRANSLATION MISSING .... ┌──────────────┐ ┌────────┐ ┌─────────┐ │ クライアント ├ ─(ネットワーク)─ ┤ リレー ├──────────────────┤ WeeChat │ └──────────────┘ └────────┘ └─────────┘ ║ ║ ║ - ╟───────────────────────────────► ║ ║ + ╟───────────────────────────────▶ ║ ║ ║ ソケットをオープン ║ クライアントを追加 ║ ║ ║ ║ - ╟───────────────────────────────► ║ ║ + ╟───────────────────────────────▶ ║ ║ + ║ cmd: handshake password=xxx,... ║ negotiate algos ║ + ║ ║ and options ║ + ║ ◀───────────────────────────────╢ ║ + ║ msg: id: "handshake" ... ║ ║ + ║ ║ ║ + ╟───────────────────────────────▶ ║ ║ ║ cmd: init password=xxx,... ║ クライアントを初期化/許可 ║ ║ ║ ║ - ╟───────────────────────────────► ║ ║ - ║ cmd: hdata buffer ... ╟─────────────────────────► ║ + ╟───────────────────────────────▶ ║ ║ + ║ cmd: hdata buffer ... ╟─────────────────────────▶ ║ ║ sync ... ║ hdata の要求 ║ hdata ║ ║ ║ の値を読み出し - ║ ║ ◄─────────────────────────╢ - ║ ◄───────────────────────────────╢ hdata ║ + ║ ║ ◀─────────────────────────╢ + ║ ◀───────────────────────────────╢ hdata ║ バッファ ║ msg: hda buffer ║ ║ を作成 ║ ║ ║ ║ ........ ║ ........ ║ ║ ║ ║ - ╟───────────────────────────────► ║ ║ - ║ cmd: input ... ╟─────────────────────────► ║ + ╟───────────────────────────────▶ ║ ║ + ║ cmd: input ... ╟─────────────────────────▶ ║ ║ ║ バッファにデータを送信 ║ バッファに ║ ║ ║ データを送信 ║ ........ ║ ........ ║ ║ ║ ║ シグナル - ║ ║ ◄─────────────────────────╢ の受信 - ║ ◄───────────────────────────────╢ シグナル XXX ║ (リレー + ║ ║ ◀─────────────────────────╢ の受信 + ║ ◀───────────────────────────────╢ シグナル XXX ║ (リレー バッファ ║ msg: id: "_buffer_..." ║ ║ がフック) を更新 ║ ║ ║ ║ ........ ║ ........ ║ ║ ║ ║ - ╟───────────────────────────────► ║ ║ + ╟───────────────────────────────▶ ║ ║ ║ cmd: ping ... ║ ║ ║ ║ ║ - ║ ◄───────────────────────────────╢ ║ + ║ ◀───────────────────────────────╢ ║ 応答 ║ msg: id: "_pong" ... ║ ║ 時間 ║ ║ ║ を計測 ║ ........ ║ ........ ║ ║ ║ ║ - ╟───────────────────────────────► ║ ║ + ╟───────────────────────────────▶ ║ ║ ║ cmd: quit ║ クライアントを切断 ║ ║ ║ ║ .... diff --git a/doc/pl/autogen/user/relay_options.adoc b/doc/pl/autogen/user/relay_options.adoc index cf113418b..033bcd1fb 100644 --- a/doc/pl/autogen/user/relay_options.adoc +++ b/doc/pl/autogen/user/relay_options.adoc @@ -116,6 +116,12 @@ ** wartości: dowolny ciąg ** domyślna wartość: `+""+` +* [[option_relay.network.auth_password]] *relay.network.auth_password* +** opis: 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: ciąg +** wartości: dowolny ciąg +** domyślna wartość: `+"*"+` + * [[option_relay.network.auth_timeout]] *relay.network.auth_timeout* ** opis: 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: liczba @@ -140,6 +146,12 @@ ** wartości: 0 .. 9 ** domyślna wartość: `+6+` +* [[option_relay.network.hash_iterations]] *relay.network.hash_iterations* +** opis: 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: liczba +** wartości: 1 .. 1000000 +** domyślna wartość: `+100000+` + * [[option_relay.network.ipv6]] *relay.network.ipv6* ** opis: pass:none[nasłuchuj domyślnie na gnieździe IPv6 (w dodatku do domyślnego IPv4); protokoły IPv4 i IPv6 mogą być wymuszane (pojedynczo lub razem) w nazwie protokołu (zobacz /help relay)] ** typ: bool @@ -152,6 +164,12 @@ ** wartości: 0 .. 2147483647 ** domyślna wartość: `+5+` +* [[option_relay.network.nonce_size]] *relay.network.nonce_size* +** opis: 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: liczba +** wartości: 8 .. 128 +** domyślna wartość: `+16+` + * [[option_relay.network.password]] *relay.network.password* ** opis: pass:none[hasło wymagane od klientów do połączenia z tym pośrednikiem (pusta wartość oznacza brak hasła, zobacz opcję relay.network.allow_empty_password) (uwaga: zawartość jest przetwarzana, zobacz /help eval)] ** typ: ciąg diff --git a/po/POTFILES.in b/po/POTFILES.in index ff67dc94a..155f68c9c 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -305,6 +305,8 @@ ./src/plugins/python/weechat-python.h ./src/plugins/relay/irc/relay-irc.c ./src/plugins/relay/irc/relay-irc.h +./src/plugins/relay/relay-auth.c +./src/plugins/relay/relay-auth.h ./src/plugins/relay/relay-buffer.c ./src/plugins/relay/relay-buffer.h ./src/plugins/relay/relay.c @@ -21,7 +21,7 @@ msgid "" msgstr "" "Project-Id-Version: WeeChat\n" "Report-Msgid-Bugs-To: flashcode@flashtux.org\n" -"POT-Creation-Date: 2020-04-12 20:23+0200\n" +"POT-Creation-Date: 2020-04-14 21:29+0200\n" "PO-Revision-Date: 2020-03-08 14:22+0100\n" "Last-Translator: Ondřej Súkup <mimi.vx@gmail.com>\n" "Language-Team: weechat-dev <weechat-dev@nongnu.org>\n" @@ -11019,6 +11019,20 @@ msgid "" "\"^(123\\.45\\.67\\.89|192\\.160\\..*)$\"" msgstr "" +#, fuzzy +msgid "" +"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\")" +msgstr "" +"čárkou rozdělený seznam pluginů pro automatické načtení při spuštění \"*\" " +"znamená všechny nalezené pluginy, jméno začínající \"!\" je negativní " +"hodnota k zabránění načtení pluginu, jména mohou začínat nebo končit \"*\" " +"pro vybrání několika pluginů (příklady: \"*\" nebo \"*,!lua,!tcl\")" + msgid "" "timeout (in seconds) for client authentication: connection is closed if the " "client is still not authenticated after this delay and the client status is " @@ -11044,6 +11058,13 @@ msgid "" msgstr "" msgid "" +"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" +msgstr "" + +msgid "" "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)" @@ -11053,6 +11074,12 @@ msgstr "" msgid "maximum number of clients connecting to a port (0 = no limit)" msgstr "maximální počet klientů připojených k portu" +msgid "" +"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" +msgstr "" + #, fuzzy msgid "" "password required by clients to access this relay (empty value means no " @@ -24,7 +24,7 @@ msgid "" msgstr "" "Project-Id-Version: WeeChat\n" "Report-Msgid-Bugs-To: flashcode@flashtux.org\n" -"POT-Creation-Date: 2020-04-12 20:23+0200\n" +"POT-Creation-Date: 2020-04-14 21:29+0200\n" "PO-Revision-Date: 2020-04-03 20:03+0200\n" "Last-Translator: Nils Görs <weechatter@arcor.de>\n" "Language-Team: German <kde-i18n-de@kde.org>\n" @@ -12965,6 +12965,21 @@ msgstr "" "Kleinschreibung zu unterscheiden muss die Zeichenkette mit \"(?-i)\" " "eingeleitet werden), Beispiele: \"^(123\\.45\\.67\\.89|192\\.160\\..*)$\"" +#, fuzzy +msgid "" +"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\")" +msgstr "" +"durch Kommata getrennte Liste der Erweiterungen, die beim Programmstart " +"automatisch geladen werden sollen; \"*\" lädt alle vorhandenen " +"Erweiterungen. Beginnt der Name hingegen mit \"!\" wird die Erweiterung " +"nicht geladen. Im Namen der Erweiterung kann der Platzhalter \"*\" verwendet " +"werden (Beispiele: \"*\" oder \"*,!lua,!tcl\")" + msgid "" "timeout (in seconds) for client authentication: connection is closed if the " "client is still not authenticated after this delay and the client status is " @@ -12995,6 +13010,13 @@ msgstr "" "Kompression ... 9 = stärkste Kompression)" msgid "" +"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" +msgstr "" + +msgid "" "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)" @@ -13010,6 +13032,12 @@ msgstr "" "keine Begrenzung)" msgid "" +"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" +msgstr "" + +msgid "" "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)" @@ -22,7 +22,7 @@ msgid "" msgstr "" "Project-Id-Version: WeeChat\n" "Report-Msgid-Bugs-To: flashcode@flashtux.org\n" -"POT-Creation-Date: 2020-04-12 20:23+0200\n" +"POT-Creation-Date: 2020-04-14 21:29+0200\n" "PO-Revision-Date: 2020-03-08 14:22+0100\n" "Last-Translator: Elián Hanisch <lambdae2@gmail.com>\n" "Language-Team: weechat-dev <weechat-dev@nongnu.org>\n" @@ -11364,6 +11364,20 @@ msgstr "" "mapeada a IPv6 (como: \"::ffff:127.0.0.1\"), ejemplo: \"^((::ffff:)?" "123\\.45\\.67\\.89|192\\.160\\..*)$\"" +#, fuzzy +msgid "" +"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\")" +msgstr "" +"lista de plugins separados por comas para cargar automáticamente al iniciar, " +"\"*\" significa todos los plugins encontrados, un nombre empezando con \"!\" " +"previene que el plugin se cargue, nombres pueden empezar o terminar con \"*" +"\" para indicar varios plugins (ejemplo: \"*\" o \"*,!lua,!tcl\")" + msgid "" "timeout (in seconds) for client authentication: connection is closed if the " "client is still not authenticated after this delay and the client status is " @@ -11391,6 +11405,13 @@ msgstr "" "WeeChat (0 = sin compresión, 1 = baja compresión ... 9 = mejor compresión)" msgid "" +"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" +msgstr "" + +msgid "" "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)" @@ -11400,6 +11421,12 @@ msgstr "" msgid "maximum number of clients connecting to a port (0 = no limit)" msgstr "número máximo de clientes conectados a un puerto" +msgid "" +"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" +msgstr "" + #, fuzzy msgid "" "password required by clients to access this relay (empty value means no " @@ -21,8 +21,8 @@ msgid "" msgstr "" "Project-Id-Version: WeeChat\n" "Report-Msgid-Bugs-To: flashcode@flashtux.org\n" -"POT-Creation-Date: 2020-04-12 20:23+0200\n" -"PO-Revision-Date: 2020-04-12 20:24+0200\n" +"POT-Creation-Date: 2020-04-14 21:29+0200\n" +"PO-Revision-Date: 2020-04-14 21:29+0200\n" "Last-Translator: Sébastien Helleu <flashcode@flashtux.org>\n" "Language-Team: weechat-dev <weechat-dev@nongnu.org>\n" "Language: fr\n" @@ -12694,6 +12694,22 @@ msgstr "" "insensible à la casse), exemple : \"^(123\\.45\\.67\\.89|192\\.160\\..*)$\"" msgid "" +"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\")" +msgstr "" +"liste des algorithmes de hachage pour l'authentification par mot de passe " +"dans le protocole relay, parmi ces valeurs : \"plain\" (mot de passe en " +"clair, non haché), \"sha256\", \"sha512\", \"pbkdf2+sha256\", " +"\"pbkdf2+sha512\" ; \"*\" signifie tous les algorithmes, un nom commençant " +"par \"!\" est une valeur négative pour empêcher un algorithme d'être " +"utilisé, le caractère joker \"*\" est autorisé dans les noms (exemples : \"*" +"\", \"pbkdf2*\", \"*,!plain\")" + +msgid "" "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)" @@ -12726,6 +12742,18 @@ msgstr "" "meilleure compression)" msgid "" +"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" +msgstr "" +"nombre d'itérations demandées au client dans le protocole weechat lorsqu'un " +"mot de passe haché avec l'algorithme PBKDF2 est utilisé pour " +"l'authentification ; plus d'itérations est mieux en terme de sécurité mais " +"est plus lent à calculer ; ce nombre ne doit pas être trop élevé si votre " +"micro-processeur est lent" + +msgid "" "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)" @@ -12739,6 +12767,15 @@ msgstr "" "nombre maximum de clients qui se connectent sur un port (0 = pas de limite)" msgid "" +"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" +msgstr "" +"taille du nonce (en octets), généré lorsqu'un client se connecte ; le client " +"doit utiliser ce nonce, concaténé au nonce client et au mot de passe pour " +"hacher le mot de passe dans la commande \"init\" du protocole weechat" + +msgid "" "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)" @@ -20,7 +20,7 @@ msgid "" msgstr "" "Project-Id-Version: WeeChat\n" "Report-Msgid-Bugs-To: flashcode@flashtux.org\n" -"POT-Creation-Date: 2020-04-12 20:23+0200\n" +"POT-Creation-Date: 2020-04-14 21:29+0200\n" "PO-Revision-Date: 2020-03-08 14:22+0100\n" "Last-Translator: Andras Voroskoi <voroskoi@frugalware.org>\n" "Language-Team: weechat-dev <weechat-dev@nongnu.org>\n" @@ -10365,6 +10365,19 @@ msgid "" "\"^(123\\.45\\.67\\.89|192\\.160\\..*)$\"" msgstr "" +#, fuzzy +msgid "" +"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\")" +msgstr "" +"automatikusan betöltendő modulok vesszővel elválasztott listája, \"*\" " +"esetén az összes fellelt modul (az elnevezés lehet részleges, például a " +"\"perl\" elegendő \"libperl.so\" helyett)" + msgid "" "timeout (in seconds) for client authentication: connection is closed if the " "client is still not authenticated after this delay and the client status is " @@ -10387,6 +10400,13 @@ msgid "" msgstr "" msgid "" +"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" +msgstr "" + +msgid "" "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)" @@ -10398,6 +10418,12 @@ msgstr "" "felhasználói parancsok maximális száma az előzményekben (0 = korlátlan)" msgid "" +"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" +msgstr "" + +msgid "" "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)" @@ -20,7 +20,7 @@ msgid "" msgstr "" "Project-Id-Version: WeeChat\n" "Report-Msgid-Bugs-To: flashcode@flashtux.org\n" -"POT-Creation-Date: 2020-04-12 20:23+0200\n" +"POT-Creation-Date: 2020-04-14 21:29+0200\n" "PO-Revision-Date: 2020-03-08 14:22+0100\n" "Last-Translator: Esteban I. Ruiz Moreno <exio4.com@gmail.com>\n" "Language-Team: weechat-dev <weechat-dev@nongnu.org>\n" @@ -11565,6 +11565,21 @@ msgstr "" "ffff:127.0.0.1\",come: \"::ffff:127.0.0.1\"), esempio: \"^((::ffff:)?" "123\\.45\\.67\\.89|192\\.160\\..*)$\"" +#, fuzzy +msgid "" +"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\")" +msgstr "" +"elenco separato da virgole di plugin da caricare automaticamente all'avvio, " +"\"*\" equivale a tutti i plugin trovati. un nome che comincia con \"!\" è un " +"valore negativo per impedire il caricamento di un plugin, i nomi possono " +"iniziare o finire con \"*\" per corrispondere a più plugin (esempi: \"*\" " +"oppure \"*,!lua,!tcl\")" + msgid "" "timeout (in seconds) for client authentication: connection is closed if the " "client is still not authenticated after this delay and the client status is " @@ -11593,6 +11608,13 @@ msgstr "" "compressione migliore)" msgid "" +"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" +msgstr "" + +msgid "" "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)" @@ -11602,6 +11624,12 @@ msgstr "" msgid "maximum number of clients connecting to a port (0 = no limit)" msgstr "numero massimo di client connessi ad una porta" +msgid "" +"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" +msgstr "" + #, fuzzy msgid "" "password required by clients to access this relay (empty value means no " @@ -20,7 +20,7 @@ msgid "" msgstr "" "Project-Id-Version: WeeChat\n" "Report-Msgid-Bugs-To: flashcode@flashtux.org\n" -"POT-Creation-Date: 2020-04-12 20:23+0200\n" +"POT-Creation-Date: 2020-04-14 21:29+0200\n" "PO-Revision-Date: 2020-03-08 14:22+0100\n" "Last-Translator: AYANOKOUZI, Ryuunosuke <i38w7i3@yahoo.co.jp>\n" "Language-Team: Japanese <https://github.com/l/weechat/tree/master/" @@ -12196,6 +12196,19 @@ msgstr "" "し、最初に \"(?-i)\" をつければ区別有り)、例: \"^(123\\.45\\.67\\.89|" "192\\.160\\..*)$\"" +#, fuzzy +msgid "" +"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\")" +msgstr "" +"スタートアップ時にロードするプラグインのコンマ区切りリスト、\"*\" は見つかっ" +"た全てのプラグイン、\"!\" から始まる名前はロードしないプラグイン、名前にワイ" +"ルドカード \"*\" を使うことができます (例: \"*\" または \"*,!lua,!tcl\")" + msgid "" "timeout (in seconds) for client authentication: connection is closed if the " "client is still not authenticated after this delay and the client status is " @@ -12224,6 +12237,13 @@ msgstr "" "い、1 = 低圧縮 ... 9 = 高圧縮)" msgid "" +"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" +msgstr "" + +msgid "" "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)" @@ -12236,6 +12256,12 @@ msgid "maximum number of clients connecting to a port (0 = no limit)" msgstr "ポートに接続するクライアントの最大数 (0 = 制限なし)" msgid "" +"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" +msgstr "" + +msgid "" "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)" @@ -22,7 +22,7 @@ msgid "" msgstr "" "Project-Id-Version: WeeChat\n" "Report-Msgid-Bugs-To: flashcode@flashtux.org\n" -"POT-Creation-Date: 2020-04-12 20:23+0200\n" +"POT-Creation-Date: 2020-04-14 21:29+0200\n" "PO-Revision-Date: 2020-04-05 13:44+0200\n" "Last-Translator: Krzysztof Korościk <soltys@soltys.info>\n" "Language-Team: Polish <kde-i18n-doc@kde.org>\n" @@ -12414,6 +12414,20 @@ msgstr "" "początku sprawi, że wielość znaków będzie miała znaczenie), przykład: " "\"^(123\\.45\\.67\\.89|192\\.160\\..*)$\"" +#, fuzzy +msgid "" +"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\")" +msgstr "" +"oddzielona przecinkami lista wtyczek do automatycznego załadowania podczas " +"startu, \"*\" oznacza wszystkie znalezione wtyczki, nazwa zaczynająca się od " +"\"!\" powoduje nie ładowanie tej wtyczki, wildcard \"*\" jest dozwolony w " +"nazwach (przykłady: \"*\" lub \"*,!lua,!tcl\")" + msgid "" "timeout (in seconds) for client authentication: connection is closed if the " "client is still not authenticated after this delay and the client status is " @@ -12443,6 +12457,13 @@ msgstr "" "(0 = kompresja wyłączona, 1 = niska kompresja ... 9 = najwyższa kompresja)" msgid "" +"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" +msgstr "" + +msgid "" "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)" @@ -12455,6 +12476,12 @@ msgid "maximum number of clients connecting to a port (0 = no limit)" msgstr "maksymalna ilość klientów łączących się na port (0 = brak limitu)" msgid "" +"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" +msgstr "" + +msgid "" "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)" @@ -20,7 +20,7 @@ msgid "" msgstr "" "Project-Id-Version: WeeChat\n" "Report-Msgid-Bugs-To: flashcode@flashtux.org\n" -"POT-Creation-Date: 2020-04-12 20:23+0200\n" +"POT-Creation-Date: 2020-04-14 21:29+0200\n" "PO-Revision-Date: 2020-03-08 14:22+0100\n" "Last-Translator: Vasco Almeida <vascomalmeida@sapo.pt>\n" "Language-Team: Portuguese <>\n" @@ -12012,6 +12012,21 @@ msgstr "" "(não destinge maiúscula e minúscula, use \"(?-i)\" no início para " "distinguir), exemplo: \"^(123\\.45\\.67\\.89|192\\.160\\..*)$\"" +#, fuzzy +msgid "" +"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\")" +msgstr "" +"lista de plugins separados por vírgula para carregar automaticamente ao " +"iniciar, \"*\" significa todos os plugins encontrados, um nome começado com " +"\"!\" serve de valor negativo para impedir que o plugin seja carregado, pode-" +"se usar o caráter universal \"*\" nos nomes (exemplos: \"*\" ou \"*,!lua,!tcl" +"\")" + msgid "" "timeout (in seconds) for client authentication: connection is closed if the " "client is still not authenticated after this delay and the client status is " @@ -12041,6 +12056,13 @@ msgstr "" "compressão ótima)" msgid "" +"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" +msgstr "" + +msgid "" "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)" @@ -12053,6 +12075,12 @@ msgid "maximum number of clients connecting to a port (0 = no limit)" msgstr "número máximo de clientes que se conectam a uma porta (0 = sem limite)" msgid "" +"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" +msgstr "" + +msgid "" "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)" diff --git a/po/pt_BR.po b/po/pt_BR.po index 94c3107ba..ffb32d768 100644 --- a/po/pt_BR.po +++ b/po/pt_BR.po @@ -21,7 +21,7 @@ msgid "" msgstr "" "Project-Id-Version: WeeChat\n" "Report-Msgid-Bugs-To: flashcode@flashtux.org\n" -"POT-Creation-Date: 2020-04-12 20:23+0200\n" +"POT-Creation-Date: 2020-04-14 21:29+0200\n" "PO-Revision-Date: 2019-11-03 08:38+0100\n" "Last-Translator: Eduardo Elias <camponez@gmail.com>\n" "Language-Team: weechat-dev <weechat-dev@nongnu.org>\n" @@ -10814,6 +10814,21 @@ msgstr "" "expressão regular com IPs permitidos a usar o relay, por exemplo: " "\"^(123\\.45\\.67\\.89|192\\.160\\..*)$\"" +#, fuzzy +msgid "" +"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\")" +msgstr "" +"lista separada por vírgulas dos plugins para carregar automaticamente " +"nainicialização, \"*\" significa todos os plugins encontrados, um nome " +"começando com \"!\" é um valor negativo para prevenir um plugin de ser " +"carrgado, nomes podem começar ou terminar com \"*\" para casar com vários " +"plugins (exemplos: \"*\" ou \"*,!lua,!tcl\")" + msgid "" "timeout (in seconds) for client authentication: connection is closed if the " "client is still not authenticated after this delay and the client status is " @@ -10841,6 +10856,13 @@ msgstr "" "compressão)" msgid "" +"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" +msgstr "" + +msgid "" "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)" @@ -10850,6 +10872,12 @@ msgstr "" msgid "maximum number of clients connecting to a port (0 = no limit)" msgstr "número máximo de clientes conectando-se a uma porta" +msgid "" +"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" +msgstr "" + #, fuzzy msgid "" "password required by clients to access this relay (empty value means no " @@ -21,7 +21,7 @@ msgid "" msgstr "" "Project-Id-Version: WeeChat\n" "Report-Msgid-Bugs-To: flashcode@flashtux.org\n" -"POT-Creation-Date: 2020-04-12 20:23+0200\n" +"POT-Creation-Date: 2020-04-14 21:29+0200\n" "PO-Revision-Date: 2020-03-08 14:22+0100\n" "Last-Translator: Aleksey V Zapparov AKA ixti <ixti@member.fsf.org>\n" "Language-Team: weechat-dev <weechat-dev@nongnu.org>\n" @@ -10401,6 +10401,19 @@ msgid "" "\"^(123\\.45\\.67\\.89|192\\.160\\..*)$\"" msgstr "" +#, fuzzy +msgid "" +"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\")" +msgstr "" +"разделённый запятыми список автоматически загружаемых при запуске plug-" +"in'ов , \"*\" означает все найденные plug-in'ы (имена могут быть не полными, " +"например \"perl\" успешно загрузит \"libperl.so\")" + msgid "" "timeout (in seconds) for client authentication: connection is closed if the " "client is still not authenticated after this delay and the client status is " @@ -10423,6 +10436,13 @@ msgid "" msgstr "" msgid "" +"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" +msgstr "" + +msgid "" "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)" @@ -10433,6 +10453,12 @@ msgid "maximum number of clients connecting to a port (0 = no limit)" msgstr "максимальное количество команд в истории (0 = не ограничено)" msgid "" +"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" +msgstr "" + +msgid "" "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)" diff --git a/po/srcfiles.cmake b/po/srcfiles.cmake index e7f7e4983..b1b6bcb19 100644 --- a/po/srcfiles.cmake +++ b/po/srcfiles.cmake @@ -306,6 +306,8 @@ SET(WEECHAT_SOURCES ./src/plugins/python/weechat-python.h ./src/plugins/relay/irc/relay-irc.c ./src/plugins/relay/irc/relay-irc.h +./src/plugins/relay/relay-auth.c +./src/plugins/relay/relay-auth.h ./src/plugins/relay/relay-buffer.c ./src/plugins/relay/relay-buffer.h ./src/plugins/relay/relay.c @@ -20,7 +20,7 @@ msgid "" msgstr "" "Project-Id-Version: WeeChat\n" "Report-Msgid-Bugs-To: flashcode@flashtux.org\n" -"POT-Creation-Date: 2020-04-12 20:23+0200\n" +"POT-Creation-Date: 2020-04-14 21:29+0200\n" "PO-Revision-Date: 2019-11-03 08:38+0100\n" "Last-Translator: Hasan Kiran <sunder67@hotmail.com>\n" "Language-Team: weechat-dev <weechat-dev@nongnu.org>\n" @@ -9454,6 +9454,15 @@ msgid "" msgstr "" msgid "" +"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\")" +msgstr "" + +msgid "" "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)" @@ -9475,6 +9484,13 @@ msgid "" msgstr "" msgid "" +"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" +msgstr "" + +msgid "" "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)" @@ -9484,6 +9500,12 @@ msgid "maximum number of clients connecting to a port (0 = no limit)" msgstr "" msgid "" +"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" +msgstr "" + +msgid "" "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)" diff --git a/po/weechat.pot b/po/weechat.pot index e685d297c..022be4825 100644 --- a/po/weechat.pot +++ b/po/weechat.pot @@ -21,7 +21,7 @@ msgid "" msgstr "" "Project-Id-Version: WeeChat\n" "Report-Msgid-Bugs-To: flashcode@flashtux.org\n" -"POT-Creation-Date: 2020-04-12 20:23+0200\n" +"POT-Creation-Date: 2020-04-14 21:29+0200\n" "PO-Revision-Date: 2014-08-16 10:27+0200\n" "Last-Translator: Sébastien Helleu <flashcode@flashtux.org>\n" "Language-Team: weechat-dev <weechat-dev@nongnu.org>\n" @@ -9315,6 +9315,15 @@ msgid "" msgstr "" msgid "" +"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\")" +msgstr "" + +msgid "" "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)" @@ -9336,6 +9345,13 @@ msgid "" msgstr "" msgid "" +"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" +msgstr "" + +msgid "" "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)" @@ -9345,6 +9361,12 @@ msgid "maximum number of clients connecting to a port (0 = no limit)" msgstr "" msgid "" +"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" +msgstr "" + +msgid "" "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)" diff --git a/src/plugins/relay/CMakeLists.txt b/src/plugins/relay/CMakeLists.txt index b8e613b1b..2d662003e 100644 --- a/src/plugins/relay/CMakeLists.txt +++ b/src/plugins/relay/CMakeLists.txt @@ -19,13 +19,9 @@ add_library(relay MODULE relay.c relay.h + relay-auth.c relay-auth.h relay-buffer.c relay-buffer.h relay-client.c relay-client.h - irc/relay-irc.c irc/relay-irc.h - weechat/relay-weechat.c weechat/relay-weechat.h - weechat/relay-weechat-msg.c weechat/relay-weechat-msg.h - weechat/relay-weechat-nicklist.c weechat/relay-weechat-nicklist.h - weechat/relay-weechat-protocol.c weechat/relay-weechat-protocol.h relay-command.c relay-command.h relay-completion.c relay-completion.h relay-config.c relay-config.h @@ -35,6 +31,13 @@ add_library(relay MODULE relay-server.c relay-server.h relay-upgrade.c relay-upgrade.h relay-websocket.c relay-websocket.h + # irc relay + irc/relay-irc.c irc/relay-irc.h + # weechat relay + weechat/relay-weechat.c weechat/relay-weechat.h + weechat/relay-weechat-msg.c weechat/relay-weechat-msg.h + weechat/relay-weechat-nicklist.c weechat/relay-weechat-nicklist.h + weechat/relay-weechat-protocol.c weechat/relay-weechat-protocol.h ) set_target_properties(relay PROPERTIES PREFIX "") diff --git a/src/plugins/relay/Makefile.am b/src/plugins/relay/Makefile.am index e2be35fd1..36914ae8f 100644 --- a/src/plugins/relay/Makefile.am +++ b/src/plugins/relay/Makefile.am @@ -25,20 +25,12 @@ lib_LTLIBRARIES = relay.la relay_la_SOURCES = relay.c \ relay.h \ + relay-auth.c \ + relay-auth.h \ relay-buffer.c \ relay-buffer.h \ relay-client.c \ relay-client.h \ - irc/relay-irc.c \ - irc/relay-irc.h \ - weechat/relay-weechat.c \ - weechat/relay-weechat.h \ - weechat/relay-weechat-msg.c \ - weechat/relay-weechat-msg.h \ - weechat/relay-weechat-nicklist.c \ - weechat/relay-weechat-nicklist.h \ - weechat/relay-weechat-protocol.c \ - weechat/relay-weechat-protocol.h \ relay-command.c \ relay-command.h \ relay-completion.c \ @@ -56,7 +48,17 @@ relay_la_SOURCES = relay.c \ relay-upgrade.c \ relay-upgrade.h \ relay-websocket.c \ - relay-websocket.h + relay-websocket.h \ + irc/relay-irc.c \ + irc/relay-irc.h \ + weechat/relay-weechat.c \ + weechat/relay-weechat.h \ + weechat/relay-weechat-msg.c \ + weechat/relay-weechat-msg.h \ + weechat/relay-weechat-nicklist.c \ + weechat/relay-weechat-nicklist.h \ + weechat/relay-weechat-protocol.c \ + weechat/relay-weechat-protocol.h relay_la_LDFLAGS = -module -no-undefined relay_la_LIBADD = $(RELAY_LFLAGS) $(ZLIB_LFLAGS) $(GNUTLS_LFLAGS) diff --git a/src/plugins/relay/relay-auth.c b/src/plugins/relay/relay-auth.c new file mode 100644 index 000000000..359eab247 --- /dev/null +++ b/src/plugins/relay/relay-auth.c @@ -0,0 +1,458 @@ +/* + * relay-auth.c - relay client authentication + * + * Copyright (C) 2003-2020 Sébastien Helleu <flashcode@flashtux.org> + * + * This file is part of WeeChat, the extensible chat client. + * + * WeeChat is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * WeeChat is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with WeeChat. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <gcrypt.h> + +#include "../weechat-plugin.h" +#include "relay.h" +#include "relay-auth.h" +#include "relay-client.h" +#include "relay-config.h" + + +/* + * this list is sorted from the least secure to the safest algorithm: + * "plain" is plain text password, the other values are hash algorithms; + * during negotiation with the client, the highest value in this list matching + * the client supported values is used + */ +char *relay_auth_password_name[] = +{ "plain", "sha256", "sha512", "pbkdf2+sha256", "pbkdf2+sha512" }; + + +/* + * Searches for a password authentication. + * + * Returns index in enum t_relay_auth_password, + * -1 if password authentication is not found. + */ + +int +relay_auth_password_search (const char *name) +{ + int i; + + for (i = 0; i < RELAY_NUM_PASSWORD_AUTHS; i++) + { + if (strcmp (relay_auth_password_name[i], name) == 0) + return i; + } + + /* authentication password type found */ + return -1; +} + +/* + * Generates a nonce: a buffer of unpredictable bytes + * + * Note: result must be freed after use. + */ + +char * +relay_auth_generate_nonce () +{ + int size; + char *nonce, *nonce_hexa; + + size = weechat_config_integer (relay_config_network_nonce_size); + + nonce = malloc (size); + if (!nonce) + return NULL; + + nonce_hexa = malloc ((size * 2) + 1); + if (!nonce_hexa) + { + free (nonce); + return NULL; + } + + gcry_create_nonce ((unsigned char *)nonce, size); + weechat_string_base_encode (16, nonce, size, nonce_hexa); + + free (nonce); + + return nonce_hexa; +} + +/* + * Checks if password received as plain text is valid. + * + * Returns: + * 1: password is valid + * 0: password is not valid + */ + +int +relay_auth_check_password_plain (const char *password, + const char *relay_password) +{ + if (!password || !relay_password) + return 0; + + return (strcmp (password, relay_password) == 0) ? 1 : 0; +} + +/* + * Authenticates with password (plain text). + * + * Returns: + * 1: authentication OK + * 0: authentication failed + */ + +int +relay_auth_password (struct t_relay_client *client, + const char *password, const char *relay_password) +{ + if (client->auth_password != RELAY_AUTH_PASSWORD_PLAIN) + return 0; + + return relay_auth_check_password_plain (password, relay_password); + +} + +/* + * Parses SHA256 or SHA512 parameters from string with format: + * + * salt:hash + * + * where: + * + * salt is the salt in hexadecimal + * hash is the hashed password with the parameters above, in hexadecimal + */ + +void +relay_auth_parse_sha (const char *parameters, + char **salt_hexa, char **salt, int *salt_size, + char **hash) +{ + char **argv; + int argc; + + *salt_hexa = NULL; + *salt = NULL; + *salt_size = 0; + *hash = NULL; + + if (!parameters) + return; + + argv = weechat_string_split (parameters, ":", NULL, 0, 0, &argc); + + if (!argv || (argc < 2)) + { + /* not enough parameters */ + if (argv) + weechat_string_free_split (argv); + return; + } + + /* parameter 1: salt */ + *salt = malloc (strlen (argv[0]) + 1); + if (*salt) + { + *salt_size = weechat_string_base_decode (16, argv[0], *salt); + if (*salt_size > 0) + *salt_hexa = strdup (argv[0]); + else + { + free (*salt); + *salt = NULL; + } + } + + /* parameter 2: the SHA256 or SHA512 hash */ + *hash = strdup (argv[1]); + + weechat_string_free_split (argv); +} + +/* + * Parses PBKDF2 parameters from string with format: + * + * salt:iterations:hash + * + * where: + * + * salt is the salt in hexadecimal + * iterations it the number of iterations (≥ 1) + * hash is the hashed password with the parameters above, in hexadecimal + */ + +void +relay_auth_parse_pbkdf2 (const char *parameters, + char **salt_hexa, char **salt, int *salt_size, + int *iterations, char **hash) +{ + char **argv, *error; + int argc; + + *salt_hexa = NULL; + *salt = NULL; + *salt_size = 0; + *iterations = 0; + *hash = NULL; + + if (!parameters) + return; + + argv = weechat_string_split (parameters, ":", NULL, 0, 0, &argc); + + if (!argv || (argc < 3)) + { + /* not enough parameters */ + if (argv) + weechat_string_free_split (argv); + return; + } + + /* parameter 1: salt */ + *salt = malloc (strlen (argv[0]) + 1); + if (*salt) + { + *salt_size = weechat_string_base_decode (16, argv[0], *salt); + if (*salt_size > 0) + *salt_hexa = strdup (argv[0]); + else + { + free (*salt); + *salt = NULL; + } + } + + /* parameter 2: iterations */ + *iterations = (int)strtol (argv[1], &error, 10); + if (!error || error[0]) + *iterations = 0; + + /* parameter 3: the PBKDF2 hash */ + *hash = strdup (argv[2]); + + weechat_string_free_split (argv); +} + +/* + * Checks if the salt received from the client is valid. + * + * It is valid if both conditions are true: + * 1. the salt is longer than the server nonce, so it means it includes a + * client nonce + * 2. the salt begins with the server nonce (client->nonce) + * + * Returns: + * 1: salt is valid + * 0: salt is not valid + */ + +int +relay_auth_check_salt (struct t_relay_client *client, const char *salt_hexa) +{ + return (salt_hexa + && client->nonce + && (strlen (salt_hexa) > strlen (client->nonce)) + && (weechat_strncasecmp (salt_hexa, client->nonce, + strlen (client->nonce)) == 0)) ? 1 : 0; +} + +/* + * Checks if password received as SHA256/SHA512 hash is valid. + * + * Returns: + * 1: password is valid + * 0: password is not valid + */ + +int +relay_auth_check_hash_sha (const char *hash_algo, + const char *salt, + int salt_size, + const char *hash_sha, + const char *relay_password) +{ + char *salt_password, hash[512 / 8], hash_hexa[((512 / 8) * 2) + 1]; + int rc, length, hash_size; + + rc = 0; + + if (salt && (salt_size > 0) && hash_sha) + { + length = salt_size + strlen (relay_password); + salt_password = malloc (length); + if (salt_password) + { + memcpy (salt_password, salt, salt_size); + memcpy (salt_password + salt_size, relay_password, + strlen (relay_password)); + if (weechat_crypto_hash (salt_password, length, + hash_algo, + hash, &hash_size)) + { + weechat_string_base_encode (16, hash, hash_size, + hash_hexa); + if (weechat_strcasecmp (hash_hexa, hash_sha) == 0) + rc = 1; + } + free (salt_password); + } + } + + return rc; +} + +/* + * Checks if password received as PBKDF2 hash is valid. + * + * Returns: + * 1: password is valid + * 0: password is not valid + */ + +int +relay_auth_check_hash_pbkdf2 (const char *hash_pbkdf2_algo, + const char *salt, + int salt_size, + int iterations, + const char *hash_pbkdf2, + const char *relay_password) +{ + char hash[512 / 8], hash_hexa[((512 / 8) * 2) + 1]; + int rc, hash_size; + + rc = 0; + + if (hash_pbkdf2_algo && salt && (salt_size > 0) && hash_pbkdf2) + { + if (weechat_crypto_hash_pbkdf2 (relay_password, + strlen (relay_password), + hash_pbkdf2_algo, + salt, salt_size, + iterations, + hash, &hash_size)) + { + weechat_string_base_encode (16, hash, hash_size, hash_hexa); + if (weechat_strcasecmp (hash_hexa, hash_pbkdf2) == 0) + rc = 1; + } + } + + return rc; +} + +/* + * Authenticates with password hash. + * + * Returns: + * 1: authentication OK + * 0: authentication failed + */ + +int +relay_auth_password_hash (struct t_relay_client *client, + const char *hashed_password, const char *relay_password) +{ + const char *pos_hash; + char *str_hash_algo; + char *hash_pbkdf2_algo, *salt_hexa, *salt, *hash_sha, *hash_pbkdf2; + int rc, auth_password, salt_size, iterations; + + rc = 0; + + str_hash_algo = NULL; + + /* no authentication supported at all? */ + if (client->auth_password < 0) + goto end; + + if (!hashed_password || !relay_password) + goto end; + + pos_hash = strchr (hashed_password, ':'); + if (!pos_hash) + goto end; + + str_hash_algo = weechat_strndup (hashed_password, + pos_hash - hashed_password); + if (!str_hash_algo) + goto end; + + pos_hash++; + + auth_password = relay_auth_password_search (str_hash_algo); + + if (auth_password != client->auth_password) + goto end; + + switch (auth_password) + { + case RELAY_AUTH_PASSWORD_SHA256: + case RELAY_AUTH_PASSWORD_SHA512: + relay_auth_parse_sha (pos_hash, &salt_hexa, &salt, &salt_size, + &hash_sha); + if (relay_auth_check_salt (client, salt_hexa) + && relay_auth_check_hash_sha (str_hash_algo, salt, salt_size, + hash_sha, relay_password)) + { + rc = 1; + } + if (salt_hexa) + free (salt_hexa); + if (salt) + free (salt); + if (hash_sha) + free (hash_sha); + break; + case RELAY_AUTH_PASSWORD_PBKDF2_SHA256: + case RELAY_AUTH_PASSWORD_PBKDF2_SHA512: + hash_pbkdf2_algo = strdup (str_hash_algo + 7); + relay_auth_parse_pbkdf2 (pos_hash, &salt_hexa, &salt, &salt_size, + &iterations, &hash_pbkdf2); + if ((iterations == client->hash_iterations) + && relay_auth_check_salt (client, salt_hexa) + && relay_auth_check_hash_pbkdf2 (hash_pbkdf2_algo, salt, + salt_size, iterations, + hash_pbkdf2, relay_password)) + { + rc = 1; + } + if (hash_pbkdf2_algo) + free (hash_pbkdf2_algo); + if (salt_hexa) + free (salt_hexa); + if (salt) + free (salt); + if (hash_pbkdf2) + free (hash_pbkdf2); + break; + case RELAY_NUM_PASSWORD_AUTHS: + break; + } + +end: + if (str_hash_algo) + free (str_hash_algo); + + return rc; +} diff --git a/src/plugins/relay/relay-auth.h b/src/plugins/relay/relay-auth.h new file mode 100644 index 000000000..1b5cc597e --- /dev/null +++ b/src/plugins/relay/relay-auth.h @@ -0,0 +1,73 @@ +/* + * Copyright (C) 2003-2020 Sébastien Helleu <flashcode@flashtux.org> + * + * This file is part of WeeChat, the extensible chat client. + * + * WeeChat is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * WeeChat is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with WeeChat. If not, see <https://www.gnu.org/licenses/>. + */ + +#ifndef WEECHAT_PLUGIN_RELAY_AUTH_H +#define WEECHAT_PLUGIN_RELAY_AUTH_H + +struct t_relay_client; + +enum t_relay_auth_password +{ + RELAY_AUTH_PASSWORD_PLAIN = 0, + RELAY_AUTH_PASSWORD_SHA256, + RELAY_AUTH_PASSWORD_SHA512, + RELAY_AUTH_PASSWORD_PBKDF2_SHA256, + RELAY_AUTH_PASSWORD_PBKDF2_SHA512, + /* number of password auths */ + RELAY_NUM_PASSWORD_AUTHS, +}; + +extern char *relay_auth_password_name[]; + +extern int relay_auth_password_search (const char *name); +extern char *relay_auth_generate_nonce (); +extern int relay_auth_check_password_plain (const char *password, + const char *relay_password); +extern int relay_auth_password (struct t_relay_client *client, + const char *password, + const char *relay_password); +extern void relay_auth_parse_sha (const char *parameters, + char **salt_hexa, + char **salt, + int *salt_size, + char **hash); +extern void relay_auth_parse_pbkdf2 (const char *parameters, + char **salt_hexa, + char **salt, + int *salt_size, + int *iterations, + char **hash); +extern int relay_auth_check_salt (struct t_relay_client *client, + const char *salt_hexa); +extern int relay_auth_check_hash_sha (const char *hash_algo, + const char *salt, + int salt_size, + const char *hash_sha, + const char *relay_password); +extern int relay_auth_check_hash_pbkdf2 (const char *hash_pbkdf2_algo, + const char *salt, + int salt_size, + int iterations, + const char *hash_pbkdf2, + const char *relay_password); +extern int relay_auth_password_hash (struct t_relay_client *client, + const char *hashed_password, + const char *relay_password); + +#endif /* WEECHAT_PLUGIN_RELAY_AUTH_H */ diff --git a/src/plugins/relay/relay-client.c b/src/plugins/relay/relay-client.c index 72de0a690..2f0f5a5da 100644 --- a/src/plugins/relay/relay-client.c +++ b/src/plugins/relay/relay-client.c @@ -36,14 +36,15 @@ #include "../weechat-plugin.h" #include "relay.h" #include "relay-client.h" -#include "irc/relay-irc.h" -#include "weechat/relay-weechat.h" +#include "relay-auth.h" #include "relay-config.h" #include "relay-buffer.h" #include "relay-network.h" #include "relay-raw.h" #include "relay-server.h" #include "relay-websocket.h" +#include "irc/relay-irc.h" +#include "weechat/relay-weechat.h" char *relay_client_status_string[] = /* status strings for display */ @@ -1269,6 +1270,7 @@ struct t_relay_client * relay_client_new (int sock, const char *address, struct t_relay_server *server) { struct t_relay_client *new_client; + int plain_text_password; #ifdef HAVE_GNUTLS int bits; struct t_config_option *ptr_option; @@ -1295,6 +1297,14 @@ relay_client_new (int sock, const char *address, struct t_relay_server *server) new_client->protocol = server->protocol; new_client->protocol_string = (server->protocol_string) ? strdup (server->protocol_string) : NULL; new_client->protocol_args = (server->protocol_args) ? strdup (server->protocol_args) : NULL; + plain_text_password = weechat_string_match_list ( + relay_auth_password_name[0], + (const char **)relay_config_network_auth_password_list, + 1); + new_client->auth_password = (plain_text_password) ? 0 : -1; + new_client->hash_iterations = weechat_config_integer ( + relay_config_network_hash_iterations); + new_client->nonce = relay_auth_generate_nonce (); new_client->listen_start_time = server->start_time; new_client->start_time = time (NULL); new_client->end_time = 0; @@ -1496,6 +1506,22 @@ relay_client_new_with_infolist (struct t_infolist *infolist) new_client->protocol_string = (str) ? strdup (str) : NULL; str = weechat_infolist_string (infolist, "protocol_args"); new_client->protocol_args = (str) ? strdup (str) : NULL; + /* "auth_password" is new in WeeChat 2.9 */ + if (weechat_infolist_search_var (infolist, "auth_password")) + new_client->auth_password = weechat_infolist_integer (infolist, "auth_password"); + else + new_client->auth_password = RELAY_AUTH_PASSWORD_PLAIN; + /* "hash_iterations" is new in WeeChat 2.9 */ + if (weechat_infolist_search_var (infolist, "hash_iterations")) + new_client->hash_iterations = weechat_infolist_integer (infolist, "hash_iterations"); + else + new_client->hash_iterations = weechat_config_integer ( + relay_config_network_hash_iterations); + /* "nonce" is new in WeeChat 2.9 */ + if (weechat_infolist_search_var (infolist, "nonce")) + new_client->nonce = strdup (weechat_infolist_string (infolist, "nonce")); + else + new_client->nonce = relay_auth_generate_nonce (); new_client->listen_start_time = weechat_infolist_time (infolist, "listen_start_time"); new_client->start_time = weechat_infolist_time (infolist, "start_time"); new_client->end_time = weechat_infolist_time (infolist, "end_time"); @@ -1693,6 +1719,8 @@ relay_client_free (struct t_relay_client *client) free (client->protocol_string); if (client->protocol_args) free (client->protocol_args); + if (client->nonce) + free (client->nonce); #ifdef HAVE_GNUTLS if (client->hook_timer_handshake) weechat_unhook (client->hook_timer_handshake); @@ -1829,6 +1857,12 @@ relay_client_add_to_infolist (struct t_infolist *infolist, return 0; if (!weechat_infolist_new_var_string (ptr_item, "protocol_args", client->protocol_args)) return 0; + if (!weechat_infolist_new_var_integer (ptr_item, "auth_password", client->auth_password)) + return 0; + if (!weechat_infolist_new_var_integer (ptr_item, "hash_iterations", client->hash_iterations)) + return 0; + if (!weechat_infolist_new_var_string (ptr_item, "nonce", client->nonce)) + return 0; if (!weechat_infolist_new_var_time (ptr_item, "listen_start_time", client->listen_start_time)) return 0; if (!weechat_infolist_new_var_time (ptr_item, "start_time", client->start_time)) @@ -1905,6 +1939,12 @@ relay_client_print_log () relay_protocol_string[ptr_client->protocol]); weechat_log_printf (" protocol_string . . . : '%s'", ptr_client->protocol_string); weechat_log_printf (" protocol_args . . . . : '%s'", ptr_client->protocol_args); + weechat_log_printf (" auth_password . . . . : %d (%s)", + ptr_client->auth_password, + (ptr_client->auth_password >= 0) ? + relay_auth_password_name[ptr_client->auth_password] : ""); + weechat_log_printf (" hash_iterations . . . : %d", ptr_client->hash_iterations); + weechat_log_printf (" nonce . . . . . . . . : '%s'", ptr_client->nonce); weechat_log_printf (" listen_start_time . . : %lld", (long long)ptr_client->listen_start_time); weechat_log_printf (" start_time. . . . . . : %lld", (long long)ptr_client->start_time); weechat_log_printf (" end_time. . . . . . . : %lld", (long long)ptr_client->end_time); diff --git a/src/plugins/relay/relay-client.h b/src/plugins/relay/relay-client.h index b01588745..368386a41 100644 --- a/src/plugins/relay/relay-client.h +++ b/src/plugins/relay/relay-client.h @@ -106,6 +106,9 @@ struct t_relay_client char *protocol_string; /* example: "ipv6.ssl.irc.freenode" */ char *protocol_args; /* arguments used for protocol */ /* example: server for irc protocol */ + int auth_password; /* password auth (negotiated/client) */ + int hash_iterations; /* hash iterations */ + char *nonce; /* nonce used in salt of hashed pwd */ time_t listen_start_time; /* when listening started */ time_t start_time; /* time of client connection */ time_t end_time; /* time of client disconnection */ @@ -124,6 +127,7 @@ struct t_relay_client }; extern char *relay_client_status_string[]; +extern char *relay_client_status_name[]; extern char *relay_client_msg_type_string[]; extern struct t_relay_client *relay_clients; extern struct t_relay_client *last_relay_client; diff --git a/src/plugins/relay/relay-config.c b/src/plugins/relay/relay-config.c index f9c66ce47..af17284b3 100644 --- a/src/plugins/relay/relay-config.c +++ b/src/plugins/relay/relay-config.c @@ -32,11 +32,11 @@ #include "../weechat-plugin.h" #include "relay.h" #include "relay-config.h" -#include "irc/relay-irc.h" #include "relay-client.h" #include "relay-buffer.h" #include "relay-network.h" #include "relay-server.h" +#include "irc/relay-irc.h" struct t_config_file *relay_config_file = NULL; @@ -60,12 +60,15 @@ struct t_config_option *relay_config_color_text_selected; struct t_config_option *relay_config_network_allow_empty_password; struct t_config_option *relay_config_network_allowed_ips; +struct t_config_option *relay_config_network_auth_password; struct t_config_option *relay_config_network_auth_timeout; struct t_config_option *relay_config_network_bind_address; struct t_config_option *relay_config_network_clients_purge_delay; struct t_config_option *relay_config_network_compression_level; +struct t_config_option *relay_config_network_hash_iterations; struct t_config_option *relay_config_network_ipv6; struct t_config_option *relay_config_network_max_clients; +struct t_config_option *relay_config_network_nonce_size; struct t_config_option *relay_config_network_password; struct t_config_option *relay_config_network_ssl_cert_key; struct t_config_option *relay_config_network_ssl_priorities; @@ -91,6 +94,7 @@ struct t_config_option *relay_config_weechat_commands; regex_t *relay_config_regex_allowed_ips = NULL; regex_t *relay_config_regex_websocket_allowed_origins = NULL; struct t_hashtable *relay_config_hashtable_irc_backlog_tags = NULL; +char **relay_config_network_auth_password_list = NULL; /* @@ -150,6 +154,36 @@ relay_config_change_network_allowed_ips (const void *pointer, void *data, } /* + * Callback for changes on option "relay.network.auth_password". + */ + +void +relay_config_change_network_auth_password (const void *pointer, void *data, + struct t_config_option *option) +{ + /* make C compiler happy */ + (void) pointer; + (void) data; + (void) option; + + if (relay_config_network_auth_password_list) + { + weechat_string_free_split (relay_config_network_auth_password_list); + relay_config_network_auth_password_list = NULL; + } + + relay_config_network_auth_password_list = weechat_string_split ( + weechat_config_string (relay_config_network_auth_password), + ",", + NULL, + WEECHAT_STRING_SPLIT_STRIP_LEFT + | WEECHAT_STRING_SPLIT_STRIP_RIGHT + | WEECHAT_STRING_SPLIT_COLLAPSE_SEPS, + 0, + NULL); +} + +/* * Callback for changes on option "relay.network.bind_address". */ @@ -1032,6 +1066,20 @@ relay_config_init () NULL, NULL, NULL, &relay_config_change_network_allowed_ips, NULL, NULL, NULL, NULL, NULL); + relay_config_network_auth_password = weechat_config_new_option ( + relay_config_file, ptr_section, + "auth_password", "string", + N_("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\")"), + NULL, 0, 0, "*", NULL, 0, + NULL, NULL, NULL, + &relay_config_change_network_auth_password, NULL, NULL, + NULL, NULL, NULL); relay_config_network_auth_timeout = weechat_config_new_option ( relay_config_file, ptr_section, "auth_timeout", "integer", @@ -1066,6 +1114,16 @@ relay_config_init () "compression)"), NULL, 0, 9, "6", NULL, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); + relay_config_network_hash_iterations = weechat_config_new_option ( + relay_config_file, ptr_section, + "hash_iterations", "integer", + N_("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"), + NULL, 1, 1000000, "100000", NULL, 0, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); relay_config_network_ipv6 = weechat_config_new_option ( relay_config_file, ptr_section, "ipv6", "boolean", @@ -1082,6 +1140,15 @@ relay_config_init () N_("maximum number of clients connecting to a port (0 = no limit)"), NULL, 0, INT_MAX, "5", NULL, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); + relay_config_network_nonce_size = weechat_config_new_option ( + relay_config_file, ptr_section, + "nonce_size", "integer", + N_("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"), + NULL, 8, 128, "16", NULL, 0, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); relay_config_network_password = weechat_config_new_option ( relay_config_file, ptr_section, "password", "string", @@ -1294,6 +1361,7 @@ relay_config_read () if (rc == WEECHAT_CONFIG_READ_OK) { relay_config_change_network_allowed_ips (NULL, NULL, NULL); + relay_config_change_network_auth_password (NULL, NULL, NULL); relay_config_change_irc_backlog_tags (NULL, NULL, NULL); } return rc; @@ -1337,4 +1405,10 @@ relay_config_free () weechat_hashtable_free (relay_config_hashtable_irc_backlog_tags); relay_config_hashtable_irc_backlog_tags = NULL; } + + if (relay_config_network_auth_password_list) + { + weechat_string_free_split (relay_config_network_auth_password_list); + relay_config_network_auth_password_list = NULL; + } } diff --git a/src/plugins/relay/relay-config.h b/src/plugins/relay/relay-config.h index 35253abb9..bc9b5a554 100644 --- a/src/plugins/relay/relay-config.h +++ b/src/plugins/relay/relay-config.h @@ -39,12 +39,15 @@ extern struct t_config_option *relay_config_color_text_selected; extern struct t_config_option *relay_config_network_allow_empty_password; extern struct t_config_option *relay_config_network_allowed_ips; +extern struct t_config_option *relay_config_network_auth_password; extern struct t_config_option *relay_config_network_auth_timeout; extern struct t_config_option *relay_config_network_bind_address; extern struct t_config_option *relay_config_network_clients_purge_delay; extern struct t_config_option *relay_config_network_compression_level; +extern struct t_config_option *relay_config_network_hash_iterations; extern struct t_config_option *relay_config_network_ipv6; extern struct t_config_option *relay_config_network_max_clients; +extern struct t_config_option *relay_config_network_nonce_size; extern struct t_config_option *relay_config_network_password; extern struct t_config_option *relay_config_network_ssl_cert_key; extern struct t_config_option *relay_config_network_ssl_priorities; @@ -64,6 +67,7 @@ extern struct t_config_option *relay_config_weechat_commands; extern regex_t *relay_config_regex_allowed_ips; extern regex_t *relay_config_regex_websocket_allowed_origins; extern struct t_hashtable *relay_config_hashtable_irc_backlog_tags; +extern char **relay_config_network_auth_password_list; extern int relay_config_check_network_totp_secret (const void *pointer, void *data, diff --git a/src/plugins/relay/weechat/relay-weechat-msg.h b/src/plugins/relay/weechat/relay-weechat-msg.h index 1ac5cc0f4..98052f1d1 100644 --- a/src/plugins/relay/weechat/relay-weechat-msg.h +++ b/src/plugins/relay/weechat/relay-weechat-msg.h @@ -70,6 +70,8 @@ extern void relay_weechat_msg_add_pointer (struct t_relay_weechat_msg *msg, void *pointer); extern void relay_weechat_msg_add_time (struct t_relay_weechat_msg *msg, time_t time); +extern void relay_weechat_msg_add_hashtable (struct t_relay_weechat_msg *msg, + struct t_hashtable *hashtable); extern int relay_weechat_msg_add_hdata (struct t_relay_weechat_msg *msg, const char *path, const char *keys); extern void relay_weechat_msg_add_infolist (struct t_relay_weechat_msg *msg, diff --git a/src/plugins/relay/weechat/relay-weechat-protocol.c b/src/plugins/relay/weechat/relay-weechat-protocol.c index 205029f66..fe9494cc2 100644 --- a/src/plugins/relay/weechat/relay-weechat-protocol.c +++ b/src/plugins/relay/weechat/relay-weechat-protocol.c @@ -31,6 +31,7 @@ #include "relay-weechat-nicklist.h" #include "../relay-buffer.h" #include "../relay-client.h" +#include "../relay-auth.h" #include "../relay-config.h" #include "../relay-raw.h" @@ -159,148 +160,151 @@ relay_weechat_protocol_is_sync (struct t_relay_client *ptr_client, } /* - * Parses PBKDF2 parameters from string with format: - * - * algorithm:salt:iterations:hash - * - * where: - * - * algorithm is "sha256" or "sha512" - * salt is the salt in hexadecimal - * iterations it the number of iterations (≥ 1) - * hash is the hashed password with the parameters above, in hexadecimal + * Replies to a client handshake command. */ void -relay_weechat_protocol_parse_pbkdf2 (const char *parameters, - char **algorithm, - char **salt, - int *salt_size, - int *iterations, - char **hash_pbkdf2) +relay_weechat_protocol_handshake_reply (struct t_relay_client *client, + const char *command) { - char **argv, *error; - int argc; - - *algorithm = NULL; - *salt = NULL; - *salt_size = 0; - *iterations = 0; - *hash_pbkdf2 = NULL; - - if (!parameters) - return; - - argv = weechat_string_split (parameters, ":", NULL, 0, 0, &argc); + struct t_relay_weechat_msg *msg; + struct t_hashtable *hashtable; + char *totp_secret, string[64]; - if (!argv || (argc < 4)) - { - /* not enough parameters */ - if (argv) - weechat_string_free_split (argv); - return; - } + totp_secret = weechat_string_eval_expression ( + weechat_config_string (relay_config_network_totp_secret), + NULL, NULL, NULL); - /* parameter 1: algorithm */ - if ((strcmp (argv[0], "sha256") == 0) - || (strcmp (argv[0], "sha512") == 0)) + hashtable = weechat_hashtable_new (32, + WEECHAT_HASHTABLE_STRING, + WEECHAT_HASHTABLE_STRING, + NULL, NULL); + if (hashtable) { - *algorithm = strdup (argv[0]); - } + weechat_hashtable_set ( + hashtable, + "auth_password", + (client->auth_password >= 0) ? + relay_auth_password_name[client->auth_password] : ""); + snprintf (string, sizeof (string), "%d", client->hash_iterations); + weechat_hashtable_set ( + hashtable, + "hash_iterations", + string); + weechat_hashtable_set ( + hashtable, + "nonce", + client->nonce); + weechat_hashtable_set ( + hashtable, + "totp", + (totp_secret && totp_secret[0]) ? "on" : "off"); - /* parameter 2: salt */ - *salt = malloc (strlen (argv[1]) + 1); - if (*salt) - *salt_size = weechat_string_base_decode (16, argv[1], *salt); + msg = relay_weechat_msg_new (command); + if (msg) + { + relay_weechat_msg_add_type (msg, RELAY_WEECHAT_MSG_OBJ_HASHTABLE); + relay_weechat_msg_add_hashtable (msg, hashtable); - /* parameter 3: iterations */ - *iterations = (int)strtol (argv[2], &error, 10); - if (!error || error[0]) - *iterations = 0; + /* send message */ + relay_weechat_msg_send (client, msg); + relay_weechat_msg_free (msg); + } - /* parameter 4: the PBKDF2 hash */ - *hash_pbkdf2 = strdup (argv[3]); + weechat_hashtable_free (hashtable); + } - weechat_string_free_split (argv); + if (totp_secret) + free (totp_secret); } + /* - * Checks if hashed password received is valid. - * - * Format of hash_password is: algorithm:hash - * - * Returns 1 if the hashed password is valid, otherwise 0. + * Callback for command "handshake" (from client). */ -int -relay_weechat_protocol_check_hash (const char *hashed_password, - const char *password) +RELAY_WEECHAT_PROTOCOL_CALLBACK(handshake) { - const char *pos_hash; - char *hash_algo, hash[512 / 8], hash_hexa[((512 / 8) * 2) + 1]; - char *hash_pbkdf2_algo, *salt, *hash_pbkdf2; - int rc, hash_size, salt_size, iterations; - - rc = 0; - - if (!hashed_password || !password) - goto end; + char **options, **auths, *pos; + int i, j, index_auth, auth_found, auth_allowed, compression; + int password_received, plain_text_password; - pos_hash = strchr (hashed_password, ':'); - if (!pos_hash) - goto end; + RELAY_WEECHAT_PROTOCOL_MIN_ARGS(0); - hash_algo = weechat_strndup (hashed_password, pos_hash - hashed_password); - if (!hash_algo) - goto end; + if (client->status != RELAY_STATUS_WAITING_AUTH) + return WEECHAT_RC_OK; - pos_hash++; + auth_found = -1; + password_received = 0; - if ((strcmp (hash_algo, "sha256") == 0) - || (strcmp (hash_algo, "sha512") == 0)) - { - if (weechat_crypto_hash (password, strlen (password), hash_algo, - hash, &hash_size)) - { - weechat_string_base_encode (16, hash, hash_size, hash_hexa); - if (weechat_strcasecmp (hash_hexa, pos_hash) == 0) - rc = 1; - } - } - else if (strcmp (hash_algo, "pbkdf2") == 0) + options = (argc > 0) ? + weechat_string_split_command (argv_eol[0], ',') : NULL; + if (options) { - relay_weechat_protocol_parse_pbkdf2 (pos_hash, - &hash_pbkdf2_algo, - &salt, - &salt_size, - &iterations, - &hash_pbkdf2); - if (hash_pbkdf2_algo && salt && (salt_size > 0) && (iterations > 0) - && hash_pbkdf2) + for (i = 0; options[i]; i++) { - if (weechat_crypto_hash_pbkdf2 (password, strlen (password), - hash_pbkdf2_algo, - salt, salt_size, - iterations, - hash, &hash_size)) + pos = strchr (options[i], '='); + if (pos) { - weechat_string_base_encode (16, hash, hash_size, hash_hexa); - if (weechat_strcasecmp (hash_hexa, hash_pbkdf2) == 0) - rc = 1; + pos[0] = '\0'; + pos++; + if (strcmp (options[i], "password") == 0) + { + password_received = 1; + auths = weechat_string_split ( + pos, + ":", + NULL, + WEECHAT_STRING_SPLIT_STRIP_LEFT + | WEECHAT_STRING_SPLIT_STRIP_RIGHT + | WEECHAT_STRING_SPLIT_COLLAPSE_SEPS, + 0, + NULL); + if (auths) + { + for (j = 0; auths[j]; j++) + { + index_auth = relay_auth_password_search ( + auths[j]); + if ((index_auth >= 0) && (index_auth > auth_found)) + { + auth_allowed = weechat_string_match_list ( + relay_auth_password_name[index_auth], + (const char **)relay_config_network_auth_password_list, + 1); + if (auth_allowed) + auth_found = index_auth; + } + } + weechat_string_free_split (auths); + } + } + else if (strcmp (options[i], "compression") == 0) + { + compression = relay_weechat_compression_search (pos); + if (compression >= 0) + RELAY_WEECHAT_DATA(client, compression) = compression; + } } } - if (hash_pbkdf2_algo) - free (hash_pbkdf2_algo); - if (salt) - free (salt); - if (hash_pbkdf2) - free (hash_pbkdf2); + weechat_string_free_split_command (options); + } + + if (!password_received) + { + plain_text_password = weechat_string_match_list ( + relay_auth_password_name[0], + (const char **)relay_config_network_auth_password_list, + 1); + if (plain_text_password) + auth_found = 0; } - free (hash_algo); + client->auth_password = auth_found; -end: - return rc; + relay_weechat_protocol_handshake_reply (client, command); + + return WEECHAT_RC_OK; } /* @@ -328,12 +332,12 @@ end: RELAY_WEECHAT_PROTOCOL_CALLBACK(init) { - char **options, *pos, *password, *totp_secret, *info_totp_args, *info_totp; + char **options, *pos, *relay_password, *totp_secret, *info_totp_args, *info_totp; int i, compression, length, password_received, totp_received; RELAY_WEECHAT_PROTOCOL_MIN_ARGS(0); - password = weechat_string_eval_expression ( + relay_password = weechat_string_eval_expression ( weechat_config_string (relay_config_network_password), NULL, NULL, NULL); totp_secret = weechat_string_eval_expression ( @@ -357,17 +361,14 @@ RELAY_WEECHAT_PROTOCOL_CALLBACK(init) if (strcmp (options[i], "password") == 0) { password_received = 1; - if (password && (strcmp (password, pos) == 0)) + if (relay_auth_password (client, pos, relay_password)) RELAY_WEECHAT_DATA(client, password_ok) = 1; } else if (strcmp (options[i], "password_hash") == 0) { password_received = 1; - if (password - && relay_weechat_protocol_check_hash (pos, password)) - { + if (relay_auth_password_hash (client, pos, relay_password)) RELAY_WEECHAT_DATA(client, password_ok) = 1; - } } else if (strcmp (options[i], "totp") == 0) { @@ -405,7 +406,7 @@ RELAY_WEECHAT_PROTOCOL_CALLBACK(init) } /* if no password received and password is empty, it's OK */ - if (!password_received && (!password || !password[0])) + if (!password_received && (!relay_password || !relay_password[0])) RELAY_WEECHAT_DATA(client, password_ok) = 1; /* if no TOTP received and totp_secret is empty, it's OK */ @@ -425,8 +426,8 @@ RELAY_WEECHAT_PROTOCOL_CALLBACK(init) relay_client_set_status (client, RELAY_STATUS_AUTH_FAILED); } - if (password) - free (password); + if (relay_password) + free (relay_password); if (totp_secret) free (totp_secret); @@ -1547,7 +1548,8 @@ relay_weechat_protocol_recv (struct t_relay_client *client, const char *data) char *pos, *id, *command, **argv, **argv_eol; int i, argc, return_code; struct t_relay_weechat_protocol_cb protocol_cb[] = - { { "init", &relay_weechat_protocol_cb_init }, + { { "handshake", &relay_weechat_protocol_cb_handshake }, + { "init", &relay_weechat_protocol_cb_init }, { "hdata", &relay_weechat_protocol_cb_hdata }, { "info", &relay_weechat_protocol_cb_info }, { "infolist", &relay_weechat_protocol_cb_infolist }, @@ -1631,13 +1633,14 @@ relay_weechat_protocol_recv (struct t_relay_client *client, const char *data) { if (strcmp (protocol_cb[i].name, command) == 0) { - if ((strcmp (protocol_cb[i].name, "init") != 0) + if ((strcmp (protocol_cb[i].name, "handshake") != 0) + && (strcmp (protocol_cb[i].name, "init") != 0) && (!RELAY_WEECHAT_DATA(client, password_ok) || !RELAY_WEECHAT_DATA(client, totp_ok))) { /* - * command is not "init" and password or totp are not set? - * then close connection! + * command is not handshake/init and password or totp are not + * set? then close connection! */ relay_client_set_status (client, RELAY_STATUS_AUTH_FAILED); diff --git a/src/plugins/relay/weechat/relay-weechat.c b/src/plugins/relay/weechat/relay-weechat.c index 8f05c4872..a9f21bcdd 100644 --- a/src/plugins/relay/weechat/relay-weechat.c +++ b/src/plugins/relay/weechat/relay-weechat.c @@ -40,7 +40,7 @@ #include "../relay-raw.h" -char *relay_weechat_compression_string[] = /* strings for compressions */ +char *relay_weechat_compression_string[] = /* strings for compression */ { "off", "zlib" }; diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 5d2d66289..145e66388 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -55,7 +55,7 @@ set(LIB_WEECHAT_UNIT_TESTS_PLUGINS_SRC unit/plugins/irc/test-irc-mode.cpp unit/plugins/irc/test-irc-nick.cpp unit/plugins/irc/test-irc-protocol.cpp - unit/plugins/relay/weechat/test-relay-weechat-protocol.cpp + unit/plugins/relay/test-relay-auth.cpp ) add_library(weechat_unit_tests_plugins MODULE ${LIB_WEECHAT_UNIT_TESTS_PLUGINS_SRC}) diff --git a/tests/Makefile.am b/tests/Makefile.am index 3c8b1f85d..8bed45056 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -72,7 +72,7 @@ lib_weechat_unit_tests_plugins_la_SOURCES = unit/plugins/irc/test-irc-color.cpp unit/plugins/irc/test-irc-mode.cpp \ unit/plugins/irc/test-irc-nick.cpp \ unit/plugins/irc/test-irc-protocol.cpp \ - unit/plugins/relay/weechat/test-relay-weechat-protocol.cpp + unit/plugins/relay/test-relay-auth.cpp lib_weechat_unit_tests_plugins_la_LDFLAGS = -module -no-undefined diff --git a/tests/unit/plugins/relay/test-relay-auth.cpp b/tests/unit/plugins/relay/test-relay-auth.cpp new file mode 100644 index 000000000..78345c60e --- /dev/null +++ b/tests/unit/plugins/relay/test-relay-auth.cpp @@ -0,0 +1,362 @@ +/* + * test-relay-auth.cpp - test client authentication functions + * + * Copyright (C) 2020 Sébastien Helleu <flashcode@flashtux.org> + * + * This file is part of WeeChat, the extensible chat client. + * + * WeeChat is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * WeeChat is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with WeeChat. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "CppUTest/TestHarness.h" + +extern "C" +{ +#include <stdio.h> +#include "src/plugins/relay/relay-auth.h" +} + +#define WEE_CHECK_PARSE_SHA(__parameters) \ + salt = (char *)0x1; \ + salt_size = -1; \ + hash_sha = (char *)0x1; \ + relay_auth_parse_sha ( \ + __parameters, \ + &salt_hexa, \ + &salt, \ + &salt_size, \ + &hash_sha); + +#define WEE_CHECK_PARSE_PBKDF2(__parameters) \ + salt = (char *)0x1; \ + salt_size = -1; \ + iterations = -1; \ + hash_pbkdf2 = (char *)0x1; \ + relay_auth_parse_pbkdf2 ( \ + __parameters, \ + &salt_hexa, \ + &salt, \ + &salt_size, \ + &iterations, \ + &hash_pbkdf2); + +TEST_GROUP(RelayAuth) +{ +}; + +/* + * Tests functions: + * relay_auth_parse_sha + */ + +TEST(RelayAuth, ParseSha) +{ + char *salt_hexa, *salt, *hash_sha; + const char salt_expected[4] = { 0x41, 0x42, 0x43, 0x44 }; /* "ABCD" */ + int salt_size; + + /* NULL string */ + WEE_CHECK_PARSE_SHA(NULL); + POINTERS_EQUAL(NULL, salt_hexa); + POINTERS_EQUAL(NULL, salt); + LONGS_EQUAL(0, salt_size); + POINTERS_EQUAL(NULL, hash_sha); + + /* not enough parameters: 0 (expected: 2) */ + WEE_CHECK_PARSE_SHA(""); + POINTERS_EQUAL(NULL, salt_hexa); + POINTERS_EQUAL(NULL, salt); + LONGS_EQUAL(0, salt_size); + POINTERS_EQUAL(NULL, hash_sha); + + /* not enough parameters: 1 (expected: 2) */ + WEE_CHECK_PARSE_SHA("41424344"); + POINTERS_EQUAL(NULL, salt_hexa); + POINTERS_EQUAL(NULL, salt); + LONGS_EQUAL(0, salt_size); + POINTERS_EQUAL(NULL, hash_sha); + + /* good parameters */ + WEE_CHECK_PARSE_SHA("41424344:5e884898da28047151d0e56f8dc6292773603d0d6aa" + "bbdd62a11ef721d1542d8"); + STRCMP_EQUAL("41424344", salt_hexa); + MEMCMP_EQUAL(salt_expected, salt, 4); + LONGS_EQUAL(4, salt_size); + STRCMP_EQUAL("5e884898da28047151d0e56f8dc6292773603d0d6aabbdd62a11ef721d1" + "542d8", + hash_sha); + free (salt_hexa); + free (salt); + free (hash_sha); + + /* wrong salt */ + WEE_CHECK_PARSE_SHA("Z:5e884898da28047151d0e56f8dc6292773603d0d6aabbdd62a" + "11ef721d1542d8"); + POINTERS_EQUAL(NULL, salt_hexa); + POINTERS_EQUAL(NULL, salt); + LONGS_EQUAL(0, salt_size); + STRCMP_EQUAL("5e884898da28047151d0e56f8dc6292773603d0d6aabbdd62a11ef721d1" + "542d8", + hash_sha); + free (hash_sha); +} + +/* + * Tests functions: + * relay_auth_parse_pbkdf2 + */ + +TEST(RelayAuth, ParsePbkdf2) +{ + char *salt_hexa, *salt, *hash_pbkdf2; + const char salt_expected[4] = { 0x41, 0x42, 0x43, 0x44 }; /* "ABCD" */ + int salt_size, iterations; + + /* NULL string */ + WEE_CHECK_PARSE_PBKDF2(NULL); + POINTERS_EQUAL(NULL, salt_hexa); + POINTERS_EQUAL(NULL, salt); + LONGS_EQUAL(0, salt_size); + LONGS_EQUAL(0, iterations); + POINTERS_EQUAL(NULL, hash_pbkdf2); + + /* not enough parameters: 0 (expected: 3) */ + WEE_CHECK_PARSE_PBKDF2(""); + POINTERS_EQUAL(NULL, salt_hexa); + POINTERS_EQUAL(NULL, salt); + LONGS_EQUAL(0, salt_size); + LONGS_EQUAL(0, iterations); + POINTERS_EQUAL(NULL, hash_pbkdf2); + + /* not enough parameters: 1 (expected: 3) */ + WEE_CHECK_PARSE_PBKDF2("41424344"); + POINTERS_EQUAL(NULL, salt_hexa); + POINTERS_EQUAL(NULL, salt); + LONGS_EQUAL(0, salt_size); + LONGS_EQUAL(0, iterations); + POINTERS_EQUAL(NULL, hash_pbkdf2); + + /* not enough parameters: 2 (expected: 3) */ + WEE_CHECK_PARSE_PBKDF2("41424344:100000"); + POINTERS_EQUAL(NULL, salt_hexa); + POINTERS_EQUAL(NULL, salt); + LONGS_EQUAL(0, salt_size); + LONGS_EQUAL(0, iterations); + POINTERS_EQUAL(NULL, hash_pbkdf2); + + /* good parameters */ + WEE_CHECK_PARSE_PBKDF2("41424344:100000:01757d53157ca14a1419e3a8cc1563536" + "520a60b76d2d48e7f9ac09afc945a1c"); + STRCMP_EQUAL("41424344", salt_hexa); + MEMCMP_EQUAL(salt_expected, salt, 4); + LONGS_EQUAL(4, salt_size); + LONGS_EQUAL(100000, iterations); + STRCMP_EQUAL("01757d53157ca14a1419e3a8cc1563536520a60b76d2d48e7f9ac09afc9" + "45a1c", + hash_pbkdf2); + free (salt_hexa); + free (salt); + free (hash_pbkdf2); + + /* wrong salt */ + WEE_CHECK_PARSE_PBKDF2("Z:100000:01757d53157ca14a1419e3a8cc1563536520a60b" + "76d2d48e7f9ac09afc945a1c"); + POINTERS_EQUAL(NULL, salt_hexa); + POINTERS_EQUAL(NULL, salt); + LONGS_EQUAL(0, salt_size); + LONGS_EQUAL(100000, iterations); + STRCMP_EQUAL("01757d53157ca14a1419e3a8cc1563536520a60b76d2d48e7f9ac09afc9" + "45a1c", + hash_pbkdf2); + free (hash_pbkdf2); + + /* wrong iterations */ + WEE_CHECK_PARSE_PBKDF2("41424344:abcd:01757d53157ca14a1419e3a8cc156353652" + "0a60b76d2d48e7f9ac09afc945a1c"); + STRCMP_EQUAL("41424344", salt_hexa); + MEMCMP_EQUAL(salt_expected, salt, 4); + LONGS_EQUAL(4, salt_size); + LONGS_EQUAL(0, iterations); + STRCMP_EQUAL("01757d53157ca14a1419e3a8cc1563536520a60b76d2d48e7f9ac09afc9" + "45a1c", + hash_pbkdf2); + free (salt_hexa); + free (salt); + free (hash_pbkdf2); +} + +/* + * Tests functions: + * relay_auth_check_password_plain + */ + +TEST(RelayAuth, CheckPasswordPlain) +{ + /* invalid arguments */ + LONGS_EQUAL(0, relay_auth_check_password_plain (NULL, NULL)); + LONGS_EQUAL(0, relay_auth_check_password_plain ("abcd", NULL)); + LONGS_EQUAL(0, relay_auth_check_password_plain (NULL, "password")); + + /* wrong password */ + LONGS_EQUAL(0, relay_auth_check_password_plain ("test", "password")); + LONGS_EQUAL(0, relay_auth_check_password_plain ("Password", "password")); + + /* good password */ + LONGS_EQUAL(1, relay_auth_check_password_plain ("", "")); + LONGS_EQUAL(1, relay_auth_check_password_plain ("password", "password")); +} + +/* + * Tests functions: + * relay_auth_check_hash_sha + */ + +TEST(RelayAuth, CheckHashSha) +{ + /* "ABCDEFGHIJKLMNOP" */ + const char salt[16] = { 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, + 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50 }; + + LONGS_EQUAL(0, + relay_auth_check_hash_sha ( + NULL, NULL, 0, NULL, NULL)); + LONGS_EQUAL(0, + relay_auth_check_hash_sha ( + "", "", 0, "", "")); + LONGS_EQUAL(0, + relay_auth_check_hash_sha ( + "sha256", NULL, 0, NULL, NULL)); + LONGS_EQUAL(0, + relay_auth_check_hash_sha ( + "sha256", salt, sizeof (salt), NULL, NULL)); + LONGS_EQUAL(0, + relay_auth_check_hash_sha ( + "sha256", salt, sizeof (salt), "", "")); + + /* SHA256: hash is for password: "wrong" */ + LONGS_EQUAL(0, + relay_auth_check_hash_sha ( + "sha256", + salt, + sizeof (salt), + "5d21c7a7d34f47623195ff4750bd65c34bb5f1ba131bf0086a498b2a" + "6a4edfcb", + "password")); + /* SHA256: hash is for password: "password" */ + LONGS_EQUAL(1, + relay_auth_check_hash_sha ( + "sha256", + salt, + sizeof (salt), + "6b1550cb48b6cd66b7152f96804b816b5ae861e4ae52ff5c7a56b7a4" + "f2fdb772", + "password")); + + /* SHA512: hash is for password: "wrong" */ + LONGS_EQUAL(0, + relay_auth_check_hash_sha ( + "sha512", + salt, + sizeof (salt), + "527d147327d77aceeb862848b404d462ce2a11e4502eda82ce0b1be1" + "958422491ca14f3fe8b94a66c61d54639d9fbed0979025ae1073ccaa" + "a66a2d2de9416221", + "password")); + /* SHA512: hash is for password: "password" */ + LONGS_EQUAL(1, + relay_auth_check_hash_sha ( + "sha512", + salt, + sizeof (salt), + "49d2c9a7f7cf630b32c0cc79b331db4eec6215e2c90bcc6c43db93f8" + "847cfdf885a4a8d36b440cb47fed79e97b35380d086a5722c3a26018" + "fdc633fe56949938", + "password")); +} + +/* + * Tests functions: + * relay_auth_check_hash_pbkdf2 + */ + +TEST(RelayAuth, CheckHashPbkdf2) +{ + /* "ABCDEFGHIJKLMNOP" */ + const char salt[16] = { 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, + 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50 }; + + + LONGS_EQUAL(0, + relay_auth_check_hash_pbkdf2 ( + NULL, NULL, 0, 0, NULL, NULL)); + LONGS_EQUAL(0, + relay_auth_check_hash_pbkdf2 ( + "", "", 0, 0, "", "")); + LONGS_EQUAL(0, + relay_auth_check_hash_pbkdf2 ( + "sha256", NULL, 0, 0, NULL, NULL)); + LONGS_EQUAL(0, + relay_auth_check_hash_pbkdf2 ( + "sha256", salt, sizeof (salt), 0, NULL, NULL)); + LONGS_EQUAL(0, + relay_auth_check_hash_pbkdf2 ( + "sha256", salt, sizeof (salt), 100000, NULL, NULL)); + LONGS_EQUAL(0, + relay_auth_check_hash_pbkdf2 ( + "sha256", salt, sizeof (salt), 100000, "", "")); + + /* PBKDF2 (SHA256): hash is for password "wrong" */ + LONGS_EQUAL(0, + relay_auth_check_hash_pbkdf2 ( + "sha256", + salt, + sizeof (salt), + 100000, + "e8f92a75f5956e9dc3499775221e9ef121bf4d09bdca4391b69aa62c" + "50c2bb6b", + "password")); + /* PBKDF2 (SHA256): hash is for password "password" */ + LONGS_EQUAL(1, + relay_auth_check_hash_pbkdf2 ( + "sha256", + salt, + sizeof (salt), + 100000, + "323d29f1762dcb5917bc8320c4eb9ea05900fc28e53cbc3e1b7f0980" + "2e35e2d0", + "password")); + + /* PBKDF2 (SHA512): hash is for password "wrong" */ + LONGS_EQUAL(0, + relay_auth_check_hash_pbkdf2 ( + "sha512", + salt, + sizeof (salt), + 100000, + "e682a3815a4d1de8d13a223932b6b0467b7d775111aae3794afb9a84" + "ee62bd50755fde725262f75d1211e8497a35c8dca8a6333bcc9f7b53" + "244f6ff567d25cfc", + "password")); + /* PBKDF2 (SHA512): hash is for password "password" */ + LONGS_EQUAL(1, + relay_auth_check_hash_pbkdf2 ( + "sha512", + salt, + sizeof (salt), + 100000, + "db166999c1f415a40570a4bbd3a26d461f87e495da215c75135b77bf" + "910a261d3749f28264d24b546fc898908d4209704700020b8dd2bca6" + "e4698208dd5aa5f2", + "password")); +} |