From 316d45917dbcec1760c3608802a7874b373ee7a3 Mon Sep 17 00:00:00 2001 From: Shivaram Lingamneni Date: Mon, 13 May 2019 01:54:50 -0400 Subject: [PATCH] pass the correct quit message when a proxied client is banned If you were banned and the ban was only detected when you proxied (because you were proxying from a DLINE'd IP), you'd get an incorrect quit message: `QUIT: Bad or unauthorized PROXY command`. This propagates the correct ban message as the quit line. --- irc/errors.go | 6 +----- irc/gateways.go | 31 +++++++++++++++---------------- irc/handlers.go | 8 +++++++- 3 files changed, 23 insertions(+), 22 deletions(-) diff --git a/irc/errors.go b/irc/errors.go index 0a5c3c5f..1fa8e5f7 100644 --- a/irc/errors.go +++ b/irc/errors.go @@ -13,7 +13,6 @@ var ( errAccountAlreadyVerified = errors.New(`Account is already verified`) errAccountCantDropPrimaryNick = errors.New("Can't unreserve primary nickname") errAccountCreation = errors.New("Account could not be created") - errAccountCredUpdate = errors.New("Could not update password hash to new method") errAccountDoesNotExist = errors.New("Account does not exist") errAccountInvalidCredentials = errors.New("Invalid account credentials") errAccountBadPassphrase = errors.New(`Passphrase contains forbidden characters or is otherwise invalid`) @@ -28,7 +27,6 @@ var ( errCallbackFailed = errors.New("Account verification could not be sent") errCertfpAlreadyExists = errors.New(`An account already exists for your certificate fingerprint`) errChannelNotOwnedByAccount = errors.New("Channel not owned by the specified account") - errChannelDoesNotExist = errors.New("Channel does not exist") errChannelAlreadyRegistered = errors.New("Channel is already registered") errChannelNameInUse = errors.New(`Channel name in use`) errInvalidChannelName = errors.New(`Invalid channel name`) @@ -38,12 +36,10 @@ var ( errNicknameReserved = errors.New("nickname is reserved") errNoExistingBan = errors.New("Ban does not exist") errNoSuchChannel = errors.New(`No such channel`) - errRenamePrivsNeeded = errors.New(`Only chanops can rename channels`) errInsufficientPrivs = errors.New("Insufficient privileges") - errSaslFail = errors.New("SASL failed") - errResumeTokenAlreadySet = errors.New("Client was already assigned a resume token") errInvalidUsername = errors.New("Invalid username") errFeatureDisabled = errors.New(`That feature is disabled`) + errBanned = errors.New("IP or nickmask banned") errInvalidParams = errors.New("Invalid parameters") ) diff --git a/irc/gateways.go b/irc/gateways.go index 95f05aee..09a551ef 100644 --- a/irc/gateways.go +++ b/irc/gateways.go @@ -46,24 +46,22 @@ func (wc *webircConfig) Populate() (err error) { } // ApplyProxiedIP applies the given IP to the client. -func (client *Client) ApplyProxiedIP(session *Session, proxiedIP string, tls bool) (success bool) { +func (client *Client) ApplyProxiedIP(session *Session, proxiedIP string, tls bool) (err error, quitMsg string) { // PROXY and WEBIRC are never accepted from a Tor listener, even if the address itself // is whitelisted: if client.isTor { - return false + return errBadProxyLine, "" } // ensure IP is sane parsedProxiedIP := net.ParseIP(proxiedIP).To16() if parsedProxiedIP == nil { - client.Quit(fmt.Sprintf(client.t("Proxied IP address is not valid: [%s]"), proxiedIP), session) - return false + return errBadProxyLine, fmt.Sprintf(client.t("Proxied IP address is not valid: [%s]"), proxiedIP) } isBanned, banMsg := client.server.checkBans(parsedProxiedIP) if isBanned { - client.Quit(banMsg, session) - return false + return errBanned, banMsg } // given IP is sane! override the client's current IP @@ -84,7 +82,7 @@ func (client *Client) ApplyProxiedIP(session *Session, proxiedIP string, tls boo client.certfp = "" client.SetMode(modes.TLS, tls) - return true + return nil, "" } // handle the PROXY command: http://www.haproxy.org/download/1.8/doc/proxy-protocol.txt @@ -93,9 +91,13 @@ func (client *Client) ApplyProxiedIP(session *Session, proxiedIP string, tls boo // unfortunately, an ipv6 SOURCEIP can start with a double colon; in this case, // the message is invalid IRC and can't be parsed normally, hence the special handling. func handleProxyCommand(server *Server, client *Client, session *Session, line string) (err error) { + var quitMsg string defer func() { if err != nil { - client.Quit(client.t("Bad or unauthorized PROXY command"), session) + if quitMsg == "" { + quitMsg = client.t("Bad or unauthorized PROXY command") + } + client.Quit(quitMsg, session) } }() @@ -106,13 +108,10 @@ func handleProxyCommand(server *Server, client *Client, session *Session, line s if utils.IPInNets(client.realIP, server.Config().Server.proxyAllowedFromNets) { // assume PROXY connections are always secure - if client.ApplyProxiedIP(session, params[2], true) { - return nil - } else { - return errBadProxyLine - } + err, quitMsg = client.ApplyProxiedIP(session, params[2], true) + return + } else { + // real source IP is not authorized to issue PROXY: + return errBadGatewayAddress } - - // real source IP is not authorized to issue PROXY: - return errBadGatewayAddress } diff --git a/irc/handlers.go b/irc/handlers.go index 66ba8e35..9508304a 100644 --- a/irc/handlers.go +++ b/irc/handlers.go @@ -2576,7 +2576,13 @@ func webircHandler(server *Server, client *Client, msg ircmsg.IrcMessage, rb *Re if strings.HasPrefix(proxiedIP, "[") && strings.HasSuffix(proxiedIP, "]") { proxiedIP = proxiedIP[1 : len(proxiedIP)-1] } - return !client.ApplyProxiedIP(rb.session, proxiedIP, secure) + err, quitMsg := client.ApplyProxiedIP(rb.session, proxiedIP, secure) + if err != nil { + client.Quit(quitMsg, rb.session) + return true + } else { + return false + } } }