ruby-secret_service 0.0.5

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,11 @@
1
+ .bundle
2
+ .DS_Store
3
+ vendor/bundle
4
+ default.pem
5
+ *.swo
6
+ resources_dump.json
7
+ hosts.txt
8
+ out
9
+ coverage
10
+ todo
11
+ *.gem
data/Gemfile ADDED
@@ -0,0 +1,7 @@
1
+ source "https://rubygems.org"
2
+
3
+ gemspec
4
+ gem "woof_util"
5
+ gem "ruby-dbus"
6
+ gem "rake"
7
+ gem "bundler"
data/Gemfile.lock ADDED
@@ -0,0 +1,36 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ ruby-secret_service (0.0.5)
5
+ ruby-dbus
6
+
7
+ GEM
8
+ remote: https://rubygems.org/
9
+ specs:
10
+ diff-lcs (1.2.4)
11
+ excon (0.16.10)
12
+ highline (1.6.19)
13
+ rake (10.1.0)
14
+ rspec (2.14.1)
15
+ rspec-core (~> 2.14.0)
16
+ rspec-expectations (~> 2.14.0)
17
+ rspec-mocks (~> 2.14.0)
18
+ rspec-core (2.14.5)
19
+ rspec-expectations (2.14.2)
20
+ diff-lcs (>= 1.1.3, < 2.0)
21
+ rspec-mocks (2.14.3)
22
+ ruby-dbus (0.9.2)
23
+ woof_util (0.0.16)
24
+ excon (~> 0.16.10)
25
+ highline (~> 1.6.15)
26
+
27
+ PLATFORMS
28
+ ruby
29
+
30
+ DEPENDENCIES
31
+ bundler
32
+ rake
33
+ rspec
34
+ ruby-dbus
35
+ ruby-secret_service!
36
+ woof_util
data/README.md ADDED
@@ -0,0 +1,46 @@
1
+ Ruby Secret Service
2
+ ===================
3
+
4
+ Native Ruby bindings for [freedesktop.org's Secret Service](http://standards.freedesktop.org/secret-service/). Uses [ruby-dbus](https://github.com/mvidner/ruby-dbus).
5
+
6
+ ##Usage
7
+ ```
8
+ require "secret_service"
9
+
10
+ ss = SecretService.new
11
+
12
+ # create a secret in the default collection
13
+ name = "my github password"
14
+ secret = "s00p3r-s33|<r1+"
15
+
16
+ ss.collection.create_item(name, secret)
17
+
18
+ # and read it back
19
+ round_trip_secret = ss.collection.get_secret(name)
20
+ round_trip_secret == secret || raise "secret reading failed"
21
+
22
+ # create new collections!
23
+ other_coll_name = "other keyring"
24
+ other_name = "my heroku password"
25
+ other_secret = "1m s00 l33t"
26
+ ss.create_collection(other_coll_name)
27
+
28
+ ss.collection(other_coll_name).create_item(other_name, other_secret)
29
+ round_trip_other = ss.collection(other_coll_name).get_secret(other_name)
30
+ round_trip_other == other_secret || raise "can't read alt collection secret"
31
+ ```
32
+
33
+ ## Caveats
34
+
35
+ * Both KWallet and GNOME Keyring _REQUIRE_ the use of X11 to prompt
36
+ the user to decrypt ("unlock") the keychain. While you can use
37
+ this in a terminal-only environment (e.g., ssh'd in from a
38
+ desktop/laptop without X11), you're going to get errors about
39
+ having to unlock collections, but there is literally no way in the
40
+ spec to pass the decryption password over DBus.
41
+ * This is written chiefly to provide a programmatic access to
42
+ Secret Service for one specific program - Heroku Toolbelt. While
43
+ there's some basic support for multiple collections and
44
+ locking/unlocking, if you're doing anything moderately complex,
45
+ you're potentially better off [doing this in Python](https://bitbucket.org/kang/python-keyring-lib/overview)
46
+
data/Rakefile ADDED
@@ -0,0 +1,7 @@
1
+ require "bundler/setup"
2
+ require "rspec/core/rake_task"
3
+ require "woof_util/gem_rake_tasks"
4
+
5
+ RSpec::Core::RakeTask.new "spec"
6
+ WoofUtil::GemRakeTasks.create_tasks
7
+
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.0.5
@@ -0,0 +1,64 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'secret_service'
4
+ require 'optparse'
5
+
6
+ options = {}
7
+ opts = OptionParser.new do |opts|
8
+ opts.banner = "Usage: #{$0} -s|-g NAME"
9
+ opts.on("-g", "--get NAME",
10
+ "Reads existing secret called NAME, prints secret to stdout") do |key|
11
+ options[:name] = key
12
+ options[:mode] = :get
13
+ end
14
+ opts.on("-s", "--set NAME",
15
+ "Creates new secret called NAME, reads secret from stdin") do |key|
16
+ options[:name] = key
17
+ options[:mode] = :set
18
+ end
19
+ end
20
+ opts.parse!
21
+
22
+ ss = SecretService.new
23
+
24
+ case options[:mode]
25
+ when :set
26
+ new_secret = STDIN.read
27
+ typeinfo = nil
28
+ attrs = ["a{ss}", {"name" => options[:name].to_s }]
29
+
30
+ properties =
31
+ {"org.freedesktop.Secret.Item.Label" => options[:name],
32
+ "org.freedesktop.Secret.Item.Attributes" => attrs
33
+ }
34
+ item = ss.collection.create_item properties, new_secret
35
+ when :get
36
+ item = ss.collection.unlocked_items({"name" => options[:name]})[0]
37
+ puts item.get_secret
38
+ else
39
+ puts opts.help
40
+ exit 1
41
+ end
42
+
43
+ exit 0
44
+ name = ARGV[0]
45
+
46
+ item = ss.collection.unlocked_items({"name" => name})[0]
47
+ puts "label: #{item.label}"
48
+ puts "last modified #{item.modified}, locked: #{item.locked?}"
49
+ puts "attributes: #{item.attributes.to_s}"
50
+
51
+ # item.attributes = ["name", "test2"]
52
+ # {"magic" => "secret_service.rb", "name" => "test"}
53
+
54
+
55
+ #item = SecretService::Item.new(ss.bus, secret_path)
56
+
57
+ #puts item.your_mom
58
+
59
+ #puts ss.init_session[1]
60
+
61
+ #item = SecretService::Item.new(session, secret_path)
62
+ #
63
+ #puts item.item["Modified"].class
64
+
@@ -0,0 +1,89 @@
1
+ class SecretService
2
+ class Collection
3
+ attr_accessor :service, :name, :path
4
+
5
+ def initialize(service, name = DEFAULT_COLLECTION, path=nil)
6
+ @service = service
7
+ @name = name
8
+ @path = path || "#{COLLECTION_PREFIX}#{name}"
9
+ @proxy = @service.get_proxy(@path, IFACE[:collection])
10
+ end
11
+
12
+ def lock!
13
+ locked_objs, prompt_path = @service.proxy.Lock [@path]
14
+ return true if prompt_path == "/" and locked_objs.include?(@path)
15
+
16
+ # need to do the prompt dance
17
+ @service.prompt!(prompt_path)
18
+ locked?
19
+ end
20
+
21
+ def unlock!
22
+ unlocked_objs, prompt_path = @service.proxy.Unlock [@path]
23
+ return true if prompt_path == "/" and unlocked_objs.include?(@path)
24
+
25
+ #nuts, stupid prompt
26
+ @service.prompt!(prompt_path)
27
+ ! locked?
28
+ end
29
+
30
+ def locked?
31
+ get_property(:locked)
32
+ end
33
+
34
+ def set_property name, new_val
35
+ @proxy.Set(IFACE[:item], name.to_s.downcase.capitalize, new_val)
36
+ end
37
+
38
+ def get_property name
39
+ @proxy.Get(IFACE[:collection], name.to_s.downcase.capitalize)[0]
40
+ end
41
+
42
+ def session
43
+ @service.session
44
+ end
45
+
46
+ def unlocked_items(search_pred = {})
47
+ @proxy.SearchItems(search_pred)[0].map {|path| Item.new self, path }
48
+ end
49
+
50
+ def locked_items(search_pref = {})
51
+ @proxy.SearchItems(search_pred)[1].map {|path| Item.new self, path }
52
+ end
53
+
54
+ def create_item name, secret, properties=nil, replace=true
55
+ if properties.nil?
56
+ # ruby-dbus's type inference system doesn't handle recursion for
57
+ # vaguely complicated structs, yet the protocol requires
58
+ # explicit type annotation. Consequently, nontrivial structs
59
+ # require the user to provide their own annotation
60
+ attrs = ["a{ss}", {"name" => name.to_s }]
61
+
62
+ properties =
63
+ {"#{SS_PREFIX}Item.Label" => name.to_s,
64
+ "#{SS_PREFIX}Item.Attributes" => attrs
65
+ }
66
+ end
67
+ result = @proxy.CreateItem(properties, secret_encode(secret), replace)
68
+ new_item_path = result[0]
69
+ Item.new(self, new_item_path)
70
+ end
71
+
72
+ def get_secret name
73
+ (unlocked_items({"name" => name})[0]).get_secret
74
+ end
75
+
76
+ def secret_encode secret_string
77
+ mime_type = "application/octet-stream"
78
+
79
+ if(secret_string.respond_to? "encoding" and
80
+ secret_string.encoding.to_s != "ASCII-8BIT")
81
+ secret_string.encode! "UTF-8"
82
+ #mime_type = "text/plain; charset=utf8"
83
+ end
84
+
85
+ [session[1], [], secret_string.bytes.to_a, mime_type]
86
+ end
87
+
88
+ end
89
+ end
@@ -0,0 +1,87 @@
1
+ class SecretService
2
+ class Item
3
+
4
+ attr_accessor :path
5
+
6
+ def initialize(collection, path)
7
+ @collection = collection
8
+ @path = path
9
+ @proxy = collection.service.get_proxy @path, IFACE[:item]
10
+ end
11
+
12
+ def modified
13
+ Time.at get_property(:modified)
14
+ end
15
+
16
+ def created
17
+ Time.at get_property(:created)
18
+ end
19
+
20
+ def locked?
21
+ get_property(:locked)
22
+ end
23
+
24
+ def lock!
25
+ locked, prompt_path = @collection.service.proxy.Lock [@path]
26
+ return true if prompt_path == "/" and locked.include? @path
27
+
28
+ # otherwise we have to handle the prompt
29
+ @collection.service.prompt!(prompt_path)
30
+ get_property(:locked)
31
+ end
32
+
33
+ def label
34
+ get_property(:label)
35
+ end
36
+
37
+ def label= new_label
38
+ set_property(:label, new_label)
39
+ end
40
+
41
+ def attributes
42
+ get_property(:attributes)
43
+ end
44
+
45
+ # TODO: this keeps throwing type errors
46
+ def attributes= new_attrs
47
+ set_property(:attributes, new_attrs)
48
+ end
49
+
50
+ def set_property name, new_val
51
+ @proxy.Set(IFACE[:item], name.to_s.downcase.capitalize, new_val)
52
+ end
53
+
54
+ def get_property name
55
+ @proxy.Get(IFACE[:item], name.to_s.downcase.capitalize)[0]
56
+ end
57
+
58
+ def session
59
+ @collection.session
60
+ end
61
+
62
+ def get_secret
63
+ secret_decode(@proxy.GetSecret(session[1]))
64
+ end
65
+
66
+ # http://standards.freedesktop.org/secret-service/ch14.html#type-Secret
67
+ def secret_decode secret_arr
68
+ secret_struct = secret_arr[0]
69
+ s = {}
70
+ [:session, :params, :bytes, :mime].each do |x|
71
+ s[x] = secret_struct.shift
72
+ end
73
+
74
+ secret_string = (s[:bytes].map {|x| x.chr}).join
75
+ if(secret_string.respond_to? "encoding" and
76
+ s[:mime] != "application/octet-stream")
77
+ charset = s[:mime].match(/charset=(.+)/)[1]
78
+ unless charset.nil?
79
+ charset.upcase!.sub! /\AUTF([\w\d])/, "UTF-#{$1}"
80
+ secret_string.force_encoding charset
81
+ end
82
+ end
83
+ secret_string
84
+ end
85
+
86
+ end
87
+ end
@@ -0,0 +1,30 @@
1
+ class SecretService
2
+ class Prompt
3
+
4
+ attr_accessor :path
5
+
6
+ class NoPromptRequired < Exception ; end
7
+
8
+ def initialize service, object_path
9
+ raise NoPromptRequired if object_path == "/"
10
+ @service = service
11
+ @path = object_path
12
+ @proxy = service.get_proxy object_path, SecretService::IFACE[:prompt]
13
+ end
14
+
15
+ def prompt!
16
+ loop = DBus::Main.new
17
+ loop << @service.bus
18
+ @proxy.on_signal("Completed") do |dismissed, result|
19
+ loop.quit
20
+ end
21
+ @proxy.Prompt ""
22
+ loop.run
23
+ end
24
+
25
+ def dismiss
26
+ @proxy.Dismiss
27
+ end
28
+
29
+ end
30
+ end
@@ -0,0 +1,86 @@
1
+ # http://standards.freedesktop.org/secret-service/ch14.html#id481899
2
+ # Creating a "secret"
3
+
4
+ class SecretService
5
+ class Secret
6
+
7
+ attr_accessor :session_path, :parameters, :content_type
8
+
9
+ def initialize attrs
10
+ @session_path = attrs[:session_path]
11
+ @parameters = attrs[:parameters] || []
12
+ @value = attrs[:value]
13
+ @content_type = attrs[:content_type] || sniff_content_type(@value)
14
+ end
15
+
16
+ def value
17
+ @value
18
+ end
19
+
20
+ def value= val
21
+ @value = val
22
+ @content_type = sniff_content_type attrs[:value]
23
+ end
24
+
25
+ # Create a new SecretService::Secret from the DBus Struct format
26
+ def self.from_struct s
27
+ initialize(:session_path => s[0][0],
28
+ :parameters => s[0][1],
29
+ :value => (s[0][2].map {|x| x.chr}).join,
30
+ :content_type => (s[0][3] == "") ? nil : s[0][3]
31
+ )
32
+ end
33
+
34
+ # Convert the human-readable version into the format expected
35
+ # by DBus.
36
+ def to_struct
37
+ [ "(oayays)",
38
+ [@session_path, @parameters, @value.bytes.to_a, @content_type]
39
+ ]
40
+ end
41
+
42
+
43
+ # Take a string, guess what the Content-type should be.
44
+ # For Ruby < 1.9, assume binary encoding. You can avoid this
45
+ # by passing in an explicit content_type to the initializer.
46
+ #
47
+ # Or, y'know, using a more recent version of the language.
48
+ def sniff_content_type str
49
+ if (str.nil? or
50
+ (not str.respond_to? :encoding ) or
51
+ (str.encoding.to_s == "ASCII-8BIT"))
52
+ "application/octet-stream"
53
+ else
54
+ "text/plain; charset=#{str.encoding}"
55
+ end
56
+ end
57
+
58
+ # Derive the Ruby String encoding from a given Content-type.
59
+ # When all else fails, assumes ASCII-8BIT (aka Binary)
60
+ def self.content_type_to_encoding content_type=nil
61
+ binary = "ASCII-8BIT"
62
+
63
+ begin
64
+ case charset = content_type.match(/; charset=(.+)\z/)[1].upcase
65
+ when /\AUTF[^-]/
66
+ # "UTF8" is a common misspelling of "UTF-8".
67
+ charset.sub! /\AUTF/, "UTF-"
68
+ when /./
69
+ # Accept charset.upcase at face value & hope for the best
70
+ charset
71
+ else
72
+ # This is a technical violation of RFC 2616, sec. 3.7.1, which
73
+ # states ISO-8859-1 is the default for "text/*" when no
74
+ # charset is specified. However, I claim UTF-8 is a safer
75
+ # assumption on the modern Internet.
76
+ charset = content_type.match(/\Atext\//) ? "UTF-8" : binary
77
+ end
78
+ "".encode charset
79
+ charset
80
+ rescue
81
+ binary
82
+ end
83
+ end
84
+
85
+ end
86
+ end
@@ -0,0 +1,96 @@
1
+ require 'dbus'
2
+
3
+ require 'secret_service/collection'
4
+ require 'secret_service/item'
5
+ require 'secret_service/secret'
6
+ require 'secret_service/prompt'
7
+
8
+ class SecretService
9
+ SECRETS = 'org.freedesktop.secrets'
10
+ SS_PREFIX = 'org.freedesktop.Secret.'
11
+ SS_PATH = '/org/freedesktop/secrets'
12
+ COLLECTION_PREFIX = '/org/freedesktop/secrets/aliases/'
13
+ DEFAULT_COLLECTION = "default"
14
+
15
+ ALGO = "plain"
16
+
17
+ DBUS_UNKNOWN_METHOD = 'org.freedesktop.DBus.Error.UnknownMethod'
18
+ DBUS_SERVICE_UNKNOWN = 'org.freedesktop.DBus.Error.ServiceUnknown'
19
+ DBUS_EXEC_FAILED = 'org.freedesktop.DBus.Error.Spawn.ExecFailed'
20
+ DBUS_NO_REPLY = 'org.freedesktop.DBus.Error.NoReply'
21
+ DBUS_NO_SUCH_OBJECT = 'org.freedesktop.Secret.Error.NoSuchObject'
22
+
23
+ IFACE = {}
24
+ [:service, :item, :collection, :prompt].each do |x|
25
+ IFACE[x] = "#{SS_PREFIX}#{x.to_s.capitalize}"
26
+ end
27
+
28
+ attr_accessor :bus, :proxy
29
+
30
+ class NoSessionBus < Exception
31
+ end
32
+
33
+ def initialize
34
+ begin
35
+ @bus = DBus::SessionBus.instance
36
+
37
+ @proxy_maker = @bus.service SECRETS
38
+ @proxy = get_proxy SS_PATH, IFACE[:service]
39
+ @collections = {}
40
+
41
+ @collection_paths = self.list_collections
42
+ rescue
43
+ raise NoSessionBus
44
+ end
45
+ end
46
+
47
+ def get_proxy path, iface=nil
48
+ obj = @proxy_maker.object path
49
+ obj.introspect
50
+ obj.default_iface = iface unless iface.nil?
51
+ obj
52
+ end
53
+
54
+ def session
55
+ @session ||= @proxy.OpenSession(ALGO, "")
56
+ end
57
+
58
+ def collection(name=DEFAULT_COLLECTION, path=nil)
59
+ @collections[name.to_s] ||= Collection.new(self, name, path)
60
+ end
61
+
62
+ def list_collections
63
+ @proxy.Get(IFACE[:service], 'Collections')
64
+ end
65
+
66
+ def create_collection name, properties=nil
67
+ properties ||= {"#{SS_PREFIX}Collection.Label" => name}
68
+
69
+ coll, prompt_path = @proxy.CreateCollection properties, ""
70
+ prompt!(prompt_path) if prompt_path != "/"
71
+ collection(name, coll)
72
+ end
73
+
74
+
75
+ def set_alias name, collection
76
+ @proxy.SetAlias name, (collection.class == String ? collection : collection.path)
77
+ end
78
+
79
+ def read_alias name
80
+ path = @proxy.ReadAlias name
81
+ collection(name, path)
82
+ end
83
+
84
+ def search_items attrs={}
85
+ @proxy.SearchItems(attrs)
86
+ end
87
+
88
+ def unlock objects
89
+ @proxy.Unlock objects
90
+ end
91
+
92
+ def prompt!(prompt_path)
93
+ SecretService::Prompt.new(self, prompt_path).prompt!
94
+ end
95
+
96
+ end
@@ -0,0 +1,19 @@
1
+ require 'find'
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = 'ruby-secret_service'
5
+ s.version = File.read("VERSION").chomp
6
+ s.summary = 'Ruby bindings for GNOME Keyring & KWallet'
7
+ s.description = "Native bindings use the D-BUS Secret Service API, docs at http://standards.freedesktop.org/secret-service/"
8
+ s.authors = ["Tom Maher"]
9
+ s.email = "tmaher@pw0n.me"
10
+ s.license = "Apache 2.0"
11
+ s.files = `git ls-files`.split("\n")
12
+ s.require_path = ["lib"]
13
+ s.homepage = "https://github.com/tmaher/ruby-secret_service"
14
+ s.add_development_dependency "woof_util"
15
+ s.add_development_dependency "rake"
16
+ s.add_development_dependency "rspec"
17
+
18
+ s.add_dependency "ruby-dbus"
19
+ end
data/spec/rss_spec.rb ADDED
@@ -0,0 +1,83 @@
1
+ require 'spec_helper'
2
+
3
+ describe SecretService do
4
+
5
+ #it "aborts when it can't find dbus" do
6
+ #state = hide_dbus_configs
7
+ #SecretService.new
8
+ #expect {SecretService.new}.to raise_error
9
+ #restore_dbus_configs state
10
+ #end
11
+
12
+ it "can create a session" do
13
+ SecretService.new.class.should_not be nil
14
+ end
15
+
16
+ it "has a default collection" do
17
+ SecretService.new.collection.should_not be nil
18
+ end
19
+
20
+ it "can lock and unlock collections" do
21
+ ss = SecretService.new
22
+ ss.collection.lock!.should eq true
23
+ ss.collection.locked?.should eq true
24
+ ss.collection.unlock!.should eq true
25
+ ss.collection.locked?.should eq false
26
+ end
27
+
28
+ it "can create and read back objects" do
29
+ name = SecureRandom.hex(8).to_s
30
+ secret = SecureRandom.hex(8).to_s
31
+ ss = SecretService.new
32
+ ss.collection.unlock!
33
+ ss.collection.create_item("rspec_test_#{name}", secret).should_not be nil
34
+ ss.collection.get_secret("rspec_test_#{name}").should eq secret
35
+ end
36
+
37
+ it "can create a new collection" do
38
+ ss = SecretService.new
39
+ coll_label = "rspec_test_collection_#{SecureRandom.hex(4)}"
40
+ new_coll = ss.create_collection coll_label
41
+ new_coll.should_not be nil
42
+ new_coll.name.should eq coll_label
43
+ end
44
+
45
+ it "can create and lock objects" do
46
+ name = SecureRandom.hex(8).to_s
47
+ secret = SecureRandom.hex(8).to_s
48
+ ss = SecretService.new
49
+ item = ss.collection.create_item("rspec_test_#{name}", secret)
50
+ item.lock!
51
+ item.locked?.should eq true
52
+ end
53
+
54
+ it "can find objects" do
55
+ ss = SecretService.new
56
+ unlocked, locked = ss.search_items
57
+ unlocked.kind_of?(Array).should eq true
58
+ locked.kind_of?(Array).should eq true
59
+ (locked + unlocked).each do |item|
60
+ item.match(/^\/org\/freedesktop\/secrets\/collection/).nil?.should eq false
61
+ end
62
+ end
63
+
64
+ it "can unlock objects" do
65
+ ss = SecretService.new
66
+ item_paths, prompt = ss.unlock(ss.search_items[1])
67
+ end
68
+
69
+ it "aborts on invalid prompt creation" do
70
+ ss = SecretService.new
71
+ expect {ss.prompt! "/"}.to raise_error SecretService::Prompt::NoPromptRequired
72
+ end
73
+
74
+ #it "can raise a prompt" do
75
+ #ss = SecretService.new
76
+ #item_paths, prompt = ss.unlock(ss.search_items[1])
77
+ #ss.prompt!(prompt)
78
+ #new_items, new_prompt = ss.unlock(ss.search_items[1])
79
+ #new_prompt.should be_nil
80
+ #puts "new_items: #{new_items}"
81
+ #end
82
+
83
+ end
@@ -0,0 +1,40 @@
1
+ require 'rubygems'
2
+ require 'bundler/setup'
3
+ require 'securerandom'
4
+
5
+ $: << File.dirname(__FILE__) + '/../lib'
6
+
7
+ require 'secret_service'
8
+
9
+ RSpec.configure do |config|
10
+ config.color_enabled = true
11
+ config.order = 'random'
12
+ config.seed = SecureRandom.random_number(2 ** 24)
13
+
14
+ # Use color not only in STDOUT but also in pagers and files
15
+ config.tty = true
16
+
17
+ # Use the specified formatter
18
+ #config.formatter = :documentation # :progress, :html, :textmate
19
+ end
20
+
21
+ def hide_dbus_configs
22
+ state = {:addr => ENV["DBUS_SESSION_BUS_ADDRESS"],
23
+ :display => ENV["DISPLAY"],
24
+ :dir => File.join(ENV["HOME"], ".dbus-#{SecureRandom.hex(4)}")
25
+ }
26
+ ENV.delete "DBUS_SESSION_BUS_ADDRESS"
27
+ ENV.delete "DISPLAY"
28
+ begin
29
+ File.rename File.join(ENV["HOME"], ".dbus"), state[:dir]
30
+ rescue; end
31
+ state
32
+ end
33
+
34
+ def restore_dbus_configs state
35
+ ENV["DBUS_SESSION_BUS_ADDRESS"] = state[:addr]
36
+ ENV["DISPLAY"] = state[:display]
37
+ begin
38
+ File.rename state[:dir], File.join(ENV["HOME"], ".dbus")
39
+ rescue; end
40
+ end
metadata ADDED
@@ -0,0 +1,124 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: ruby-secret_service
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.5
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Tom Maher
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2013-08-16 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: woof_util
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :development
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
30
+ - !ruby/object:Gem::Dependency
31
+ name: rake
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ type: :development
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ - !ruby/object:Gem::Dependency
47
+ name: rspec
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ! '>='
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ type: :development
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ - !ruby/object:Gem::Dependency
63
+ name: ruby-dbus
64
+ requirement: !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ! '>='
68
+ - !ruby/object:Gem::Version
69
+ version: '0'
70
+ type: :runtime
71
+ prerelease: false
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ! '>='
76
+ - !ruby/object:Gem::Version
77
+ version: '0'
78
+ description: Native bindings use the D-BUS Secret Service API, docs at http://standards.freedesktop.org/secret-service/
79
+ email: tmaher@pw0n.me
80
+ executables: []
81
+ extensions: []
82
+ extra_rdoc_files: []
83
+ files:
84
+ - .gitignore
85
+ - Gemfile
86
+ - Gemfile.lock
87
+ - README.md
88
+ - Rakefile
89
+ - VERSION
90
+ - bin/secretservice.rb
91
+ - lib/secret_service.rb
92
+ - lib/secret_service/collection.rb
93
+ - lib/secret_service/item.rb
94
+ - lib/secret_service/prompt.rb
95
+ - lib/secret_service/secret.rb
96
+ - ruby-secret_service.gemspec
97
+ - spec/rss_spec.rb
98
+ - spec/spec_helper.rb
99
+ homepage: https://github.com/tmaher/ruby-secret_service
100
+ licenses:
101
+ - Apache 2.0
102
+ post_install_message:
103
+ rdoc_options: []
104
+ require_paths:
105
+ - - lib
106
+ required_ruby_version: !ruby/object:Gem::Requirement
107
+ none: false
108
+ requirements:
109
+ - - ! '>='
110
+ - !ruby/object:Gem::Version
111
+ version: '0'
112
+ required_rubygems_version: !ruby/object:Gem::Requirement
113
+ none: false
114
+ requirements:
115
+ - - ! '>='
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ requirements: []
119
+ rubyforge_project:
120
+ rubygems_version: 1.8.23
121
+ signing_key:
122
+ specification_version: 3
123
+ summary: Ruby bindings for GNOME Keyring & KWallet
124
+ test_files: []