From e03f2be5f1dba14951158a0738dbee54f651f21b Mon Sep 17 00:00:00 2001 From: Val Lorentz Date: Tue, 21 Mar 2023 19:03:20 +0100 Subject: [PATCH] Implement draft/sasl-ir --- lib/irc/handler.ex | 11 ++++++++++- test/irc/handler_test.exs | 31 +++++++++++++++++++++++++++++-- 2 files changed, 39 insertions(+), 3 deletions(-) diff --git a/lib/irc/handler.ex b/lib/irc/handler.ex index 88c5807..16e509c 100644 --- a/lib/irc/handler.ex +++ b/lib/irc/handler.ex @@ -75,6 +75,9 @@ defmodule M51.IrcConn.Handler do # https://ircv3.net/specs/extensions/sasl-3.1 "sasl" => {:sasl, "PLAIN"}, + # https://github.com/ircv3/ircv3-specifications/pull/520 + "draft/sasl-ir" => {:sasl_ir, nil}, + # https://ircv3.net/specs/extensions/server-time "server-time" => {:server_time, nil}, @@ -400,10 +403,16 @@ defmodule M51.IrcConn.Handler do nil - {"AUTHENTICATE", ["PLAIN" | _]} -> + {"AUTHENTICATE", ["PLAIN"]} -> send.(%M51.Irc.Command{command: "AUTHENTICATE", params: ["+"]}) nil + {"AUTHENTICATE", ["PLAIN" | params]} -> + # SASL-IR: https://github.com/ircv3/ircv3-specifications/pull/520 + # Call this function recursively without the mechanism, to be handled + # by the next case below + handle_connreg(sup_pid, %{command | params: params}, nick) + {"AUTHENTICATE", [param | _]} -> # this catches both invalid mechs and actual PLAIN message. # FIXME: add some state to tell the two apart. diff --git a/test/irc/handler_test.exs b/test/irc/handler_test.exs index a4087e5..29277ce 100644 --- a/test/irc/handler_test.exs +++ b/test/irc/handler_test.exs @@ -18,8 +18,8 @@ defmodule M51.IrcConn.HandlerTest do use ExUnit.Case, async: false doctest M51.IrcConn.Handler - @cap_ls_302 ":server. CAP * LS :account-tag batch draft/account-registration=before-connect draft/channel-rename draft/chathistory draft/multiline=max-bytes=8192 echo-message extended-join labeled-response message-tags sasl=PLAIN server-time soju.im/account-required standard-replies userhost-in-names\r\n" - @cap_ls ":server. CAP * LS :account-tag batch draft/account-registration draft/channel-rename draft/chathistory draft/multiline echo-message extended-join labeled-response message-tags sasl server-time soju.im/account-required standard-replies userhost-in-names\r\n" + @cap_ls_302 ":server. CAP * LS :account-tag batch draft/account-registration=before-connect draft/channel-rename draft/chathistory draft/multiline=max-bytes=8192 draft/sasl-ir echo-message extended-join labeled-response message-tags sasl=PLAIN server-time soju.im/account-required standard-replies userhost-in-names\r\n" + @cap_ls ":server. CAP * LS :account-tag batch draft/account-registration draft/channel-rename draft/chathistory draft/multiline draft/sasl-ir echo-message extended-join labeled-response message-tags sasl server-time soju.im/account-required standard-replies userhost-in-names\r\n" @isupport "CASEMAPPING=rfc3454 CLIENTTAGDENY=*,-draft/react,-draft/reply CHANLIMIT= CHANTYPES=#! CHATHISTORY=1000 MAXTARGETS=1 MSGREFTYPES=msgid PREFIX= TARGMAX=JOIN:1,PART:1 UTF8ONLY :are supported by this server\r\n" setup do @@ -189,6 +189,33 @@ defmodule M51.IrcConn.HandlerTest do assert M51.IrcConn.State.gecos(state) == "My GECOS" end + test "Connection registration with SASL-IR", %{state: state, handler: handler} do + send(handler, cmd("CAP LS 302")) + assert_line(@cap_ls_302) + + send(handler, cmd("CAP REQ sasl")) + assert_line(":server. CAP * ACK :sasl\r\n") + + send(handler, cmd("NICK foo:example.org")) + send(handler, cmd("USER ident * * :My GECOS")) + + # foo:example.org\x00foo:example.org\x00correct password + send(handler, cmd("AUTHENTICATE PLAIN Zm9vOmV4YW1wbGUub3JnAGZvbzpleGFtcGxlLm9yZwBjb3JyZWN0IHBhc3N3b3Jk") + ) + + assert_line( + ":server. 900 foo:example.org foo:example.org!foo@example.org foo:example.org :You are now logged in as foo:example.org\r\n" + ) + + assert_line(":server. 903 foo:example.org :Authentication successful\r\n") + + send(handler, cmd("CAP END")) + assert_welcome("foo:example.org") + + assert M51.IrcConn.State.nick(state) == "foo:example.org" + assert M51.IrcConn.State.gecos(state) == "My GECOS" + end + test "Connection registration with AUTHENTICATE before NICK", %{state: state, handler: handler} do send(handler, cmd("CAP LS 302")) assert_line(@cap_ls_302)