]> err.no Git - pwstore/blobdiff - pws.rb
Add configuration file and use that to look up per-repository trusted uesrs
[pwstore] / pws.rb
diff --git a/pws.rb b/pws.rb
index c4b6d1cca83aa49a98292eee0cf94ec42447f848..d90c94003fa22e91fafe9aae5c8c31a81e0a87e9 100755 (executable)
--- a/pws.rb
+++ b/pws.rb
@@ -2,7 +2,8 @@
 
 # password store management tool
 
-# Copyright (c) 2008, 2009 Peter Palfrader <peter@palfrader.org>
+# Copyright (c) 2008, 2009, 2011, 2013 Peter Palfrader <peter@palfrader.org>
+# Copyright (c) 2014 Fastly
 #
 # Permission is hereby granted, free of charge, to any person obtaining
 # a copy of this software and associated documentation files (the
@@ -34,6 +35,7 @@ GNUPG = "/usr/bin/gpg"
 GROUP_PATTERN = "@[a-zA-Z0-9-]+"
 USER_PATTERN = "[a-zA-Z0-9:-]+"
 $program_name = File.basename($0, '.*')
+CONFIG_FILE = ENV['HOME']+ "/.pws.yaml"
 
 $editor = ENV['EDITOR']
 if $editor == nil
@@ -49,6 +51,11 @@ class GnuPG
   @@my_keys = nil
   @@my_fprs = nil
   @@keyid_fpr_mapping = {}
+  @@extra_args = []
+
+  def GnuPG.extra_args=(val)
+    @@extra_args = val
+  end
 
   def GnuPG.readwrite3(intxt, infd, stdoutfd, stderrfd, statusfd=nil)
     outtxt, stderrtxt, statustxt = ''
@@ -93,7 +100,7 @@ class GnuPG
       STDERR.reopen(errW)
       begin
         if do_status
-          exec(cmd, "--status-fd=#{statW.fileno}",  *args)
+          exec(cmd, "--status-fd=#{statW.fileno}", *@@extra_args, *args)
         else
           exec(cmd, *args)
         end
@@ -228,17 +235,36 @@ def read_input(query, default_yes=true)
 end
 
 class GroupConfig
-  def initialize
+  def initialize(dirname=".", trusted_users=nil)
+    @dirname = dirname
+    if trusted_users
+      @trusted_users = load_trusted_users(trusted_users)
+    elsif FileTest.exists?(CONFIG_FILE)
+      t = {}
+      begin
+        yaml = YAML::load_file(CONFIG_FILE)
+        yaml["trusted_users"].each do |k,v|
+            t[File.expand_path(k)] = v
+        end
+        @trusted_users = t[File.expand_path(dirname)]
+        if @trusted_users.nil?
+          raise ("Could not find #{File.expand_path(dirname)} in configuration file #{CONFIG_FILE}")
+        end
+      rescue Psych::SyntaxError, ArgumentError => e
+        raise("Could not parse YAML: #{e.message}")
+      end
+    else
+      @trusted_users = load_trusted_users(ENV['HOME']+'/.pws-trusted-users')
+    end
     parse_file
     expand_groups
   end
 
-  def verify(content)
+  def load_trusted_users(trusted_users_file)
     begin
-      f = File.open(ENV['HOME']+'/.pws-trusted-users')
+      f = File.open(trusted_users_file)
     rescue Exception => e
-      STDERR.puts e
-      exit(1)
+      raise e
     end
 
     trusted = []
@@ -249,6 +275,10 @@ class GroupConfig
 
       trusted.push line
     end
+    trusted
+  end
+
+  def verify(content)
 
     args = []
     args.push "--keyring=./.keyring" if FileTest.exists?(".keyring")
@@ -270,17 +300,15 @@ class GroupConfig
       STDERR.puts stderrtxt
       STDERR.puts "and via statusfd:"
       STDERR.puts statustxt
-      exit(1)
+      raise "Not goodsig"
     end
 
-    if not trusted.include?(validsig)
-      STDERR.puts ".users file is signed by #{validsig} which is not in ~/.pws-trusted-users"
-      exit(1)
+    if not @trusted_users.include?(validsig)
+      raise ".users file is signed by #{validsig} which is not in #{@trusted_users}"
     end
 
     if not exitstatus==0
-      STDERR.puts "gpg verify failed for .users file"
-      exit(1)
+      raise "gpg verify failed for .users file"
     end
 
     return outtxt
@@ -288,10 +316,9 @@ class GroupConfig
 
   def parse_file
     begin
-      f = File.open('.users')
+      f = File.open(File.join(@dirname, '.users'))
     rescue Exception => e
-      STDERR.puts e
-      exit(1)
+      raise e
     end
 
     users = f.read
@@ -356,7 +383,7 @@ class GroupConfig
       had_progress = false
       all_expanded = true
       @groups.each_pair do |groupname, group|
-        group['keys'] = [] unless group['keys'] 
+        group['keys'] = [] unless group['keys']
 
         still_contains_groups = false
         group['members_to_do'].clone.each do |member|
@@ -533,8 +560,8 @@ class EncryptedData
 end
 
 class EncryptedFile < EncryptedData
-  def initialize(filename, new=false)
-    @groupconfig = GroupConfig.new
+  def initialize(filename, new=false, trusted_file=nil)
+    @groupconfig = GroupConfig.new(dirname=File.dirname(filename), trusted_users=trusted_file)
     @new = new
     if @new
       @readers = []