aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Sadie Powell2021-11-24 07:17:50 +0000
committerGravatar Sadie Powell2021-11-24 07:17:50 +0000
commit2ec53e10ee5325df12586c72471efabb07cb9d70 (patch)
tree7f06c35178be0c65048d9f2ff30b73b2bebb36a5
parentDon't allow routing INFO to remote servers. (diff)
parentMake parsing websocket proxy headers more robust. (diff)
Merge branch 'insp3' into master.
-rw-r--r--docs/conf/helpop.conf.example9
-rw-r--r--docs/conf/providers/irccloud.conf.example3
-rw-r--r--include/typedefs.h2
-rw-r--r--include/users.h116
-rw-r--r--src/configreader.cpp1
-rw-r--r--src/modules/m_anticaps.cpp6
-rw-r--r--src/modules/m_banredirect.cpp32
-rw-r--r--src/modules/m_httpd_stats.cpp4
-rw-r--r--src/modules/m_messageflood.cpp6
-rw-r--r--src/modules/m_repeat.cpp7
-rw-r--r--src/modules/m_timedbans.cpp6
-rw-r--r--src/modules/m_websocket.cpp20
-rw-r--r--src/users.cpp39
-rwxr-xr-xtools/mkdescriptions12
-rwxr-xr-xtools/testssl4
15 files changed, 140 insertions, 127 deletions
diff --git a/docs/conf/helpop.conf.example b/docs/conf/helpop.conf.example
index 86a3e6f4e..d133c3bf3 100644
--- a/docs/conf/helpop.conf.example
+++ b/docs/conf/helpop.conf.example
@@ -51,9 +51,12 @@ match against the nickname of the network service and the oper type of
the network service.
">
-<helpop key="sslinfo" title="/SSLINFO <nick>" value="
-Displays information on the TLS connection and certificate of the
-target user.
+<helpop key="sslinfo" title="/SSLINFO <chan>|<nick>" value="
+If a channel is specified then display TLS connection information
+for users in the specified channel.
+
+If a user is specified then display information on the TLS (SSL)
+connection and certificate of the specified user.
">
<helpop key="uninvite" title="/UNINVITE <nick> <channel>" value="
diff --git a/docs/conf/providers/irccloud.conf.example b/docs/conf/providers/irccloud.conf.example
index 92358c8b6..4fbe3da90 100644
--- a/docs/conf/providers/irccloud.conf.example
+++ b/docs/conf/providers/irccloud.conf.example
@@ -13,7 +13,8 @@
<connect name="IRCCloud (IPv4)"
parent="IRCCloud"
- allow="5.254.36.56/29 192.184.8.103 192.184.9.108 192.184.9.112 192.184.10.118 192.184.10.9">
+ allow="5.254.36.56/29 192.184.8.103 192.184.9.108 192.184.9.112 192.184.10.118 192.184.10.9"
+ uniqueusername="yes">
# This is not typically needed as each user has their own IPv6 but if you have
# <cidr:ipv6clone> set to a value lower than 128 you will need to enable it.
diff --git a/include/typedefs.h b/include/typedefs.h
index 1685cef7d..3e70b392d 100644
--- a/include/typedefs.h
+++ b/include/typedefs.h
@@ -49,7 +49,7 @@ class User;
class XLine;
class XLineManager;
class XLineFactory;
-struct ConnectClass;
+class ConnectClass;
class ModResult;
namespace ClientProtocol
diff --git a/include/users.h b/include/users.h
index 6bb72170a..3b7b7e73f 100644
--- a/include/users.h
+++ b/include/users.h
@@ -65,100 +65,84 @@ enum RegistrationState {
REG_ALL = 7 /* REG_NICKUSER plus next bit along */
};
-/** Holds information relevant to &lt;connect allow&gt; and &lt;connect deny&gt; tags in the config file.
- */
-struct CoreExport ConnectClass
+/** Represents \<connect> class tags from the server config */
+class CoreExport ConnectClass : public refcountbase
{
+ public:
+ /** The synthesized (with all inheritance applied) config tag this class was read from. */
std::shared_ptr<ConfigTag> config;
- /** Type of line, either CC_ALLOW or CC_DENY
- */
- char type;
- /** True if this class uses fake lag to manage flood, false if it kills */
- bool fakelag = true;
+ /** The hosts that this user can connect from. */
+ std::vector<std::string> hosts;
- /** Connect class name
- */
+ /** The name of this connect class. */
std::string name;
- /** Max time to register the connection in seconds
- */
- unsigned long registration_timeout = 0;
+ /** If non-empty then the password a user must specify in PASS to be assigned to this class. */
+ std::string password;
- /** Hosts that this connect class can be used by. */
- std::vector<std::string> hosts;
+ /** If non-empty then the hash algorithm that the password field is hashed with. */
+ std::string passwordhash;
- /** Number of seconds between pings for this line
- */
- unsigned long pingtime = 0;
+ /** If non-empty then the server ports which a user has to be connecting on. */
+ insp::flat_set<int> ports;
- /** Maximum size of sendq for users in this class (bytes)
- * Users cannot send commands if they go over this limit
- */
- unsigned long softsendqmax = 0;
+ /** The type of class this. */
+ char type;
- /** Maximum size of sendq for users in this class (bytes)
- * Users are killed if they go over this limit
- */
- unsigned long hardsendqmax = 0;
+ /** Whether fake lag is used by this class. */
+ bool fakelag:1;
- /** Maximum size of recvq for users in this class (bytes)
- */
- unsigned long recvqmax = 0;
+ /** Whether to warn server operators about the limit for this class being reached. */
+ bool maxconnwarn:1;
- /** Seconds worth of penalty before penalty system activates
- */
- unsigned long penaltythreshold = 0;
+ /** Whether the DNS hostnames of users in this class should be resolved. */
+ bool resolvehostnames:1;
- /** Maximum rate of commands (units: millicommands per second) */
- unsigned long commandrate = 0;
+ /** Whether this class is for a shared host where the username (ident) uniquely identifies users. */
+ bool uniqueusername:1;
- /** Local max when connecting by this connection class
- */
- unsigned long maxlocal = 0;
+ /** Maximum rate of commands (units: millicommands per second). */
+ unsigned long commandrate = 0;
- /** Global max when connecting by this connection class
- */
- unsigned long maxglobal = 0;
+ /** The maximum number of bytes that users in this class can have in their send queue before they are disconnected. */
+ unsigned long hardsendqmax = 0;
- /** True if max connections for this class is hit and a warning is wanted
- */
- bool maxconnwarn = true;
+ /** The maximum number of users in this class that can connect to the local server from one host. */
+ unsigned long limit = 0;
- /** Max channels for this class
- */
+ /** The maximum number of channels that users in this class can join. */
unsigned long maxchans = 20;
- /** How many users may be in this connect class before they are refused?
- * (0 = no limit = default)
- */
- unsigned long limit = 0;
+ /** The maximum number of users in this class that can connect to the entire network from one host. */
+ unsigned long maxglobal = 0;
- /** If set to true, no user DNS lookups are to be performed
- */
- bool resolvehostnames = true;
+ /** The maximum number of users that can be in this class on the local server. */
+ unsigned long maxlocal = 0;
- /**
- * If non-empty the server ports which this user has to be using
- */
- insp::flat_set<int> ports;
+ /** The amount of penalty that a user in this class can have before the penalty system activates. */
+ unsigned long penaltythreshold = 0;
- /** If non-empty then the password a user must specify in PASS to be assigned to this class. */
- std::string password;
+ /** The number of seconds between keepalive checks for idle clients in this class. */
+ unsigned long pingtime = 0;
- /** If non-empty then the hash algorithm that the password field is hashed with. */
- std::string passwordhash;
+ /** The maximum number of bytes that users in this class can have in their receive queue before they are disconnected. */
+ unsigned long recvqmax = 0;
- /** Create a new connect class with no settings.
- */
+ /** The number of seconds that connecting users have to register within in this class. */
+ unsigned long registration_timeout = 0;
+
+ /** The maximum number of bytes that users in this class can have in their send queue before their commands stop being processed. */
+ unsigned long softsendqmax = 0;
+
+ /** Creates a new connect class from a config tag. */
ConnectClass(std::shared_ptr<ConfigTag> tag, char type, const std::vector<std::string>& masks);
- /** Create a new connect class with inherited settings.
- */
+ /** Creates a new connect class with a parent from a config tag. */
ConnectClass(std::shared_ptr<ConfigTag> tag, char type, const std::vector<std::string>& masks, std::shared_ptr<ConnectClass> parent);
- /** Update the settings in this block to match the given block */
- void Update(const std::shared_ptr<ConnectClass> newSettings);
+ /** Update the settings in this block to match the given class */
+ void Update(const std::shared_ptr<ConnectClass> klass);
/** Retrieves the name of this connect class. */
const std::string& GetName() const { return name; }
diff --git a/src/configreader.cpp b/src/configreader.cpp
index ed1463147..86329355e 100644
--- a/src/configreader.cpp
+++ b/src/configreader.cpp
@@ -274,6 +274,7 @@ void ServerConfig::CrossCheckConnectBlocks(ServerConfig* current)
me->maxconnwarn = tag->getBool("maxconnwarn", me->maxconnwarn);
me->limit = tag->getUInt("limit", me->limit);
me->resolvehostnames = tag->getBool("resolvehostnames", me->resolvehostnames);
+ me->uniqueusername = tag->getBool("uniqueusername", me->uniqueusername);
me->password = tag->getString("password", me->password);
me->passwordhash = tag->getString("hash", me->passwordhash);
diff --git a/src/modules/m_anticaps.cpp b/src/modules/m_anticaps.cpp
index 619d87158..9972aca32 100644
--- a/src/modules/m_anticaps.cpp
+++ b/src/modules/m_anticaps.cpp
@@ -155,6 +155,7 @@ class ModuleAntiCaps final
: public Module
{
private:
+ ChanModeReference banmode;
CheckExemption::EventProvider exemptionprov;
std::bitset<UCHAR_MAX + 1> uppercase;
std::bitset<UCHAR_MAX + 1> lowercase;
@@ -167,8 +168,8 @@ class ModuleAntiCaps final
banmask.append(user->GetDisplayedHost());
Modes::ChangeList changelist;
- changelist.push_add(ServerInstance->Modes.FindMode('b', MODETYPE_CHANNEL), banmask);
- ServerInstance->Modes.Process(ServerInstance->FakeClient, channel, NULL, changelist);
+ changelist.push_add(*banmode, banmask);
+ ServerInstance->Modes.Process(ServerInstance->FakeClient, channel, nullptr, changelist);
}
void InformUser(Channel* channel, User* user, const std::string& message)
@@ -179,6 +180,7 @@ class ModuleAntiCaps final
public:
ModuleAntiCaps()
: Module(VF_VENDOR | VF_COMMON, "Adds channel mode B (anticaps) which allows channels to block messages which are excessively capitalised.")
+ , banmode(this, "ban")
, exemptionprov(this)
, mode(this)
{
diff --git a/src/modules/m_banredirect.cpp b/src/modules/m_banredirect.cpp
index cfe813b8b..ac86d63c7 100644
--- a/src/modules/m_banredirect.cpp
+++ b/src/modules/m_banredirect.cpp
@@ -52,13 +52,14 @@ typedef std::vector<BanRedirectEntry> BanRedirectList;
class BanRedirect final
: public ModeWatcher
{
- ChanModeReference ban;
public:
- SimpleExtItem<BanRedirectList> extItem;
+ ChanModeReference banmode;
+ SimpleExtItem<BanRedirectList> redirectlist;
+
BanRedirect(Module* parent)
: ModeWatcher(parent, "ban", MODETYPE_CHANNEL)
- , ban(parent, "ban")
- , extItem(parent, "banredirect", ExtensionItem::EXT_CHANNEL)
+ , banmode(parent, "ban")
+ , redirectlist(parent, "banredirect", ExtensionItem::EXT_CHANNEL)
{
}
@@ -85,7 +86,7 @@ class BanRedirect final
if (change.param.find('#') == std::string::npos)
return true;
- ListModeBase* banlm = static_cast<ListModeBase*>(*ban);
+ ListModeBase* banlm = static_cast<ListModeBase*>(*banmode);
unsigned long maxbans = banlm->GetLimit(channel);
ListModeBase::ModeList* list = banlm->GetList(channel);
if (list && change.adding && maxbans <= list->size())
@@ -184,11 +185,11 @@ class BanRedirect final
if (change.adding)
{
/* It's a properly valid redirecting ban, and we're adding it */
- redirects = extItem.Get(channel);
+ redirects = redirectlist.Get(channel);
if (!redirects)
{
redirects = new BanRedirectList;
- extItem.Set(channel, redirects);
+ redirectlist.Set(channel, redirects);
}
else
{
@@ -215,7 +216,7 @@ class BanRedirect final
else
{
/* Removing a ban, if there's no extensible there are no redirecting bans and we're fine. */
- redirects = extItem.Get(channel);
+ redirects = redirectlist.Get(channel);
if (redirects)
{
/* But there were, so we need to remove the matching one if there is one */
@@ -228,7 +229,7 @@ class BanRedirect final
if(redirects->empty())
{
- extItem.Unset(channel);
+ redirectlist.Unset(channel);
}
break;
@@ -250,7 +251,7 @@ class ModuleBanRedirect final
: public Module
{
private:
- BanRedirect re;
+ BanRedirect banwatcher;
bool nofollow = false;
ChanModeReference limitmode;
ChanModeReference redirectmode;
@@ -258,7 +259,7 @@ class ModuleBanRedirect final
public:
ModuleBanRedirect()
: Module(VF_VENDOR | VF_COMMON, "Allows specifying a channel to redirect a banned user to in the ban mask.")
- , re(this)
+ , banwatcher(this)
, limitmode(this, "limit")
, redirectmode(this, "redirect")
{
@@ -269,18 +270,17 @@ class ModuleBanRedirect final
if (type == ExtensionItem::EXT_CHANNEL)
{
Channel* chan = static_cast<Channel*>(item);
- BanRedirectList* redirects = re.extItem.Get(chan);
+ BanRedirectList* redirects = banwatcher.redirectlist.Get(chan);
if(redirects)
{
- ModeHandler* ban = ServerInstance->Modes.FindMode('b', MODETYPE_CHANNEL);
Modes::ChangeList changelist;
for (auto& redirect : *redirects)
- changelist.push_remove(ban, redirect.targetchan.insert(0, redirect.banmask));
+ changelist.push_remove(*banwatcher.banmode, redirect.targetchan.insert(0, redirect.banmask));
for (const auto& redirect : *redirects)
- changelist.push_add(ban, redirect.banmask);
+ changelist.push_add(*banwatcher.banmode, redirect.banmask);
ServerInstance->Modes.Process(ServerInstance->FakeClient, chan, NULL, changelist, ModeParser::MODE_LOCALONLY);
}
@@ -291,7 +291,7 @@ class ModuleBanRedirect final
{
if (!override && chan)
{
- BanRedirectList* redirects = re.extItem.Get(chan);
+ BanRedirectList* redirects = banwatcher.redirectlist.Get(chan);
if (redirects)
{
diff --git a/src/modules/m_httpd_stats.cpp b/src/modules/m_httpd_stats.cpp
index bcbcfba81..5d35d6fdf 100644
--- a/src/modules/m_httpd_stats.cpp
+++ b/src/modules/m_httpd_stats.cpp
@@ -210,7 +210,7 @@ namespace Stats
{
data << "<user>";
data << "<nickname>" << u->nick << "</nickname><uuid>" << u->uuid << "</uuid><realhost>"
- << u->GetRealHost() << "</realhost><displayhost>" << u->GetDisplayedHost() << "</displayhost><realname>"
+ << Sanitize(u->GetRealHost()) << "</realhost><displayhost>" << Sanitize(u->GetDisplayedHost()) << "</displayhost><realname>"
<< Sanitize(u->GetRealName()) << "</realname><server>" << u->server->GetName() << "</server><signon>"
<< u->signon << "</signon><age>" << u->age << "</age>";
@@ -229,7 +229,7 @@ namespace Stats
<< lu->GetClass()->GetName() << "</connectclass><lastmsg>"
<< lu->idle_lastmsg << "</lastmsg>";
- data << "<ipaddress>" << u->GetIPString() << "</ipaddress>";
+ data << "<ipaddress>" << Sanitize(u->GetIPString()) << "</ipaddress>";
DumpMeta(data, u);
diff --git a/src/modules/m_messageflood.cpp b/src/modules/m_messageflood.cpp
index cab7a9879..4149e9dc8 100644
--- a/src/modules/m_messageflood.cpp
+++ b/src/modules/m_messageflood.cpp
@@ -115,6 +115,7 @@ class ModuleMsgFlood final
, public CTCTags::EventListener
{
private:
+ ChanModeReference banmode;
CheckExemption::EventProvider exemptionprov;
MsgFlood mf;
double notice;
@@ -125,6 +126,7 @@ private:
ModuleMsgFlood()
: Module(VF_VENDOR, "Adds channel mode f (flood) which helps protect against spammers which mass-message channels.")
, CTCTags::EventListener(this)
+ , banmode(this, "ban")
, exemptionprov(this)
, mf(this)
{
@@ -161,8 +163,8 @@ private:
if (f->ban)
{
Modes::ChangeList changelist;
- changelist.push_add(ServerInstance->Modes.FindMode('b', MODETYPE_CHANNEL), "*!*@" + user->GetDisplayedHost());
- ServerInstance->Modes.Process(ServerInstance->FakeClient, dest, NULL, changelist);
+ changelist.push_add(*banmode, "*!*@" + user->GetDisplayedHost());
+ ServerInstance->Modes.Process(ServerInstance->FakeClient, dest, nullptr, changelist);
}
const std::string kickMessage = "Channel flood triggered (trigger is " + ConvToStr(f->lines) +
diff --git a/src/modules/m_repeat.cpp b/src/modules/m_repeat.cpp
index f88f2552b..8b47d5c4b 100644
--- a/src/modules/m_repeat.cpp
+++ b/src/modules/m_repeat.cpp
@@ -356,12 +356,15 @@ class RepeatMode final
class RepeatModule final
: public Module
{
+ private:
+ ChanModeReference banmode;
CheckExemption::EventProvider exemptionprov;
RepeatMode rm;
public:
RepeatModule()
: Module(VF_VENDOR | VF_COMMON, "Adds channel mode E (repeat) which helps protect against spammers which spam the same message repeatedly.")
+ , banmode(this, "ban")
, exemptionprov(this)
, rm(this)
{
@@ -404,8 +407,8 @@ class RepeatModule final
if (settings->Action == ChannelSettings::ACT_BAN)
{
Modes::ChangeList changelist;
- changelist.push_add(ServerInstance->Modes.FindMode('b', MODETYPE_CHANNEL), "*!*@" + user->GetDisplayedHost());
- ServerInstance->Modes.Process(ServerInstance->FakeClient, chan, NULL, changelist);
+ changelist.push_add(*banmode, "*!*@" + user->GetDisplayedHost());
+ ServerInstance->Modes.Process(ServerInstance->FakeClient, chan, nullptr, changelist);
}
memb->chan->KickUser(ServerInstance->FakeClient, user, rm.GetKickMessage());
diff --git a/src/modules/m_timedbans.cpp b/src/modules/m_timedbans.cpp
index e6a2712d3..65db00b88 100644
--- a/src/modules/m_timedbans.cpp
+++ b/src/modules/m_timedbans.cpp
@@ -215,12 +215,14 @@ class ModuleTimedBans final
: public Module
{
private:
+ ChanModeReference banmode;
CommandTban cmd;
BanWatcher banwatcher;
public:
ModuleTimedBans()
: Module(VF_VENDOR | VF_COMMON, "Adds the /TBAN command which allows channel operators to add bans which will be expired after the specified period.")
+ , banmode(this, "ban")
, cmd(this)
, banwatcher(this)
{
@@ -261,8 +263,8 @@ class ModuleTimedBans final
}
Modes::ChangeList setban;
- setban.push_remove(ServerInstance->Modes.FindMode('b', MODETYPE_CHANNEL), timedban.mask);
- ServerInstance->Modes.Process(ServerInstance->FakeClient, timedban.chan, NULL, setban);
+ setban.push_remove(*banmode, timedban.mask);
+ ServerInstance->Modes.Process(ServerInstance->FakeClient, timedban.chan, nullptr, setban);
}
}
diff --git a/src/modules/m_websocket.cpp b/src/modules/m_websocket.cpp
index d682d77df..5d7b95c36 100644
--- a/src/modules/m_websocket.cpp
+++ b/src/modules/m_websocket.cpp
@@ -386,15 +386,23 @@ class WebSocketHook final
irc::sockets::sockaddrs realsa(luser->client_sa);
HTTPHeaderFinder proxyheader;
- if (proxyheader.Find(recvq, "X-Real-IP:", 10, reqend)
- && irc::sockets::aptosa(proxyheader.ExtractValue(recvq), realsa.port(), realsa))
+ if (proxyheader.Find(recvq, "X-Real-IP:", 10, reqend) || proxyheader.Find(recvq, "X-Forwarded-For:", 16, reqend))
{
- // Nothing to do here.
+ // Attempt to parse the proxy HTTP header.
+ irc::sockets::aptosa(proxyheader.ExtractValue(recvq), realsa.port(), realsa);
}
- else if (proxyheader.Find(recvq, "X-Forwarded-For:", 16, reqend)
- && irc::sockets::aptosa(proxyheader.ExtractValue(recvq), realsa.port(), realsa))
+ else
{
- // Nothing to do here.
+ // The proxy header is missing.
+ FailHandshake(sock, "HTTP/1.1 400 Bad Request\r\nConnection: close\r\n\r\n", "WebSocket: Received a proxied HTTP request that did not send a real IP address header");
+ return -1;
+ }
+
+ if (realsa.family() == AF_UNSPEC)
+ {
+ // The proxy header value contains a malformed value.
+ FailHandshake(sock, "HTTP/1.1 400 Bad Request\r\nConnection: close\r\n\r\n", "WebSocket: Received a proxied HTTP request that sent a malformed real IP address");
+ return -1;
}
for (const auto& proxyrange : config.proxyranges)
diff --git a/src/users.cpp b/src/users.cpp
index f96c95a9d..7d91de2b3 100644
--- a/src/users.cpp
+++ b/src/users.cpp
@@ -1218,9 +1218,13 @@ const std::string& FakeUser::GetFullRealHost()
ConnectClass::ConnectClass(std::shared_ptr<ConfigTag> tag, char t, const std::vector<std::string>& masks)
: config(tag)
- , type(t)
- , name("unnamed")
, hosts(masks)
+ , name("unnamed")
+ , type(t)
+ , fakelag(true)
+ , maxconnwarn(true)
+ , resolvehostnames(true)
+ , uniqueusername(false)
{
}
@@ -1255,25 +1259,26 @@ ConnectClass::ConnectClass(std::shared_ptr<ConfigTag> tag, char t, const std::ve
void ConnectClass::Update(const std::shared_ptr<ConnectClass> src)
{
+ commandrate = src->commandrate;
config = src->config;
- type = src->type;
fakelag = src->fakelag;
- name = src->name;
- registration_timeout = src->registration_timeout;
- hosts = src->hosts;
- pingtime = src->pingtime;
- softsendqmax = src->softsendqmax;
hardsendqmax = src->hardsendqmax;
- recvqmax = src->recvqmax;
- penaltythreshold = src->penaltythreshold;
- commandrate = src->commandrate;
- maxlocal = src->maxlocal;
- maxglobal = src->maxglobal;
- maxconnwarn = src->maxconnwarn;
- maxchans = src->maxchans;
+ hosts = src->hosts;
limit = src->limit;
- resolvehostnames = src->resolvehostnames;
- ports = src->ports;
+ maxchans = src->maxchans;
+ maxconnwarn = src->maxconnwarn;
+ maxglobal = src->maxglobal;
+ maxlocal = src->maxlocal;
+ name = src->name;
password = src->password;
passwordhash = src->passwordhash;
+ penaltythreshold = src->penaltythreshold;
+ pingtime = src->pingtime;
+ ports = src->ports;
+ recvqmax = src->recvqmax;
+ registration_timeout = src->registration_timeout;
+ resolvehostnames = src->resolvehostnames;
+ softsendqmax = src->softsendqmax;
+ type = src->type;
+ uniqueusername = src->uniqueusername;
}
diff --git a/tools/mkdescriptions b/tools/mkdescriptions
index 83e2f0bda..c8ed9bdb4 100755
--- a/tools/mkdescriptions
+++ b/tools/mkdescriptions
@@ -22,14 +22,14 @@ use v5.26.0;
use strict;
use warnings FATAL => qw(all);
+use CommonMark ();
use File::Basename qw(basename dirname);
use File::Spec::Functions qw(catdir catfile rel2abs);
use FindBin qw($RealDir);
use HTML::FormatText ();
use HTML::TreeBuilder ();
-use Text::Markdown::Hoedown qw(HOEDOWN_HTML_SKIP_HTML markdown);
use Text::Sentence qw(split_sentences);
-use YAML::Tiny ();
+use YAML qw(LoadFile);
use lib dirname $RealDir;
use make::common;
@@ -50,11 +50,11 @@ for my $module (<$root/src/modules/extra/m_*.cpp>, <$root/src/modules/m_*.cpp>,
my $docfile = catfile $docdir, "$1.yml";
print_error "unable to find the module documentation at $docfile!" unless -f $docfile;
- my $docdata = YAML::Tiny->read($docfile) or print_error "unable to read from $docfile: $!";
- print_error "unable to find the module description in $docfile!" unless $docdata->[0]->{description};
+ my ($docdata, undef, undef) = LoadFile($docfile) or print_error "unable to read from $docfile: $!";
+ print_error "unable to find the module description in $docfile!" unless $docdata->{description};
- my $docraw = $docdata->[0]->{description} =~ s/^(?:This module )//r;
- my $docrendered = markdown ucfirst $docraw, extensions => HOEDOWN_HTML_SKIP_HTML;
+ my $docraw = $docdata->{description} =~ s/^(?:This module )//r;
+ my $docrendered = CommonMark->markdown_to_html(ucfirst $docraw);
my $docplain = HTML::FormatText->new(leftmargin => 0, rightmargin => ~0)->format(HTML::TreeBuilder->new->parse($docrendered));
my $description = (split_sentences $docplain)[0] =~ s/"/\\"/gr;
diff --git a/tools/testssl b/tools/testssl
index 8de70c906..947553e98 100755
--- a/tools/testssl
+++ b/tools/testssl
@@ -139,8 +139,10 @@ ${\CC_RED}no${\CC_RESET}
It appears that something is wrong with your server. Make sure that:
- - You are not using an old version of GnuTLS, mbedTLS, or OpenSSL which only
+ * You are not using an old version of GnuTLS, mbedTLS, or OpenSSL which only
supports deprecated algorithms like SSLv3.
+ * If you are using a self-signed certificate (not recommended) that you passed
+ the `selfsigned` argument to this script.
The error provided by the TLS library was: