summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/inspircd.h6
-rw-r--r--src/helperfuncs.cpp59
2 files changed, 65 insertions, 0 deletions
diff --git a/include/inspircd.h b/include/inspircd.h
index a7f19f483..447fb8441 100644
--- a/include/inspircd.h
+++ b/include/inspircd.h
@@ -381,6 +381,12 @@ class CoreExport InspIRCd
*/
static bool DefaultIsChannel(const std::string& channel);
+ /** Determines whether a hostname is valid according to RFC 5891 rules.
+ * @param host The hostname to validate.
+ * @return True if the hostname is valid; otherwise, false.
+ */
+ static bool IsHost(const std::string& host);
+
/** Return true if str looks like a server ID
* @param sid string to check against
*/
diff --git a/src/helperfuncs.cpp b/src/helperfuncs.cpp
index 111e1363f..8ced78ae8 100644
--- a/src/helperfuncs.cpp
+++ b/src/helperfuncs.cpp
@@ -267,6 +267,65 @@ bool InspIRCd::DefaultIsIdent(const std::string& n)
return true;
}
+bool InspIRCd::IsHost(const std::string& host)
+{
+ // Hostnames must be non-empty and shorter than the maximum hostname length.
+ if (host.empty() || host.length() > ServerInstance->Config->Limits.MaxHost)
+ return false;
+
+ unsigned int numdashes = 0;
+ unsigned int numdots = 0;
+ bool seendot = false;
+ const std::string::const_iterator hostend = host.end() - 1;
+ for (std::string::const_iterator iter = host.begin(); iter != host.end(); ++iter)
+ {
+ unsigned char chr = static_cast<unsigned char>(*iter);
+
+ // If the current character is a label separator.
+ if (chr == '.')
+ {
+ numdots++;
+
+ // Consecutive separators are not allowed and dashes can not exist at the start or end
+ // of labels and separators must only exist between labels.
+ if (seendot || numdashes || iter == host.begin() || iter == hostend)
+ return false;
+
+ seendot = true;
+ continue;
+ }
+
+ // If this point is reached then the character is not a dot.
+ seendot = false;
+
+ // If the current character is a dash.
+ if (chr == '-')
+ {
+ // Consecutive separators are not allowed and dashes can not exist at the start or end
+ // of labels and separators must only exist between labels.
+ if (seendot || numdashes >= 2 || iter == host.begin() || iter == hostend)
+ return false;
+
+ numdashes += 1;
+ continue;
+ }
+
+ // If this point is reached then the character is not a dash.
+ numdashes = 0;
+
+ // Alphanumeric characters are allowed at any position.
+ if ((chr >= '0' && chr <= '9') || (chr >= 'A' && chr <= 'Z') || (chr >= 'a' && chr <= 'z'))
+ continue;
+
+ return false;
+ }
+
+ // Whilst simple hostnames (e.g. localhost) are valid we do not allow the server to use
+ // them to prevent issues with clients that differentiate between short client and server
+ // prefixes by checking whether the nickname contains a dot.
+ return numdots;
+}
+
bool InspIRCd::IsSID(const std::string &str)
{
/* Returns true if the string given is exactly 3 characters long,