Beispiel #1
0
func (p *Plugin) dumpBans(target string) {
	num := 0

	// Fetch ban list
	banlist, err := p.mode.Bans(target)
	if err != nil {
		logging.Warn("Could not fetch ban list, old bans won't get handled")
		return
	}

	tbmgr := p.ensureTemporaryBanManager(target)

	// Save only bans from us
	for _, ban := range banlist {
		if ban.Nick != p.bot.Me().Nick {
			// Not a ban from us (going by the nickname at least)
			isOldHostmask := false
			for _, hostmask := range p.OldHostmasks {
				// TODO - Test this implementation
				hostmask = regexp.QuoteMeta(hostmask)
				hostmask = strings.Replace(hostmask, "\\*", ".*", -1)
				hostmask = strings.Replace(hostmask, "\\?", ".?", -1)
				if matched, err := regexp.MatchString(hostmask, ban.Src); matched {
					isOldHostmask = true
					break
				} else if err != nil {
					logging.Error("vpnbot.Plugin: dumpBans regular expression failed: %v",
						err)
					break
				}
			}
			if !isOldHostmask {
				// Not a ban from an old hostmask either
				continue
			}
		}

		if _, ok := tbmgr.Get(ban.Hostmask); ok {
			// We already have this ban saved
			continue
		}

		if err := tbmgr.Add(NewTemporaryBan(
			ban.Nick,
			ban.Hostmask,
			ban.Src,
			"Migrated old ban",
			48*time.Hour+ban.Timestamp.Sub(time.Now()))); err != nil {
			logging.Warn("Could not migrate ban on %v: %v", ban.Hostmask, err)
		}

		num++
	}

	if num > 0 {
		p.syncBans(target)
		logging.Info("Migrated %v bans", num)
	}
}
Beispiel #2
0
// Removes a Nick from being tracked.
func (st *stateTracker) DelNick(n string) {
	if nk, ok := st.nicks[n]; ok {
		if nk != st.me {
			st.delNick(nk)
		} else {
			logging.Warn("Tracker.DelNick(): won't delete myself.")
		}
	} else {
		logging.Warn("Tracker.DelNick(): %s not tracked.", n)
	}
}
Beispiel #3
0
// Removes a nick from being tracked.
func (st *stateTracker) DelNick(n string) *Nick {
	st.mu.Lock()
	defer st.mu.Unlock()
	if nk, ok := st.nicks[n]; ok {
		if nk == st.me {
			logging.Warn("Tracker.DelNick(): won't delete myself.")
			return nil
		}
		st.delNick(nk)
		return nk.Nick()
	}
	logging.Warn("Tracker.DelNick(): %s not tracked.", n)
	return nil
}
Beispiel #4
0
// Creates a new Channel, initialises it, and stores it so it
// can be properly tracked for state management purposes.
func (st *stateTracker) NewChannel(c string) *Channel {
	if c == "" {
		logging.Warn("Tracker.NewChannel(): Not tracking empty channel.")
		return nil
	}
	st.mu.Lock()
	defer st.mu.Unlock()
	if _, ok := st.chans[c]; ok {
		logging.Warn("Tracker.NewChannel(): %s already tracked.", c)
		return nil
	}
	st.chans[c] = newChannel(c)
	return st.chans[c].Channel()
}
Beispiel #5
0
// Creates a new nick, initialises it, and stores it so it
// can be properly tracked for state management purposes.
func (st *stateTracker) NewNick(n string) *Nick {
	if n == "" {
		logging.Warn("Tracker.NewNick(): Not tracking empty nick.")
		return nil
	}
	st.mu.Lock()
	defer st.mu.Unlock()
	if _, ok := st.nicks[n]; ok {
		logging.Warn("Tracker.NewNick(): %s already tracked.", n)
		return nil
	}
	st.nicks[n] = newNick(n)
	return st.nicks[n].Nick()
}
// Handle 352 who reply
func (conn *Conn) h_352(line *Line) {
	nk := conn.st.GetNick(line.Args[5])
	if nk == nil {
		logging.Warn("irc.352(): received WHO reply for unknown nick %s",
			line.Args[5])
		return
	}
	if conn.Me().Equals(nk) {
		return
	}
	// XXX: do we care about the actual server the nick is on?
	//      or the hop count to this server?
	// last arg contains "<hop count> <real name>"
	a := strings.SplitN(line.Args[len(line.Args)-1], " ", 2)
	conn.st.NickInfo(nk.Nick, line.Args[2], line.Args[3], a[1])
	if idx := strings.Index(line.Args[6], "*"); idx != -1 {
		conn.st.NickModes(nk.Nick, "+o")
	}
	if idx := strings.Index(line.Args[6], "B"); idx != -1 {
		conn.st.NickModes(nk.Nick, "+B")
	}
	if idx := strings.Index(line.Args[6], "H"); idx != -1 {
		conn.st.NickModes(nk.Nick, "+i")
	}
}
Beispiel #7
0
// Removes a Channel from being tracked.
func (st *stateTracker) DelChannel(c string) {
	if ch, ok := st.chans[c]; ok {
		st.delChannel(ch)
	} else {
		logging.Warn("Tracker.DelChannel(): %s not tracked.", c)
	}
}
Beispiel #8
0
func migrated(coll string) bool {
	var d done
	if err := ms.db.Get(K{{"collection", coll}}, &d); err != nil {
		logging.Warn("Checking migrated status for %q: %v", coll, err)
	}
	return d.Migrated
}
// Handle 352 who reply
func (conn *Conn) h_352(line *Line) {
	nk := conn.st.GetNick(line.Args[5])
	if nk == nil {
		logging.Warn("irc.352(): received WHO reply for unknown nick %s",
			line.Args[5])
		return
	}
	if nk == conn.Me() {
		return
	}
	nk.Ident = line.Args[2]
	nk.Host = line.Args[3]
	// XXX: do we care about the actual server the nick is on?
	//      or the hop count to this server?
	// last arg contains "<hop count> <real name>"
	a := strings.SplitN(line.Args[len(line.Args)-1], " ", 2)
	nk.Name = a[1]
	if idx := strings.Index(line.Args[6], "*"); idx != -1 {
		nk.Modes.Oper = true
	}
	if idx := strings.Index(line.Args[6], "B"); idx != -1 {
		nk.Modes.Bot = true
	}
	if idx := strings.Index(line.Args[6], "H"); idx != -1 {
		nk.Modes.Invisible = true
	}
}
Beispiel #10
0
// Dissociates an already known nick from an already known channel.
// Does some tidying up to stop tracking nicks we're no longer on
// any common channels with, and channels we're no longer on.
func (st *stateTracker) Dissociate(ch *Channel, nk *Nick) {
	if ch == nil || nk == nil {
		logging.Error("Tracker.Dissociate(): passed nil values :-(")
	} else if _ch, ok := st.chans[ch.Name]; !ok || ch != _ch {
		// As we can implicitly delete both nicks and channels from being
		// tracked by dissociating one from the other, we should verify that
		// we're not being passed an old Nick or Channel.
		logging.Error("Tracker.Dissociate(): channel %s not found in "+
			"(or differs from) internal state.", ch.Name)
	} else if _nk, ok := st.nicks[nk.Nick]; !ok || nk != _nk {
		logging.Error("Tracker.Dissociate(): nick %s not found in "+
			"(or differs from) internal state.", nk.Nick)
	} else if _, ok := nk.IsOn(ch); !ok {
		logging.Warn("Tracker.Dissociate(): %s not on %s.",
			nk.Nick, ch.Name)
	} else if nk == st.me {
		// I'm leaving the channel for some reason, so it won't be tracked.
		st.delChannel(ch)
	} else {
		// Remove the nick from the channel and the channel from the nick.
		ch.delNick(nk)
		nk.delChannel(ch)
		if len(nk.chans) == 0 {
			// We're no longer in any channels with this nick.
			st.delNick(nk)
		}
	}
}
// Handle JOINs to channels to maintain state
func (conn *Conn) h_JOIN(line *Line) {
	ch := conn.st.GetChannel(line.Args[0])
	nk := conn.st.GetNick(line.Nick)
	if ch == nil {
		// first we've seen of this channel, so should be us joining it
		// NOTE this will also take care of nk == nil && ch == nil
		if nk != conn.cfg.Me {
			logging.Warn("irc.JOIN(): JOIN to unknown channel %s received "+
				"from (non-me) nick %s", line.Args[0], line.Nick)
			return
		}
		ch = conn.st.NewChannel(line.Args[0])
		// since we don't know much about this channel, ask server for info
		// we get the channel users automatically in 353 and the channel
		// topic in 332 on join, so we just need to get the modes
		conn.Mode(ch.Name)
		// sending a WHO for the channel is MUCH more efficient than
		// triggering a WHOIS on every nick from the 353 handler
		conn.Who(ch.Name)
	}
	if nk == nil {
		// this is the first we've seen of this nick
		nk = conn.st.NewNick(line.Nick)
		nk.Ident = line.Ident
		nk.Host = line.Host
		// since we don't know much about this nick, ask server for info
		conn.Who(nk.Nick)
	}
	// this takes care of both nick and channel linking \o/
	conn.st.Associate(ch, nk)
}
Beispiel #12
0
func (p *Plugin) syncBans(target string) {
	// Synchronize bans to file
	logging.Debug("Synchronizing temporary bans for %v to disk...", target)
	fn := p.getTempbansFilename(target)
	f, err := os.Create(fn)
	if err != nil {
		logging.Warn("Could not save temporary bans for %v: %v",
			fn, target, err.Error())
	}
	defer f.Close()

	// Load temporary bans from this file
	if err := p.ensureTemporaryBanManager(target).Export(f); err != nil {
		logging.Warn("Could not save temporary bans: %v", err.Error())
	}
}
Beispiel #13
0
// Associates an already known nick with an already known channel.
func (st *stateTracker) Associate(ch *Channel, nk *Nick) *ChanPrivs {
	if ch == nil || nk == nil {
		logging.Error("Tracker.Associate(): passed nil values :-(")
		return nil
	} else if _ch, ok := st.chans[ch.Name]; !ok || ch != _ch {
		// As we can implicitly delete both nicks and channels from being
		// tracked by dissociating one from the other, we should verify that
		// we're not being passed an old Nick or Channel.
		logging.Error("Tracker.Associate(): channel %s not found in "+
			"(or differs from) internal state.", ch.Name)
		return nil
	} else if _nk, ok := st.nicks[nk.Nick]; !ok || nk != _nk {
		logging.Error("Tracker.Associate(): nick %s not found in "+
			"(or differs from) internal state.", nk.Nick)
		return nil
	} else if _, ok := nk.IsOn(ch); ok {
		logging.Warn("Tracker.Associate(): %s already on %s.",
			nk.Nick, ch.Name)
		return nil
	}
	cp := new(ChanPrivs)
	ch.addNick(nk, cp)
	nk.addChannel(ch, cp)
	return cp
}
Beispiel #14
0
// Dissociates an already known nick from an already known channel.
// Does some tidying up to stop tracking nicks we're no longer on
// any common channels with, and channels we're no longer on.
func (st *stateTracker) Dissociate(c, n string) {
	st.mu.Lock()
	defer st.mu.Unlock()
	nk, nok := st.nicks[n]
	ch, c*k := st.chans[c]

	if !c*k {
		// As we can implicitly delete both nicks and channels from being
		// tracked by dissociating one from the other, we should verify that
		// we're not being passed an old Nick or Channel.
		logging.Error("Tracker.Dissociate(): channel %s not found in "+
			"internal state.", c)
	} else if !nok {
		logging.Error("Tracker.Dissociate(): nick %s not found in "+
			"internal state.", n)
	} else if _, ok := nk.isOn(ch); !ok {
		logging.Warn("Tracker.Dissociate(): %s not on %s.",
			nk.nick, ch.name)
	} else if nk == st.me {
		// I'm leaving the channel for some reason, so it won't be tracked.
		st.delChannel(ch)
	} else {
		// Remove the nick from the channel and the channel from the nick.
		ch.delNick(nk)
		nk.delChannel(ch)
		if len(nk.chans) == 0 {
			// We're no longer in any channels with this nick.
			st.delNick(nk)
		}
	}
}
Beispiel #15
0
// Associates an already known nick with an already known channel.
func (st *stateTracker) Associate(c, n string) *ChanPrivs {
	st.mu.Lock()
	defer st.mu.Unlock()
	nk, nok := st.nicks[n]
	ch, c*k := st.chans[c]

	if !c*k {
		// As we can implicitly delete both nicks and channels from being
		// tracked by dissociating one from the other, we should verify that
		// we're not being passed an old Nick or Channel.
		logging.Error("Tracker.Associate(): channel %s not found in "+
			"internal state.", c)
		return nil
	} else if !nok {
		logging.Error("Tracker.Associate(): nick %s not found in "+
			"internal state.", n)
		return nil
	} else if _, ok := nk.isOn(ch); ok {
		logging.Warn("Tracker.Associate(): %s already on %s.",
			nk, ch)
		return nil
	}
	cp := new(ChanPrivs)
	ch.addNick(nk, cp)
	nk.addChannel(ch, cp)
	return cp.Copy()
}
// Handle 332 topic reply on join to channel
func (conn *Conn) h_332(line *Line) {
	if ch := conn.st.GetChannel(line.Args[1]); ch != nil {
		ch.Topic = line.Args[2]
	} else {
		logging.Warn("irc.332(): received TOPIC value for unknown channel %s",
			line.Args[1])
	}
}
// Handle 324 mode reply
func (conn *Conn) h_324(line *Line) {
	if ch := conn.st.GetChannel(line.Args[1]); ch != nil {
		ch.ParseModes(line.Args[2], line.Args[3:]...)
	} else {
		logging.Warn("irc.324(): received MODE settings for unknown channel %s",
			line.Args[1])
	}
}
// Handle 311 whois reply
func (conn *Conn) h_311(line *Line) {
	if nk := conn.st.GetNick(line.Args[1]); nk != nil && !conn.Me().Equals(nk) {
		conn.st.NickInfo(line.Args[1], line.Args[2], line.Args[3], line.Args[5])
	} else {
		logging.Warn("irc.311(): received WHOIS info for unknown nick %s",
			line.Args[1])
	}
}
Beispiel #19
0
// Creates a new Nick, initialises it, and stores it so it
// can be properly tracked for state management purposes.
func (st *stateTracker) NewNick(n string) *Nick {
	if _, ok := st.nicks[n]; ok {
		logging.Warn("Tracker.NewNick(): %s already tracked.", n)
		return nil
	}
	st.nicks[n] = NewNick(n)
	return st.nicks[n]
}
Beispiel #20
0
// Creates a new Channel, initialises it, and stores it so it
// can be properly tracked for state management purposes.
func (st *stateTracker) NewChannel(c string) *Channel {
	if _, ok := st.chans[c]; ok {
		logging.Warn("Tracker.NewChannel(): %s already tracked.", c)
		return nil
	}
	st.chans[c] = NewChannel(c)
	return st.chans[c]
}
Beispiel #21
0
// Associates a Nick with a Channel
func (ch *Channel) addNick(nk *Nick, cp *ChanPrivs) {
	if _, ok := ch.nicks[nk]; !ok {
		ch.nicks[nk] = cp
		ch.lookup[nk.Nick] = nk
	} else {
		logging.Warn("Channel.addNick(): %s already on %s.", nk.Nick, ch.Name)
	}
}
Beispiel #22
0
// Disassociates a Nick from a Channel.
func (ch *Channel) delNick(nk *Nick) {
	if _, ok := ch.nicks[nk]; ok {
		delete(ch.nicks, nk)
		delete(ch.lookup, nk.Nick)
	} else {
		logging.Warn("Channel.delNick(): %s not on %s.", nk.Nick, ch.Name)
	}
}
// Handle 671 whois reply (nick connected via SSL)
func (conn *Conn) h_671(line *Line) {
	if nk := conn.st.GetNick(line.Args[1]); nk != nil {
		nk.Modes.SSL = true
	} else {
		logging.Warn("irc.671(): received WHOIS SSL info for unknown nick %s",
			line.Args[1])
	}
}
// Handle TOPIC changes for channels
func (conn *Conn) h_TOPIC(line *Line) {
	if ch := conn.st.GetChannel(line.Args[0]); ch != nil {
		ch.Topic = line.Args[1]
	} else {
		logging.Warn("irc.TOPIC(): topic change on unknown channel %s",
			line.Args[0])
	}
}
Beispiel #25
0
// Disassociates a Channel from a Nick.
func (nk *nick) delChannel(ch *channel) {
	if _, ok := nk.chans[ch]; ok {
		delete(nk.chans, ch)
		delete(nk.lookup, ch.name)
	} else {
		logging.Warn("Nick.delChannel(): %s not on %s.", nk.nick, ch.name)
	}
}
Beispiel #26
0
// Associates a Channel with a Nick.
func (nk *nick) addChannel(ch *channel, cp *ChanPrivs) {
	if _, ok := nk.chans[ch]; !ok {
		nk.chans[ch] = cp
		nk.lookup[ch.name] = ch
	} else {
		logging.Warn("Nick.addChannel(): %s already on %s.", nk.nick, ch.name)
	}
}
// Handle MODE changes for channels we know about (and our nick personally)
func (conn *Conn) h_MODE(line *Line) {
	if ch := conn.st.GetChannel(line.Args[0]); ch != nil {
		// channel modes first
		ch.ParseModes(line.Args[1], line.Args[2:]...)
	} else if nk := conn.st.GetNick(line.Args[0]); nk != nil {
		// nick mode change, should be us
		if nk != conn.cfg.Me {
			logging.Warn("irc.MODE(): recieved MODE %s for (non-me) nick %s",
				line.Args[1], line.Args[0])
			return
		}
		nk.ParseModes(line.Args[1])
	} else {
		logging.Warn("irc.MODE(): not sure what to do with MODE %s",
			strings.Join(line.Args, " "))
	}
}
Beispiel #28
0
func (line *Line) argslen(minlen int) bool {
	pc, _, _, _ := runtime.Caller(1)
	fn := runtime.FuncForPC(pc)
	if len(line.Args) <= minlen {
		logging.Warn("%s: too few arguments: %s", fn.Name(), strings.Join(line.Args, " "))
		return false
	}
	return true
}
Beispiel #29
0
// Creates a new plugin instance.
func New(b bot.Bot) *Plugin {
	plugin := &Plugin{
		bot: b,
	}

	// Handle INVITE
	b.HandleFunc("invite",
		func(conn *client.Conn, line *client.Line) {
			if len(line.Args) < 2 {
				return
			}
			channel := line.Args[1]
			joinChan := make(chan interface{})

			go func() {
				defer conn.HandleFunc("join",
					func(conn *client.Conn, line *client.Line) {
						// Is this us joining somewhere?
						if line.Nick != conn.Me().Nick {
							return
						}

						// JOIN message should always have a channel sent with it
						if len(line.Args) < 1 {
							return
						}

						// Is this the channel we got invited to?
						if line.Args[0] != channel {
							return
						}

						// Yup, we're done here
						joinChan <- struct{}{}
					}).Remove()

				select {
				case <-time.After(10 * time.Second):
					// Oops, we timed out
					logging.Warn("Timed out while waiting for us to join %v",
						channel)
					return
				case <-joinChan:
				}

				// We have joined successfully, let's send our hello message!
				b.Privmsg(channel, "Hi, I'm vpn, I automatically get rid of bad "+
					"IP-changing ban evading bots! I need half-op (+h/%) to do "+
					"this properly, thank you!")
			}()

			// Join and wait until joined
			b.Join(channel)
		})

	return plugin
}
// Handle 311 whois reply
func (conn *Conn) h_311(line *Line) {
	if nk := conn.st.GetNick(line.Args[1]); nk != nil && nk != conn.Me() {
		nk.Ident = line.Args[2]
		nk.Host = line.Args[3]
		nk.Name = line.Args[5]
	} else {
		logging.Warn("irc.311(): received WHOIS info for unknown nick %s",
			line.Args[1])
	}
}