3
0
mirror of https://github.com/ergochat/ergo.git synced 2025-04-01 13:27:07 +02:00

Merge pull request #485 from slingamn/utc.2

another handful of fixes
This commit is contained in:
Daniel Oaks 2019-05-13 16:40:54 +10:00 committed by GitHub
commit 12b2a0751b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 105 additions and 133 deletions

View File

@ -56,7 +56,7 @@ func NewChannel(s *Server, name string, registered bool) *Channel {
} }
channel := &Channel{ channel := &Channel{
createdTime: time.Now(), // may be overwritten by applyRegInfo createdTime: time.Now().UTC(), // may be overwritten by applyRegInfo
lists: map[modes.Mode]*UserMaskSet{ lists: map[modes.Mode]*UserMaskSet{
modes.BanMask: NewUserMaskSet(), modes.BanMask: NewUserMaskSet(),
modes.ExceptMask: NewUserMaskSet(), modes.ExceptMask: NewUserMaskSet(),
@ -292,7 +292,7 @@ func (channel *Channel) SetRegistered(founder string) error {
return errChannelAlreadyRegistered return errChannelAlreadyRegistered
} }
channel.registeredFounder = founder channel.registeredFounder = founder
channel.registeredTime = time.Now() channel.registeredTime = time.Now().UTC()
channel.accountToUMode[founder] = modes.ChannelFounder channel.accountToUMode[founder] = modes.ChannelFounder
return nil return nil
} }
@ -686,7 +686,7 @@ func (channel *Channel) Part(client *Client, message string, rb *ResponseBuffer)
// 2. Send JOIN and MODE lines to channel participants (including the new client) // 2. Send JOIN and MODE lines to channel participants (including the new client)
// 3. Replay missed message history to the client // 3. Replay missed message history to the client
func (channel *Channel) Resume(newClient, oldClient *Client, timestamp time.Time) { func (channel *Channel) Resume(newClient, oldClient *Client, timestamp time.Time) {
now := time.Now() now := time.Now().UTC()
channel.resumeAndAnnounce(newClient, oldClient) channel.resumeAndAnnounce(newClient, oldClient)
if !timestamp.IsZero() { if !timestamp.IsZero() {
channel.replayHistoryForResume(newClient, timestamp, now) channel.replayHistoryForResume(newClient, timestamp, now)
@ -910,7 +910,7 @@ func (channel *Channel) SetTopic(client *Client, topic string, rb *ResponseBuffe
channel.stateMutex.Lock() channel.stateMutex.Lock()
channel.topic = topic channel.topic = topic
channel.topicSetBy = client.nickMaskString channel.topicSetBy = client.nickMaskString
channel.topicSetTime = time.Now() channel.topicSetTime = time.Now().UTC()
channel.stateMutex.Unlock() channel.stateMutex.Unlock()
prefix := client.NickMaskString() prefix := client.NickMaskString()
@ -975,7 +975,6 @@ func (channel *Channel) SendSplitMessage(command string, minPrefixMode modes.Mod
nickmask := client.NickMaskString() nickmask := client.NickMaskString()
account := client.AccountName() account := client.AccountName()
chname := channel.Name() chname := channel.Name()
now := time.Now().UTC()
// STATUSMSG targets are prefixed with the supplied min-prefix, e.g., @#channel // STATUSMSG targets are prefixed with the supplied min-prefix, e.g., @#channel
if minPrefixMode != modes.Mode(0) { if minPrefixMode != modes.Mode(0) {
@ -983,7 +982,6 @@ func (channel *Channel) SendSplitMessage(command string, minPrefixMode modes.Mod
} }
// send echo-message // send echo-message
// TODO this should use `now` as the time for consistency
if rb.session.capabilities.Has(caps.EchoMessage) { if rb.session.capabilities.Has(caps.EchoMessage) {
var tagsToUse map[string]string var tagsToUse map[string]string
if rb.session.capabilities.Has(caps.MessageTags) { if rb.session.capabilities.Has(caps.MessageTags) {
@ -1005,9 +1003,9 @@ func (channel *Channel) SendSplitMessage(command string, minPrefixMode modes.Mod
tagsToUse = clientOnlyTags tagsToUse = clientOnlyTags
} }
if histType == history.Tagmsg && session.capabilities.Has(caps.MessageTags) { if histType == history.Tagmsg && session.capabilities.Has(caps.MessageTags) {
session.sendFromClientInternal(false, now, message.Msgid, nickmask, account, tagsToUse, command, chname) session.sendFromClientInternal(false, message.Time, message.Msgid, nickmask, account, tagsToUse, command, chname)
} else { } else {
session.sendSplitMsgFromClientInternal(false, now, nickmask, account, tagsToUse, command, chname, message) session.sendSplitMsgFromClientInternal(false, nickmask, account, tagsToUse, command, chname, message)
} }
} }
@ -1030,9 +1028,9 @@ func (channel *Channel) SendSplitMessage(command string, minPrefixMode modes.Mod
} }
if histType == history.Tagmsg { if histType == history.Tagmsg {
session.sendFromClientInternal(false, now, message.Msgid, nickmask, account, tagsToUse, command, chname) session.sendFromClientInternal(false, message.Time, message.Msgid, nickmask, account, tagsToUse, command, chname)
} else { } else {
session.sendSplitMsgFromClientInternal(false, now, nickmask, account, tagsToUse, command, chname, message) session.sendSplitMsgFromClientInternal(false, nickmask, account, tagsToUse, command, chname, message)
} }
} }
} }

View File

@ -163,9 +163,30 @@ type ClientDetails struct {
accountName string accountName string
} }
// NewClient sets up a new client and runs its goroutine. // RunClient sets up a new client and runs its goroutine.
func RunNewClient(server *Server, conn clientConn) { func (server *Server) RunClient(conn clientConn) {
now := time.Now() var isBanned bool
var banMsg string
var realIP net.IP
if conn.IsTor {
realIP = utils.IPv4LoopbackAddress
isBanned, banMsg = server.checkTorLimits()
} else {
realIP = utils.AddrToIP(conn.Conn.RemoteAddr())
isBanned, banMsg = server.checkBans(realIP)
}
if isBanned {
// this might not show up properly on some clients,
// but our objective here is just to close the connection out before it has a load impact on us
conn.Conn.Write([]byte(fmt.Sprintf(errorMsg, banMsg)))
conn.Conn.Close()
return
}
server.logger.Info("localconnect-ip", fmt.Sprintf("Client connecting from %v", realIP))
now := time.Now().UTC()
config := server.Config() config := server.Config()
fullLineLenLimit := ircmsg.MaxlenTagsFromClient + config.Limits.LineLen.Rest fullLineLenLimit := ircmsg.MaxlenTagsFromClient + config.Limits.LineLen.Rest
// give them 1k of grace over the limit: // give them 1k of grace over the limit:
@ -194,6 +215,7 @@ func RunNewClient(server *Server, conn clientConn) {
capState: caps.NoneState, capState: caps.NoneState,
ctime: now, ctime: now,
atime: now, atime: now,
realIP: realIP,
} }
session.SetMaxlenRest() session.SetMaxlenRest()
client.sessions = []*Session{session} client.sessions = []*Session{session}
@ -204,19 +226,17 @@ func RunNewClient(server *Server, conn clientConn) {
client.certfp, _ = socket.CertFP() client.certfp, _ = socket.CertFP()
} }
remoteAddr := conn.Conn.RemoteAddr()
if conn.IsTor { if conn.IsTor {
client.SetMode(modes.TLS, true) client.SetMode(modes.TLS, true)
session.realIP = utils.AddrToIP(remoteAddr)
// cover up details of the tor proxying infrastructure (not a user privacy concern, // cover up details of the tor proxying infrastructure (not a user privacy concern,
// but a hardening measure): // but a hardening measure):
session.proxiedIP = utils.IPv4LoopbackAddress session.proxiedIP = utils.IPv4LoopbackAddress
session.rawHostname = config.Server.TorListeners.Vhost session.rawHostname = config.Server.TorListeners.Vhost
} else { } else {
session.realIP = utils.AddrToIP(remoteAddr)
// set the hostname for this client (may be overridden later by PROXY or WEBIRC) // set the hostname for this client (may be overridden later by PROXY or WEBIRC)
session.rawHostname = utils.LookupHostname(session.realIP.String()) session.rawHostname = utils.LookupHostname(session.realIP.String())
client.cloakedHostname = config.Server.Cloaks.ComputeCloak(session.realIP) client.cloakedHostname = config.Server.Cloaks.ComputeCloak(session.realIP)
remoteAddr := conn.Conn.RemoteAddr()
if utils.AddrIsLocal(remoteAddr) { if utils.AddrIsLocal(remoteAddr) {
// treat local connections as secure (may be overridden later by WEBIRC) // treat local connections as secure (may be overridden later by WEBIRC)
client.SetMode(modes.TLS, true) client.SetMode(modes.TLS, true)
@ -409,8 +429,7 @@ func (client *Client) playReattachMessages(session *Session) {
// Active updates when the client was last 'active' (i.e. the user should be sitting in front of their client). // Active updates when the client was last 'active' (i.e. the user should be sitting in front of their client).
func (client *Client) Active(session *Session) { func (client *Client) Active(session *Session) {
// TODO normalize all times to utc? now := time.Now().UTC()
now := time.Now()
client.stateMutex.Lock() client.stateMutex.Lock()
defer client.stateMutex.Unlock() defer client.stateMutex.Unlock()
session.atime = now session.atime = now
@ -472,7 +491,7 @@ func (client *Client) tryResume() (success bool) {
success = true success = true
// this is a bit racey // this is a bit racey
client.resumeDetails.ResumedAt = time.Now() client.resumeDetails.ResumedAt = time.Now().UTC()
client.nickTimer.Touch(nil) client.nickTimer.Touch(nil)
@ -496,7 +515,7 @@ func (client *Client) tryResume() (success bool) {
hostname := client.Hostname() hostname := client.Hostname()
friends := make(ClientSet) friends := make(ClientSet)
oldestLostMessage := time.Now() oldestLostMessage := time.Now().UTC()
// work out how much time, if any, is not covered by history buffers // work out how much time, if any, is not covered by history buffers
for _, channel := range channels { for _, channel := range channels {
@ -569,7 +588,7 @@ func (client *Client) tryResumeChannels() {
// replay direct PRIVSMG history // replay direct PRIVSMG history
if !details.Timestamp.IsZero() { if !details.Timestamp.IsZero() {
now := time.Now() now := time.Now().UTC()
items, complete := client.history.Between(details.Timestamp, now, false, 0) items, complete := client.history.Between(details.Timestamp, now, false, 0)
rb := NewResponseBuffer(client.Sessions()[0]) rb := NewResponseBuffer(client.Sessions()[0])
client.replayPrivmsgHistory(rb, items, complete) client.replayPrivmsgHistory(rb, items, complete)
@ -1072,12 +1091,12 @@ func (client *Client) destroy(beingResumed bool, session *Session) {
// SendSplitMsgFromClient sends an IRC PRIVMSG/NOTICE coming from a specific client. // SendSplitMsgFromClient sends an IRC PRIVMSG/NOTICE coming from a specific client.
// Adds account-tag to the line as well. // Adds account-tag to the line as well.
func (session *Session) sendSplitMsgFromClientInternal(blocking bool, serverTime time.Time, nickmask, accountName string, tags map[string]string, command, target string, message utils.SplitMessage) { func (session *Session) sendSplitMsgFromClientInternal(blocking bool, nickmask, accountName string, tags map[string]string, command, target string, message utils.SplitMessage) {
if session.capabilities.Has(caps.MaxLine) || message.Wrapped == nil { if session.capabilities.Has(caps.MaxLine) || message.Wrapped == nil {
session.sendFromClientInternal(blocking, serverTime, message.Msgid, nickmask, accountName, tags, command, target, message.Message) session.sendFromClientInternal(blocking, message.Time, message.Msgid, nickmask, accountName, tags, command, target, message.Message)
} else { } else {
for _, messagePair := range message.Wrapped { for _, messagePair := range message.Wrapped {
session.sendFromClientInternal(blocking, serverTime, messagePair.Msgid, nickmask, accountName, tags, command, target, messagePair.Message) session.sendFromClientInternal(blocking, message.Time, messagePair.Msgid, nickmask, accountName, tags, command, target, messagePair.Message)
} }
} }
} }

View File

@ -309,8 +309,9 @@ func init() {
minParams: 4, minParams: 4,
}, },
"WHO": { "WHO": {
handler: whoHandler, handler: whoHandler,
minParams: 1, minParams: 1,
leaveClientIdle: true,
}, },
"WHOIS": { "WHOIS": {
handler: whoisHandler, handler: whoisHandler,

View File

@ -98,17 +98,6 @@ func (cl *Limiter) RemoveClient(addr net.IP) {
} }
} }
// NewLimiter returns a new connection limit handler.
// The handler is functional, but disabled; it can be enabled via `ApplyConfig`.
func NewLimiter() *Limiter {
var cl Limiter
// initialize empty population; all other state is configurable
cl.population = make(map[string]int)
return &cl
}
// ApplyConfig atomically applies a config update to a connection limit handler // ApplyConfig atomically applies a config update to a connection limit handler
func (cl *Limiter) ApplyConfig(config LimiterConfig) error { func (cl *Limiter) ApplyConfig(config LimiterConfig) error {
// assemble exempted nets // assemble exempted nets
@ -120,6 +109,10 @@ func (cl *Limiter) ApplyConfig(config LimiterConfig) error {
cl.Lock() cl.Lock()
defer cl.Unlock() defer cl.Unlock()
if cl.population == nil {
cl.population = make(map[string]int)
}
cl.enabled = config.Enabled cl.enabled = config.Enabled
cl.ipv4Mask = net.CIDRMask(config.CidrLenIPv4, 32) cl.ipv4Mask = net.CIDRMask(config.CidrLenIPv4, 32)
cl.ipv6Mask = net.CIDRMask(config.CidrLenIPv6, 128) cl.ipv6Mask = net.CIDRMask(config.CidrLenIPv6, 128)

View File

@ -45,7 +45,7 @@ type GenericThrottle struct {
// it either denies it (by returning false) or allows it (by returning true) // it either denies it (by returning false) or allows it (by returning true)
// and records it // and records it
func (g *GenericThrottle) Touch() (throttled bool, remainingTime time.Duration) { func (g *GenericThrottle) Touch() (throttled bool, remainingTime time.Duration) {
return g.touch(time.Now()) return g.touch(time.Now().UTC())
} }
func (g *GenericThrottle) touch(now time.Time) (throttled bool, remainingTime time.Duration) { func (g *GenericThrottle) touch(now time.Time) (throttled bool, remainingTime time.Duration) {
@ -150,17 +150,6 @@ func (ct *Throttler) BanMessage() string {
return ct.banMessage return ct.banMessage
} }
// NewThrottler returns a new client connection throttler.
// The throttler is functional, but disabled; it can be enabled via `ApplyConfig`.
func NewThrottler() *Throttler {
var ct Throttler
// initialize empty population; all other state is configurable
ct.population = make(map[string]ThrottleDetails)
return &ct
}
// ApplyConfig atomically applies a config update to a throttler // ApplyConfig atomically applies a config update to a throttler
func (ct *Throttler) ApplyConfig(config ThrottlerConfig) error { func (ct *Throttler) ApplyConfig(config ThrottlerConfig) error {
// assemble exempted nets // assemble exempted nets
@ -172,6 +161,10 @@ func (ct *Throttler) ApplyConfig(config ThrottlerConfig) error {
ct.Lock() ct.Lock()
defer ct.Unlock() defer ct.Unlock()
if ct.population == nil {
ct.population = make(map[string]ThrottleDetails)
}
ct.enabled = config.Enabled ct.enabled = config.Enabled
ct.ipv4Mask = net.CIDRMask(config.CidrLenIPv4, 32) ct.ipv4Mask = net.CIDRMask(config.CidrLenIPv4, 32)
ct.ipv6Mask = net.CIDRMask(config.CidrLenIPv6, 128) ct.ipv6Mask = net.CIDRMask(config.CidrLenIPv6, 128)

View File

@ -72,9 +72,9 @@ func makeTestThrottler(v4len, v6len int) *Throttler {
ConnectionsPerCidr: maxConnections, ConnectionsPerCidr: maxConnections,
Duration: minute, Duration: minute,
} }
throttler := NewThrottler() var throttler Throttler
throttler.ApplyConfig(config) throttler.ApplyConfig(config)
return throttler return &throttler
} }
func TestConnectionThrottle(t *testing.T) { func TestConnectionThrottle(t *testing.T) {

View File

@ -34,7 +34,7 @@ type IPBanInfo struct {
} }
func (info IPBanInfo) timeLeft() time.Duration { func (info IPBanInfo) timeLeft() time.Duration {
return info.TimeCreated.Add(info.Duration).Sub(time.Now()) return time.Until(info.TimeCreated.Add(info.Duration))
} }
func (info IPBanInfo) TimeLeft() string { func (info IPBanInfo) TimeLeft() string {
@ -114,7 +114,7 @@ func (dm *DLineManager) AddNetwork(network net.IPNet, duration time.Duration, re
Reason: reason, Reason: reason,
OperReason: operReason, OperReason: operReason,
OperName: operName, OperName: operName,
TimeCreated: time.Now(), TimeCreated: time.Now().UTC(),
Duration: duration, Duration: duration,
} }

View File

@ -13,7 +13,6 @@ var (
errAccountAlreadyVerified = errors.New(`Account is already verified`) errAccountAlreadyVerified = errors.New(`Account is already verified`)
errAccountCantDropPrimaryNick = errors.New("Can't unreserve primary nickname") errAccountCantDropPrimaryNick = errors.New("Can't unreserve primary nickname")
errAccountCreation = errors.New("Account could not be created") 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") errAccountDoesNotExist = errors.New("Account does not exist")
errAccountInvalidCredentials = errors.New("Invalid account credentials") errAccountInvalidCredentials = errors.New("Invalid account credentials")
errAccountBadPassphrase = errors.New(`Passphrase contains forbidden characters or is otherwise invalid`) 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") errCallbackFailed = errors.New("Account verification could not be sent")
errCertfpAlreadyExists = errors.New(`An account already exists for your certificate fingerprint`) errCertfpAlreadyExists = errors.New(`An account already exists for your certificate fingerprint`)
errChannelNotOwnedByAccount = errors.New("Channel not owned by the specified account") errChannelNotOwnedByAccount = errors.New("Channel not owned by the specified account")
errChannelDoesNotExist = errors.New("Channel does not exist")
errChannelAlreadyRegistered = errors.New("Channel is already registered") errChannelAlreadyRegistered = errors.New("Channel is already registered")
errChannelNameInUse = errors.New(`Channel name in use`) errChannelNameInUse = errors.New(`Channel name in use`)
errInvalidChannelName = errors.New(`Invalid channel name`) errInvalidChannelName = errors.New(`Invalid channel name`)
@ -38,12 +36,10 @@ var (
errNicknameReserved = errors.New("nickname is reserved") errNicknameReserved = errors.New("nickname is reserved")
errNoExistingBan = errors.New("Ban does not exist") errNoExistingBan = errors.New("Ban does not exist")
errNoSuchChannel = errors.New(`No such channel`) errNoSuchChannel = errors.New(`No such channel`)
errRenamePrivsNeeded = errors.New(`Only chanops can rename channels`)
errInsufficientPrivs = errors.New("Insufficient privileges") 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") errInvalidUsername = errors.New("Invalid username")
errFeatureDisabled = errors.New(`That feature is disabled`) errFeatureDisabled = errors.New(`That feature is disabled`)
errBanned = errors.New("IP or nickmask banned")
errInvalidParams = errors.New("Invalid parameters") errInvalidParams = errors.New("Invalid parameters")
) )

View File

@ -46,24 +46,22 @@ func (wc *webircConfig) Populate() (err error) {
} }
// ApplyProxiedIP applies the given IP to the client. // 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 // PROXY and WEBIRC are never accepted from a Tor listener, even if the address itself
// is whitelisted: // is whitelisted:
if client.isTor { if client.isTor {
return false return errBadProxyLine, ""
} }
// ensure IP is sane // ensure IP is sane
parsedProxiedIP := net.ParseIP(proxiedIP).To16() parsedProxiedIP := net.ParseIP(proxiedIP).To16()
if parsedProxiedIP == nil { if parsedProxiedIP == nil {
client.Quit(fmt.Sprintf(client.t("Proxied IP address is not valid: [%s]"), proxiedIP), session) return errBadProxyLine, fmt.Sprintf(client.t("Proxied IP address is not valid: [%s]"), proxiedIP)
return false
} }
isBanned, banMsg := client.server.checkBans(parsedProxiedIP) isBanned, banMsg := client.server.checkBans(parsedProxiedIP)
if isBanned { if isBanned {
client.Quit(banMsg, session) return errBanned, banMsg
return false
} }
// given IP is sane! override the client's current IP // 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.certfp = ""
client.SetMode(modes.TLS, tls) client.SetMode(modes.TLS, tls)
return true return nil, ""
} }
// handle the PROXY command: http://www.haproxy.org/download/1.8/doc/proxy-protocol.txt // 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, // 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. // 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) { func handleProxyCommand(server *Server, client *Client, session *Session, line string) (err error) {
var quitMsg string
defer func() { defer func() {
if err != nil { 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) { if utils.IPInNets(client.realIP, server.Config().Server.proxyAllowedFromNets) {
// assume PROXY connections are always secure // assume PROXY connections are always secure
if client.ApplyProxiedIP(session, params[2], true) { err, quitMsg = client.ApplyProxiedIP(session, params[2], true)
return nil return
} else { } else {
return errBadProxyLine // real source IP is not authorized to issue PROXY:
} return errBadGatewayAddress
} }
// real source IP is not authorized to issue PROXY:
return errBadGatewayAddress
} }

View File

@ -356,7 +356,7 @@ func (channel *Channel) Rename(name, nameCasefolded string) {
channel.name = name channel.name = name
channel.nameCasefolded = nameCasefolded channel.nameCasefolded = nameCasefolded
if channel.registeredFounder != "" { if channel.registeredFounder != "" {
channel.registeredTime = time.Now() channel.registeredTime = time.Now().UTC()
} }
channel.stateMutex.Unlock() channel.stateMutex.Unlock()
} }

View File

@ -2019,7 +2019,7 @@ func messageHandler(server *Server, client *Client, msg ircmsg.IrcMessage, rb *R
session.sendFromClientInternal(false, splitMsg.Time, splitMsg.Msgid, nickMaskString, accountName, clientOnlyTags, msg.Command, tnick) session.sendFromClientInternal(false, splitMsg.Time, splitMsg.Msgid, nickMaskString, accountName, clientOnlyTags, msg.Command, tnick)
} }
} else { } else {
session.sendSplitMsgFromClientInternal(false, splitMsg.Time, nickMaskString, accountName, clientOnlyTags, msg.Command, tnick, splitMsg) session.sendSplitMsgFromClientInternal(false, nickMaskString, accountName, clientOnlyTags, msg.Command, tnick, splitMsg)
} }
} }
} }
@ -2039,7 +2039,7 @@ func messageHandler(server *Server, client *Client, msg ircmsg.IrcMessage, rb *R
if histType == history.Tagmsg && rb.session.capabilities.Has(caps.MessageTags) { if histType == history.Tagmsg && rb.session.capabilities.Has(caps.MessageTags) {
session.sendFromClientInternal(false, splitMsg.Time, splitMsg.Msgid, nickMaskString, accountName, clientOnlyTags, msg.Command, tnick) session.sendFromClientInternal(false, splitMsg.Time, splitMsg.Msgid, nickMaskString, accountName, clientOnlyTags, msg.Command, tnick)
} else { } else {
session.sendSplitMsgFromClientInternal(false, splitMsg.Time, nickMaskString, accountName, clientOnlyTags, msg.Command, tnick, splitMsg) session.sendSplitMsgFromClientInternal(false, nickMaskString, accountName, clientOnlyTags, msg.Command, tnick, splitMsg)
} }
} }
if histType != history.Notice && user.Away() { if histType != history.Notice && user.Away() {
@ -2377,7 +2377,7 @@ func setnameHandler(server *Server, client *Client, msg ircmsg.IrcMessage, rb *R
// TIME // TIME
func timeHandler(server *Server, client *Client, msg ircmsg.IrcMessage, rb *ResponseBuffer) bool { func timeHandler(server *Server, client *Client, msg ircmsg.IrcMessage, rb *ResponseBuffer) bool {
rb.Add(nil, server.name, RPL_TIME, client.nick, server.name, time.Now().Format(time.RFC1123)) rb.Add(nil, server.name, RPL_TIME, client.nick, server.name, time.Now().UTC().Format(time.RFC1123))
return false return false
} }
@ -2576,7 +2576,13 @@ func webircHandler(server *Server, client *Client, msg ircmsg.IrcMessage, rb *Re
if strings.HasPrefix(proxiedIP, "[") && strings.HasSuffix(proxiedIP, "]") { if strings.HasPrefix(proxiedIP, "[") && strings.HasSuffix(proxiedIP, "]") {
proxiedIP = proxiedIP[1 : len(proxiedIP)-1] 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
}
} }
} }

View File

@ -176,7 +176,7 @@ func hsRequestHandler(server *Server, client *Client, command string, params []s
hsNotice(rb, client.t("An error occurred")) hsNotice(rb, client.t("An error occurred"))
return return
} }
elapsed := time.Now().Sub(account.VHost.LastRequestTime) elapsed := time.Since(account.VHost.LastRequestTime)
remainingTime := server.AccountConfig().VHosts.UserRequests.Cooldown - elapsed remainingTime := server.AccountConfig().VHosts.UserRequests.Cooldown - elapsed
// you can update your existing request, but if you were rejected, // you can update your existing request, but if you were rejected,
// you can't spam a replacement request // you can't spam a replacement request

View File

@ -72,7 +72,7 @@ func (km *KLineManager) AddMask(mask string, duration time.Duration, reason, ope
Reason: reason, Reason: reason,
OperReason: operReason, OperReason: operReason,
OperName: operName, OperName: operName,
TimeCreated: time.Now(), TimeCreated: time.Now().UTC(),
Duration: duration, Duration: duration,
} }
km.addMaskInternal(mask, info) km.addMaskInternal(mask, info)

View File

@ -19,13 +19,9 @@ type MonitorManager struct {
// (all nicks must be normalized externally by casefolding) // (all nicks must be normalized externally by casefolding)
} }
// NewMonitorManager returns a new MonitorManager. func (mm *MonitorManager) Initialize() {
func NewMonitorManager() *MonitorManager { mm.watching = make(map[*Client]map[string]bool)
mm := MonitorManager{ mm.watchedby = make(map[string]map[*Client]bool)
watching: make(map[*Client]map[string]bool),
watchedby: make(map[string]map[*Client]bool),
}
return &mm
} }
// AlertAbout alerts everyone monitoring `client`'s nick that `client` is now {on,off}line. // AlertAbout alerts everyone monitoring `client`'s nick that `client` is now {on,off}line.

View File

@ -5,6 +5,7 @@ package irc
import ( import (
"fmt" "fmt"
"time"
"github.com/goshuirc/irc-go/ircfmt" "github.com/goshuirc/irc-go/ircfmt"
@ -612,7 +613,7 @@ func nsSessionsHandler(server *Server, client *Client, command string, params []
} }
nsNotice(rb, fmt.Sprintf(client.t("IP address: %s"), session.ip.String())) nsNotice(rb, fmt.Sprintf(client.t("IP address: %s"), session.ip.String()))
nsNotice(rb, fmt.Sprintf(client.t("Hostname: %s"), session.hostname)) nsNotice(rb, fmt.Sprintf(client.t("Hostname: %s"), session.hostname))
nsNotice(rb, fmt.Sprintf(client.t("Created at: %s"), session.ctime.Format(IRCv3TimestampFormat))) nsNotice(rb, fmt.Sprintf(client.t("Created at: %s"), session.ctime.Format(time.RFC1123)))
nsNotice(rb, fmt.Sprintf(client.t("Last active: %s"), session.atime.Format(IRCv3TimestampFormat))) nsNotice(rb, fmt.Sprintf(client.t("Last active: %s"), session.atime.Format(time.RFC1123)))
} }
} }

View File

@ -27,7 +27,6 @@ import (
"github.com/oragono/oragono/irc/logger" "github.com/oragono/oragono/irc/logger"
"github.com/oragono/oragono/irc/modes" "github.com/oragono/oragono/irc/modes"
"github.com/oragono/oragono/irc/sno" "github.com/oragono/oragono/irc/sno"
"github.com/oragono/oragono/irc/utils"
"github.com/tidwall/buntdb" "github.com/tidwall/buntdb"
) )
@ -67,15 +66,15 @@ type Server struct {
clients ClientManager clients ClientManager
config unsafe.Pointer config unsafe.Pointer
configFilename string configFilename string
connectionLimiter *connection_limits.Limiter connectionLimiter connection_limits.Limiter
connectionThrottler *connection_limits.Throttler connectionThrottler connection_limits.Throttler
ctime time.Time ctime time.Time
dlines *DLineManager dlines *DLineManager
helpIndexManager HelpIndexManager helpIndexManager HelpIndexManager
klines *KLineManager klines *KLineManager
listeners map[string]*ListenerWrapper listeners map[string]*ListenerWrapper
logger *logger.Manager logger *logger.Manager
monitorManager *MonitorManager monitorManager MonitorManager
name string name string
nameCasefolded string nameCasefolded string
rehashMutex sync.Mutex // tier 4 rehashMutex sync.Mutex // tier 4
@ -83,7 +82,7 @@ type Server struct {
pprofServer *http.Server pprofServer *http.Server
resumeManager ResumeManager resumeManager ResumeManager
signals chan os.Signal signals chan os.Signal
snomasks *SnoManager snomasks SnoManager
store *buntdb.DB store *buntdb.DB
torLimiter connection_limits.TorLimiter torLimiter connection_limits.TorLimiter
whoWas WhoWasList whoWas WhoWasList
@ -110,20 +109,19 @@ type clientConn struct {
func NewServer(config *Config, logger *logger.Manager) (*Server, error) { func NewServer(config *Config, logger *logger.Manager) (*Server, error) {
// initialize data structures // initialize data structures
server := &Server{ server := &Server{
connectionLimiter: connection_limits.NewLimiter(), ctime: time.Now().UTC(),
connectionThrottler: connection_limits.NewThrottler(), listeners: make(map[string]*ListenerWrapper),
listeners: make(map[string]*ListenerWrapper), logger: logger,
logger: logger, rehashSignal: make(chan os.Signal, 1),
monitorManager: NewMonitorManager(), signals: make(chan os.Signal, len(ServerExitSignals)),
rehashSignal: make(chan os.Signal, 1),
signals: make(chan os.Signal, len(ServerExitSignals)),
snomasks: NewSnoManager(),
} }
server.clients.Initialize() server.clients.Initialize()
server.semaphores.Initialize() server.semaphores.Initialize()
server.resumeManager.Initialize(server) server.resumeManager.Initialize(server)
server.whoWas.Initialize(config.Limits.WhowasEntries) server.whoWas.Initialize(config.Limits.WhowasEntries)
server.monitorManager.Initialize()
server.snomasks.Initialize()
if err := server.applyConfig(config, true); err != nil { if err := server.applyConfig(config, true); err != nil {
return nil, err return nil, err
@ -208,30 +206,6 @@ func (server *Server) Run() {
} }
} }
func (server *Server) acceptClient(conn clientConn) {
var isBanned bool
var banMsg string
var ipaddr net.IP
if conn.IsTor {
ipaddr = utils.IPv4LoopbackAddress
isBanned, banMsg = server.checkTorLimits()
} else {
ipaddr = utils.AddrToIP(conn.Conn.RemoteAddr())
isBanned, banMsg = server.checkBans(ipaddr)
}
if isBanned {
// this might not show up properly on some clients, but our objective here is just to close the connection out before it has a load impact on us
conn.Conn.Write([]byte(fmt.Sprintf(errorMsg, banMsg)))
conn.Conn.Close()
return
}
server.logger.Info("localconnect-ip", fmt.Sprintf("Client connecting from %v", ipaddr))
go RunNewClient(server, conn)
}
func (server *Server) checkBans(ipaddr net.IP) (banned bool, message string) { func (server *Server) checkBans(ipaddr net.IP) (banned bool, message string) {
// check DLINEs // check DLINEs
isBanned, info := server.dlines.CheckIP(ipaddr) isBanned, info := server.dlines.CheckIP(ipaddr)
@ -339,7 +313,7 @@ func (server *Server) createListener(addr string, tlsConfig *tls.Config, isTor b
IsTor: isTor, IsTor: isTor,
} }
// hand off the connection // hand off the connection
go server.acceptClient(newConn) go server.RunClient(newConn)
} }
if shouldStop { if shouldStop {
@ -576,7 +550,6 @@ func (server *Server) rehash() error {
func (server *Server) applyConfig(config *Config, initial bool) (err error) { func (server *Server) applyConfig(config *Config, initial bool) (err error) {
if initial { if initial {
server.ctime = time.Now()
server.configFilename = config.Filename server.configFilename = config.Filename
server.name = config.Server.Name server.name = config.Server.Name
server.nameCasefolded = config.Server.nameCasefolded server.nameCasefolded = config.Server.nameCasefolded

View File

@ -14,11 +14,8 @@ type SnoManager struct {
sendLists map[sno.Mask]map[*Client]bool sendLists map[sno.Mask]map[*Client]bool
} }
// NewSnoManager returns a new SnoManager func (m *SnoManager) Initialize() {
func NewSnoManager() *SnoManager {
var m SnoManager
m.sendLists = make(map[sno.Mask]map[*Client]bool) m.sendLists = make(map[sno.Mask]map[*Client]bool)
return &m
} }
// AddMasks adds the given snomasks to the client. // AddMasks adds the given snomasks to the client.