class BasicAuth::Htpasswd
Attributes
path[RW]
realm[RW]
Public Class Methods
_to64(v, n)
click to toggle source
# File lib/basic_auth/htpasswd.rb, line 114 def Htpasswd._to64(v, n) chars = "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" output = "" n.times do output << chars[v & 0x3f] v >>= 6 end output end
crypt_md5(pass, salt)
click to toggle source
# File lib/basic_auth/htpasswd.rb, line 77 def Htpasswd.crypt_md5(pass, salt) ctx = Digest::MD5.new.update("#{pass}$apr1$#{salt}") final = Digest::MD5.new.update("#{pass}#{salt}#{pass}").digest!.bytes l = pass.length while l > 0 ctx.update(final[0 .. (l > 16 ? 16 : l) - 1].pack("C*")) l -= 16 end l = pass.length while l > 0 ctx.update(l % 2 != 0 ? "\0" : pass[0]) l >>= 1 end final = ctx.digest! 1000.times do |i| ctx = Digest::MD5.new ctx.update(i % 2 != 0 ? pass : final) ctx.update(salt) if i % 3 != 0 ctx.update(pass) if i % 7 != 0 ctx.update(i % 2 != 0 ? final : pass) final = ctx.digest! end final = final.bytes hash = "" for a, b, c in [[0, 6, 12], [1, 7, 13], [2, 8, 14], [3, 9, 15], [4, 10, 5]] hash << _to64(final[a] << 16 | final[b] << 8 | final[c], 4) end hash << _to64(final[11], 2) "$apr1$#{salt}$#{hash}" end
crypt_sha1(pass)
click to toggle source
# File lib/basic_auth/htpasswd.rb, line 124 def Htpasswd.crypt_sha1(pass) "{SHA}" + [Digest::SHA1.new.update(pass).digest!].pack("m").chomp end
new(path, realm=nil)
click to toggle source
# File lib/basic_auth/htpasswd.rb, line 33 def initialize(path, realm=nil) @path = path @realm = realm end
validate(pass, hash)
click to toggle source
# File lib/basic_auth/htpasswd.rb, line 128 def Htpasswd.validate(pass, hash) if /^\$apr1\$(.*)\$/.match(hash) encoded = crypt_md5(pass, $1) elsif /^{SHA}/.match(hash) encoded = crypt_sha1(pass) else raise "crypt-style password hash is not supported" end return encoded == hash end
Public Instance Methods
call(env)
click to toggle source
# File lib/basic_auth/htpasswd.rb, line 38 def call(env) if /\/\.ht/.match(env['PATH_INFO']) return [ 404, { "Content-Type" => "text/plain" }, [ "not found" ] ] end auth = env['HTTP_AUTHORIZATION'] # Example: Basic dXNlcjpwYXNz # dXNlcjpwYXNz is base64 encoded if auth method, cred = *auth.split(' ') if method.casecmp("basic") == 0 user, pass = cred.unpack("m")[0].split(':', 2) begin if validate(user, pass) return true end rescue => e $stderr.puts "failed to validate password using file:#{@path}:#{e.message}" return false end end end false end
data()
click to toggle source
# File lib/basic_auth/htpasswd.rb, line 72 def data return @@data if @@data && !ENV['BASIC_AUTH_NO_CACHE'] @@data = File.readlines(@path) end
validate(user, pass)
click to toggle source
# File lib/basic_auth/htpasswd.rb, line 61 def validate(user, pass) data.each do |line| line_user, hash = line.chomp.split(':', 2) if user == line_user && self.class.validate(pass, hash) return true end end return false end