Class: Keychain::Item

Inherits:
Sec::Base show all
Defined in:
lib/keychain/item.rb

Overview

An individual item from the keychain. Individual accessors are generated for the items attributes

Constant Summary collapse

ATTR_MAP =
{CF::Base.typecast(Sec::kSecAttrAccess) => :access,
CF::Base.typecast(Sec::kSecAttrAccount) => :account,
CF::Base.typecast(Sec::kSecAttrAuthenticationType) => :authentication_type,
CF::Base.typecast(Sec::kSecAttrComment) => :comment,
CF::Base.typecast(Sec::kSecAttrCreationDate) => :created_at,
CF::Base.typecast(Sec::kSecAttrCreator) => :creator,
CF::Base.typecast(Sec::kSecAttrDescription) => :description,
CF::Base.typecast(Sec::kSecAttrGeneric) => :generic,
CF::Base.typecast(Sec::kSecAttrIsInvisible) => :invisible,
CF::Base.typecast(Sec::kSecAttrIsNegative) => :negative,
CF::Base.typecast(Sec::kSecAttrLabel) => :label,
CF::Base.typecast(Sec::kSecAttrModificationDate) => :updated_at,
CF::Base.typecast(Sec::kSecAttrPath) => :path,
CF::Base.typecast(Sec::kSecAttrPort) => :port,
CF::Base.typecast(Sec::kSecAttrProtocol) => :protocol,
CF::Base.typecast(Sec::kSecAttrSecurityDomain) => :security_domain,
CF::Base.typecast(Sec::kSecAttrServer) => :server,
CF::Base.typecast(Sec::kSecAttrService) => :service,
CF::Base.typecast(Sec::kSecAttrType) => :type,
CF::Base.typecast(Sec::kSecClass)    => :klass}
INVERSE_ATTR_MAP =
ATTR_MAP.invert

Instance Attribute Summary

Attributes inherited from Sec::Base

#attributes

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from Sec::Base

define_attributes, #initialize, #keychain, #load_attributes, register_type, #update_self_from_dictionary

Constructor Details

This class inherits a constructor from Sec::Base

Class Method Details

.from_dictionary_of_attributes(cf_dict) ⇒ Object



110
111
112
# File 'lib/keychain/item.rb', line 110

def self.from_dictionary_of_attributes(cf_dict)
  new(0).tap {|item| item.send :update_self_from_dictionary, cf_dict}
end

.new(attrs_or_pointer) ⇒ Object

Creates a new keychain item either from an FFI::Pointer or a hash of attributes

Parameters:

  • attrs_or_pointer (FFI::Pointer, Hash)

    Either an FFI::Pointer to an existing SecKeychainItemRef to wrap or hash of attributes to create a new, unsaved Keychain::Item from see Scope#create



51
52
53
54
55
56
57
58
59
# File 'lib/keychain/item.rb', line 51

def self.new(attrs_or_pointer)
  if attrs_or_pointer.is_a? Hash
    super(0).tap do |result|
      attrs_or_pointer.each {|k,v| result.send("#{k}=", v)}
    end
  else
    super
  end
end

Instance Method Details

#deleteObject

Removes the item from the associated keychain



63
64
65
66
67
# File 'lib/keychain/item.rb', line 63

def delete
  status = Sec.SecKeychainItemDelete(self)
  Sec.check_osstatus(status)
  self
end

#inspectString

returns a programmer friendly description of the item

Returns:

  • (String)


41
42
43
# File 'lib/keychain/item.rb', line 41

def inspect
  "<SecKeychainItem 0x#{@ptr.address.to_s(16)} #{service ? "service: #{service}" : "server: #{server}"} account: #{}>"
end

#passwordString

Fetches the password data associated with the item. This may cause the user to be asked for access

Returns:

  • (String)

    The password data, an ASCII_8BIT encoded string



79
80
81
82
83
84
85
86
87
88
# File 'lib/keychain/item.rb', line 79

def password
  return @unsaved_password if @unsaved_password
  out_buffer = FFI::MemoryPointer.new(:pointer)
  status = Sec.SecItemCopyMatching({Sec::Query::ITEM_LIST => CF::Array.immutable([self]),
                                    Sec::Query::SEARCH_LIST => [self.keychain],
                                    Sec::Query::CLASS => self.klass,
                                    Sec::Query::RETURN_DATA => true}.to_cf, out_buffer)
  Sec.check_osstatus(status)
  CF::Base.typecast(out_buffer.read_pointer).to_s
end

#password=(value) ⇒ String

Note:

The new password is not saved into the keychain until you call #save!

Set a new password for the item

Parameters:

  • value (String)

    The new value for the password

Returns:

  • (String)

    The set value



73
74
75
# File 'lib/keychain/item.rb', line 73

def password=(value)
  @unsaved_password = value
end

#persisted?Boolean

Whether the item has been persisted to the keychain

Returns:

  • (Boolean)


116
117
118
# File 'lib/keychain/item.rb', line 116

def persisted?
  !@ptr.null?
end

#save!(options = {}) ⇒ Keychain::Item

Attempts to update the keychain with any changes made to the item or saves a previously unpersisted item

Parameters:

  • options (optional, Hash) (defaults to: {})

    extra options when saving the item

Options Hash (options):

  • :keychain (Keychain::Keychain)

    when saving an unsaved item, they keychain to save it in

Returns:



95
96
97
98
99
100
101
102
103
104
105
106
107
# File 'lib/keychain/item.rb', line 95

def save!(options={})
  if persisted?
    cf_dict = update
  else
    cf_dict = create(options)
    self.ptr = cf_dict[Sec::Value::REF].to_ptr
    self.retain.release_on_gc
  end
  @unsaved_password = nil
  update_self_from_dictionary(cf_dict)
  cf_dict.release
  self
end