diff options
author | mh <mh@immerda.ch> | 2011-07-27 18:43:55 +0200 |
---|---|---|
committer | mh <mh@immerda.ch> | 2011-07-27 18:43:55 +0200 |
commit | 9146a541ff96b92f4f14c6292307b68dc4673097 (patch) | |
tree | 3637ab49056565fad3566d78698634c2a6ab7265 /lib |
initial release of trocla
Diffstat (limited to 'lib')
-rw-r--r-- | lib/VERSION | 4 | ||||
-rw-r--r-- | lib/trocla.rb | 91 | ||||
-rw-r--r-- | lib/trocla/default_config.yaml | 7 | ||||
-rw-r--r-- | lib/trocla/formats.rb | 32 | ||||
-rw-r--r-- | lib/trocla/formats/md5crypt.rb | 6 | ||||
-rw-r--r-- | lib/trocla/formats/mysql.rb | 6 | ||||
-rw-r--r-- | lib/trocla/formats/pgsql.rb | 7 | ||||
-rw-r--r-- | lib/trocla/formats/plain.rb | 7 | ||||
-rw-r--r-- | lib/trocla/util.rb | 14 | ||||
-rw-r--r-- | lib/trocla/version.rb | 22 |
10 files changed, 196 insertions, 0 deletions
diff --git a/lib/VERSION b/lib/VERSION new file mode 100644 index 0000000..a81c87a --- /dev/null +++ b/lib/VERSION @@ -0,0 +1,4 @@ +major:0 +minor:0 +patch:1 +build:
\ No newline at end of file diff --git a/lib/trocla.rb b/lib/trocla.rb new file mode 100644 index 0000000..fe7696c --- /dev/null +++ b/lib/trocla.rb @@ -0,0 +1,91 @@ +require 'trocla/version' +require 'trocla/util' +require 'trocla/formats' + +class Trocla + + def initialize(config_file=nil) + if config_file + @config_file = File.expand_path(config_file) + elsif File.exists?(def_config_file=File.expand_path('~/.troclarc.yaml')) || File.exists?(def_config_file=File.expand_path('/etc/troclarc.yaml')) + @config_file = def_config_file + end + end + + def password(key,format,options={}) + options = config['options'].merge(options) + raise "Format #{format} is not supported! Supported formats: #{Trocla::Formats.all.join(', ')}" unless Trocla::Formats::available?(format) + + unless (password=get_password(key,format)).nil? + return password + end + + plain_pwd = get_password(key,'plain') + if options['random'] && plain_pwd.nil? + plain_pwd = Trocla::Util.random_str(options['length']) + set_password(key,'plain',plain_pwd) unless format == 'plain' + 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)) + end + + def get_password(key,format) + cache.fetch(key,{})[format] + end + + def reset_password(key,format,options={}) + set_password(key,format,nil) + password(key,format,options) + end + + def delete_password(key,format=nil) + if format.nil? + cache.delete(key) + else + old_val = (h = cache.fetch(key,{})).delete(format) + h.empty? ? cache.delete(key) : cache[key] = h + old_val + end + end + + def set_password(key,format,password,delete_plain=false) + if ((format=format) == 'plain') && !delete_plain + h = (cache[key] = { 'plain' => password }) + else + h = (cache[key] = cache.fetch(key,{}).merge({ format => password })) + end + h[format] + end + + private + def cache + @cache ||= build_cache + end + + def build_cache + require 'moneta' + require "moneta/adapters/#{config['adapter'].downcase}" + lconfig = config + Moneta::Builder.new { run eval( "Moneta::Adapters::#{lconfig['adapter']}"), lconfig['adapter_options'] } + end + + def config + @config ||= read_config + end + + def read_config + if @config_file.nil? + default_config + else + raise "Configfile #{@config_file} does not exist!" unless File.exists?(@config_file) + default_config.merge(YAML.load(File.read(@config_file))) + end + end + + def default_config + require 'yaml' + YAML.load(File.read(File.expand_path(File.join(File.dirname(__FILE__),'trocla','default_config.yaml')))) + end + +end
\ No newline at end of file diff --git a/lib/trocla/default_config.yaml b/lib/trocla/default_config.yaml new file mode 100644 index 0000000..502e7f1 --- /dev/null +++ b/lib/trocla/default_config.yaml @@ -0,0 +1,7 @@ +--- +options: + random: true + length: 12 +adapter: YAML +adapter_options: + :path: '/tmp/trocla.yaml' diff --git a/lib/trocla/formats.rb b/lib/trocla/formats.rb new file mode 100644 index 0000000..3cf31bd --- /dev/null +++ b/lib/trocla/formats.rb @@ -0,0 +1,32 @@ +class Trocla::Formats + 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 + 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 diff --git a/lib/trocla/formats/md5crypt.rb b/lib/trocla/formats/md5crypt.rb new file mode 100644 index 0000000..f52e2a1 --- /dev/null +++ b/lib/trocla/formats/md5crypt.rb @@ -0,0 +1,6 @@ +# salted crypt +class Trocla::Formats::Md5crypt + def format(plain_password,options={}) + plain_password.crypt('$1$' << Trocla::Util.random_str(8) << '$') + end +end
\ No newline at end of file diff --git a/lib/trocla/formats/mysql.rb b/lib/trocla/formats/mysql.rb new file mode 100644 index 0000000..7fbc3a7 --- /dev/null +++ b/lib/trocla/formats/mysql.rb @@ -0,0 +1,6 @@ +class Trocla::Formats::Mysql + 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 diff --git a/lib/trocla/formats/pgsql.rb b/lib/trocla/formats/pgsql.rb new file mode 100644 index 0000000..05c23ce --- /dev/null +++ b/lib/trocla/formats/pgsql.rb @@ -0,0 +1,7 @@ +class Trocla::Formats::Pgsql + require 'digest/md5' + def format(plain_password,options={}) + raise "You need pass the username in the options for this format" unless options['username'] + "md5" + Digest::MD5.hexdigest(plain_password + options['username']) + end +end
\ No newline at end of file diff --git a/lib/trocla/formats/plain.rb b/lib/trocla/formats/plain.rb new file mode 100644 index 0000000..98797d2 --- /dev/null +++ b/lib/trocla/formats/plain.rb @@ -0,0 +1,7 @@ +class Trocla::Formats::Plain + + def format(plain_password,options={}) + plain_password + end + +end
\ No newline at end of file diff --git a/lib/trocla/util.rb b/lib/trocla/util.rb new file mode 100644 index 0000000..468206d --- /dev/null +++ b/lib/trocla/util.rb @@ -0,0 +1,14 @@ +class Trocla + class Util + class << self + def random_str(length=12) + (1..length).collect{|a| chars[rand(chars.size)] }.join.to_s + end + + private + def chars + @chars ||= (('a'..'z').to_a + ('A'..'Z').to_a + ('0'..'9').to_a) + "+*%/()@&=?![]{}-_.,;:<>".split(//) + end + end + end +end
\ No newline at end of file diff --git a/lib/trocla/version.rb b/lib/trocla/version.rb new file mode 100644 index 0000000..6d9476b --- /dev/null +++ b/lib/trocla/version.rb @@ -0,0 +1,22 @@ +# encoding: utf-8 +class Trocla + class VERSION + version = {} + File.read(File.join(File.dirname(__FILE__), '../', 'VERSION')).each_line do |line| + type, value = line.chomp.split(":") + next if type =~ /^\s+$/ || value =~ /^\s+$/ + version[type] = value + end + + MAJOR = version['major'] + MINOR = version['minor'] + PATCH = version['patch'] + BUILD = version['build'] + + STRING = [MAJOR, MINOR, PATCH, BUILD].compact.join('.') + + def self.version + STRING + end + end +end |