From b45b7f018d49eeeada7ece3d05382798bbcd55e4 Mon Sep 17 00:00:00 2001 From: Sadie Powell Date: Sun, 21 Feb 2021 01:59:44 +0000 Subject: Add a command to the cgiirc module for encoding/decoding hex idents. --- docs/conf/helpop.conf.example | 23 +++++--- src/modules/m_cgiirc.cpp | 118 +++++++++++++++++++++++++++++------------- 2 files changed, 96 insertions(+), 45 deletions(-) diff --git a/docs/conf/helpop.conf.example b/docs/conf/helpop.conf.example index df886608d..a2a09fa87 100644 --- a/docs/conf/helpop.conf.example +++ b/docs/conf/helpop.conf.example @@ -32,14 +32,14 @@ parameter for this command. + + WriteNotice("*** HEXIP: You can only hex encode an IPv4 address!"); + return CMD_FAILURE; + } + + uint32_t addr = sa.in4.sin_addr.s_addr; + user->WriteNotice(InspIRCd::Format("*** HEXIP: %s encodes to %02x%02x%02x%02x.", + sa.addr().c_str(), (addr & 0xFF), ((addr >> 8) & 0xFF), ((addr >> 16) & 0xFF), + ((addr >> 24) & 0xFF))); + return CMD_SUCCESS; + } + + if (ParseIP(parameters[0], sa)) + { + user->WriteNotice(InspIRCd::Format("*** HEXIP: %s decodes to %s.", + parameters[0].c_str(), sa.addr().c_str())); + return CMD_SUCCESS; + } + + user->WriteNotice(InspIRCd::Format("*** HEXIP: %s is not a valid raw or hex encoded IPv4 address.", + parameters[0].c_str())); + return CMD_FAILURE; + } + + static bool ParseIP(const std::string& in, irc::sockets::sockaddrs& out) + { + const char* ident = NULL; + if (in.length() == 8) + { + // The ident is an IPv4 address encoded in hexadecimal with two characters + // per address segment. + ident = in.c_str(); + } + else if (in.length() == 9 && in[0] == '~') + { + // The same as above but m_ident got to this user before we did. Strip the + // ident prefix and continue as normal. + ident = in.c_str() + 1; + } + else + { + // The user either does not have an IPv4 in their ident or the gateway server + // is also running an identd. In the latter case there isn't really a lot we + // can do so we just assume that the client in question is not connecting via + // an ident gateway. + return false; + } + + // Try to convert the IP address to a string. If this fails then the user + // does not have an IPv4 address in their ident. + errno = 0; + unsigned long address = strtoul(ident, NULL, 16); + if (errno) + return false; + + out.in4.sin_family = AF_INET; + out.in4.sin_addr.s_addr = htonl(address); + return true; + } +}; + class CommandWebIRC : public SplitCommand { public: @@ -236,49 +314,15 @@ class ModuleCgiIRC , public Whois::EventListener { private: + CommandHexIP cmdhexip; CommandWebIRC cmdwebirc; std::vector hosts; - static bool ParseIdent(LocalUser* user, irc::sockets::sockaddrs& out) - { - const char* ident = NULL; - if (user->ident.length() == 8) - { - // The ident is an IPv4 address encoded in hexadecimal with two characters - // per address segment. - ident = user->ident.c_str(); - } - else if (user->ident.length() == 9 && user->ident[0] == '~') - { - // The same as above but m_ident got to this user before we did. Strip the - // ident prefix and continue as normal. - ident = user->ident.c_str() + 1; - } - else - { - // The user either does not have an IPv4 in their ident or the gateway server - // is also running an identd. In the latter case there isn't really a lot we - // can do so we just assume that the client in question is not connecting via - // an ident gateway. - return false; - } - - // Try to convert the IP address to a string. If this fails then the user - // does not have an IPv4 address in their ident. - errno = 0; - unsigned long address = strtoul(ident, NULL, 16); - if (errno) - return false; - - out.in4.sin_family = AF_INET; - out.in4.sin_addr.s_addr = htonl(address); - return true; - } - public: ModuleCgiIRC() : WebIRC::EventListener(this) , Whois::EventListener(this) + , cmdhexip(this) , cmdwebirc(this) { } @@ -392,7 +436,7 @@ class ModuleCgiIRC // We have matched an block! Try to parse the encoded IPv4 address // out of the ident. irc::sockets::sockaddrs address(user->client_sa); - if (!ParseIdent(user, address)) + if (!CommandHexIP::ParseIP(user->ident, address)) return MOD_RES_PASSTHRU; // Store the hostname and IP of the gateway for later use. -- cgit v1.2.3