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 | a51c247d69b2b765ad59f9a79093e25f74ebcc83 (patch) | |
tree | 917edf75632ae6b091e8ef6580cd076e96d4debc /xS | |
parent | f26e6361f333c7747d39c4d8f494fa44d5e2fd2f (diff) | |
download | xK-a51c247d69b2b765ad59f9a79093e25f74ebcc83.tar.gz xK-a51c247d69b2b765ad59f9a79093e25f74ebcc83.tar.xz xK-a51c247d69b2b765ad59f9a79093e25f74ebcc83.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.
Diffstat (limited to 'xS')
-rw-r--r-- | xS/main.go | 50 |
1 files changed, 45 insertions, 5 deletions
@@ -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}, |