3
0
mirror of https://github.com/ergochat/ergo.git synced 2024-11-15 00:19:29 +01:00

Merge pull request #2146 from slingamn/webirc.1

add a config switch to accept hostnames from WEBIRC
This commit is contained in:
Shivaram Lingamneni 2024-04-14 20:46:01 +02:00 committed by GitHub
commit 15d686c593
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 62 additions and 36 deletions

View File

@ -218,6 +218,10 @@ server:
# - "192.168.1.1" # - "192.168.1.1"
# - "192.168.10.1/24" # - "192.168.10.1/24"
# whether to accept the hostname parameter on the WEBIRC line as the IRC hostname
# (the default/recommended Ergo configuration will use cloaks instead)
accept-hostname: false
# maximum length of clients' sendQ in bytes # maximum length of clients' sendQ in bytes
# this should be big enough to hold bursts of channel/direct messages # this should be big enough to hold bursts of channel/direct messages
max-sendq: 96k max-sendq: 96k

View File

@ -160,13 +160,14 @@ type Session struct {
idleTimer *time.Timer idleTimer *time.Timer
pingSent bool // we sent PING to a putatively idle connection and we're waiting for PONG pingSent bool // we sent PING to a putatively idle connection and we're waiting for PONG
sessionID int64 sessionID int64
socket *Socket socket *Socket
realIP net.IP realIP net.IP
proxiedIP net.IP proxiedIP net.IP
rawHostname string rawHostname string
isTor bool hostnameFinalized bool
hideSTS bool isTor bool
hideSTS bool
fakelag Fakelag fakelag Fakelag
deferredFakelagCount int deferredFakelagCount int
@ -488,12 +489,21 @@ func (client *Client) resizeHistory(config *Config) {
} }
} }
// resolve an IP to an IRC-ready hostname, using reverse DNS, forward-confirming if necessary, // once we have the final IP address (from the connection itself or from proxy data),
// and sending appropriate notices to the client // compute the various possibilities for the hostname:
func (client *Client) lookupHostname(session *Session, overwrite bool) { // * In the default/recommended configuration, via the cloak algorithm
// * If hostname lookup is enabled, via (forward-confirmed) reverse DNS
// * If WEBIRC was used, possibly via the hostname passed on the WEBIRC line
func (client *Client) finalizeHostname(session *Session) {
// only allow this once, since registration can fail (e.g. if the nickname is in use)
if session.hostnameFinalized {
return
}
session.hostnameFinalized = true
if session.isTor { if session.isTor {
return return
} // else: even if cloaking is enabled, look up the real hostname to show to operators }
config := client.server.Config() config := client.server.Config()
ip := session.realIP ip := session.realIP
@ -501,30 +511,27 @@ func (client *Client) lookupHostname(session *Session, overwrite bool) {
ip = session.proxiedIP ip = session.proxiedIP
} }
var hostname string // even if cloaking is enabled, we may want to look up the real hostname to show to operators:
lookupSuccessful := false if session.rawHostname == "" {
if config.Server.lookupHostnames { var hostname string
session.Notice("*** Looking up your hostname...") lookupSuccessful := false
hostname, lookupSuccessful = utils.LookupHostname(ip, config.Server.ForwardConfirmHostnames) if config.Server.lookupHostnames {
if lookupSuccessful { session.Notice("*** Looking up your hostname...")
session.Notice("*** Found your hostname") hostname, lookupSuccessful = utils.LookupHostname(ip, config.Server.ForwardConfirmHostnames)
if lookupSuccessful {
session.Notice("*** Found your hostname")
} else {
session.Notice("*** Couldn't look up your hostname")
}
} else { } else {
session.Notice("*** Couldn't look up your hostname") hostname = utils.IPStringToHostname(ip.String())
} }
} else { session.rawHostname = hostname
hostname = utils.IPStringToHostname(ip.String())
} }
session.rawHostname = hostname // these will be discarded if this is actually a reattach:
cloakedHostname := config.Server.Cloaks.ComputeCloak(ip) client.rawHostname = session.rawHostname
client.stateMutex.Lock() client.cloakedHostname = config.Server.Cloaks.ComputeCloak(ip)
defer client.stateMutex.Unlock()
// update the hostname if this is a new connection, but not if it's a reattach
if overwrite || client.rawHostname == "" {
client.rawHostname = hostname
client.cloakedHostname = cloakedHostname
client.updateNickMaskNoMutex()
}
} }
func (client *Client) doIdentLookup(conn net.Conn) { func (client *Client) doIdentLookup(conn net.Conn) {

View File

@ -32,6 +32,7 @@ type webircConfig struct {
Fingerprint *string // legacy name for certfp, #1050 Fingerprint *string // legacy name for certfp, #1050
Certfp string Certfp string
Hosts []string Hosts []string
AcceptHostname bool `yaml:"accept-hostname"`
allowedNets []net.IPNet allowedNets []net.IPNet
} }

View File

@ -3512,8 +3512,9 @@ func webircHandler(server *Server, client *Client, msg ircmsg.Message, rb *Respo
} }
} }
config := server.Config()
givenPassword := []byte(msg.Params[0]) givenPassword := []byte(msg.Params[0])
for _, info := range server.Config().Server.WebIRC { for _, info := range config.Server.WebIRC {
if utils.IPInNets(client.realIP, info.allowedNets) { if utils.IPInNets(client.realIP, info.allowedNets) {
// confirm password and/or fingerprint // confirm password and/or fingerprint
if 0 < len(info.Password) && bcrypt.CompareHashAndPassword(info.Password, givenPassword) != nil { if 0 < len(info.Password) && bcrypt.CompareHashAndPassword(info.Password, givenPassword) != nil {
@ -3523,11 +3524,23 @@ func webircHandler(server *Server, client *Client, msg ircmsg.Message, rb *Respo
continue continue
} }
err, quitMsg := client.ApplyProxiedIP(rb.session, net.ParseIP(msg.Params[3]), secure) candidateIP := msg.Params[3]
err, quitMsg := client.ApplyProxiedIP(rb.session, net.ParseIP(candidateIP), secure)
if err != nil { if err != nil {
client.Quit(quitMsg, rb.session) client.Quit(quitMsg, rb.session)
return true return true
} else { } else {
if info.AcceptHostname {
candidateHostname := msg.Params[2]
if candidateHostname != candidateIP {
if utils.IsHostname(candidateHostname) {
rb.session.rawHostname = candidateHostname
} else {
// log this at debug level since it may be spammy
server.logger.Debug("internal", "invalid hostname from WEBIRC", candidateHostname)
}
}
}
return false return false
} }
} }

View File

@ -314,9 +314,7 @@ func (server *Server) checkBanScriptExemptSASL(config *Config, session *Session)
func (server *Server) tryRegister(c *Client, session *Session) (exiting bool) { func (server *Server) tryRegister(c *Client, session *Session) (exiting bool) {
// XXX PROXY or WEBIRC MUST be sent as the first line of the session; // XXX PROXY or WEBIRC MUST be sent as the first line of the session;
// if we are here at all that means we have the final value of the IP // if we are here at all that means we have the final value of the IP
if session.rawHostname == "" { c.finalizeHostname(session)
session.client.lookupHostname(session, false)
}
// try to complete registration normally // try to complete registration normally
// XXX(#1057) username can be filled in by an ident query without the client // XXX(#1057) username can be filled in by an ident query without the client

View File

@ -192,6 +192,9 @@ server:
# - "192.168.1.1" # - "192.168.1.1"
# - "192.168.10.1/24" # - "192.168.10.1/24"
# whether to accept the hostname parameter on the WEBIRC line as the IRC hostname
accept-hostname: true
# maximum length of clients' sendQ in bytes # maximum length of clients' sendQ in bytes
# this should be big enough to hold bursts of channel/direct messages # this should be big enough to hold bursts of channel/direct messages
max-sendq: 96k max-sendq: 96k