class Keychain::Keychain

Wrapper class for individual keychains. Corresponds to a SecKeychainRef

Public Instance Methods

add_to_search_list() click to toggle source

Add the keychain to the default searchlist

# File lib/keychain/keychain.rb, line 60
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).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
delete() click to toggle source

Removes the keychain from the search path and deletes the corresponding file (SecKeychainDelete)

See developer.apple.com/library/mac/documentation/security/Reference/keychainservices/Reference/reference.html#//apple_ref/c/func/SecKeychainDelete @return self

# File lib/keychain/keychain.rb, line 159
def delete
  status = Sec.SecKeychainDelete(self)
  Sec.check_osstatus(status)
  self
end
exists?() click to toggle source
# File lib/keychain/keychain.rb, line 219
def exists?
  begin
    readable?
    true
  rescue NoSuchKeychainError
    false
  end
end
generic_passwords() click to toggle source

Returns a scope for generic passwords contained in this keychain

@return [Keychain::Scope] a new scope object

# File lib/keychain/keychain.rb, line 112
def generic_passwords
  Scope.new(Sec::Classes::GENERIC, self)
end
import(input, app_list=[]) click to toggle source

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

# File lib/keychain/keychain.rb, line 123
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
inspect() click to toggle source

returns a description of the keychain @return [String]

# File lib/keychain/keychain.rb, line 151
def inspect
  "<SecKeychain 0x#{@ptr.address.to_s(16)}: #{path}>"
end
internet_passwords() click to toggle source

Returns a scope for internet passwords contained in this keychain

@return [Keychain::Scope] a new scope object

# File lib/keychain/keychain.rb, line 105
def internet_passwords
  Scope.new(Sec::Classes::INTERNET, self)
end
lock!() click to toggle source

Locks the keychain

# File lib/keychain/keychain.rb, line 183
def lock!
  status = Sec.SecKeychainLock(self)
  Sec.check_osstatus status
end
lock_interval() click to toggle source

Returns the duration (in seconds) after which the keychain will be locked

@return [Boolean]

# File lib/keychain/keychain.rb, line 82
def lock_interval
  get_settings[:lock_interval]
end
lock_interval=(value) click to toggle source

Sets the duration (in seconds) after which the keychain will be locked

@param [Integer] value dutarion in seconds

# File lib/keychain/keychain.rb, line 98
def lock_interval= value
  put_settings(get_settings.tap {|s| s[:lock_interval] = value})
end
lock_on_sleep=(value) click to toggle source

Set whether the keychain will be locked if the machine goes to sleep

@param [Boolean] value

# File lib/keychain/keychain.rb, line 90
def lock_on_sleep= value
  put_settings(get_settings.tap {|s| s[:lock_on_sleep] = value ? 1 : 0})
end
lock_on_sleep?() click to toggle source

Returns whether the keychain will be locked if the machine goes to sleep

@return [Boolean]

# File lib/keychain/keychain.rb, line 74
def lock_on_sleep?
  get_settings[:lock_on_sleep] != 0
end
locked?() click to toggle source

Returns whether the keychain is locked @return [Boolean]

# File lib/keychain/keychain.rb, line 203
def locked?
  !status_flag?(:kSecUnlockStateStatus)
end
path() click to toggle source

Returns the path at which the keychain is stored

See developer.apple.com/library/mac/documentation/security/Reference/keychainservices/Reference/reference.html#//apple_ref/c/func/SecKeychainGetPath

@return [String] path to the keychain file

# File lib/keychain/keychain.rb, line 170
def path
  out_buffer = FFI::MemoryPointer.new(:uchar, 2048)
  io_size = FFI::MemoryPointer.new(:uint32)
  io_size.put_uint32(0, out_buffer.size)

  status = Sec.SecKeychainGetPath(self,io_size, out_buffer)
  Sec.check_osstatus(status)

  out_buffer.read_string(io_size.get_uint32(0)).force_encoding(Encoding::UTF_8)
end
readable?() click to toggle source

Returns whether the keychain is readable @return [Boolean]

# File lib/keychain/keychain.rb, line 209
def readable?
  status_flag?(:kSecReadPermStatus)
end
unlock!(password=nil) click to toggle source

Unlocks the keychain

@param [optional, String] password the password to unlock the keychain with. If no password is supplied the keychain will prompt the user for a password

# File lib/keychain/keychain.rb, line 191
def unlock! password=nil
  if password
    password = password.encode(Encoding::UTF_8)
    status = Sec.SecKeychainUnlock self, password.bytesize, password, 1
  else
    status = Sec.SecKeychainUnlock self, 0, nil, 0
  end
  Sec.check_osstatus status
end
writeable?() click to toggle source

Returns whether the keychain is writable @return [Boolean]

# File lib/keychain/keychain.rb, line 215
def writeable?
  status_flag?(:kSecWritePermStatus)
end

Private Instance Methods

get_settings() click to toggle source
# File lib/keychain/keychain.rb, line 237
def get_settings
  settings = Sec::KeychainSettings.new
  settings[:version] = 1
  status = Sec.SecKeychainCopySettings(self, settings)
  Sec.check_osstatus status
  settings
end
get_trusted_apps(apps) click to toggle source
# File lib/keychain/keychain.rb, line 245
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
put_settings(settings) click to toggle source
# File lib/keychain/keychain.rb, line 256
def put_settings settings
  status = Sec.SecKeychainSetSettings(self, settings)
  Sec.check_osstatus status
  settings
end
status_flag?(enum_name) click to toggle source
# File lib/keychain/keychain.rb, line 230
def status_flag? enum_name
  out = FFI::MemoryPointer.new(:uint32)
  status = Sec.SecKeychainGetStatus(self,out);
  Sec.check_osstatus status
  (out.get_uint32(0) & Sec.enum_value(enum_name)).nonzero?
end