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 # create a new IrcAuth instance.
23 # bot:: associated bot class
28 if(File.exist?("#{@bot.botclass}/users.rbot"))
29 IO.foreach("#{@bot.botclass}/users.rbot") do |line|
30 if(line =~ /\s*(\d+)\s*(\S+)/)
37 if(File.exist?("#{@bot.botclass}/levels.rbot"))
38 IO.foreach("#{@bot.botclass}/levels.rbot") do |line|
39 if(line =~ /\s*(\d+)\s*(\S+)/)
42 @levels[command] = level
48 # save current users and levels to files.
49 # levels are written to #{botclass}/levels.rbot
50 # users are written to #{botclass}/users.rbot
52 Dir.mkdir("#{@bot.botclass}") if(!File.exist?("#{@bot.botclass}"))
53 File.open("#{@bot.botclass}/users.rbot", "w") do |file|
54 @users.each do |key, value|
55 file.puts "#{value} #{key}"
58 File.open("#{@bot.botclass}/levels.rbot", "w") do |file|
59 @levels.each do |key, value|
60 file.puts "#{value} #{key}"
65 # command:: command user wishes to perform
66 # mask:: hostmask of user
67 # tell:: optional recipient for "insufficient auth" message
69 # returns true if user with hostmask +mask+ is permitted to perform
70 # +command+ optionally pass tell as the target for the "insufficient auth"
71 # message, if the user is not authorised
72 def allow?(command, mask, tell=nil)
73 auth = userlevel(mask)
74 if(auth >= @levels[command])
77 debug "#{mask} is not allowed to perform #{command}"
78 @bot.say tell, "insufficient \"#{command}\" auth (have #{auth}, need #{@levels[command]})" if tell
83 # add user with hostmask matching +mask+ with initial auth level +level+
84 def useradd(mask, level)
90 # mask:: mask of user to remove
91 # remove user with mask +mask+
98 # command:: command to adjust
99 # level:: new auth level for the command
100 # set required auth level of +command+ to +level+
101 def setlevel(command, level)
102 @levels[command] = level
106 # mask:: mask of user
107 # returns the authlevel of user with mask +mask+
108 # finds the matching user which has the highest authlevel (so you can have
109 # a default level of 5 for *!*@*, and yet still give higher levels to
111 # go through hostmask list, find match with _highest_ level (all users
114 @users.each {|user,userlevel|
115 if(Irc.netmaskmatch(user, mask))
116 level = userlevel if userlevel > level
122 # return all currently defined commands (for which auth is required) and
123 # their required authlevels
125 reply = "Current levels are:"
126 @levels.sort.each {|a|
129 reply += " #{key}(#{value})"
134 # return all currently defined users and their authlevels
136 reply = "Current users are:"
137 @users.sort.each {|a|
140 reply += " #{key}(#{value})"
149 return "setlevel <command> <level> => Sets required level for <command> to <level> (private addressing only)"
151 return "useradd <mask> <level> => Add user <mask> at level <level> (private addressing only)"
153 return "userdel <mask> => Remove user <mask> (private addressing only)"
155 return "auth <masterpw> => Recognise your hostmask as bot master (private addressing only)"
157 return "levels => list commands and their required levels (private addressing only)"
159 return "users => list users and their levels (private addressing only)"
161 return "Auth module (User authentication) topics: setlevel, useradd, userdel, auth, levels, users"
167 if(m.address? && m.private?)
169 when (/^setlevel\s+(\S+)\s+(\d+)$/)
170 if(@bot.auth.allow?("auth", m.source, m.replyto))
171 @bot.auth.setlevel($1, $2.to_i)
172 m.reply "level for #$1 set to #$2"
174 when (/^useradd\s+(\S+)\s+(\d+)/)
175 if(@bot.auth.allow?("auth", m.source, m.replyto))
176 @bot.auth.useradd($1, $2.to_i)
177 m.reply "added user #$1 at level #$2"
179 when (/^userdel\s+(\S+)/)
180 if(@bot.auth.allow?("auth", m.source, m.replyto))
181 @bot.auth.userdel($1)
182 m.reply "user #$1 is gone"
184 when (/^auth\s+(\S+)/)
185 if($1 == @bot.config["PASSWD"])
186 @bot.auth.useradd(Regexp.escape(m.source), 1000)
187 m.reply "Identified, security level maxed out"
189 m.reply "incorrect password"
192 m.reply @bot.auth.showlevels if(@bot.auth.allow?("config", m.source, m.replyto))
194 m.reply @bot.auth.showusers if(@bot.auth.allow?("config", m.source, m.replyto))