diff options
author | Přemysl Eric Janouch <p@janouch.name> | 2022-03-15 18:58:27 +0100 |
---|---|---|
committer | Přemysl Eric Janouch <p@janouch.name> | 2022-03-15 19:57:31 +0100 |
commit | 9603456cd6f76554f0be8af1eb23c20872ad8e3d (patch) | |
tree | e7acc4edb998dc4ce97ff80dbab92f2b384e5c4c | |
parent | b832a38ca63a4bdc777291709baaad233e25e2a4 (diff) | |
download | haven-9603456cd6f76554f0be8af1eb23c20872ad8e3d.tar.gz haven-9603456cd6f76554f0be8af1eb23c20872ad8e3d.tar.xz haven-9603456cd6f76554f0be8af1eb23c20872ad8e3d.zip |
hid: add WebIRC support
Such clients can only be identified through STATS L.
It's a bit weird to abuse the "port" field this way,
but right now, it serves its purpose.
-rw-r--r-- | hid/main.go | 50 |
1 files changed, 45 insertions, 5 deletions
diff --git a/hid/main.go b/hid/main.go index fd8d8fb..43a04f2 100644 --- a/hid/main.go +++ b/hid/main.go @@ -1,5 +1,5 @@ // -// Copyright (c) 2014 - 2018, Přemysl Eric Janouch <p@janouch.name> +// Copyright (c) 2014 - 2022, Přemysl Eric Janouch <p@janouch.name> // // Permission to use, copy, modify, and/or distribute this software for any // purpose with or without fee is hereby granted. @@ -414,6 +414,7 @@ var configTable = []simpleConfigItem{ {"bind", ":6667", "Bind addresses of the IRC server"}, {"tls_cert", "", "Server TLS certificate (PEM)"}, {"tls_key", "", "Server TLS private key (PEM)"}, + {"webirc_password", "", "Password for WebIRC"}, {"operators", "", "IRCop TLS certificate SHA-256 fingerprints"}, @@ -1437,6 +1438,44 @@ var ircCapHandlers = map[string]func(*client, *ircCapArgs){ // XXX: Maybe these also deserve to be methods for client? They operate on // global state, though. +func ircParseWEBIRCOptions(options string, out map[string]string) { + for _, option := range strings.Split(options, " ") { + if equal := strings.IndexByte(option, '='); equal < 0 { + out[option] = "" + } else { + out[option[:equal]] = ircUnescapeMessageTag(option[equal+1:]) + } + } +} + +func ircHandleWEBIRC(msg *message, c *client) { + if len(msg.params) < 4 { + c.sendReply(ERR_NEEDMOREPARAMS, msg.command) + return + } + + password, gateway, hostname := msg.params[0], msg.params[1], msg.params[2] + if config["webirc_password"] != password { + c.closeLink("Invalid WebIRC password") + return + } + + options := make(map[string]string) + if len(msg.params) >= 5 { + ircParseWEBIRCOptions(msg.params[4], options) + } + + c.hostname = hostname + c.port = "WebIRC-" + gateway + c.address = net.JoinHostPort(hostname, c.port) + + // Note that this overrides the gateway's certificate, conditionally. + fp, _ := options["certfp-sha-256"] + if _, secure := options["secure"]; secure && ircIsValidFingerprint(fp) { + c.tlsCertFingerprint = strings.ToLower(fp) + } +} + func ircHandleCAP(msg *message, c *client) { if len(msg.params) < 1 { c.sendReply(ERR_NEEDMOREPARAMS, msg.command) @@ -2908,10 +2947,11 @@ func ircHandleDIE(msg *message, c *client) { // TODO: Add a minimal parameter count? // TODO: Add a field for oper-only commands? Use flags? var ircHandlers = map[string]*ircCommand{ - "CAP": {false, ircHandleCAP, 0, 0}, - "PASS": {false, ircHandlePASS, 0, 0}, - "NICK": {false, ircHandleNICK, 0, 0}, - "USER": {false, ircHandleUSER, 0, 0}, + "WEBIRC": {false, ircHandleWEBIRC, 0, 0}, + "CAP": {false, ircHandleCAP, 0, 0}, + "PASS": {false, ircHandlePASS, 0, 0}, + "NICK": {false, ircHandleNICK, 0, 0}, + "USER": {false, ircHandleUSER, 0, 0}, "USERHOST": {true, ircHandleUSERHOST, 0, 0}, "LUSERS": {true, ircHandleLUSERS, 0, 0}, |