mirror of
https://github.com/ergochat/ergo.git
synced 2025-05-06 14:47:29 +02:00
WEBIRC: Allow protecting with fingerprint and parse tls
flag
This commit is contained in:
parent
07a16b2502
commit
b0649cb5d3
@ -402,7 +402,7 @@ func LoadConfig(filename string) (config *Config, err error) {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
err = webirc.ProcessPassword()
|
err = webirc.Populate()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("Could not parse WebIRC config: %s", err.Error())
|
return nil, fmt.Errorf("Could not parse WebIRC config: %s", err.Error())
|
||||||
}
|
}
|
||||||
|
@ -6,8 +6,10 @@
|
|||||||
package irc
|
package irc
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/oragono/oragono/irc/passwd"
|
"github.com/oragono/oragono/irc/passwd"
|
||||||
|
|
||||||
@ -18,23 +20,51 @@ import (
|
|||||||
type webircConfig struct {
|
type webircConfig struct {
|
||||||
PasswordString string `yaml:"password"`
|
PasswordString string `yaml:"password"`
|
||||||
Password []byte `yaml:"password-bytes"`
|
Password []byte `yaml:"password-bytes"`
|
||||||
|
Fingerprint string
|
||||||
Hosts []string
|
Hosts []string
|
||||||
}
|
}
|
||||||
|
|
||||||
// ProcessPassword populates our password.
|
// Populate fills out our password or fingerprint.
|
||||||
func (wc *webircConfig) ProcessPassword() error {
|
func (wc *webircConfig) Populate() (err error) {
|
||||||
password, error := passwd.DecodePasswordHash(wc.PasswordString)
|
if wc.Fingerprint == "" && wc.PasswordString == "" {
|
||||||
wc.Password = password
|
return errors.New("Fingerprint or password needs to be specified")
|
||||||
return error
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// WEBIRC password gateway hostname ip
|
if wc.PasswordString != "" {
|
||||||
|
var password []byte
|
||||||
|
password, err = passwd.DecodePasswordHash(wc.PasswordString)
|
||||||
|
wc.Password = password
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// WEBIRC <password> <gateway> <hostname> <ip> [:flag1 flag2=x flag3]
|
||||||
func webircHandler(server *Server, client *Client, msg ircmsg.IrcMessage) bool {
|
func webircHandler(server *Server, client *Client, msg ircmsg.IrcMessage) bool {
|
||||||
// only allow unregistered clients to use this command
|
// only allow unregistered clients to use this command
|
||||||
if client.registered {
|
if client.registered {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// process flags
|
||||||
|
var secure bool
|
||||||
|
if 4 < len(msg.Params) {
|
||||||
|
for _, x := range strings.Split(msg.Params[4], " ") {
|
||||||
|
// split into key=value
|
||||||
|
var key string
|
||||||
|
if strings.Contains(x, "=") {
|
||||||
|
y := strings.SplitN(x, "=", 2)
|
||||||
|
key, _ = y[0], y[1]
|
||||||
|
} else {
|
||||||
|
key = x
|
||||||
|
}
|
||||||
|
|
||||||
|
// only accept "tls" flag if the gateway's connection to us is secure as well
|
||||||
|
if strings.ToLower(key) == "tls" && client.flags[TLS] {
|
||||||
|
secure = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
clientAddress := utils.IPString(client.socket.conn.RemoteAddr())
|
clientAddress := utils.IPString(client.socket.conn.RemoteAddr())
|
||||||
clientHostname := client.hostname
|
clientHostname := client.hostname
|
||||||
server.configurableStateMutex.RLock()
|
server.configurableStateMutex.RLock()
|
||||||
@ -42,13 +72,17 @@ func webircHandler(server *Server, client *Client, msg ircmsg.IrcMessage) bool {
|
|||||||
for _, info := range server.webirc {
|
for _, info := range server.webirc {
|
||||||
for _, address := range info.Hosts {
|
for _, address := range info.Hosts {
|
||||||
if clientHostname == address || clientAddress == address {
|
if clientHostname == address || clientAddress == address {
|
||||||
// confirm password
|
// confirm password and/or fingerprint
|
||||||
givenPassword := msg.Params[0]
|
givenPassword := msg.Params[0]
|
||||||
if passwd.ComparePasswordString(info.Password, givenPassword) == nil {
|
if 0 < len(info.Password) && passwd.ComparePasswordString(info.Password, givenPassword) != nil {
|
||||||
proxiedIP := msg.Params[3]
|
continue
|
||||||
|
|
||||||
return client.ApplyProxiedIP(proxiedIP)
|
|
||||||
}
|
}
|
||||||
|
if 0 < len(info.Fingerprint) && client.certfp != info.Fingerprint {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
proxiedIP := msg.Params[3]
|
||||||
|
return client.ApplyProxiedIP(proxiedIP, secure)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -73,7 +107,8 @@ func proxyHandler(server *Server, client *Client, msg ircmsg.IrcMessage) bool {
|
|||||||
if clientHostname == address || clientAddress == address {
|
if clientHostname == address || clientAddress == address {
|
||||||
proxiedIP := msg.Params[1]
|
proxiedIP := msg.Params[1]
|
||||||
|
|
||||||
return client.ApplyProxiedIP(proxiedIP)
|
// assume PROXY connections are always secure
|
||||||
|
return client.ApplyProxiedIP(proxiedIP, true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
client.Quit("PROXY command is not usable from your address")
|
client.Quit("PROXY command is not usable from your address")
|
||||||
@ -81,7 +116,7 @@ func proxyHandler(server *Server, client *Client, msg ircmsg.IrcMessage) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ApplyProxiedIP applies the given IP to the client.
|
// ApplyProxiedIP applies the given IP to the client.
|
||||||
func (client *Client) ApplyProxiedIP(proxiedIP string) (exiting bool) {
|
func (client *Client) ApplyProxiedIP(proxiedIP string, tls bool) (exiting bool) {
|
||||||
// ensure IP is sane
|
// ensure IP is sane
|
||||||
parsedProxiedIP := net.ParseIP(proxiedIP)
|
parsedProxiedIP := net.ParseIP(proxiedIP)
|
||||||
if parsedProxiedIP == nil {
|
if parsedProxiedIP == nil {
|
||||||
@ -99,5 +134,14 @@ func (client *Client) ApplyProxiedIP(proxiedIP string) (exiting bool) {
|
|||||||
client.proxiedIP = proxiedIP
|
client.proxiedIP = proxiedIP
|
||||||
client.rawHostname = utils.LookupHostname(proxiedIP)
|
client.rawHostname = utils.LookupHostname(proxiedIP)
|
||||||
client.hostname = client.rawHostname
|
client.hostname = client.rawHostname
|
||||||
|
|
||||||
|
// set tls info
|
||||||
|
client.certfp = ""
|
||||||
|
if tls {
|
||||||
|
client.flags[TLS] = true
|
||||||
|
} else {
|
||||||
|
delete(client.flags, TLS)
|
||||||
|
}
|
||||||
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
@ -463,11 +463,16 @@ Views the version of software and the RPL_ISUPPORT tokens for the given server.`
|
|||||||
},
|
},
|
||||||
"webirc": {
|
"webirc": {
|
||||||
oper: true, // not really, but it's restricted anyways
|
oper: true, // not really, but it's restricted anyways
|
||||||
text: `WEBIRC <password> <gateway> <hostname> <ip>
|
text: `WEBIRC <password> <gateway> <hostname> <ip> [:<flags>]
|
||||||
|
|
||||||
Used by web<->IRC gateways and bouncers, the WEBIRC command allows gateways to
|
Used by web<->IRC gateways and bouncers, the WEBIRC command allows gateways to
|
||||||
pass-through the real IP addresses of clients:
|
pass-through the real IP addresses of clients:
|
||||||
ircv3.net/specs/extensions/webirc.html`,
|
ircv3.net/specs/extensions/webirc.html
|
||||||
|
|
||||||
|
<flags> is a list of space-separated strings indicating various details about
|
||||||
|
the connection from the client to the gateway, such as:
|
||||||
|
|
||||||
|
- tls: this flag indicates that the client->gateway connection is secure`,
|
||||||
},
|
},
|
||||||
"who": {
|
"who": {
|
||||||
text: `WHO <name> [o]
|
text: `WHO <name> [o]
|
||||||
|
@ -69,6 +69,9 @@ server:
|
|||||||
webirc:
|
webirc:
|
||||||
# one webirc block -- should correspond to one set of gateways
|
# one webirc block -- should correspond to one set of gateways
|
||||||
-
|
-
|
||||||
|
# tls fingerprint the gateway must connect with to use this webirc block
|
||||||
|
fingerprint: 938dd33f4b76dcaf7ce5eb25c852369cb4b8fb47ba22fc235aa29c6623a5f182
|
||||||
|
|
||||||
# password the gateway uses to connect, made with oragono genpasswd
|
# password the gateway uses to connect, made with oragono genpasswd
|
||||||
password: JDJhJDA0JG9rTTVERlNRa0hpOEZpNkhjZE95SU9Da1BseFdlcWtOTEQxNEFERVlqbEZNTkdhOVlYUkMu
|
password: JDJhJDA0JG9rTTVERlNRa0hpOEZpNkhjZE95SU9Da1BseFdlcWtOTEQxNEFERVlqbEZNTkdhOVlYUkMu
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user