yakg 0.0.2 → 0.0.3
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +3 -1
- data/Gemfile.lock +19 -21
- data/VERSION +1 -1
- data/lib/yakg/backend/macos-keychain.rb +226 -0
- data/lib/yakg/backend/netrc-fallback.rb +41 -0
- data/lib/yakg/backend.rb +6 -215
- data/lib/yakg.rb +8 -0
- data/vendor/gems/Gemfile +4 -0
- data/vendor/gems/Gemfile.lock +13 -0
- data/vendor/gems/installit.sh +33 -0
- data/vendor/gems/ruby/1.8/gems/corefoundation-0.2.0/CHANGELOG +12 -0
- data/vendor/gems/ruby/1.8/gems/corefoundation-0.2.0/LICENSE +8 -0
- data/vendor/gems/ruby/1.8/gems/corefoundation-0.2.0/README.md +40 -0
- data/vendor/gems/ruby/1.8/gems/corefoundation-0.2.0/lib/corefoundation/array.rb +123 -0
- data/vendor/gems/ruby/1.8/gems/corefoundation-0.2.0/lib/corefoundation/base.rb +197 -0
- data/vendor/gems/ruby/1.8/gems/corefoundation-0.2.0/lib/corefoundation/boolean.rb +25 -0
- data/vendor/gems/ruby/1.8/gems/corefoundation-0.2.0/lib/corefoundation/data.rb +42 -0
- data/vendor/gems/ruby/1.8/gems/corefoundation-0.2.0/lib/corefoundation/date.rb +32 -0
- data/vendor/gems/ruby/1.8/gems/corefoundation-0.2.0/lib/corefoundation/dictionary.rb +114 -0
- data/vendor/gems/ruby/1.8/gems/corefoundation-0.2.0/lib/corefoundation/extensions.rb +158 -0
- data/vendor/gems/ruby/1.8/gems/corefoundation-0.2.0/lib/corefoundation/null.rb +11 -0
- data/vendor/gems/ruby/1.8/gems/corefoundation-0.2.0/lib/corefoundation/number.rb +98 -0
- data/vendor/gems/ruby/1.8/gems/corefoundation-0.2.0/lib/corefoundation/string.rb +91 -0
- data/vendor/gems/ruby/1.8/gems/corefoundation-0.2.0/lib/corefoundation/version.rb +4 -0
- data/vendor/gems/ruby/1.8/gems/corefoundation-0.2.0/lib/corefoundation.rb +13 -0
- data/vendor/gems/ruby/1.8/gems/corefoundation-0.2.0/spec/array_spec.rb +92 -0
- data/vendor/gems/ruby/1.8/gems/corefoundation-0.2.0/spec/boolean_spec.rb +24 -0
- data/vendor/gems/ruby/1.8/gems/corefoundation-0.2.0/spec/data_spec.rb +30 -0
- data/vendor/gems/ruby/1.8/gems/corefoundation-0.2.0/spec/date_spec.rb +25 -0
- data/vendor/gems/ruby/1.8/gems/corefoundation-0.2.0/spec/dictionary_spec.rb +81 -0
- data/vendor/gems/ruby/1.8/gems/corefoundation-0.2.0/spec/extensions_spec.rb +127 -0
- data/vendor/gems/ruby/1.8/gems/corefoundation-0.2.0/spec/null_spec.rb +7 -0
- data/vendor/gems/ruby/1.8/gems/corefoundation-0.2.0/spec/number_spec.rb +52 -0
- data/vendor/gems/ruby/1.8/gems/corefoundation-0.2.0/spec/spec_helper.rb +10 -0
- data/vendor/gems/ruby/1.8/gems/corefoundation-0.2.0/spec/string_spec.rb +48 -0
- data/vendor/gems/ruby/1.8/gems/ffi-1.8.1/.require_paths +3 -0
- data/vendor/gems/ruby/1.8/gems/ffi-1.8.1/COPYING +674 -0
- data/vendor/gems/ruby/1.8/gems/ffi-1.8.1/COPYING.LESSER +165 -0
- data/vendor/gems/ruby/1.8/gems/ffi-1.8.1/History.txt +1 -0
- data/vendor/gems/ruby/1.8/gems/ffi-1.8.1/LICENSE +14 -0
- data/vendor/gems/ruby/1.8/gems/ffi-1.8.1/README.md +109 -0
- data/vendor/gems/ruby/1.8/gems/ffi-1.8.1/Rakefile +219 -0
- data/vendor/gems/ruby/1.8/gems/ffi-1.8.1/ffi.gemspec +22 -0
- data/vendor/gems/ruby/1.8/gems/ffi-1.8.1/gen/Rakefile +30 -0
- data/vendor/gems/ruby/1.8/gems/ffi-1.8.1/gen/log +1 -0
- data/vendor/gems/ruby/1.8/gems/ffi-1.8.1/lib/ffi/autopointer.rb +184 -0
- data/vendor/gems/ruby/1.8/gems/ffi-1.8.1/lib/ffi/buffer.rb +4 -0
- data/vendor/gems/ruby/1.8/gems/ffi-1.8.1/lib/ffi/callback.rb +4 -0
- data/vendor/gems/ruby/1.8/gems/ffi-1.8.1/lib/ffi/enum.rb +162 -0
- data/vendor/gems/ruby/1.8/gems/ffi-1.8.1/lib/ffi/errno.rb +33 -0
- data/vendor/gems/ruby/1.8/gems/ffi-1.8.1/lib/ffi/ffi.iml +11 -0
- data/vendor/gems/ruby/1.8/gems/ffi-1.8.1/lib/ffi/ffi.rb +33 -0
- data/vendor/gems/ruby/1.8/gems/ffi-1.8.1/lib/ffi/io.rb +52 -0
- data/vendor/gems/ruby/1.8/gems/ffi-1.8.1/lib/ffi/library.rb +489 -0
- data/vendor/gems/ruby/1.8/gems/ffi-1.8.1/lib/ffi/managedstruct.rb +55 -0
- data/vendor/gems/ruby/1.8/gems/ffi-1.8.1/lib/ffi/memorypointer.rb +1 -0
- data/vendor/gems/ruby/1.8/gems/ffi-1.8.1/lib/ffi/platform/arm-linux/types.conf +104 -0
- data/vendor/gems/ruby/1.8/gems/ffi-1.8.1/lib/ffi/platform/i386-cygwin/types.conf +3 -0
- data/vendor/gems/ruby/1.8/gems/ffi-1.8.1/lib/ffi/platform/i386-darwin/types.conf +100 -0
- data/vendor/gems/ruby/1.8/gems/ffi-1.8.1/lib/ffi/platform/i386-freebsd/types.conf +152 -0
- data/vendor/gems/ruby/1.8/gems/ffi-1.8.1/lib/ffi/platform/i386-linux/types.conf +103 -0
- data/vendor/gems/ruby/1.8/gems/ffi-1.8.1/lib/ffi/platform/i386-netbsd/types.conf +126 -0
- data/vendor/gems/ruby/1.8/gems/ffi-1.8.1/lib/ffi/platform/i386-openbsd/types.conf +126 -0
- data/vendor/gems/ruby/1.8/gems/ffi-1.8.1/lib/ffi/platform/i386-solaris/types.conf +122 -0
- data/vendor/gems/ruby/1.8/gems/ffi-1.8.1/lib/ffi/platform/i386-windows/types.conf +105 -0
- data/vendor/gems/ruby/1.8/gems/ffi-1.8.1/lib/ffi/platform/i486-gnu/types.conf +107 -0
- data/vendor/gems/ruby/1.8/gems/ffi-1.8.1/lib/ffi/platform/ia64-linux/types.conf +104 -0
- data/vendor/gems/ruby/1.8/gems/ffi-1.8.1/lib/ffi/platform/mips-linux/types.conf +102 -0
- data/vendor/gems/ruby/1.8/gems/ffi-1.8.1/lib/ffi/platform/mipsel-linux/types.conf +102 -0
- data/vendor/gems/ruby/1.8/gems/ffi-1.8.1/lib/ffi/platform/powerpc-aix/types.conf +180 -0
- data/vendor/gems/ruby/1.8/gems/ffi-1.8.1/lib/ffi/platform/powerpc-darwin/types.conf +100 -0
- data/vendor/gems/ruby/1.8/gems/ffi-1.8.1/lib/ffi/platform/powerpc-linux/types.conf +100 -0
- data/vendor/gems/ruby/1.8/gems/ffi-1.8.1/lib/ffi/platform/s390-linux/types.conf +102 -0
- data/vendor/gems/ruby/1.8/gems/ffi-1.8.1/lib/ffi/platform/s390x-linux/types.conf +102 -0
- data/vendor/gems/ruby/1.8/gems/ffi-1.8.1/lib/ffi/platform/sparc-linux/types.conf +102 -0
- data/vendor/gems/ruby/1.8/gems/ffi-1.8.1/lib/ffi/platform/sparc-solaris/types.conf +128 -0
- data/vendor/gems/ruby/1.8/gems/ffi-1.8.1/lib/ffi/platform/sparcv9-solaris/types.conf +128 -0
- data/vendor/gems/ruby/1.8/gems/ffi-1.8.1/lib/ffi/platform/x86_64-darwin/types.conf +100 -0
- data/vendor/gems/ruby/1.8/gems/ffi-1.8.1/lib/ffi/platform/x86_64-freebsd/types.conf +128 -0
- data/vendor/gems/ruby/1.8/gems/ffi-1.8.1/lib/ffi/platform/x86_64-linux/types.conf +102 -0
- data/vendor/gems/ruby/1.8/gems/ffi-1.8.1/lib/ffi/platform/x86_64-netbsd/types.conf +126 -0
- data/vendor/gems/ruby/1.8/gems/ffi-1.8.1/lib/ffi/platform/x86_64-openbsd/types.conf +126 -0
- data/vendor/gems/ruby/1.8/gems/ffi-1.8.1/lib/ffi/platform/x86_64-solaris/types.conf +122 -0
- data/vendor/gems/ruby/1.8/gems/ffi-1.8.1/lib/ffi/platform/x86_64-windows/types.conf +27 -0
- data/vendor/gems/ruby/1.8/gems/ffi-1.8.1/lib/ffi/platform.rb +139 -0
- data/vendor/gems/ruby/1.8/gems/ffi-1.8.1/lib/ffi/pointer.rb +122 -0
- data/vendor/gems/ruby/1.8/gems/ffi-1.8.1/lib/ffi/struct.rb +356 -0
- data/vendor/gems/ruby/1.8/gems/ffi-1.8.1/lib/ffi/struct_layout_builder.rb +211 -0
- data/vendor/gems/ruby/1.8/gems/ffi-1.8.1/lib/ffi/tools/const_generator.rb +229 -0
- data/vendor/gems/ruby/1.8/gems/ffi-1.8.1/lib/ffi/tools/generator.rb +60 -0
- data/vendor/gems/ruby/1.8/gems/ffi-1.8.1/lib/ffi/tools/generator_task.rb +36 -0
- data/vendor/gems/ruby/1.8/gems/ffi-1.8.1/lib/ffi/tools/struct_generator.rb +194 -0
- data/vendor/gems/ruby/1.8/gems/ffi-1.8.1/lib/ffi/tools/types_generator.rb +135 -0
- data/vendor/gems/ruby/1.8/gems/ffi-1.8.1/lib/ffi/types.rb +177 -0
- data/vendor/gems/ruby/1.8/gems/ffi-1.8.1/lib/ffi/union.rb +32 -0
- data/vendor/gems/ruby/1.8/gems/ffi-1.8.1/lib/ffi/variadic.rb +65 -0
- data/vendor/gems/ruby/1.8/gems/ffi-1.8.1/lib/ffi/version.rb +4 -0
- data/vendor/gems/ruby/1.8/gems/ffi-1.8.1/lib/ffi.rb +28 -0
- data/vendor/gems/ruby/1.8/gems/ffi-1.8.1/lib/ffi_c.bundle +0 -0
- data/vendor/gems/ruby/1.8/gems/ffi-1.8.1/libtest/Benchmark.c +52 -0
- data/vendor/gems/ruby/1.8/gems/ffi-1.8.1/libtest/BoolTest.c +31 -0
- data/vendor/gems/ruby/1.8/gems/ffi-1.8.1/libtest/BufferTest.c +31 -0
- data/vendor/gems/ruby/1.8/gems/ffi-1.8.1/libtest/ClosureTest.c +190 -0
- data/vendor/gems/ruby/1.8/gems/ffi-1.8.1/libtest/EnumTest.c +34 -0
- data/vendor/gems/ruby/1.8/gems/ffi-1.8.1/libtest/FunctionTest.c +58 -0
- data/vendor/gems/ruby/1.8/gems/ffi-1.8.1/libtest/GNUmakefile +149 -0
- data/vendor/gems/ruby/1.8/gems/ffi-1.8.1/libtest/GlobalVariable.c +62 -0
- data/vendor/gems/ruby/1.8/gems/ffi-1.8.1/libtest/LastErrorTest.c +21 -0
- data/vendor/gems/ruby/1.8/gems/ffi-1.8.1/libtest/NumberTest.c +132 -0
- data/vendor/gems/ruby/1.8/gems/ffi-1.8.1/libtest/PointerTest.c +63 -0
- data/vendor/gems/ruby/1.8/gems/ffi-1.8.1/libtest/ReferenceTest.c +23 -0
- data/vendor/gems/ruby/1.8/gems/ffi-1.8.1/libtest/StringTest.c +34 -0
- data/vendor/gems/ruby/1.8/gems/ffi-1.8.1/libtest/StructTest.c +240 -0
- data/vendor/gems/ruby/1.8/gems/ffi-1.8.1/libtest/UnionTest.c +43 -0
- data/vendor/gems/ruby/1.8/gems/ffi-1.8.1/libtest/VariadicTest.c +62 -0
- data/vendor/gems/ruby/1.8/specifications/corefoundation-0.2.0.gemspec +44 -0
- data/vendor/gems/ruby/1.8/specifications/ffi-1.8.1.gemspec +43 -0
- metadata +115 -3
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,33 +1,29 @@
|
|
1
|
-
GIT
|
2
|
-
remote: https://github.com/tmaher/corefoundation.git
|
3
|
-
revision: e4cb21a7985577c44cd0aa8f9f17e9b6b6e09141
|
4
|
-
specs:
|
5
|
-
corefoundation (0.1.4)
|
6
|
-
ffi
|
7
|
-
|
8
1
|
PATH
|
9
2
|
remote: .
|
10
3
|
specs:
|
11
|
-
yakg (0.0.
|
4
|
+
yakg (0.0.3)
|
12
5
|
corefoundation
|
13
6
|
ffi
|
14
7
|
|
15
8
|
GEM
|
16
9
|
remote: https://rubygems.org/
|
17
10
|
specs:
|
18
|
-
|
11
|
+
corefoundation (0.2.0)
|
12
|
+
ffi
|
13
|
+
diff-lcs (1.2.4)
|
19
14
|
excon (0.16.10)
|
20
|
-
ffi (1.
|
21
|
-
highline (1.6.
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
rspec-
|
26
|
-
rspec-
|
27
|
-
|
28
|
-
rspec-
|
29
|
-
|
30
|
-
|
15
|
+
ffi (1.8.1)
|
16
|
+
highline (1.6.18)
|
17
|
+
netrc (0.7.7)
|
18
|
+
rake (10.0.4)
|
19
|
+
rspec (2.13.0)
|
20
|
+
rspec-core (~> 2.13.0)
|
21
|
+
rspec-expectations (~> 2.13.0)
|
22
|
+
rspec-mocks (~> 2.13.0)
|
23
|
+
rspec-core (2.13.1)
|
24
|
+
rspec-expectations (2.13.0)
|
25
|
+
diff-lcs (>= 1.1.3, < 2.0)
|
26
|
+
rspec-mocks (2.13.1)
|
31
27
|
woof_util (0.0.16)
|
32
28
|
excon (~> 0.16.10)
|
33
29
|
highline (~> 1.6.15)
|
@@ -36,7 +32,9 @@ PLATFORMS
|
|
36
32
|
ruby
|
37
33
|
|
38
34
|
DEPENDENCIES
|
39
|
-
corefoundation
|
35
|
+
corefoundation
|
36
|
+
ffi (~> 1.8.1)
|
37
|
+
netrc
|
40
38
|
rake
|
41
39
|
rspec
|
42
40
|
woof_util
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.0.
|
1
|
+
0.0.3
|
@@ -0,0 +1,226 @@
|
|
1
|
+
# https://developer.apple.com/library/mac/#documentation/security/Reference/keychainservices/Reference/reference.html
|
2
|
+
|
3
|
+
Gem.use_paths(nil, Gem.path << Yakg::Misc::VENDOR_GEM_DIR)
|
4
|
+
require "ffi"
|
5
|
+
require "corefoundation"
|
6
|
+
|
7
|
+
class Yakg
|
8
|
+
module Backend
|
9
|
+
module MacosKeychain
|
10
|
+
|
11
|
+
def self.framework name
|
12
|
+
"/System/Library/Frameworks/#{name}.framework/#{name}"
|
13
|
+
end
|
14
|
+
|
15
|
+
class KeychainError < Exception
|
16
|
+
end
|
17
|
+
|
18
|
+
extend FFI::Library
|
19
|
+
NULL = FFI::Pointer::NULL
|
20
|
+
ffi_lib(FFI::Library::LIBC,
|
21
|
+
framework(:CoreFoundation),
|
22
|
+
framework(:Security))
|
23
|
+
|
24
|
+
attach_function :malloc, [:size_t], :pointer
|
25
|
+
attach_function :free, [:pointer], :void
|
26
|
+
attach_function :CFRelease, [:pointer], :void
|
27
|
+
|
28
|
+
attach_function(:SecKeychainItemFreeContent,
|
29
|
+
[:pointer, :pointer], :uint32)
|
30
|
+
|
31
|
+
attach_function(:SecKeychainFindGenericPassword,
|
32
|
+
[:pointer, :uint32, :string, :uint32, :string,
|
33
|
+
:pointer, :pointer, :pointer],
|
34
|
+
:uint32)
|
35
|
+
|
36
|
+
attach_function(:SecKeychainAddGenericPassword,
|
37
|
+
[:pointer, :uint32, :string, :uint32, :string,
|
38
|
+
:uint32, :pointer, :pointer],
|
39
|
+
:uint32)
|
40
|
+
|
41
|
+
attach_function(:SecKeychainItemDelete, [:pointer], :uint32)
|
42
|
+
attach_function(:SecCopyErrorMessageString, [:uint32, :pointer],
|
43
|
+
:pointer)
|
44
|
+
|
45
|
+
attach_function(:SecKeychainItemModifyContent,
|
46
|
+
[:pointer, :pointer, :uint32, :string], :uint32)
|
47
|
+
|
48
|
+
attach_function(:SecKeychainSearchCreateFromAttributes,
|
49
|
+
[:pointer, :uint32, :pointer, :pointer], :uint32)
|
50
|
+
attach_function(:SecKeychainSearchCopyNext,
|
51
|
+
[:pointer, :pointer], :uint32)
|
52
|
+
attach_function(:SecKeychainItemCopyAttributesAndData,
|
53
|
+
[:pointer, :pointer, :pointer, :pointer,
|
54
|
+
:pointer, :pointer], :uint32)
|
55
|
+
attach_function(:SecKeychainItemFreeAttributesAndData,
|
56
|
+
[:pointer, :pointer], :uint32)
|
57
|
+
|
58
|
+
def error_message code
|
59
|
+
CF::String.new(SecCopyErrorMessageString(code, NULL)).to_s
|
60
|
+
end
|
61
|
+
|
62
|
+
def raise_error? code
|
63
|
+
raise KeychainError.new(error_message code) if code != 0
|
64
|
+
code
|
65
|
+
end
|
66
|
+
|
67
|
+
def delete acct, svc
|
68
|
+
pw_length = FFI::MemoryPointer.new :uint32
|
69
|
+
pw_val = FFI::MemoryPointer.new :pointer
|
70
|
+
item_ref = FFI::MemoryPointer.new :pointer
|
71
|
+
raise_error? SecKeychainFindGenericPassword(NULL, svc.length, svc,
|
72
|
+
acct.length, acct,
|
73
|
+
pw_length, pw_val,
|
74
|
+
item_ref)
|
75
|
+
raise_error? SecKeychainItemFreeContent(NULL, pw_val.read_pointer)
|
76
|
+
raise_error? SecKeychainItemDelete(item_ref.read_pointer)
|
77
|
+
CFRelease item_ref.read_pointer
|
78
|
+
true
|
79
|
+
end
|
80
|
+
|
81
|
+
def get acct, svc
|
82
|
+
pw_length = FFI::MemoryPointer.new :uint32
|
83
|
+
pw_val = FFI::MemoryPointer.new :pointer
|
84
|
+
retval = SecKeychainFindGenericPassword(NULL, svc.length, svc,
|
85
|
+
acct.length, acct,
|
86
|
+
pw_length, pw_val, NULL)
|
87
|
+
return nil unless 0 == retval
|
88
|
+
pw = pw_val.read_pointer.read_string(pw_length.read_int)
|
89
|
+
retval = SecKeychainItemFreeContent(NULL, pw_val.read_pointer)
|
90
|
+
return nil unless 0 == retval
|
91
|
+
|
92
|
+
pw
|
93
|
+
end
|
94
|
+
|
95
|
+
def set acct, value, svc
|
96
|
+
pw_length = FFI::MemoryPointer.new :uint32
|
97
|
+
pw_val = FFI::MemoryPointer.new :pointer
|
98
|
+
item_ref = FFI::MemoryPointer.new :pointer
|
99
|
+
retval = SecKeychainFindGenericPassword(NULL, svc.length, svc,
|
100
|
+
acct.length, acct,
|
101
|
+
pw_length, pw_val, item_ref)
|
102
|
+
if retval != 0
|
103
|
+
raise_error? SecKeychainAddGenericPassword(NULL, svc.length, svc,
|
104
|
+
acct.length, acct,
|
105
|
+
value.length, value, NULL)
|
106
|
+
else
|
107
|
+
raise_error? SecKeychainItemFreeContent(NULL, pw_val.read_pointer)
|
108
|
+
raise_error? SecKeychainItemModifyContent(item_ref.read_pointer, NULL,
|
109
|
+
value.length, value)
|
110
|
+
CFRelease item_ref.read_pointer
|
111
|
+
end
|
112
|
+
true
|
113
|
+
end
|
114
|
+
|
115
|
+
class SecKeychainAttributeList < FFI::Struct
|
116
|
+
layout(:count, :uint32,
|
117
|
+
:attr, :pointer)
|
118
|
+
end
|
119
|
+
|
120
|
+
def self.s2i s
|
121
|
+
s.unpack("N")[0].to_i
|
122
|
+
end
|
123
|
+
def s2i s
|
124
|
+
s.unpack("N")[0].to_i
|
125
|
+
end
|
126
|
+
|
127
|
+
enum :SecItemAttr, [:kSecCreatiofnDateItemAttr, s2i('cdat'),
|
128
|
+
:kSecModDateItemAttr, s2i('mdat'),
|
129
|
+
:kSecDescriptionItemAttr, s2i('desc'),
|
130
|
+
:kSecCommentItemAttr, s2i('icmt'),
|
131
|
+
:kSecCreatorItemAttr, s2i('crtr'),
|
132
|
+
:kSecTypeItemAttr, s2i('type'),
|
133
|
+
:kSecScriptCodeItemAttr, s2i('scrp'),
|
134
|
+
:kSecLabelItemAttr, s2i('labl'),
|
135
|
+
:kSecInvisibleItemAttr, s2i('invi'),
|
136
|
+
:kSecNegativeItemAttr, s2i('nega'),
|
137
|
+
:kSecCustomIconItemAttr, s2i('cusi'),
|
138
|
+
:kSecAccountItemAttr, s2i('acct'),
|
139
|
+
:kSecServiceItemAttr, s2i('svce'),
|
140
|
+
:kSecGenericItemAttr, s2i('gena'),
|
141
|
+
:kSecSecurityDomainItemAttr, s2i('sdmn'),
|
142
|
+
:kSecServerItemAttr, s2i('srvr'),
|
143
|
+
:kSecAuthenticationTypeItemAttr, s2i('atyp'),
|
144
|
+
:kSecPortItemAttr, s2i('port'),
|
145
|
+
:kSecPathItemAttr, s2i('path'),
|
146
|
+
:kSecVolumeItemAttr, s2i('vlme'),
|
147
|
+
:kSecAddressItemAttr, s2i('addr'),
|
148
|
+
:kSecSignatureItemAttr, s2i('ssig'),
|
149
|
+
:kSecProtocolItemAttr, s2i('ptcl'),
|
150
|
+
:kSecCertificateType, s2i('ctyp'),
|
151
|
+
:kSecCertificateEncoding, s2i('cenc'),
|
152
|
+
:kSecCrlType, s2i('crtp'),
|
153
|
+
:kSecCrlEncoding, s2i('crnc'),
|
154
|
+
:kSecAlias, s2i('alis')
|
155
|
+
]
|
156
|
+
|
157
|
+
class SecKeychainAttribute < FFI::Struct
|
158
|
+
layout(:tag, :SecItemAttr,
|
159
|
+
:length, :uint32,
|
160
|
+
:data, :pointer)
|
161
|
+
end
|
162
|
+
|
163
|
+
class SecKeychainAttributeInfo < FFI::Struct
|
164
|
+
layout(:count, :uint32,
|
165
|
+
:tag, :pointer,
|
166
|
+
:format, :pointer)
|
167
|
+
end
|
168
|
+
|
169
|
+
def list svc
|
170
|
+
search_ref = FFI::MemoryPointer.new :pointer
|
171
|
+
found_item = FFI::MemoryPointer.new :pointer
|
172
|
+
found_attr_list = FFI::MemoryPointer.new :pointer
|
173
|
+
svc_attr = SecKeychainAttribute.new
|
174
|
+
|
175
|
+
acct_info = SecKeychainAttributeInfo.new
|
176
|
+
acct_info[:count] = 1
|
177
|
+
acct_info[:tag] = FFI::MemoryPointer.new :uint32
|
178
|
+
acct_info[:tag].write_array_of_int [s2i("acct")]
|
179
|
+
acct_info[:format] = FFI::MemoryPointer.new :uint32
|
180
|
+
acct_info[:format].write_array_of_int [0]
|
181
|
+
|
182
|
+
svc_attr[:tag] = s2i "svce"
|
183
|
+
svc_attr[:length] = svc.length
|
184
|
+
svc_attr[:data] = FFI::MemoryPointer.from_string(svc)
|
185
|
+
|
186
|
+
search_attr_list = SecKeychainAttributeList.new
|
187
|
+
search_attr_list[:count] = 1
|
188
|
+
search_attr_list[:attr] = svc_attr.pointer
|
189
|
+
|
190
|
+
raise_error? SecKeychainSearchCreateFromAttributes(NULL,
|
191
|
+
s2i("genp"),
|
192
|
+
search_attr_list,
|
193
|
+
search_ref)
|
194
|
+
|
195
|
+
acct_names = []
|
196
|
+
while true
|
197
|
+
retval = SecKeychainSearchCopyNext(search_ref.read_pointer,
|
198
|
+
found_item)
|
199
|
+
# the magic "no more items" number
|
200
|
+
break if retval == 4294941996
|
201
|
+
raise_error? retval
|
202
|
+
|
203
|
+
raise_error? SecKeychainItemCopyAttributesAndData(found_item.read_pointer,
|
204
|
+
acct_info,
|
205
|
+
NULL,
|
206
|
+
found_attr_list,
|
207
|
+
NULL, NULL)
|
208
|
+
f = SecKeychainAttributeList.new found_attr_list.read_pointer
|
209
|
+
next if f[:count] != 1
|
210
|
+
|
211
|
+
a = SecKeychainAttribute.new f[:attr]
|
212
|
+
next if a[:tag] != :kSecAccountItemAttr
|
213
|
+
|
214
|
+
acct_names.push a[:data].get_string(0, a[:length])
|
215
|
+
end
|
216
|
+
|
217
|
+
raise_error? SecKeychainItemFreeAttributesAndData(found_attr_list.read_pointer,
|
218
|
+
NULL)
|
219
|
+
CFRelease search_ref.read_pointer
|
220
|
+
|
221
|
+
acct_names
|
222
|
+
end
|
223
|
+
|
224
|
+
end
|
225
|
+
end
|
226
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require "netrc"
|
2
|
+
|
3
|
+
class Yakg
|
4
|
+
module Backend
|
5
|
+
module NetrcFallback
|
6
|
+
|
7
|
+
def set acct, value, svc
|
8
|
+
n = Netrc.read
|
9
|
+
n["#{svc}/#{acct}"] = [acct, value]
|
10
|
+
n.save
|
11
|
+
acct
|
12
|
+
end
|
13
|
+
|
14
|
+
def get acct, svc
|
15
|
+
n = Netrc.read
|
16
|
+
if n["#{svc}/#{acct}"].nil?
|
17
|
+
nil
|
18
|
+
else
|
19
|
+
n["#{svc}/#{acct}"][1]
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def delete acct, svc
|
24
|
+
n = Netrc.read
|
25
|
+
n.delete "#{svc}/#{acct}"
|
26
|
+
n.save
|
27
|
+
true
|
28
|
+
end
|
29
|
+
|
30
|
+
def list svc
|
31
|
+
known = []
|
32
|
+
Netrc.read.each do |x|
|
33
|
+
next unless x[1].match /^#{svc}/
|
34
|
+
known.push(x[1].sub(/^#{svc}\//, ""))
|
35
|
+
end
|
36
|
+
known
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
data/lib/yakg/backend.rb
CHANGED
@@ -1,220 +1,11 @@
|
|
1
|
-
# https://developer.apple.com/library/mac/#documentation/security/Reference/keychainservices/Reference/reference.html
|
2
|
-
require "ffi"
|
3
|
-
require "corefoundation"
|
4
|
-
|
5
1
|
class Yakg
|
6
2
|
module Backend
|
7
|
-
|
8
|
-
|
9
|
-
|
3
|
+
if RUBY_PLATFORM.match("-darwin")
|
4
|
+
require "yakg/backend/macos-keychain"
|
5
|
+
extend Yakg::Backend::MacosKeychain
|
6
|
+
else
|
7
|
+
require "yakg/backend/netrc-fallback"
|
8
|
+
extend Yakg::Backend::NetrcFallback
|
10
9
|
end
|
11
|
-
|
12
|
-
class KeychainError < Exception
|
13
|
-
end
|
14
|
-
|
15
|
-
extend FFI::Library
|
16
|
-
NULL = FFI::Pointer::NULL
|
17
|
-
ffi_lib(FFI::Library::LIBC,
|
18
|
-
framework(:CoreFoundation),
|
19
|
-
framework(:Security))
|
20
|
-
|
21
|
-
attach_function :malloc, [:size_t], :pointer
|
22
|
-
attach_function :free, [:pointer], :void
|
23
|
-
attach_function :CFRelease, [:pointer], :void
|
24
|
-
|
25
|
-
attach_function(:SecKeychainItemFreeContent,
|
26
|
-
[:pointer, :pointer], :uint32)
|
27
|
-
|
28
|
-
attach_function(:SecKeychainFindGenericPassword,
|
29
|
-
[:pointer, :uint32, :string, :uint32, :string,
|
30
|
-
:pointer, :pointer, :pointer],
|
31
|
-
:uint32)
|
32
|
-
|
33
|
-
attach_function(:SecKeychainAddGenericPassword,
|
34
|
-
[:pointer, :uint32, :string, :uint32, :string,
|
35
|
-
:uint32, :pointer, :pointer],
|
36
|
-
:uint32)
|
37
|
-
|
38
|
-
attach_function(:SecKeychainItemDelete, [:pointer], :uint32)
|
39
|
-
attach_function(:SecCopyErrorMessageString, [:uint32, :pointer],
|
40
|
-
:pointer)
|
41
|
-
|
42
|
-
attach_function(:SecKeychainItemModifyContent,
|
43
|
-
[:pointer, :pointer, :uint32, :string], :uint32)
|
44
|
-
|
45
|
-
attach_function(:SecKeychainSearchCreateFromAttributes,
|
46
|
-
[:pointer, :uint32, :pointer, :pointer], :uint32)
|
47
|
-
attach_function(:SecKeychainSearchCopyNext,
|
48
|
-
[:pointer, :pointer], :uint32)
|
49
|
-
attach_function(:SecKeychainItemCopyAttributesAndData,
|
50
|
-
[:pointer, :pointer, :pointer, :pointer,
|
51
|
-
:pointer, :pointer], :uint32)
|
52
|
-
attach_function(:SecKeychainItemFreeAttributesAndData,
|
53
|
-
[:pointer, :pointer], :uint32)
|
54
|
-
|
55
|
-
def self.error_message code
|
56
|
-
CF::String.new(SecCopyErrorMessageString(code, NULL)).to_s
|
57
|
-
end
|
58
|
-
|
59
|
-
def self.raise_error? code
|
60
|
-
raise KeychainError.new(error_message code) if code != 0
|
61
|
-
code
|
62
|
-
end
|
63
|
-
|
64
|
-
def self.delete acct, svc
|
65
|
-
pw_length = FFI::MemoryPointer.new :uint32
|
66
|
-
pw_val = FFI::MemoryPointer.new :pointer
|
67
|
-
item_ref = FFI::MemoryPointer.new :pointer
|
68
|
-
raise_error? SecKeychainFindGenericPassword(NULL, svc.length, svc,
|
69
|
-
acct.length, acct,
|
70
|
-
pw_length, pw_val,
|
71
|
-
item_ref)
|
72
|
-
raise_error? SecKeychainItemFreeContent(NULL, pw_val.read_pointer)
|
73
|
-
raise_error? SecKeychainItemDelete(item_ref.read_pointer)
|
74
|
-
CFRelease item_ref.read_pointer
|
75
|
-
true
|
76
|
-
end
|
77
|
-
|
78
|
-
def self.get acct, svc
|
79
|
-
pw_length = FFI::MemoryPointer.new :uint32
|
80
|
-
pw_val = FFI::MemoryPointer.new :pointer
|
81
|
-
retval = SecKeychainFindGenericPassword(NULL, svc.length, svc,
|
82
|
-
acct.length, acct,
|
83
|
-
pw_length, pw_val, NULL)
|
84
|
-
return nil unless 0 == retval
|
85
|
-
pw = pw_val.read_pointer.read_string(pw_length.read_int)
|
86
|
-
retval = SecKeychainItemFreeContent(NULL, pw_val.read_pointer)
|
87
|
-
return nil unless 0 == retval
|
88
|
-
|
89
|
-
pw
|
90
|
-
end
|
91
|
-
|
92
|
-
def self.set acct, value, svc
|
93
|
-
pw_length = FFI::MemoryPointer.new :uint32
|
94
|
-
pw_val = FFI::MemoryPointer.new :pointer
|
95
|
-
item_ref = FFI::MemoryPointer.new :pointer
|
96
|
-
retval = SecKeychainFindGenericPassword(NULL, svc.length, svc,
|
97
|
-
acct.length, acct,
|
98
|
-
pw_length, pw_val, item_ref)
|
99
|
-
if retval != 0
|
100
|
-
raise_error? SecKeychainAddGenericPassword(NULL, svc.length, svc,
|
101
|
-
acct.length, acct,
|
102
|
-
value.length, value, NULL)
|
103
|
-
else
|
104
|
-
raise_error? SecKeychainItemFreeContent(NULL, pw_val.read_pointer)
|
105
|
-
raise_error? SecKeychainItemModifyContent(item_ref.read_pointer, NULL,
|
106
|
-
value.length, value)
|
107
|
-
CFRelease item_ref.read_pointer
|
108
|
-
end
|
109
|
-
true
|
110
|
-
end
|
111
|
-
|
112
|
-
class SecKeychainAttributeList < FFI::Struct
|
113
|
-
layout(:count, :uint32,
|
114
|
-
:attr, :pointer)
|
115
|
-
end
|
116
|
-
|
117
|
-
def self.s2i s
|
118
|
-
s.unpack("N")[0].to_i
|
119
|
-
end
|
120
|
-
|
121
|
-
enum :SecItemAttr, [:kSecCreatiofnDateItemAttr, s2i('cdat'),
|
122
|
-
:kSecModDateItemAttr, s2i('mdat'),
|
123
|
-
:kSecDescriptionItemAttr, s2i('desc'),
|
124
|
-
:kSecCommentItemAttr, s2i('icmt'),
|
125
|
-
:kSecCreatorItemAttr, s2i('crtr'),
|
126
|
-
:kSecTypeItemAttr, s2i('type'),
|
127
|
-
:kSecScriptCodeItemAttr, s2i('scrp'),
|
128
|
-
:kSecLabelItemAttr, s2i('labl'),
|
129
|
-
:kSecInvisibleItemAttr, s2i('invi'),
|
130
|
-
:kSecNegativeItemAttr, s2i('nega'),
|
131
|
-
:kSecCustomIconItemAttr, s2i('cusi'),
|
132
|
-
:kSecAccountItemAttr, s2i('acct'),
|
133
|
-
:kSecServiceItemAttr, s2i('svce'),
|
134
|
-
:kSecGenericItemAttr, s2i('gena'),
|
135
|
-
:kSecSecurityDomainItemAttr, s2i('sdmn'),
|
136
|
-
:kSecServerItemAttr, s2i('srvr'),
|
137
|
-
:kSecAuthenticationTypeItemAttr, s2i('atyp'),
|
138
|
-
:kSecPortItemAttr, s2i('port'),
|
139
|
-
:kSecPathItemAttr, s2i('path'),
|
140
|
-
:kSecVolumeItemAttr, s2i('vlme'),
|
141
|
-
:kSecAddressItemAttr, s2i('addr'),
|
142
|
-
:kSecSignatureItemAttr, s2i('ssig'),
|
143
|
-
:kSecProtocolItemAttr, s2i('ptcl'),
|
144
|
-
:kSecCertificateType, s2i('ctyp'),
|
145
|
-
:kSecCertificateEncoding, s2i('cenc'),
|
146
|
-
:kSecCrlType, s2i('crtp'),
|
147
|
-
:kSecCrlEncoding, s2i('crnc'),
|
148
|
-
:kSecAlias, s2i('alis')
|
149
|
-
]
|
150
|
-
|
151
|
-
class SecKeychainAttribute < FFI::Struct
|
152
|
-
layout(:tag, :SecItemAttr,
|
153
|
-
:length, :uint32,
|
154
|
-
:data, :pointer)
|
155
|
-
end
|
156
|
-
|
157
|
-
class SecKeychainAttributeInfo < FFI::Struct
|
158
|
-
layout(:count, :uint32,
|
159
|
-
:tag, :pointer,
|
160
|
-
:format, :pointer)
|
161
|
-
end
|
162
|
-
|
163
|
-
|
164
|
-
def self.list svc
|
165
|
-
search_ref = FFI::MemoryPointer.new :pointer
|
166
|
-
found_item = FFI::MemoryPointer.new :pointer
|
167
|
-
found_attr_list = FFI::MemoryPointer.new :pointer
|
168
|
-
svc_attr = SecKeychainAttribute.new
|
169
|
-
|
170
|
-
acct_info = SecKeychainAttributeInfo.new
|
171
|
-
acct_info[:count] = 1
|
172
|
-
acct_info[:tag] = FFI::MemoryPointer.new :uint32
|
173
|
-
acct_info[:tag].write_array_of_int [s2i("acct")]
|
174
|
-
acct_info[:format] = FFI::MemoryPointer.new :uint32
|
175
|
-
acct_info[:format].write_array_of_int [0]
|
176
|
-
|
177
|
-
svc_attr[:tag] = s2i "svce"
|
178
|
-
svc_attr[:length] = svc.length
|
179
|
-
svc_attr[:data] = FFI::MemoryPointer.from_string(svc)
|
180
|
-
|
181
|
-
search_attr_list = SecKeychainAttributeList.new
|
182
|
-
search_attr_list[:count] = 1
|
183
|
-
search_attr_list[:attr] = svc_attr.pointer
|
184
|
-
|
185
|
-
raise_error? SecKeychainSearchCreateFromAttributes(NULL,
|
186
|
-
s2i("genp"),
|
187
|
-
search_attr_list,
|
188
|
-
search_ref)
|
189
|
-
|
190
|
-
acct_names = []
|
191
|
-
while true
|
192
|
-
retval = SecKeychainSearchCopyNext(search_ref.read_pointer,
|
193
|
-
found_item)
|
194
|
-
# the magic "no more items" number
|
195
|
-
break if retval == 4294941996
|
196
|
-
raise_error? retval
|
197
|
-
|
198
|
-
raise_error? SecKeychainItemCopyAttributesAndData(found_item.read_pointer,
|
199
|
-
acct_info,
|
200
|
-
NULL,
|
201
|
-
found_attr_list,
|
202
|
-
NULL, NULL)
|
203
|
-
f = SecKeychainAttributeList.new found_attr_list.read_pointer
|
204
|
-
next if f[:count] != 1
|
205
|
-
|
206
|
-
a = SecKeychainAttribute.new f[:attr]
|
207
|
-
next if a[:tag] != :kSecAccountItemAttr
|
208
|
-
|
209
|
-
acct_names.push a[:data].get_string(0, a[:length])
|
210
|
-
end
|
211
|
-
|
212
|
-
raise_error? SecKeychainItemFreeAttributesAndData(found_attr_list.read_pointer,
|
213
|
-
NULL)
|
214
|
-
CFRelease search_ref.read_pointer
|
215
|
-
|
216
|
-
acct_names
|
217
|
-
end
|
218
|
-
|
219
10
|
end
|
220
11
|
end
|
data/lib/yakg.rb
CHANGED
data/vendor/gems/Gemfile
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
#!/bin/bash -x
|
2
|
+
|
3
|
+
# default mac os path
|
4
|
+
export PATH="/usr/bin:/usr/sbin:/bin:/sbin:/usr/local/bin:/usr/local/sbin"
|
5
|
+
DIR="$( cd "$( dirname "$0" )" && pwd )" ; cd $DIR
|
6
|
+
|
7
|
+
if ! [ -r `basename $0 2>/dev/null` ]; then
|
8
|
+
echo "FAIL! can't cd to the parent of $0"
|
9
|
+
exit 1
|
10
|
+
fi
|
11
|
+
|
12
|
+
if [ -r ruby ] && ! [ -d ruby ]; then
|
13
|
+
echo "FAIL! ./ruby exists and is not a directory"
|
14
|
+
exit 2
|
15
|
+
fi
|
16
|
+
|
17
|
+
rm -rf Gemfile.lock ruby
|
18
|
+
bundle install --path `pwd`
|
19
|
+
|
20
|
+
FFI_C=`find ruby -type f -name ffi_c.bundle | head -n 1`
|
21
|
+
if [ "x${FFI_C}" = "x" ]; then
|
22
|
+
echo "FAIL! Couldn't install ffi"
|
23
|
+
exit 3
|
24
|
+
fi
|
25
|
+
|
26
|
+
CFRB=`find ruby -type f -name corefoundation.rb | head -n 1`
|
27
|
+
if [ "x${CFRB}" = "x" ]; then
|
28
|
+
echo "FAIL! Couldn't install corefoundation"
|
29
|
+
exit 4
|
30
|
+
fi
|
31
|
+
|
32
|
+
rm -rf ./ruby/*/gems/ffi-*/{ext,spec}
|
33
|
+
rm -rf ./ruby/*/cache
|
@@ -0,0 +1,8 @@
|
|
1
|
+
The MIT License
|
2
|
+
Copyright (c) 2012 Frederick Cheung
|
3
|
+
|
4
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
5
|
+
|
6
|
+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
7
|
+
|
8
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|