Module: OS::Mac::FFI::Security Private

Extended by:
NativeLibrary
Defined in:
os/mac/ffi/security.rb

Overview

This module is part of a private API. This module may only be used in the Homebrew/brew repository. Third parties should avoid using this module if possible, as it may be removed or changed without warning.

Security.framework code-signing wrapper.

Every Core Foundation object is scoped to a CoreFoundation::ReleasePool so it is released before returning to the caller. Security.framework objects especially must never be left to GC-time release: their destructors log via os_log, which crashes when run on the child side of fork (e.g. in Utils.popen). https://github.com/Homebrew/brew/issues/23606

Constant Summary collapse

FUNCTION_ARGUMENT_TYPES =

This constant is part of a private API. This constant may only be used in the Homebrew/brew repository. Third parties should avoid using this constant if possible, as it may be removed or changed without warning.

T.let(
  [Fiddle::TYPE_VOIDP, Fiddle::TYPE_UINT32_T, Fiddle::TYPE_VOIDP].freeze,
  T::Array[Integer],
)
VALIDATION_FLAGS =

This constant is part of a private API. This constant may only be used in the Homebrew/brew repository. Third parties should avoid using this constant if possible, as it may be removed or changed without warning.

Validate every architecture, nested code and strict bundle structure. https://developer.apple.com/documentation/security/static-code-validation-flags

T.let(((1 << 0) | (1 << 3) | (1 << 4)).freeze, Integer)
REQUIREMENT_FAILED_STATUS =

This constant is part of a private API. This constant may only be used in the Homebrew/brew repository. Third parties should avoid using this constant if possible, as it may be removed or changed without warning.

https://developer.apple.com/documentation/security/errseccsreqfailed

-67050

Class Method Summary collapse

Class Method Details

.designated_requirement(path) ⇒ String?

This method is part of a private API. This method may only be used in the Homebrew/brew repository. Third parties should avoid using this method if possible, as it may be removed or changed without warning.

A designated requirement is macOS's durable identity for recognising successive versions of the same signed code. https://developer.apple.com/documentation/security/applying-code-requirements

Parameters:

Returns:



76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
# File 'os/mac/ffi/security.rb', line 76

def self.designated_requirement(path)
  CoreFoundation.with_release_pool do |pool|
    code = static_code(path, pool)
    next if code.nil?

    requirement = retained_pointer(pool) do |result|
      # https://developer.apple.com/documentation/security/seccodecopydesignatedrequirement%28_%3A_%3A_%3A%29
      function(
        "SecCodeCopyDesignatedRequirement",
        FUNCTION_ARGUMENT_TYPES,
        Fiddle::TYPE_INT,
      ).call(code, 0, result)
    end
    next if requirement.nil?

    # Validate sealed content against its own identity before trusting it.
    # https://developer.apple.com/documentation/security/secstaticcodecheckvalidity%28_%3A_%3A_%3A%29
    next unless function(
      "SecStaticCodeCheckValidity",
      FUNCTION_ARGUMENT_TYPES,
      Fiddle::TYPE_INT,
    ).call(code, VALIDATION_FLAGS, requirement).zero?

    requirement_string = retained_pointer(pool) do |result|
      function(
        "SecRequirementCopyString",
        FUNCTION_ARGUMENT_TYPES,
        Fiddle::TYPE_INT,
      ).call(requirement, 0, result)
    end
    next if requirement_string.nil?

    ObjectiveC.message_send(
      requirement_string,
      "UTF8String",
      [],
      Fiddle::TYPE_VOIDP,
    ).to_s
  end
end

.requirement_match(path, requirement) ⇒ Boolean?

This method is part of a private API. This method may only be used in the Homebrew/brew repository. Third parties should avoid using this method if possible, as it may be removed or changed without warning.

Parameters:

Returns:

  • (Boolean, nil)


118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
# File 'os/mac/ffi/security.rb', line 118

def self.requirement_match(path, requirement)
  CoreFoundation.with_release_pool do |pool|
    code = static_code(path, pool)
    next if code.nil?

    requirement_string = pool.track(CoreFoundation.string_create(requirement))
    next if requirement_string.null?

    compiled_requirement = retained_pointer(pool) do |result|
      # https://developer.apple.com/documentation/security/1394522-secrequirementcreatewithstring
      function(
        "SecRequirementCreateWithString",
        FUNCTION_ARGUMENT_TYPES,
        Fiddle::TYPE_INT,
      ).call(requirement_string, 0, result)
    end
    next if compiled_requirement.nil?

    status = function(
      "SecStaticCodeCheckValidity",
      FUNCTION_ARGUMENT_TYPES,
      Fiddle::TYPE_INT,
    ).call(code, VALIDATION_FLAGS, compiled_requirement)
    next true if status.zero?

    false if status == REQUIREMENT_FAILED_STATUS
  end
end