brew/Library/Homebrew/cask/quarantine.rb

190 lines
5.7 KiB
Ruby
Raw Normal View History

2023-03-18 16:03:10 -07:00
# typed: true
# frozen_string_literal: true
require "development_tools"
2020-08-09 01:34:07 +02:00
require "cask/exceptions"
2018-09-06 08:29:14 +02:00
module Cask
2020-08-24 23:44:12 +02:00
# Helper module for quarantining files.
#
# @api private
module Quarantine
QUARANTINE_ATTRIBUTE = "com.apple.quarantine"
QUARANTINE_SCRIPT = (HOMEBREW_LIBRARY_PATH/"cask/utils/quarantine.swift").freeze
COPY_XATTRS_SCRIPT = (HOMEBREW_LIBRARY_PATH/"cask/utils/copy-xattrs.swift").freeze
2023-03-18 16:03:10 -07:00
def self.swift
@swift ||= DevelopmentTools.locate("swift")
end
2023-03-18 16:03:10 -07:00
private_class_method :swift
2023-03-18 16:03:10 -07:00
def self.xattr
@xattr ||= DevelopmentTools.locate("xattr")
end
2023-03-18 16:03:10 -07:00
private_class_method :xattr
2023-03-18 16:03:10 -07:00
def self.swift_target_args
["-target", "#{Hardware::CPU.arch}-apple-macosx#{MacOS.version}"]
end
2023-03-18 16:03:10 -07:00
private_class_method :swift_target_args
2020-10-20 12:03:48 +02:00
sig { returns(Symbol) }
2023-03-18 16:03:10 -07:00
def self.check_quarantine_support
odebug "Checking quarantine support"
2021-07-19 10:02:19 +08:00
if !system_command(xattr, args: ["-h"], print_stderr: false).success?
odebug "There's no working version of `xattr` on this system."
:xattr_broken
elsif swift.nil?
odebug "Swift is not available on this system."
:no_swift
else
api_check = system_command(swift,
args: [*swift_target_args, QUARANTINE_SCRIPT],
print_stderr: false)
case api_check.exit_status
when 2
odebug "Quarantine is available."
:quarantine_available
else
odebug "Unknown support status"
:unknown
end
end
end
2023-03-18 16:03:10 -07:00
def self.available?
@status ||= check_quarantine_support
@status == :quarantine_available
end
2023-03-18 16:03:10 -07:00
def self.detect(file)
return if file.nil?
odebug "Verifying Gatekeeper status of #{file}"
quarantine_status = !status(file).empty?
odebug "#{file} is #{quarantine_status ? "quarantined" : "not quarantined"}"
quarantine_status
end
2023-03-18 16:03:10 -07:00
def self.status(file)
system_command(xattr,
args: ["-p", QUARANTINE_ATTRIBUTE, file],
print_stderr: false).stdout.rstrip
end
2023-03-18 16:03:10 -07:00
def self.toggle_no_translocation_bit(attribute)
fields = attribute.split(";")
# Fields: status, epoch, download agent, event ID
# Let's toggle the app translocation bit, bit 8
2018-10-03 21:03:22 +00:00
# http://www.openradar.me/radar?id=5022734169931776
fields[0] = (fields[0].to_i(16) | 0x0100).to_s(16).rjust(4, "0")
fields.join(";")
end
2023-03-18 16:03:10 -07:00
def self.release!(download_path: nil)
return unless detect(download_path)
odebug "Releasing #{download_path} from quarantine"
quarantiner = system_command(xattr,
2018-11-02 17:18:07 +00:00
args: [
"-d",
QUARANTINE_ATTRIBUTE,
download_path,
],
print_stderr: false)
return if quarantiner.success?
raise CaskQuarantineReleaseError.new(download_path, quarantiner.stderr)
end
2023-03-18 16:03:10 -07:00
def self.cask!(cask: nil, download_path: nil, action: true)
return if cask.nil? || download_path.nil?
return if detect(download_path)
odebug "Quarantining #{download_path}"
quarantiner = system_command(swift,
2018-11-02 17:18:07 +00:00
args: [
*swift_target_args,
QUARANTINE_SCRIPT,
download_path,
cask.url.to_s,
cask.homepage.to_s,
],
print_stderr: false)
return if quarantiner.success?
case quarantiner.exit_status
when 2
raise CaskQuarantineError.new(download_path, "Insufficient parameters")
else
raise CaskQuarantineError.new(download_path, quarantiner.stderr)
end
end
2023-03-18 16:03:10 -07:00
def self.propagate(from: nil, to: nil)
return if from.nil? || to.nil?
raise CaskError, "#{from} was not quarantined properly." unless detect(from)
odebug "Propagating quarantine from #{from} to #{to}"
quarantine_status = toggle_no_translocation_bit(status(from))
2019-10-15 18:32:37 +02:00
resolved_paths = Pathname.glob(to/"**/*", File::FNM_DOTMATCH).reject(&:symlink?)
system_command!("/usr/bin/xargs",
2018-11-02 17:18:07 +00:00
args: [
"-0",
"--",
"/bin/chmod",
"-h",
"u+w",
],
2018-10-08 18:23:21 +00:00
input: resolved_paths.join("\0"))
quarantiner = system_command("/usr/bin/xargs",
2018-11-02 17:18:07 +00:00
args: [
"-0",
"--",
xattr,
"-w",
QUARANTINE_ATTRIBUTE,
quarantine_status,
],
2018-11-02 17:18:07 +00:00
input: resolved_paths.join("\0"),
print_stderr: false)
return if quarantiner.success?
raise CaskQuarantinePropagationError.new(to, quarantiner.stderr)
end
def self.copy_xattrs(from, to)
odebug "Copying xattrs from #{from} to #{to}"
2023-04-24 10:50:01 -05:00
system_command!(swift,
args: [
*swift_target_args,
COPY_XATTRS_SCRIPT,
from,
to,
])
end
end
end