Skip to content

Commit

Permalink
Fix SASL authentication process for Oragono IRCd #356
Browse files Browse the repository at this point in the history
  How to test:

  1. Connect without SASL enabled
  2. Send these commands to NickServ
     /msg NickServ REGISTER <secret>
     /msg NickServ CERT ADD # Might be optional, but does not hurt
  3. Edit connection settings:
     Username                      = REGISTER nick/username
     Password                      = REGISTER secret
     SASL authentication mechanism = Plain
  4. Update (and reconnect) to the server
  • Loading branch information
Jan Henning Thorsen committed Jan 8, 2021
1 parent e127eed commit 0786e60
Show file tree
Hide file tree
Showing 3 changed files with 35 additions and 12 deletions.
3 changes: 3 additions & 0 deletions Changes
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
Revision history for perl distribution Convos

5.09 Not Released
- Fix SASL authentication process for Oragono IRCd (and others) #356

5.08 2021-01-05T12:21:00+0900
- Fix "convos version" after install/upgrade #539
- Fix reading notificatins with unicode
Expand Down
30 changes: 23 additions & 7 deletions lib/Convos/Core/Connection/Irc.pm
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,9 @@ sub disconnect_p {
my $p = Mojo::Promise->new;
return $p->resolve({}) unless $self->{stream};

$self->{disconnecting} = 1; # Prevent getting queued
$self->{myinfo}{authenticated} = false;
$self->{myinfo}{capabilities} = {};
$self->{disconnecting} = 1; # Prevent getting queued
$self->_write("QUIT :https://convos.chat", sub { $self->_stream_remove($p) });
return $p;
}
Expand Down Expand Up @@ -86,15 +88,29 @@ sub _connect_args_p {
$self->_periodic_events;
$url->port($params->param('tls') ? 6669 : 6667) unless $url->port;
$params->param(nick => $self->nick) unless $params->param('nick');
$self->{myinfo}{nick} = $params->param('nick');
$self->{myinfo}{authenticated} = false;
$self->{myinfo}{capabilities} = {};
$self->{myinfo}{nick} = $params->param('nick');

return $self->SUPER::_connect_args_p;
}

sub _irc_event_903 {
sub _irc_event_900 { goto &_irc_event_sasl_status } # RPL_LOGGEDIN
sub _irc_event_901 { goto &_irc_event_sasl_status } # RPL_LOGGEDOUT
sub _irc_event_902 { goto &_irc_event_sasl_status } # ERR_NICKLOCKED
sub _irc_event_903 { goto &_irc_event_sasl_status } # RPL_SASLSUCCESS
sub _irc_event_904 { goto &_irc_event_sasl_status } # ERR_SASLFAIL
sub _irc_event_905 { goto &_irc_event_sasl_status } # ERR_SASLTOOLONG
sub _irc_event_906 { goto &_irc_event_sasl_status } # ERR_SASLABORTED
sub _irc_event_907 { goto &_irc_event_sasl_status } # ERR_SASLALREADY
sub _irc_event_908 { goto &_irc_event_cap } # RPL_SASLMECHS

sub _irc_event_sasl_status {
my ($self, $msg) = @_;
$msg->{error} = 1 if $msg->{command} =~ m!90[14567]!;
$self->_irc_event_fallback($msg);
$self->_write("CAP END\r\n");
$self->{myinfo}{authenticated} = $msg->{command} =~ m!90[03]! ? true : false;
$self->emit(state => me => $self->{myinfo});
}

sub _irc_event_cap {
Expand All @@ -107,11 +123,11 @@ sub _irc_event_cap {
push @cap_req, 'sasl' if $self->{myinfo}{capabilities}{sasl} and $self->_sasl_mechanism;
$self->_write(@cap_req ? sprintf "CAP REQ :%s\r\n", join ' ', @cap_req : "CAP END\r\n");
}
elsif ($msg->{raw_line} =~ m!\sACK\s:(.+)!) {
elsif ($msg->{raw_line} =~ m!\sACK\W*(.+)!) {
my ($capabilities, $mech) = ($1, $self->_sasl_mechanism);
$self->_write("AUTHENTICATE $mech\r\n") if $capabilities =~ m!\bsasl\b!;
}
elsif ($msg->{raw_line} =~ m!\sNAC!) {
else {
$self->_write("CAP END\r\n");
}
}
Expand Down Expand Up @@ -189,7 +205,7 @@ sub _irc_event_fallback {
highlight => false,
message => join(' ', @params),
ts => time,
type => $msg->{command} =~ m!err! ? 'error' : 'notice',
type => $msg->{error} || $msg->{command} =~ m!err! ? 'error' : 'notice',
}
);
}
Expand Down
14 changes: 9 additions & 5 deletions t/irc-sasl.t
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,15 @@ $server->client($connection)->server_event_ok('_irc_event_cap')->server_event_ok
->server_event_ok('_irc_event_authenticate')->server_write_ok(":example AUTHENTICATE +\r\n")
->client_event_ok('_irc_event_authenticate')->server_event_ok('_irc_event_authenticate')
->server_write_ok(
"example 900 superwoman superwoman!superwoman\@localhost superwoman :You are now logged in as superwoman\r\n"
)->server_write_ok(['welcome.irc'])->client_event_ok('_irc_event_rpl_welcome')
->process_ok('capabilities handshake');
":server 900 superwoman superwoman!superwoman\@localhost superwoman :You are now logged in as superwoman\r\n"
)->client_event_ok('_irc_event_900')->server_write_ok(['welcome.irc'])
->client_event_ok('_irc_event_rpl_welcome')->process_ok('capabilities handshake');

is_deeply(
$connection->TO_JSON->{me},
{
capabilities => {
authenticated => true,
capabilities => {
'account-notify' => true,
'away-notify' => true,
'chghost' => true,
Expand All @@ -50,6 +51,7 @@ is_deeply(
note 'plain';
$connection->url->query->param(sasl => 'plain');
$connection->disconnect_p->then(sub { $connection->connect_p })->wait;
is $connection->TO_JSON->{me}{authenticated}, false, 'not authenticated after reconnect';

$server->client($connection)->server_event_ok('_irc_event_cap')->server_event_ok('_irc_event_nick')
->server_write_ok(":example CAP * LS * :account-notify away-notify chghost extended-join\r\n")
Expand All @@ -59,8 +61,10 @@ $server->client($connection)->server_event_ok('_irc_event_cap')->server_event_ok
->server_event_ok('_irc_event_authenticate')->server_write_ok(":example AUTHENTICATE +\r\n")
->client_event_ok('_irc_event_authenticate')->server_event_ok('_irc_event_authenticate')
->server_write_ok(
"example 900 superwoman superwoman!superwoman\@localhost superwoman :You are now logged in as superwoman\r\n"
":server 900 superwoman superwoman!superwoman\@localhost superwoman :You are now logged in as superwoman\r\n"
)->server_write_ok(['welcome.irc'])->client_event_ok('_irc_event_rpl_welcome')
->process_ok('capabilities handshake');

is $connection->TO_JSON->{me}{authenticated}, true, 'authenticated';

done_testing;

0 comments on commit 0786e60

Please sign in to comment.