From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on dcvr.yhbt.net X-Spam-Level: X-Spam-ASN: X-Spam-Status: No, score=-4.0 required=3.0 tests=ALL_TRUSTED,BAYES_00 shortcircuit=no autolearn=ham autolearn_force=no version=3.4.2 Received: from localhost (dcvr.yhbt.net [127.0.0.1]) by dcvr.yhbt.net (Postfix) with ESMTP id CD8F21F4B7 for ; Sun, 30 Jun 2019 22:36:35 +0000 (UTC) From: Eric Wong To: meta@public-inbox.org Subject: [PATCH 2/2] nntp: add support for CAPABILITIES command Date: Sun, 30 Jun 2019 22:36:35 +0000 Message-Id: <20190630223635.4687-3-e@80x24.org> In-Reply-To: <20190630223635.4687-1-e@80x24.org> References: <20190630223635.4687-1-e@80x24.org> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit List-Id: Some clients may rely on this for STARTTLS support. --- lib/PublicInbox/NNTP.pm | 19 +++++++++++++++++++ t/nntpd-tls.t | 18 ++++++++++++++++++ t/nntpd.t | 5 +++++ 3 files changed, 42 insertions(+) diff --git a/lib/PublicInbox/NNTP.pm b/lib/PublicInbox/NNTP.pm index 57a67a50..d106e315 100644 --- a/lib/PublicInbox/NNTP.pm +++ b/lib/PublicInbox/NNTP.pm @@ -31,6 +31,14 @@ my @OVERVIEW = qw(Subject From Date Message-ID References Xref); my $OVERVIEW_FMT = join(":\r\n", @OVERVIEW, qw(Bytes Lines)) . ":\r\n"; my $LIST_HEADERS = join("\r\n", @OVERVIEW, qw(:bytes :lines Xref To Cc)) . "\r\n"; +my $CAPABILITIES = <<""; +101 Capability list:\r +VERSION 2\r +READER\r +NEWNEWS\r +LIST ACTIVE ACTIVE.TIMES NEWSGROUPS OVERVIEW.FMT\r +HDR\r +OVER\r my $EXPMAP; # fd -> [ idle_time, $self ] my $expt; @@ -121,6 +129,17 @@ sub process_line ($$) { res($self, $res); } +# The keyword argument is not used (rfc3977 5.2.2) +sub cmd_capabilities ($;$) { + my ($self, undef) = @_; + my $res = $CAPABILITIES; + if (ref($self->{sock}) ne 'IO::Socket::SSL' && + $self->{nntpd}->{accept_tls}) { + $res .= "STARTTLS\r\n"; + } + $res .= '.'; +} + sub cmd_mode ($$) { my ($self, $arg) = @_; $arg = uc $arg; diff --git a/t/nntpd-tls.t b/t/nntpd-tls.t index 82b63f3e..4cf53daa 100644 --- a/t/nntpd-tls.t +++ b/t/nntpd-tls.t @@ -128,6 +128,8 @@ for my $args ( my $c = Net::NNTP->new($nntps_addr, %o, SSL => 1); my $list = $c->list; is_deeply($list, $expect, 'NNTPS LIST works'); + unlike(get_capa($c), qr/\bSTARTTLS\r\n/, + 'STARTTLS not advertised for NNTPS'); is($c->command('QUIT')->response(), Net::Cmd::CMD_OK(), 'QUIT works'); is(0, sysread($c, my $buf, 1), 'got EOF after QUIT'); @@ -139,6 +141,8 @@ for my $args ( is($c->code, 382, 'got 382 for STARTTLS'); $list = $c->list; is_deeply($list, $expect, 'LIST works after STARTTLS'); + unlike(get_capa($c), qr/\bSTARTTLS\r\n/, + 'STARTTLS not advertised after STARTTLS'); # Net::NNTP won't let us do dumb things, but we need to test # dumb things, so use Net::Cmd directly: @@ -149,6 +153,7 @@ for my $args ( # STARTTLS with bad hostname $o{SSL_hostname} = $o{SSL_verifycn_name} = 'server.invalid'; $c = Net::NNTP->new($starttls_addr, %o); + like(get_capa($c), qr/\bSTARTTLS\r\n/, 'STARTTLS advertised'); $list = $c->list; is_deeply($list, $expect, 'plain LIST works again'); ok(!$c->starttls, 'STARTTLS fails with bad hostname'); @@ -217,4 +222,17 @@ for my $args ( } } done_testing(); + +sub get_capa { + my ($sock) = @_; + syswrite($sock, "CAPABILITIES\r\n"); + my $capa = ''; + do { + my $r = sysread($sock, $capa, 8192, length($capa)); + die "unexpected: $!" unless defined($r); + die 'unexpected EOF' if $r == 0; + } until $capa =~ /\.\r\n\z/; + $capa; +} + 1; diff --git a/t/nntpd.t b/t/nntpd.t index 0e59de07..1c5ae8d7 100644 --- a/t/nntpd.t +++ b/t/nntpd.t @@ -143,6 +143,11 @@ EOF 'got greeting'); $s->autoflush(1); + syswrite($s, "CAPABILITIES\r\n"); + $buf = read_til_dot($s); + like($buf, qr/\r\nVERSION 2\r\n/s, 'CAPABILITIES works'); + unlike($buf, qr/STARTTLS/s, 'STARTTLS not advertised'); + syswrite($s, "NEWGROUPS 19990424 000000 GMT\r\n"); $buf = read_til_dot($s); like($buf, qr/\A231 list of /, 'newgroups OK'); -- EW