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