ruby-keychain 0.1.0 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/{README → README.markdown} +15 -3
- data/lib/keychain.rb +31 -5
- data/lib/keychain/error.rb +4 -1
- data/lib/keychain/keychain.rb +3 -0
- data/lib/keychain/scope.rb +1 -1
- data/lib/keychain/sec.rb +4 -1
- data/lib/keychain/version.rb +1 -1
- data/spec/keychain_spec.rb +23 -1
- metadata +3 -3
data/{README → README.markdown}
RENAMED
@@ -1,5 +1,17 @@
|
|
1
|
+
# @markup markdown
|
2
|
+
|
1
3
|
A set of ruby bindings for the OS X keychain, written using ffi
|
2
4
|
|
5
|
+
Installation
|
6
|
+
============
|
7
|
+
|
8
|
+
gem install ruby-keychain
|
9
|
+
|
10
|
+
or in your gemfile,
|
11
|
+
|
12
|
+
gem 'ruby-keychain', :require => 'keychain'
|
13
|
+
|
14
|
+
|
3
15
|
Introduction
|
4
16
|
============
|
5
17
|
|
@@ -13,12 +25,12 @@ Most operations will act on either the default keychain, or the default keychain
|
|
13
25
|
|
14
26
|
Keychain.default #the default keychain, usually /Users/<username>/Library/Keychains/<username>.keychain
|
15
27
|
Keychain.open(path) #opens a keychain file
|
16
|
-
Keychain.create(path, password) #creates a new keychain at the specified path
|
17
|
-
|
28
|
+
Keychain.create(path, password) # creates a new keychain at the specified path, with the specified password
|
29
|
+
# omit the password to make the keychain prompt the user
|
18
30
|
|
19
31
|
|
20
32
|
Searching for Keychain Items
|
21
|
-
|
33
|
+
=============================
|
22
34
|
|
23
35
|
The top level constant `Keychain` as well as individual keychain objects have two methods `internet_passwords` and `generic_passwords` that return scope like objects. You can do
|
24
36
|
|
data/lib/keychain.rb
CHANGED
@@ -14,17 +14,22 @@ module Keychain
|
|
14
14
|
# See https://developer.apple.com/library/mac/documentation/security/Reference/keychainservices/Reference/reference.html#//apple_ref/c/func/SecKeychainCreate
|
15
15
|
# @param [String] path The path to the keychain file to create
|
16
16
|
# If it is not absolute it is interpreted relative to ~/Library/Keychains
|
17
|
-
# @param [String] password The password to use for the keychain
|
17
|
+
# @param [optional, String] password The password to use for the keychain. if not supplied, the user will be prompted for a password
|
18
18
|
# @return [Keychain::Keychain] a keychain object representing the newly created keychain
|
19
19
|
|
20
|
-
def create(path, password)
|
21
|
-
password = password.encode(Encoding::UTF_8)
|
20
|
+
def create(path, password=nil)
|
22
21
|
path = path.encode(Encoding::UTF_8)
|
23
|
-
|
24
22
|
out_buffer = FFI::MemoryPointer.new(:pointer)
|
25
|
-
|
23
|
+
|
24
|
+
if password
|
25
|
+
password = password.encode(Encoding::UTF_8)
|
26
|
+
status = Sec.SecKeychainCreate(path, password.bytesize, FFI::MemoryPointer.from_string(password), 0,
|
26
27
|
nil, out_buffer)
|
27
28
|
|
29
|
+
else
|
30
|
+
status = Sec.SecKeychainCreate(path, 0, nil, 1, nil, out_buffer)
|
31
|
+
end
|
32
|
+
|
28
33
|
Sec.check_osstatus(status)
|
29
34
|
Keychain.new(out_buffer.read_pointer).release_on_gc
|
30
35
|
end
|
@@ -68,5 +73,26 @@ module Keychain
|
|
68
73
|
def generic_passwords
|
69
74
|
Scope.new(Sec::Classes::GENERIC)
|
70
75
|
end
|
76
|
+
|
77
|
+
# sets whether user interaction is allowed
|
78
|
+
# If false then operations that would require user interaction (for example prompting the user for a password to unlock a keychain)
|
79
|
+
# will raise InteractionNotAllowedError
|
80
|
+
# @param [Boolean] value
|
81
|
+
def user_interaction_allowed= value
|
82
|
+
status = Sec.SecKeychainSetUserInteractionAllowed( value ? 1 : 0)
|
83
|
+
Sec.check_osstatus(status)
|
84
|
+
value
|
85
|
+
end
|
86
|
+
|
87
|
+
# Returns whether user interaction is allowed
|
88
|
+
# If false then operations that would require user interaction (for example prompting the user for a password to unlock a keychain)
|
89
|
+
# will raise InteractionNotAllowedError
|
90
|
+
# @return whether interaction is allowed
|
91
|
+
def user_interaction_allowed?
|
92
|
+
out_buffer = FFI::MemoryPointer.new(:uchar)
|
93
|
+
status = Sec.SecKeychainGetUserInteractionAllowed(out_buffer)
|
94
|
+
Sec.check_osstatus(status)
|
95
|
+
out_buffer.read_uchar.nonzero?
|
96
|
+
end
|
71
97
|
end
|
72
98
|
end
|
data/lib/keychain/error.rb
CHANGED
@@ -31,4 +31,7 @@ class Keychain::AuthFailedError < Keychain::Error; end
|
|
31
31
|
class Keychain::UserCancelledError < Keychain::Error; end
|
32
32
|
# Raised when an action fails because the underlying keychain
|
33
33
|
# does not exist
|
34
|
-
class Keychain::NoSuchKeychainError < Keychain::Error; end
|
34
|
+
class Keychain::NoSuchKeychainError < Keychain::Error; end
|
35
|
+
# Raised when an action would rewuire user interaction but user interaction
|
36
|
+
# is not allowed. See Keychain.user_interaction_allowed=
|
37
|
+
class Keychain::InteractionNotAllowedError < Keychain::Error; end
|
data/lib/keychain/keychain.rb
CHANGED
@@ -24,6 +24,9 @@ module Sec
|
|
24
24
|
|
25
25
|
attach_function 'SecKeychainGetStatus', [:keychainref, :pointer], :osstatus
|
26
26
|
|
27
|
+
attach_function 'SecKeychainSetUserInteractionAllowed', [:uchar], :osstatus
|
28
|
+
|
29
|
+
attach_function 'SecKeychainGetUserInteractionAllowed', [:pointer], :osstatus
|
27
30
|
enum :keychainStatus, [
|
28
31
|
:kSecUnlockStateStatus, 1,
|
29
32
|
:kSecReadPermStatus, 2,
|
data/lib/keychain/scope.rb
CHANGED
data/lib/keychain/sec.rb
CHANGED
@@ -11,7 +11,8 @@ module Sec
|
|
11
11
|
:errSecDuplicateItem, -25299,
|
12
12
|
:errSecAuthFailed, -25293,
|
13
13
|
:errSecNoSuchKeychain, -25294,
|
14
|
-
:errCancelled, -128
|
14
|
+
:errCancelled, -128,
|
15
|
+
:errSecInteractionNotAllowed, -25308
|
15
16
|
]
|
16
17
|
|
17
18
|
attach_variable 'kSecClassInternetPassword', :pointer
|
@@ -155,6 +156,8 @@ module Sec
|
|
155
156
|
raise Keychain::AuthFailedError.new(result)
|
156
157
|
when Sec.enum_value(:errSecNoSuchKeychain)
|
157
158
|
raise Keychain::NoSuchKeychainError.new(result)
|
159
|
+
when Sec.enum_value(:errSecInteractionNotAllowed)
|
160
|
+
raise Keychain::InteractionNotAllowedError.new(result)
|
158
161
|
else
|
159
162
|
raise Keychain::Error.new(result)
|
160
163
|
end
|
data/lib/keychain/version.rb
CHANGED
data/spec/keychain_spec.rb
CHANGED
@@ -1,6 +1,20 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe Keychain do
|
4
|
+
|
5
|
+
describe 'user interaction' do
|
6
|
+
it 'should be true by default' do
|
7
|
+
Keychain.user_interaction_allowed?.should be_true
|
8
|
+
end
|
9
|
+
|
10
|
+
it 'should be changeable' do
|
11
|
+
Keychain.user_interaction_allowed = false
|
12
|
+
Keychain.user_interaction_allowed?.should be_false
|
13
|
+
Keychain.user_interaction_allowed = true
|
14
|
+
Keychain.user_interaction_allowed?.should be_true
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
4
18
|
describe 'default' do
|
5
19
|
it "should return the login keychain" do
|
6
20
|
Keychain.default.path.should == File.expand_path(File.join(ENV['HOME'], 'Library','Keychains', 'login.keychain'))
|
@@ -14,7 +28,7 @@ describe Keychain do
|
|
14
28
|
end
|
15
29
|
end
|
16
30
|
|
17
|
-
describe '
|
31
|
+
describe 'create' do
|
18
32
|
it 'should create the keychain' do
|
19
33
|
begin
|
20
34
|
keychain = Keychain.create(File.join(Dir.tmpdir, "other_keychain_spec_#{Time.now.to_i}_#{Time.now.usec}_#{rand(1000)}.keychain"),
|
@@ -24,6 +38,14 @@ describe Keychain do
|
|
24
38
|
keychain.delete
|
25
39
|
end
|
26
40
|
end
|
41
|
+
|
42
|
+
context 'no password supplied' do
|
43
|
+
#we have to stub this out as it would trigger a dialog box prompting for a password
|
44
|
+
it 'should create a keychain by prompting the user' do
|
45
|
+
Sec.should_receive('SecKeychainCreate').with('akeychain', 0, nil, 1, nil,kind_of(FFI::Pointer)).and_return(0)
|
46
|
+
Keychain.create('akeychain')
|
47
|
+
end
|
48
|
+
end
|
27
49
|
end
|
28
50
|
|
29
51
|
describe 'exists?' do
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ruby-keychain
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.1
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-11-
|
12
|
+
date: 2012-11-21 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: ffi
|
@@ -124,7 +124,7 @@ files:
|
|
124
124
|
- spec/keychain_item_spec.rb
|
125
125
|
- spec/keychain_spec.rb
|
126
126
|
- spec/spec_helper.rb
|
127
|
-
- README
|
127
|
+
- README.markdown
|
128
128
|
- LICENSE
|
129
129
|
homepage: http://github.com/fcheung/keychain
|
130
130
|
licenses:
|