lib/localhost/authority.rb in localhost-1.3.0 vs lib/localhost/authority.rb in localhost-1.3.1

- old
+ new

@@ -15,17 +15,36 @@ module Localhost # Represents a single public/private key pair for a given hostname. class Authority # Where to store the key pair on the filesystem. This is a subdirectory # of $XDG_STATE_HOME, or ~/.local/state/ when that's not defined. - def self.path - File.expand_path("localhost.rb", ENV.fetch("XDG_STATE_HOME", "~/.local/state")) + # + # Ensures that the directory to store the certificate exists. If the legacy + # directory (~/.localhost/) exists, it is moved into the new XDG Basedir + # compliant directory. + # + # After May 2025, the old_root option may be removed. + def self.path(env = ENV, old_root: nil) + path = File.expand_path("localhost.rb", env.fetch("XDG_STATE_HOME", "~/.local/state")) + + unless File.directory?(path) + FileUtils.mkdir_p(path, mode: 0700) + end + + # Migrates the legacy dir ~/.localhost/ to the XDG compliant directory + old_root ||= File.expand_path("~/.localhost") + if File.directory?(old_root) + FileUtils.mv(Dir.glob(File.join(old_root, "*")), path, force: true) + FileUtils.rmdir(old_root) + end + + return path end # List all certificate authorities in the given directory: def self.list(root = self.path) - return to_enum(:list) unless block_given? + return to_enum(:list, root) unless block_given? Dir.glob("*.crt", base: root) do |path| name = File.basename(path, ".crt") authority = self.new(name, root: root) @@ -64,14 +83,10 @@ # The hostname of the certificate authority. attr :hostname BITS = 1024*2 - def ecdh_key - @ecdh_key ||= OpenSSL::PKey::EC.new "prime256v1" - end - def dh_key @dh_key ||= OpenSSL::PKey::DH.new(BITS) end # The private key path. @@ -155,12 +170,10 @@ context.tmp_dh_callback = proc {self.dh_key} end if context.respond_to? :ecdh_curves= context.ecdh_curves = 'P-256:P-384:P-521' - elsif context.respond_to? :tmp_ecdh_callback= - context.tmp_ecdh_callback = proc {self.ecdh_key} end context.set_params( ciphers: SERVER_CIPHERS, verify_mode: OpenSSL::SSL::VERIFY_NONE, @@ -178,15 +191,13 @@ ) end end def load(path = @root) - ensure_authority_path_exists(path) - certificate_path = File.join(path, "#{@hostname}.crt") key_path = File.join(path, "#{@hostname}.key") - + return false unless File.exist?(certificate_path) and File.exist?(key_path) certificate = OpenSSL::X509::Certificate.new(File.read(certificate_path)) key = OpenSSL::PKey::RSA.new(File.read(key_path)) @@ -198,12 +209,10 @@ return true end def save(path = @root) - ensure_authority_path_exists(path) - lockfile_path = File.join(path, "#{@hostname}.lock") File.open(lockfile_path, File::RDWR|File::CREAT, 0644) do |lockfile| lockfile.flock(File::LOCK_EX) @@ -214,23 +223,9 @@ File.write( File.join(path, "#{@hostname}.key"), self.key.to_pem ) - end - end - - # Ensures that the directory to store the certificate exists. If the legacy - # directory (~/.localhost/) exists, it is moved into the new XDG Basedir - # compliant directory. - def ensure_authority_path_exists(path = @root) - old_root = File.expand_path("~/.localhost") - - if File.directory?(old_root) and not File.directory?(path) - # Migrates the legacy dir ~/.localhost/ to the XDG compliant directory - File.rename(old_root, path) - elsif not File.directory?(path) - FileUtils.makedirs(path, mode: 0700) end end end end