diff options
author | Hiroshi SHIBATA <[email protected]> | 2020-11-02 13:44:28 +0900 |
---|---|---|
committer | Hiroshi SHIBATA <[email protected]> | 2020-12-10 18:06:25 +0900 |
commit | 5dc786bf86bb6e0da2639f88659598ec8b9db30d (patch) | |
tree | 87cc4d68088fc7c2616c7c1bef44c36ca10fa01f /tool/lib/webrick/httpauth/htdigest.rb | |
parent | 46d3ea2c2569e2e5a9ee3e7e206f07f0f8b693f5 (diff) |
Move webrick library into internal test toolchain
Notes
Notes:
Merged: https://github.com/ruby/ruby/pull/3729
Diffstat (limited to 'tool/lib/webrick/httpauth/htdigest.rb')
-rw-r--r-- | tool/lib/webrick/httpauth/htdigest.rb | 132 |
1 files changed, 132 insertions, 0 deletions
diff --git a/tool/lib/webrick/httpauth/htdigest.rb b/tool/lib/webrick/httpauth/htdigest.rb new file mode 100644 index 0000000000..93b18e2c75 --- /dev/null +++ b/tool/lib/webrick/httpauth/htdigest.rb @@ -0,0 +1,132 @@ +# frozen_string_literal: false +# +# httpauth/htdigest.rb -- Apache compatible htdigest file +# +# Author: IPR -- Internet Programming with Ruby -- writers +# Copyright (c) 2003 Internet Programming with Ruby writers. All rights +# reserved. +# +# $IPR: htdigest.rb,v 1.4 2003/07/22 19:20:45 gotoyuzo Exp $ + +require_relative 'userdb' +require_relative 'digestauth' +require 'tempfile' + +module WEBrick + module HTTPAuth + + ## + # Htdigest accesses apache-compatible digest password files. Passwords are + # matched to a realm where they are valid. For security, the path for a + # digest password database should be stored outside of the paths available + # to the HTTP server. + # + # Htdigest is intended for use with WEBrick::HTTPAuth::DigestAuth and + # stores passwords using cryptographic hashes. + # + # htpasswd = WEBrick::HTTPAuth::Htdigest.new 'my_password_file' + # htpasswd.set_passwd 'my realm', 'username', 'password' + # htpasswd.flush + + class Htdigest + include UserDB + + ## + # Open a digest password database at +path+ + + def initialize(path) + @path = path + @mtime = Time.at(0) + @digest = Hash.new + @mutex = Thread::Mutex::new + @auth_type = DigestAuth + File.open(@path,"a").close unless File.exist?(@path) + reload + end + + ## + # Reloads passwords from the database + + def reload + mtime = File::mtime(@path) + if mtime > @mtime + @digest.clear + File.open(@path){|io| + while line = io.gets + line.chomp! + user, realm, pass = line.split(/:/, 3) + unless @digest[realm] + @digest[realm] = Hash.new + end + @digest[realm][user] = pass + end + } + @mtime = mtime + end + end + + ## + # Flush the password database. If +output+ is given the database will + # be written there instead of to the original path. + + def flush(output=nil) + output ||= @path + tmp = Tempfile.create("htpasswd", File::dirname(output)) + renamed = false + begin + each{|item| tmp.puts(item.join(":")) } + tmp.close + File::rename(tmp.path, output) + renamed = true + ensure + tmp.close + File.unlink(tmp.path) if !renamed + end + end + + ## + # Retrieves a password from the database for +user+ in +realm+. If + # +reload_db+ is true the database will be reloaded first. + + def get_passwd(realm, user, reload_db) + reload() if reload_db + if hash = @digest[realm] + hash[user] + end + end + + ## + # Sets a password in the database for +user+ in +realm+ to +pass+. + + def set_passwd(realm, user, pass) + @mutex.synchronize{ + unless @digest[realm] + @digest[realm] = Hash.new + end + @digest[realm][user] = make_passwd(realm, user, pass) + } + end + + ## + # Removes a password from the database for +user+ in +realm+. + + def delete_passwd(realm, user) + if hash = @digest[realm] + hash.delete(user) + end + end + + ## + # Iterate passwords in the database. + + def each # :yields: [user, realm, password_hash] + @digest.keys.sort.each{|realm| + hash = @digest[realm] + hash.keys.sort.each{|user| + yield([user, realm, hash[user]]) + } + } + end + end + end +end |