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

add a config switch to accept hostnames from WEBIRC

See #1686; this allows i2pd to pass the i2p address to Ergo, which may be
useful for moderation under some circumstances.
This commit is contained in:
Shivaram Lingamneni 2024-04-13 21:43:41 -04:00
parent 1f4b5248a0
commit 7726160ec7
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

@ -165,6 +165,7 @@ type Session struct {
realIP net.IP realIP net.IP
proxiedIP net.IP proxiedIP net.IP
rawHostname string rawHostname string
hostnameFinalized bool
isTor bool isTor bool
hideSTS bool hideSTS bool
@ -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,6 +511,8 @@ func (client *Client) lookupHostname(session *Session, overwrite bool) {
ip = session.proxiedIP ip = session.proxiedIP
} }
// even if cloaking is enabled, we may want to look up the real hostname to show to operators:
if session.rawHostname == "" {
var hostname string var hostname string
lookupSuccessful := false lookupSuccessful := false
if config.Server.lookupHostnames { if config.Server.lookupHostnames {
@ -514,17 +526,12 @@ func (client *Client) lookupHostname(session *Session, overwrite bool) {
} else { } else {
hostname = utils.IPStringToHostname(ip.String()) hostname = utils.IPStringToHostname(ip.String())
} }
session.rawHostname = hostname session.rawHostname = hostname
cloakedHostname := config.Server.Cloaks.ComputeCloak(ip)
client.stateMutex.Lock()
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()
} }
// these will be discarded if this is actually a reattach:
client.rawHostname = session.rawHostname
client.cloakedHostname = config.Server.Cloaks.ComputeCloak(ip)
} }
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