aboutsummaryrefslogtreecommitdiff
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
commit9603456cd6f76554f0be8af1eb23c20872ad8e3d (patch)
treee7acc4edb998dc4ce97ff80dbab92f2b384e5c4c
parentb832a38ca63a4bdc777291709baaad233e25e2a4 (diff)
downloadhaven-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.go50
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},