lib/keychain/keychain.rb in ruby-keychain-0.2.1 vs lib/keychain/keychain.rb in ruby-keychain-0.3.0
- old
+ new
@@ -1,7 +1,17 @@
module Sec
+ enum :SecExternalItemType, [:kSecItemTypeUnknown ,
+ :kSecItemTypePrivateKey,
+ :kSecItemTypePublicKey,
+ :kSecItemTypeSessionKey,
+ :kSecItemTypeCertificate,
+ :kSecItemTypeAggregate]
+
+ attach_function 'SecAccessCreate', [:pointer, :pointer, :pointer], :osstatus
+ attach_function 'SecTrustedApplicationCreateFromPath', [:string, :pointer], :osstatus
+
attach_function 'SecKeychainCopyDefault', [:pointer], :osstatus
attach_function 'SecKeychainDelete', [:keychainref], :osstatus
attach_function 'SecKeychainOpen', [:string, :pointer], :osstatus
attach_function 'SecKeychainGetPath', [:keychainref, :pointer, :pointer], :osstatus
@@ -17,10 +27,18 @@
:lock_on_sleep, :uchar,
:use_lock_interval, :uchar, #apple ignores this
:lock_interval, :uint32
end
+ class Keychain::TrustedApplication < Sec::Base
+ register_type 'SecTrustedApplication'
+ end
+
+ class Keychain::Access < Sec::Base
+ register_type 'SecAccess'
+ end
+
attach_function 'SecKeychainSetSettings', [:keychainref, KeychainSettings], :osstatus
attach_function 'SecKeychainCopySettings', [:keychainref, KeychainSettings], :osstatus
attach_function 'SecKeychainLock', [:keychainref], :osstatus
attach_function 'SecKeychainUnlock', [:keychainref, :uint32, :pointer, :uchar], :osstatus
@@ -48,11 +66,11 @@
#
def add_to_search_list
list = FFI::MemoryPointer.new(:pointer)
status = Sec.SecKeychainCopySearchList(list)
Sec.check_osstatus(status)
- ruby_list = CF::Base.typecast(list.read_pointer).to_ruby
+ ruby_list = CF::Base.typecast(list.read_pointer).release_on_gc.to_ruby
ruby_list << self unless ruby_list.include?(self)
status = Sec.SecKeychainSetSearchList(CF::Array.immutable(ruby_list))
Sec.check_osstatus(status)
self
end
@@ -100,10 +118,43 @@
# @return [Keychain::Scope] a new scope object
def generic_passwords
Scope.new(Sec::Classes::GENERIC, self)
end
+ # Imports item from string or file to this keychain
+ #
+ # @param [IO, String] input IO object or String with raw data to import
+ # @param [Array <String>] app_list List of applications which will be
+ # permitted to access imported items
+ # @return [Array <SecKeychainItem>] List of imported keychain objects,
+ # each of which may be a SecCertificate, SecKey, or SecIdentity instance
+ def import(input, app_list=[])
+ input = input.read if input.is_a? IO
+
+ # Create array of TrustedApplication objects
+ trusted_apps = get_trusted_apps(app_list)
+
+ # Create an Access object
+ access_buffer = FFI::MemoryPointer.new(:pointer)
+ status = Sec.SecAccessCreate(path.to_cf, trusted_apps, access_buffer)
+ Sec.check_osstatus status
+ access = CF::Base.typecast(access_buffer.read_pointer)
+
+ key_params = Sec::SecItemImportExportKeyParameters.new
+ key_params[:accessRef] = access
+
+ # Import item to the keychain
+ cf_data = CF::Data.from_string(input).release_on_gc
+ cf_array = FFI::MemoryPointer.new(:pointer)
+ status = Sec.SecItemImport(cf_data, nil, :kSecFormatUnknown, :kSecItemTypeUnknown, :kSecItemPemArmour, key_params, self, cf_array)
+ access.release
+ Sec.check_osstatus status
+ item_array = CF::Base.typecast(cf_array.read_pointer).release_on_gc
+
+ item_array.to_ruby
+ end
+
# returns a description of the keychain
# @return [String]
def inspect
"<SecKeychain 0x#{@ptr.address.to_s(16)}: #{path}>"
end
@@ -194,9 +245,20 @@
settings = Sec::KeychainSettings.new
settings[:version] = 1
status = Sec.SecKeychainCopySettings(self, settings)
Sec.check_osstatus status
settings
+ end
+
+ def get_trusted_apps apps
+ trusted_app_array = apps.map do |path|
+ trusted_app_buffer = FFI::MemoryPointer.new(:pointer)
+ status = Sec.SecTrustedApplicationCreateFromPath(
+ path.encode(Encoding::UTF_8), trusted_app_buffer)
+ Sec.check_osstatus(status)
+ CF::Base.typecast(trusted_app_buffer.read_pointer).release_on_gc
+ end
+ trusted_app_array.to_cf
end
def put_settings settings
status = Sec.SecKeychainSetSettings(self, settings)
Sec.check_osstatus status
\ No newline at end of file