From 08ac533d2156b666ae6ca68e797992629051315f Mon Sep 17 00:00:00 2001 From: mh Date: Fri, 27 Jun 2014 19:22:44 +0200 Subject: make it possible that formats can query back to trocla itself, so they can lookup other 'keys' --- bin/trocla | 5 +- lib/trocla.rb | 6 +- lib/trocla/formats.rb | 20 +++++-- lib/trocla/formats/bcrypt.rb | 2 +- lib/trocla/formats/md5crypt.rb | 2 +- lib/trocla/formats/mysql.rb | 4 +- lib/trocla/formats/pgsql.rb | 2 +- lib/trocla/formats/plain.rb | 4 +- lib/trocla/formats/sha1.rb | 2 +- lib/trocla/formats/sha256crypt.rb | 2 +- lib/trocla/formats/sha512crypt.rb | 2 +- lib/trocla/formats/ssha.rb | 2 +- lib/trocla/formats/x509.rb | 118 +++++++++++++++++++------------------- 13 files changed, 91 insertions(+), 80 deletions(-) diff --git a/bin/trocla b/bin/trocla index dd32f84..6949318 100755 --- a/bin/trocla +++ b/bin/trocla @@ -65,10 +65,11 @@ def set(options) password = options.delete(:password) || STDIN.read.chomp end format = options.delete(:trocla_format) - Trocla.new(options.delete(:config_file)).set_password( + trocla = Trocla.new(options.delete(:config_file)) + trocla.set_password( options.delete(:trocla_key), format, - Trocla::Formats[format].format(password, options.delete(:other_options).shift.to_s) + trocla.formats(format).format(password, options.delete(:other_options).shift.to_s) ) "" end diff --git a/lib/trocla.rb b/lib/trocla.rb index a239be8..8d916b2 100644 --- a/lib/trocla.rb +++ b/lib/trocla.rb @@ -27,7 +27,7 @@ class Trocla elsif !options['random'] && plain_pwd.nil? raise "Password must be present as plaintext if you don't want a random password" end - set_password(key,format,Trocla::Formats[format].format(plain_pwd,options)) + set_password(key,format,self.formats(format).format(plain_pwd,options)) end def get_password(key,format) @@ -58,6 +58,10 @@ class Trocla h[format] end + def formats(format) + (@format_cache||={})[format] ||= Trocla::Formats[format].new(self) + end + private def cache @cache ||= build_cache diff --git a/lib/trocla/formats.rb b/lib/trocla/formats.rb index 3cf31bd..0103c4e 100644 --- a/lib/trocla/formats.rb +++ b/lib/trocla/formats.rb @@ -1,32 +1,40 @@ class Trocla::Formats + + class Base + attr_reader :trocla + def initialize(trocla) + @trocla = trocla + end + end + class << self def [](format) formats[format.downcase] end - + def all Dir[File.expand_path(File.join(File.dirname(__FILE__),'formats','*.rb'))].collect{|f| File.basename(f,'.rb').downcase } end - + def available?(format) all.include?(format.downcase) end - + private def formats @@formats ||= Hash.new do |hash, format| format = format.downcase if File.exists?(path(format)) require "trocla/formats/#{format}" - hash[format] = (eval "Trocla::Formats::#{format.capitalize}").new + hash[format] = (eval "Trocla::Formats::#{format.capitalize}") else raise "Format #{format} is not supported!" end end end - + def path(format) File.expand_path(File.join(File.dirname(__FILE__),'formats',"#{format}.rb")) end end -end \ No newline at end of file +end diff --git a/lib/trocla/formats/bcrypt.rb b/lib/trocla/formats/bcrypt.rb index 7196e54..4b6fb33 100644 --- a/lib/trocla/formats/bcrypt.rb +++ b/lib/trocla/formats/bcrypt.rb @@ -1,4 +1,4 @@ -class Trocla::Formats::Bcrypt +class Trocla::Formats::Bcrypt < Trocla::Formats::Base require 'bcrypt' def format(plain_password,options={}) BCrypt::Password.create(plain_password).to_s diff --git a/lib/trocla/formats/md5crypt.rb b/lib/trocla/formats/md5crypt.rb index 36e3a3c..80d2f09 100644 --- a/lib/trocla/formats/md5crypt.rb +++ b/lib/trocla/formats/md5crypt.rb @@ -1,5 +1,5 @@ # salted crypt -class Trocla::Formats::Md5crypt +class Trocla::Formats::Md5crypt < Trocla::Formats::Base def format(plain_password,options={}) plain_password.crypt('$1$' << Trocla::Util.salt << '$') end diff --git a/lib/trocla/formats/mysql.rb b/lib/trocla/formats/mysql.rb index 7fbc3a7..a097f95 100644 --- a/lib/trocla/formats/mysql.rb +++ b/lib/trocla/formats/mysql.rb @@ -1,6 +1,6 @@ -class Trocla::Formats::Mysql +class Trocla::Formats::Mysql < Trocla::Formats::Base require 'digest/sha1' def format(plain_password,options={}) "*" + Digest::SHA1.hexdigest(Digest::SHA1.digest(plain_password)).upcase end -end \ No newline at end of file +end diff --git a/lib/trocla/formats/pgsql.rb b/lib/trocla/formats/pgsql.rb index de233c7..ef4fed3 100644 --- a/lib/trocla/formats/pgsql.rb +++ b/lib/trocla/formats/pgsql.rb @@ -1,4 +1,4 @@ -class Trocla::Formats::Pgsql +class Trocla::Formats::Pgsql < Trocla::Formats::Base require 'digest/md5' def format(plain_password,options={}) raise "You need pass the username as an option to use this format" unless options['username'] diff --git a/lib/trocla/formats/plain.rb b/lib/trocla/formats/plain.rb index 98797d2..79502e0 100644 --- a/lib/trocla/formats/plain.rb +++ b/lib/trocla/formats/plain.rb @@ -1,7 +1,7 @@ -class Trocla::Formats::Plain +class Trocla::Formats::Plain < Trocla::Formats::Base def format(plain_password,options={}) plain_password end -end \ No newline at end of file +end diff --git a/lib/trocla/formats/sha1.rb b/lib/trocla/formats/sha1.rb index 3de75c7..1321b35 100644 --- a/lib/trocla/formats/sha1.rb +++ b/lib/trocla/formats/sha1.rb @@ -1,4 +1,4 @@ -class Trocla::Formats::Sha1 +class Trocla::Formats::Sha1 < Trocla::Formats::Base require 'digest/sha1' require 'base64' def format(plain_password,options={}) diff --git a/lib/trocla/formats/sha256crypt.rb b/lib/trocla/formats/sha256crypt.rb index 6bd1b72..e34c149 100644 --- a/lib/trocla/formats/sha256crypt.rb +++ b/lib/trocla/formats/sha256crypt.rb @@ -1,5 +1,5 @@ # salted crypt -class Trocla::Formats::Sha256crypt +class Trocla::Formats::Sha256crypt < Trocla::Formats::Base def format(plain_password,options={}) plain_password.crypt('$5$' << Trocla::Util.salt << '$') end diff --git a/lib/trocla/formats/sha512crypt.rb b/lib/trocla/formats/sha512crypt.rb index d2725c1..47eb11e 100644 --- a/lib/trocla/formats/sha512crypt.rb +++ b/lib/trocla/formats/sha512crypt.rb @@ -1,5 +1,5 @@ # salted crypt -class Trocla::Formats::Sha512crypt +class Trocla::Formats::Sha512crypt < Trocla::Formats::Base def format(plain_password,options={}) plain_password.crypt('$6$' << Trocla::Util.salt << '$') end diff --git a/lib/trocla/formats/ssha.rb b/lib/trocla/formats/ssha.rb index eaac6bb..a2e0d02 100644 --- a/lib/trocla/formats/ssha.rb +++ b/lib/trocla/formats/ssha.rb @@ -1,7 +1,7 @@ # salted crypt require 'base64' require 'digest' -class Trocla::Formats::Ssha +class Trocla::Formats::Ssha < Trocla::Formats::Base def format(plain_password,options={}) salt = options['salt'] || Trocla::Util.salt(16) "{SSHA}"+Base64.encode64("#{Digest::SHA1.digest("#{plain_password}#{salt}")}#{salt}").chomp diff --git a/lib/trocla/formats/x509.rb b/lib/trocla/formats/x509.rb index 5cb1fb2..219cd38 100644 --- a/lib/trocla/formats/x509.rb +++ b/lib/trocla/formats/x509.rb @@ -1,4 +1,4 @@ -class Trocla::Formats::X509 +class Trocla::Formats::X509 < Trocla::Formats::Base require 'openssl' def format(plain_password,options={}) @@ -24,65 +24,6 @@ class Trocla::Formats::X509 altnames = options['altnames'] || nil altnames.collect { |v| "DNS:#{v}" }.join(', ') if altnames - # nice help: https://gist.github.com/mitfik/1922961 - - def mkkey(len) - OpenSSL::PKey::RSA.generate(len) - end - - def mkreq(subject,public_key) - request = OpenSSL::X509::Request.new - request.version = 0 - request.subject = subject - request.public_key = public_key - - request - end - - def mkcert(serial,subject,issuer,public_key,days,altnames) - cert = OpenSSL::X509::Certificate.new - issuer = cert if issuer == nil - cert.subject = subject - cert.issuer = issuer.subject - cert.not_before = Time.now - cert.not_after = Time.now + days * 24 * 60 * 60 - cert.public_key = public_key - cert.serial = serial - cert.version = 2 - - ef = OpenSSL::X509::ExtensionFactory.new - ef.subject_certificate = cert - ef.issuer_certificate = issuer - cert.extensions = [ ef.create_extension("subjectKeyIdentifier", "hash") ] - cert.add_extension ef.create_extension("basicConstraints","CA:TRUE", true) if subject == issuer - cert.add_extension ef.create_extension("basicConstraints","CA:FALSE", true) if subject != issuer - cert.add_extension ef.create_extension("keyUsage", "nonRepudiation, digitalSignature, keyEncipherment", true) - cert.add_extension ef.create_extension("subjectAltName", altnames, true) if altnames - cert.add_extension ef.create_extension("authorityKeyIdentifier", "keyid:always,issuer:always") - - cert - end - - def getca(ca) - subreq = Trocla.new - subreq.get_password(ca,'x509') - end - - def getserial(ca,serial) - subreq = Trocla.new - newser = subreq.get_password("#{ca}_serial",'plain') - if newser - newser + 1 - else - serial - end - end - - def setserial(ca,serial) - subreq = Trocla.new - subreq.set_password("#{ca}_serial",'plain',serial) - end - begin key = mkkey(keysize) rescue Exception => e @@ -127,4 +68,61 @@ class Trocla::Formats::X509 key.send("to_pem") + cert.send("to_pem") end end + private + + # nice help: https://gist.github.com/mitfik/1922961 + + def mkkey(len) + OpenSSL::PKey::RSA.generate(len) + end + + def mkreq(subject,public_key) + request = OpenSSL::X509::Request.new + request.version = 0 + request.subject = subject + request.public_key = public_key + + request + end + + def mkcert(serial,subject,issuer,public_key,days,altnames) + cert = OpenSSL::X509::Certificate.new + issuer = cert if issuer == nil + cert.subject = subject + cert.issuer = issuer.subject + cert.not_before = Time.now + cert.not_after = Time.now + days * 24 * 60 * 60 + cert.public_key = public_key + cert.serial = serial + cert.version = 2 + + ef = OpenSSL::X509::ExtensionFactory.new + ef.subject_certificate = cert + ef.issuer_certificate = issuer + cert.extensions = [ ef.create_extension("subjectKeyIdentifier", "hash") ] + cert.add_extension ef.create_extension("basicConstraints","CA:TRUE", true) if subject == issuer + cert.add_extension ef.create_extension("basicConstraints","CA:FALSE", true) if subject != issuer + cert.add_extension ef.create_extension("keyUsage", "nonRepudiation, digitalSignature, keyEncipherment", true) + cert.add_extension ef.create_extension("subjectAltName", altnames, true) if altnames + cert.add_extension ef.create_extension("authorityKeyIdentifier", "keyid:always,issuer:always") + + cert + end + + def getca(ca) + trocla.get_password(ca,'x509') + end + + def getserial(ca,serial) + newser = trocla.get_password("#{ca}_serial",'plain') + if newser + newser + 1 + else + serial + end + end + + def setserial(ca,serial) + trocla.set_password("#{ca}_serial",'plain',serial) + end end -- cgit v1.2.3