summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPřemysl Eric Janouch <p@janouch.name>2022-03-15 18:58:27 +0100
committerPřemysl Eric Janouch <p@janouch.name>2022-03-15 19:57:31 +0100
commita51c247d69b2b765ad59f9a79093e25f74ebcc83 (patch)
tree917edf75632ae6b091e8ef6580cd076e96d4debc
parentf26e6361f333c7747d39c4d8f494fa44d5e2fd2f (diff)
downloadxK-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.
-rw-r--r--xS/main.go50
1 files changed, 45 insertions, 5 deletions
diff --git a/xS/main.go b/xS/main.go
index fd8d8fb..43a04f2 100644
--- a/xS/main.go
+++ b/xS/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},