3 # globmask:: glob to test with
4 # netmask:: netmask to test against
5 # Compare a netmask with a standard IRC glob, e.g foo!bar@baz.com would
6 # match *!*@baz.com, foo!*@*, *!bar@*, etc.
7 def Irc.netmaskmatch(globmask, netmask)
8 regmask = globmask.gsub(/\*/, ".*?")
9 return true if(netmask =~ /#{regmask}/)
13 # check if a string is an actual IRC hostmask
19 # User-level authentication to allow/disallow access to bot commands based
20 # on hostmask and userlevel.
22 BotConfig.register BotConfigStringValue.new('auth.password',
23 :default => "Your password for maxing your auth with the bot (used to associate new hostmasks with your owner-status etc)")
25 # create a new IrcAuth instance.
26 # bot:: associated bot class
31 if(File.exist?("#{@bot.botclass}/users.rbot"))
32 IO.foreach("#{@bot.botclass}/users.rbot") do |line|
33 if(line =~ /\s*(\d+)\s*(\S+)/)
40 if(File.exist?("#{@bot.botclass}/levels.rbot"))
41 IO.foreach("#{@bot.botclass}/levels.rbot") do |line|
42 if(line =~ /\s*(\d+)\s*(\S+)/)
45 @levels[command] = level
51 # save current users and levels to files.
52 # levels are written to #{botclass}/levels.rbot
53 # users are written to #{botclass}/users.rbot
55 Dir.mkdir("#{@bot.botclass}") if(!File.exist?("#{@bot.botclass}"))
56 File.open("#{@bot.botclass}/users.rbot", "w") do |file|
57 @users.each do |key, value|
58 file.puts "#{value} #{key}"
61 File.open("#{@bot.botclass}/levels.rbot", "w") do |file|
62 @levels.each do |key, value|
63 file.puts "#{value} #{key}"
68 # command:: command user wishes to perform
69 # mask:: hostmask of user
70 # tell:: optional recipient for "insufficient auth" message
72 # returns true if user with hostmask +mask+ is permitted to perform
73 # +command+ optionally pass tell as the target for the "insufficient auth"
74 # message, if the user is not authorised
75 def allow?(command, mask, tell=nil)
76 auth = userlevel(mask)
77 if(auth >= @levels[command])
80 debug "#{mask} is not allowed to perform #{command}"
81 @bot.say tell, "insufficient \"#{command}\" auth (have #{auth}, need #{@levels[command]})" if tell
86 # add user with hostmask matching +mask+ with initial auth level +level+
87 def useradd(mask, level)
93 # mask:: mask of user to remove
94 # remove user with mask +mask+
101 # command:: command to adjust
102 # level:: new auth level for the command
103 # set required auth level of +command+ to +level+
104 def setlevel(command, level)
105 @levels[command] = level
109 # mask:: mask of user
110 # returns the authlevel of user with mask +mask+
111 # finds the matching user which has the highest authlevel (so you can have
112 # a default level of 5 for *!*@*, and yet still give higher levels to
114 # go through hostmask list, find match with _highest_ level (all users
117 @users.each {|user,userlevel|
118 if(Irc.netmaskmatch(user, mask))
119 level = userlevel if userlevel > level
125 # return all currently defined commands (for which auth is required) and
126 # their required authlevels
128 reply = "Current levels are:"
129 @levels.sort.each {|a|
132 reply += " #{key}(#{value})"
137 # return all currently defined users and their authlevels
139 reply = "Current users are:"
140 @users.sort.each {|a|
143 reply += " #{key}(#{value})"
152 return "setlevel <command> <level> => Sets required level for <command> to <level> (private addressing only)"
154 return "useradd <mask> <level> => Add user <mask> at level <level> (private addressing only)"
156 return "userdel <mask> => Remove user <mask> (private addressing only)"
158 return "auth <masterpw> => Recognise your hostmask as bot master (private addressing only)"
160 return "levels => list commands and their required levels (private addressing only)"
162 return "users => list users and their levels (private addressing only)"
164 return "Auth module (User authentication) topics: setlevel, useradd, userdel, auth, levels, users"
170 if(m.address? && m.private?)
172 when (/^setlevel\s+(\S+)\s+(\d+)$/)
173 if(@bot.auth.allow?("auth", m.source, m.replyto))
174 @bot.auth.setlevel($1, $2.to_i)
175 m.reply "level for #$1 set to #$2"
177 when (/^useradd\s+(\S+)\s+(\d+)/)
178 if(@bot.auth.allow?("auth", m.source, m.replyto))
179 @bot.auth.useradd($1, $2.to_i)
180 m.reply "added user #$1 at level #$2"
182 when (/^userdel\s+(\S+)/)
183 if(@bot.auth.allow?("auth", m.source, m.replyto))
184 @bot.auth.userdel($1)
185 m.reply "user #$1 is gone"
187 when (/^auth\s+(\S+)/)
188 if($1 == @bot.config["auth.password"])
189 @bot.auth.useradd(Regexp.escape(m.source), 1000)
190 m.reply "Identified, security level maxed out"
192 m.reply "incorrect password"
195 m.reply @bot.auth.showlevels if(@bot.auth.allow?("config", m.source, m.replyto))
197 m.reply @bot.auth.showusers if(@bot.auth.allow?("config", m.source, m.replyto))