Enforce channel keys, invites, +s and +H on the IRC listener (closes #122)
check / check (push) Waiting to run
check / check (push) Waiting to run
The IRC listener's JOIN now passes the channel key on, INVITE records the invite, LIST and WHOIS hide +s channels from non-members with the queries the HTTP API uses, and PRIVMSG to a +H channel gets 404. The INVITE checks and the channel hashcash check move from the HTTP handlers into the service, so both transports run the same code. An IRC client cannot attach a stamp, so its PRIVMSG to a +H channel always fails that check. The unfiltered channel list query, now unused, is removed. Model: opus-5-5 Co-authored-by: clawbot <sneak+clawbot@sneak.cloud>
This commit was merged in pull request #139.
This commit is contained in:
@@ -150,7 +150,9 @@ func (c *Conn) handlePrivmsg(
|
||||
}
|
||||
|
||||
// handleJoin joins one or more channels via the shared
|
||||
// service layer.
|
||||
// service layer. The optional second parameter holds the
|
||||
// channel keys, comma-separated in the order of the
|
||||
// channels.
|
||||
func (c *Conn) handleJoin(
|
||||
ctx context.Context,
|
||||
msg *Message,
|
||||
@@ -164,14 +166,24 @@ func (c *Conn) handleJoin(
|
||||
return
|
||||
}
|
||||
|
||||
for chanName := range strings.SplitSeq(msg.Params[0], ",") {
|
||||
var keys []string
|
||||
if len(msg.Params) > 1 {
|
||||
keys = strings.Split(msg.Params[1], ",")
|
||||
}
|
||||
|
||||
for idx, chanName := range strings.Split(msg.Params[0], ",") {
|
||||
chanName = strings.TrimSpace(chanName)
|
||||
|
||||
if !strings.HasPrefix(chanName, "#") {
|
||||
chanName = "#" + chanName
|
||||
}
|
||||
|
||||
c.joinChannel(ctx, chanName)
|
||||
key := ""
|
||||
if idx < len(keys) {
|
||||
key = keys[idx]
|
||||
}
|
||||
|
||||
c.joinChannel(ctx, chanName, key)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -179,10 +191,10 @@ func (c *Conn) handleJoin(
|
||||
// and delivers topic/names on the wire.
|
||||
func (c *Conn) joinChannel(
|
||||
ctx context.Context,
|
||||
channel string,
|
||||
channel, key string,
|
||||
) {
|
||||
result, err := c.svc.JoinChannel(
|
||||
ctx, c.sessionID, c.nick, channel, "",
|
||||
ctx, c.sessionID, c.nick, channel, key,
|
||||
)
|
||||
if err != nil {
|
||||
c.sendIRCError(err)
|
||||
@@ -763,10 +775,11 @@ func (c *Conn) handleNames(
|
||||
c.deliverNames(ctx, channel, chID)
|
||||
}
|
||||
|
||||
// handleList sends the channel list.
|
||||
// handleList sends the channel list, leaving out +s
|
||||
// channels the user is not on.
|
||||
func (c *Conn) handleList(ctx context.Context) {
|
||||
channels, err := c.database.ListAllChannelsWithCounts(
|
||||
ctx,
|
||||
channels, err := c.database.ListAllChannelsWithCountsFiltered(
|
||||
ctx, c.sessionID,
|
||||
)
|
||||
if err != nil {
|
||||
c.sendNumeric(
|
||||
@@ -886,14 +899,15 @@ func (c *Conn) whoisOper(
|
||||
}
|
||||
}
|
||||
|
||||
// whoisChannels sends 319 RPL_WHOISCHANNELS.
|
||||
// whoisChannels sends 319 RPL_WHOISCHANNELS, leaving out
|
||||
// +s channels the querier is not on.
|
||||
func (c *Conn) whoisChannels(
|
||||
ctx context.Context,
|
||||
target string,
|
||||
targetID int64,
|
||||
) {
|
||||
userChannels, _ := c.database.GetSessionChannels(
|
||||
ctx, targetID,
|
||||
userChannels, _ := c.database.GetSessionChannelsFiltered(
|
||||
ctx, targetID, c.sessionID,
|
||||
)
|
||||
if len(userChannels) == 0 {
|
||||
return
|
||||
@@ -1230,36 +1244,11 @@ func (c *Conn) handleInvite(
|
||||
targetNick := msg.Params[0]
|
||||
channel := msg.Params[1]
|
||||
|
||||
chID, err := c.database.GetChannelByName(ctx, channel)
|
||||
if err != nil {
|
||||
c.sendNumeric(
|
||||
irc.ErrNoSuchChannel,
|
||||
channel, "No such channel",
|
||||
)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
isMember, _ := c.database.IsChannelMember(
|
||||
ctx, chID, c.sessionID,
|
||||
)
|
||||
if !isMember {
|
||||
c.sendNumeric(
|
||||
irc.ErrNotOnChannel,
|
||||
channel, "You're not on that channel",
|
||||
)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
targetID, err := c.database.GetSessionByNick(
|
||||
ctx, targetNick,
|
||||
targetID, err := c.svc.InviteUser(
|
||||
ctx, c.sessionID, c.nick, targetNick, channel,
|
||||
)
|
||||
if err != nil {
|
||||
c.sendNumeric(
|
||||
irc.ErrNoSuchNick,
|
||||
targetNick, "No such nick",
|
||||
)
|
||||
c.sendIRCError(err)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user