mirror of
				https://github.com/ergochat/ergo.git
				synced 2025-10-31 13:57:23 +01:00 
			
		
		
		
	
						commit
						12b2a0751b
					
				| @ -56,7 +56,7 @@ func NewChannel(s *Server, name string, registered bool) *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{ | ||||
| 			modes.BanMask:    NewUserMaskSet(), | ||||
| 			modes.ExceptMask: NewUserMaskSet(), | ||||
| @ -292,7 +292,7 @@ func (channel *Channel) SetRegistered(founder string) error { | ||||
| 		return errChannelAlreadyRegistered | ||||
| 	} | ||||
| 	channel.registeredFounder = founder | ||||
| 	channel.registeredTime = time.Now() | ||||
| 	channel.registeredTime = time.Now().UTC() | ||||
| 	channel.accountToUMode[founder] = modes.ChannelFounder | ||||
| 	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) | ||||
| // 3. Replay missed message history to the client | ||||
| func (channel *Channel) Resume(newClient, oldClient *Client, timestamp time.Time) { | ||||
| 	now := time.Now() | ||||
| 	now := time.Now().UTC() | ||||
| 	channel.resumeAndAnnounce(newClient, oldClient) | ||||
| 	if !timestamp.IsZero() { | ||||
| 		channel.replayHistoryForResume(newClient, timestamp, now) | ||||
| @ -910,7 +910,7 @@ func (channel *Channel) SetTopic(client *Client, topic string, rb *ResponseBuffe | ||||
| 	channel.stateMutex.Lock() | ||||
| 	channel.topic = topic | ||||
| 	channel.topicSetBy = client.nickMaskString | ||||
| 	channel.topicSetTime = time.Now() | ||||
| 	channel.topicSetTime = time.Now().UTC() | ||||
| 	channel.stateMutex.Unlock() | ||||
| 
 | ||||
| 	prefix := client.NickMaskString() | ||||
| @ -975,7 +975,6 @@ func (channel *Channel) SendSplitMessage(command string, minPrefixMode modes.Mod | ||||
| 	nickmask := client.NickMaskString() | ||||
| 	account := client.AccountName() | ||||
| 	chname := channel.Name() | ||||
| 	now := time.Now().UTC() | ||||
| 
 | ||||
| 	// STATUSMSG targets are prefixed with the supplied min-prefix, e.g., @#channel | ||||
| 	if minPrefixMode != modes.Mode(0) { | ||||
| @ -983,7 +982,6 @@ func (channel *Channel) SendSplitMessage(command string, minPrefixMode modes.Mod | ||||
| 	} | ||||
| 
 | ||||
| 	// send echo-message | ||||
| 	// TODO this should use `now` as the time for consistency | ||||
| 	if rb.session.capabilities.Has(caps.EchoMessage) { | ||||
| 		var tagsToUse map[string]string | ||||
| 		if rb.session.capabilities.Has(caps.MessageTags) { | ||||
| @ -1005,9 +1003,9 @@ func (channel *Channel) SendSplitMessage(command string, minPrefixMode modes.Mod | ||||
| 			tagsToUse = clientOnlyTags | ||||
| 		} | ||||
| 		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 { | ||||
| 			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 { | ||||
| 				session.sendFromClientInternal(false, now, message.Msgid, nickmask, account, tagsToUse, command, chname) | ||||
| 				session.sendFromClientInternal(false, message.Time, message.Msgid, nickmask, account, tagsToUse, command, chname) | ||||
| 			} else { | ||||
| 				session.sendSplitMsgFromClientInternal(false, now, nickmask, account, tagsToUse, command, chname, message) | ||||
| 				session.sendSplitMsgFromClientInternal(false, nickmask, account, tagsToUse, command, chname, message) | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| @ -163,9 +163,30 @@ type ClientDetails struct { | ||||
| 	accountName        string | ||||
| } | ||||
| 
 | ||||
| // NewClient sets up a new client and runs its goroutine. | ||||
| func RunNewClient(server *Server, conn clientConn) { | ||||
| 	now := time.Now() | ||||
| // RunClient sets up a new client and runs its goroutine. | ||||
| func (server *Server) RunClient(conn clientConn) { | ||||
| 	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() | ||||
| 	fullLineLenLimit := ircmsg.MaxlenTagsFromClient + config.Limits.LineLen.Rest | ||||
| 	// give them 1k of grace over the limit: | ||||
| @ -194,6 +215,7 @@ func RunNewClient(server *Server, conn clientConn) { | ||||
| 		capState:   caps.NoneState, | ||||
| 		ctime:      now, | ||||
| 		atime:      now, | ||||
| 		realIP:     realIP, | ||||
| 	} | ||||
| 	session.SetMaxlenRest() | ||||
| 	client.sessions = []*Session{session} | ||||
| @ -204,19 +226,17 @@ func RunNewClient(server *Server, conn clientConn) { | ||||
| 		client.certfp, _ = socket.CertFP() | ||||
| 	} | ||||
| 
 | ||||
| 	remoteAddr := conn.Conn.RemoteAddr() | ||||
| 	if conn.IsTor { | ||||
| 		client.SetMode(modes.TLS, true) | ||||
| 		session.realIP = utils.AddrToIP(remoteAddr) | ||||
| 		// cover up details of the tor proxying infrastructure (not a user privacy concern, | ||||
| 		// but a hardening measure): | ||||
| 		session.proxiedIP = utils.IPv4LoopbackAddress | ||||
| 		session.rawHostname = config.Server.TorListeners.Vhost | ||||
| 	} else { | ||||
| 		session.realIP = utils.AddrToIP(remoteAddr) | ||||
| 		// set the hostname for this client (may be overridden later by PROXY or WEBIRC) | ||||
| 		session.rawHostname = utils.LookupHostname(session.realIP.String()) | ||||
| 		client.cloakedHostname = config.Server.Cloaks.ComputeCloak(session.realIP) | ||||
| 		remoteAddr := conn.Conn.RemoteAddr() | ||||
| 		if utils.AddrIsLocal(remoteAddr) { | ||||
| 			// treat local connections as secure (may be overridden later by WEBIRC) | ||||
| 			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). | ||||
| func (client *Client) Active(session *Session) { | ||||
| 	// TODO normalize all times to utc? | ||||
| 	now := time.Now() | ||||
| 	now := time.Now().UTC() | ||||
| 	client.stateMutex.Lock() | ||||
| 	defer client.stateMutex.Unlock() | ||||
| 	session.atime = now | ||||
| @ -472,7 +491,7 @@ func (client *Client) tryResume() (success bool) { | ||||
| 	success = true | ||||
| 
 | ||||
| 	// this is a bit racey | ||||
| 	client.resumeDetails.ResumedAt = time.Now() | ||||
| 	client.resumeDetails.ResumedAt = time.Now().UTC() | ||||
| 
 | ||||
| 	client.nickTimer.Touch(nil) | ||||
| 
 | ||||
| @ -496,7 +515,7 @@ func (client *Client) tryResume() (success bool) { | ||||
| 	hostname := client.Hostname() | ||||
| 
 | ||||
| 	friends := make(ClientSet) | ||||
| 	oldestLostMessage := time.Now() | ||||
| 	oldestLostMessage := time.Now().UTC() | ||||
| 
 | ||||
| 	// work out how much time, if any, is not covered by history buffers | ||||
| 	for _, channel := range channels { | ||||
| @ -569,7 +588,7 @@ func (client *Client) tryResumeChannels() { | ||||
| 
 | ||||
| 	// replay direct PRIVSMG history | ||||
| 	if !details.Timestamp.IsZero() { | ||||
| 		now := time.Now() | ||||
| 		now := time.Now().UTC() | ||||
| 		items, complete := client.history.Between(details.Timestamp, now, false, 0) | ||||
| 		rb := NewResponseBuffer(client.Sessions()[0]) | ||||
| 		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. | ||||
| // 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 { | ||||
| 		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 { | ||||
| 		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) | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @ -309,8 +309,9 @@ func init() { | ||||
| 			minParams:    4, | ||||
| 		}, | ||||
| 		"WHO": { | ||||
| 			handler:   whoHandler, | ||||
| 			minParams: 1, | ||||
| 			handler:         whoHandler, | ||||
| 			minParams:       1, | ||||
| 			leaveClientIdle: true, | ||||
| 		}, | ||||
| 		"WHOIS": { | ||||
| 			handler:   whoisHandler, | ||||
|  | ||||
| @ -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 | ||||
| func (cl *Limiter) ApplyConfig(config LimiterConfig) error { | ||||
| 	// assemble exempted nets | ||||
| @ -120,6 +109,10 @@ func (cl *Limiter) ApplyConfig(config LimiterConfig) error { | ||||
| 	cl.Lock() | ||||
| 	defer cl.Unlock() | ||||
| 
 | ||||
| 	if cl.population == nil { | ||||
| 		cl.population = make(map[string]int) | ||||
| 	} | ||||
| 
 | ||||
| 	cl.enabled = config.Enabled | ||||
| 	cl.ipv4Mask = net.CIDRMask(config.CidrLenIPv4, 32) | ||||
| 	cl.ipv6Mask = net.CIDRMask(config.CidrLenIPv6, 128) | ||||
|  | ||||
| @ -45,7 +45,7 @@ type GenericThrottle struct { | ||||
| // it either denies it (by returning false) or allows it (by returning true) | ||||
| // and records it | ||||
| 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) { | ||||
| @ -150,17 +150,6 @@ func (ct *Throttler) BanMessage() string { | ||||
| 	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 | ||||
| func (ct *Throttler) ApplyConfig(config ThrottlerConfig) error { | ||||
| 	// assemble exempted nets | ||||
| @ -172,6 +161,10 @@ func (ct *Throttler) ApplyConfig(config ThrottlerConfig) error { | ||||
| 	ct.Lock() | ||||
| 	defer ct.Unlock() | ||||
| 
 | ||||
| 	if ct.population == nil { | ||||
| 		ct.population = make(map[string]ThrottleDetails) | ||||
| 	} | ||||
| 
 | ||||
| 	ct.enabled = config.Enabled | ||||
| 	ct.ipv4Mask = net.CIDRMask(config.CidrLenIPv4, 32) | ||||
| 	ct.ipv6Mask = net.CIDRMask(config.CidrLenIPv6, 128) | ||||
|  | ||||
| @ -72,9 +72,9 @@ func makeTestThrottler(v4len, v6len int) *Throttler { | ||||
| 		ConnectionsPerCidr: maxConnections, | ||||
| 		Duration:           minute, | ||||
| 	} | ||||
| 	throttler := NewThrottler() | ||||
| 	var throttler Throttler | ||||
| 	throttler.ApplyConfig(config) | ||||
| 	return throttler | ||||
| 	return &throttler | ||||
| } | ||||
| 
 | ||||
| func TestConnectionThrottle(t *testing.T) { | ||||
|  | ||||
| @ -34,7 +34,7 @@ type IPBanInfo struct { | ||||
| } | ||||
| 
 | ||||
| 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 { | ||||
| @ -114,7 +114,7 @@ func (dm *DLineManager) AddNetwork(network net.IPNet, duration time.Duration, re | ||||
| 		Reason:      reason, | ||||
| 		OperReason:  operReason, | ||||
| 		OperName:    operName, | ||||
| 		TimeCreated: time.Now(), | ||||
| 		TimeCreated: time.Now().UTC(), | ||||
| 		Duration:    duration, | ||||
| 	} | ||||
| 
 | ||||
|  | ||||
| @ -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") | ||||
| ) | ||||
| 
 | ||||
|  | ||||
| @ -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 | ||||
| } | ||||
|  | ||||
| @ -356,7 +356,7 @@ func (channel *Channel) Rename(name, nameCasefolded string) { | ||||
| 	channel.name = name | ||||
| 	channel.nameCasefolded = nameCasefolded | ||||
| 	if channel.registeredFounder != "" { | ||||
| 		channel.registeredTime = time.Now() | ||||
| 		channel.registeredTime = time.Now().UTC() | ||||
| 	} | ||||
| 	channel.stateMutex.Unlock() | ||||
| } | ||||
|  | ||||
| @ -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) | ||||
| 						} | ||||
| 					} 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) { | ||||
| 					session.sendFromClientInternal(false, splitMsg.Time, splitMsg.Msgid, nickMaskString, accountName, clientOnlyTags, msg.Command, tnick) | ||||
| 				} 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() { | ||||
| @ -2377,7 +2377,7 @@ func setnameHandler(server *Server, client *Client, msg ircmsg.IrcMessage, rb *R | ||||
| 
 | ||||
| // TIME | ||||
| 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 | ||||
| } | ||||
| 
 | ||||
| @ -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 | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
|  | ||||
| @ -176,7 +176,7 @@ func hsRequestHandler(server *Server, client *Client, command string, params []s | ||||
| 		hsNotice(rb, client.t("An error occurred")) | ||||
| 		return | ||||
| 	} | ||||
| 	elapsed := time.Now().Sub(account.VHost.LastRequestTime) | ||||
| 	elapsed := time.Since(account.VHost.LastRequestTime) | ||||
| 	remainingTime := server.AccountConfig().VHosts.UserRequests.Cooldown - elapsed | ||||
| 	// you can update your existing request, but if you were rejected, | ||||
| 	// you can't spam a replacement request | ||||
|  | ||||
| @ -72,7 +72,7 @@ func (km *KLineManager) AddMask(mask string, duration time.Duration, reason, ope | ||||
| 		Reason:      reason, | ||||
| 		OperReason:  operReason, | ||||
| 		OperName:    operName, | ||||
| 		TimeCreated: time.Now(), | ||||
| 		TimeCreated: time.Now().UTC(), | ||||
| 		Duration:    duration, | ||||
| 	} | ||||
| 	km.addMaskInternal(mask, info) | ||||
|  | ||||
| @ -19,13 +19,9 @@ type MonitorManager struct { | ||||
| 	// (all nicks must be normalized externally by casefolding) | ||||
| } | ||||
| 
 | ||||
| // NewMonitorManager returns a new MonitorManager. | ||||
| func NewMonitorManager() *MonitorManager { | ||||
| 	mm := MonitorManager{ | ||||
| 		watching:  make(map[*Client]map[string]bool), | ||||
| 		watchedby: make(map[string]map[*Client]bool), | ||||
| 	} | ||||
| 	return &mm | ||||
| func (mm *MonitorManager) Initialize() { | ||||
| 	mm.watching = make(map[*Client]map[string]bool) | ||||
| 	mm.watchedby = make(map[string]map[*Client]bool) | ||||
| } | ||||
| 
 | ||||
| // AlertAbout alerts everyone monitoring `client`'s nick that `client` is now {on,off}line. | ||||
|  | ||||
| @ -5,6 +5,7 @@ package irc | ||||
| 
 | ||||
| import ( | ||||
| 	"fmt" | ||||
| 	"time" | ||||
| 
 | ||||
| 	"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("Hostname:    %s"), session.hostname)) | ||||
| 		nsNotice(rb, fmt.Sprintf(client.t("Created at:  %s"), session.ctime.Format(IRCv3TimestampFormat))) | ||||
| 		nsNotice(rb, fmt.Sprintf(client.t("Last active: %s"), session.atime.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(time.RFC1123))) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @ -27,7 +27,6 @@ import ( | ||||
| 	"github.com/oragono/oragono/irc/logger" | ||||
| 	"github.com/oragono/oragono/irc/modes" | ||||
| 	"github.com/oragono/oragono/irc/sno" | ||||
| 	"github.com/oragono/oragono/irc/utils" | ||||
| 	"github.com/tidwall/buntdb" | ||||
| ) | ||||
| 
 | ||||
| @ -67,15 +66,15 @@ type Server struct { | ||||
| 	clients             ClientManager | ||||
| 	config              unsafe.Pointer | ||||
| 	configFilename      string | ||||
| 	connectionLimiter   *connection_limits.Limiter | ||||
| 	connectionThrottler *connection_limits.Throttler | ||||
| 	connectionLimiter   connection_limits.Limiter | ||||
| 	connectionThrottler connection_limits.Throttler | ||||
| 	ctime               time.Time | ||||
| 	dlines              *DLineManager | ||||
| 	helpIndexManager    HelpIndexManager | ||||
| 	klines              *KLineManager | ||||
| 	listeners           map[string]*ListenerWrapper | ||||
| 	logger              *logger.Manager | ||||
| 	monitorManager      *MonitorManager | ||||
| 	monitorManager      MonitorManager | ||||
| 	name                string | ||||
| 	nameCasefolded      string | ||||
| 	rehashMutex         sync.Mutex // tier 4 | ||||
| @ -83,7 +82,7 @@ type Server struct { | ||||
| 	pprofServer         *http.Server | ||||
| 	resumeManager       ResumeManager | ||||
| 	signals             chan os.Signal | ||||
| 	snomasks            *SnoManager | ||||
| 	snomasks            SnoManager | ||||
| 	store               *buntdb.DB | ||||
| 	torLimiter          connection_limits.TorLimiter | ||||
| 	whoWas              WhoWasList | ||||
| @ -110,20 +109,19 @@ type clientConn struct { | ||||
| func NewServer(config *Config, logger *logger.Manager) (*Server, error) { | ||||
| 	// initialize data structures | ||||
| 	server := &Server{ | ||||
| 		connectionLimiter:   connection_limits.NewLimiter(), | ||||
| 		connectionThrottler: connection_limits.NewThrottler(), | ||||
| 		listeners:           make(map[string]*ListenerWrapper), | ||||
| 		logger:              logger, | ||||
| 		monitorManager:      NewMonitorManager(), | ||||
| 		rehashSignal:        make(chan os.Signal, 1), | ||||
| 		signals:             make(chan os.Signal, len(ServerExitSignals)), | ||||
| 		snomasks:            NewSnoManager(), | ||||
| 		ctime:        time.Now().UTC(), | ||||
| 		listeners:    make(map[string]*ListenerWrapper), | ||||
| 		logger:       logger, | ||||
| 		rehashSignal: make(chan os.Signal, 1), | ||||
| 		signals:      make(chan os.Signal, len(ServerExitSignals)), | ||||
| 	} | ||||
| 
 | ||||
| 	server.clients.Initialize() | ||||
| 	server.semaphores.Initialize() | ||||
| 	server.resumeManager.Initialize(server) | ||||
| 	server.whoWas.Initialize(config.Limits.WhowasEntries) | ||||
| 	server.monitorManager.Initialize() | ||||
| 	server.snomasks.Initialize() | ||||
| 
 | ||||
| 	if err := server.applyConfig(config, true); err != nil { | ||||
| 		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) { | ||||
| 	// check DLINEs | ||||
| 	isBanned, info := server.dlines.CheckIP(ipaddr) | ||||
| @ -339,7 +313,7 @@ func (server *Server) createListener(addr string, tlsConfig *tls.Config, isTor b | ||||
| 					IsTor: isTor, | ||||
| 				} | ||||
| 				// hand off the connection | ||||
| 				go server.acceptClient(newConn) | ||||
| 				go server.RunClient(newConn) | ||||
| 			} | ||||
| 
 | ||||
| 			if shouldStop { | ||||
| @ -576,7 +550,6 @@ func (server *Server) rehash() error { | ||||
| 
 | ||||
| func (server *Server) applyConfig(config *Config, initial bool) (err error) { | ||||
| 	if initial { | ||||
| 		server.ctime = time.Now() | ||||
| 		server.configFilename = config.Filename | ||||
| 		server.name = config.Server.Name | ||||
| 		server.nameCasefolded = config.Server.nameCasefolded | ||||
|  | ||||
| @ -14,11 +14,8 @@ type SnoManager struct { | ||||
| 	sendLists     map[sno.Mask]map[*Client]bool | ||||
| } | ||||
| 
 | ||||
| // NewSnoManager returns a new SnoManager | ||||
| func NewSnoManager() *SnoManager { | ||||
| 	var m SnoManager | ||||
| func (m *SnoManager) Initialize() { | ||||
| 	m.sendLists = make(map[sno.Mask]map[*Client]bool) | ||||
| 	return &m | ||||
| } | ||||
| 
 | ||||
| // AddMasks adds the given snomasks to the client. | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Daniel Oaks
						Daniel Oaks