| 
									
										
										
										
											2020-10-10 14:16:11 +02:00
										 |  |  | # typed: false | 
					
						
							| 
									
										
										
										
											2019-04-19 15:38:03 +09:00
										 |  |  | # frozen_string_literal: true | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-08-31 13:16:11 +00:00
										 |  |  | 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 | 
					
						
							| 
									
										
										
										
											2018-08-31 13:16:11 +00:00
										 |  |  |   module Quarantine | 
					
						
							| 
									
										
										
										
											2020-10-20 12:03:48 +02:00
										 |  |  |     extend T::Sig | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-08-31 13:16:11 +00:00
										 |  |  |     module_function | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-19 15:38:03 +09:00
										 |  |  |     QUARANTINE_ATTRIBUTE = "com.apple.quarantine" | 
					
						
							| 
									
										
										
										
											2018-08-31 13:16:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-03 19:39:07 +01:00
										 |  |  |     QUARANTINE_SCRIPT = (HOMEBREW_LIBRARY_PATH/"cask/utils/quarantine.swift").freeze | 
					
						
							| 
									
										
										
										
											2018-08-31 13:16:11 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def swift | 
					
						
							|  |  |  |       @swift ||= DevelopmentTools.locate("swift") | 
					
						
							|  |  |  |     end | 
					
						
							| 
									
										
										
										
											2020-08-24 23:44:12 +02:00
										 |  |  |     private :swift | 
					
						
							| 
									
										
										
										
											2018-08-31 13:16:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-26 20:55:54 +00:00
										 |  |  |     def xattr | 
					
						
							|  |  |  |       @xattr ||= DevelopmentTools.locate("xattr") | 
					
						
							|  |  |  |     end | 
					
						
							| 
									
										
										
										
											2020-08-24 23:44:12 +02:00
										 |  |  |     private :xattr | 
					
						
							| 
									
										
										
										
											2018-09-26 20:55:54 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-20 12:03:48 +02:00
										 |  |  |     sig { returns(Symbol) } | 
					
						
							| 
									
										
										
										
											2018-09-04 21:11:29 +00:00
										 |  |  |     def check_quarantine_support | 
					
						
							|  |  |  |       odebug "Checking quarantine support" | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-13 01:27:36 +00:00
										 |  |  |       if !system_command(xattr, print_stderr: false).success? | 
					
						
							| 
									
										
										
										
											2018-09-26 20:55:54 +00:00
										 |  |  |         odebug "There's not a working version of xattr." | 
					
						
							|  |  |  |         :xattr_broken | 
					
						
							|  |  |  |       elsif swift.nil? | 
					
						
							| 
									
										
										
										
											2018-09-04 21:11:29 +00:00
										 |  |  |         odebug "Swift is not available on this system." | 
					
						
							| 
									
										
										
										
											2018-09-14 15:48:16 +00:00
										 |  |  |         :no_swift | 
					
						
							|  |  |  |       else | 
					
						
							|  |  |  |         api_check = system_command(swift, | 
					
						
							| 
									
										
										
										
											2018-11-02 17:18:07 +00:00
										 |  |  |                                    args:         [QUARANTINE_SCRIPT], | 
					
						
							| 
									
										
										
										
											2018-09-14 15:48:16 +00:00
										 |  |  |                                    print_stderr: false) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         case api_check.exit_status | 
					
						
							|  |  |  |         when 5
 | 
					
						
							|  |  |  |           odebug "This feature requires the macOS 10.10 SDK or higher." | 
					
						
							|  |  |  |           :no_quarantine | 
					
						
							|  |  |  |         when 2
 | 
					
						
							|  |  |  |           odebug "Quarantine is available." | 
					
						
							|  |  |  |           :quarantine_available | 
					
						
							|  |  |  |         else | 
					
						
							|  |  |  |           odebug "Unknown support status" | 
					
						
							|  |  |  |           :unknown | 
					
						
							|  |  |  |         end | 
					
						
							| 
									
										
										
										
											2018-09-04 21:11:29 +00:00
										 |  |  |       end | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-08-31 13:16:11 +00:00
										 |  |  |     def available? | 
					
						
							| 
									
										
										
										
											2018-09-04 21:11:29 +00:00
										 |  |  |       @status ||= check_quarantine_support | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       @status == :quarantine_available | 
					
						
							| 
									
										
										
										
											2018-08-31 13:16:11 +00:00
										 |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def 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 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-04 21:11:29 +00:00
										 |  |  |     def status(file) | 
					
						
							| 
									
										
										
										
											2018-09-26 20:55:54 +00:00
										 |  |  |       system_command(xattr, | 
					
						
							| 
									
										
										
										
											2018-09-04 21:11:29 +00:00
										 |  |  |                      args:         ["-p", QUARANTINE_ATTRIBUTE, file], | 
					
						
							|  |  |  |                      print_stderr: false).stdout.rstrip | 
					
						
							| 
									
										
										
										
											2018-08-31 13:16:11 +00:00
										 |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-26 20:55:54 +00:00
										 |  |  |     def toggle_no_translocation_bit(attribute) | 
					
						
							|  |  |  |       fields = attribute.split(";") | 
					
						
							| 
									
										
										
										
											2018-09-07 15:37:31 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |       # 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 | 
					
						
							| 
									
										
										
										
											2018-09-07 15:37:31 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |       fields[0] = (fields[0].to_i(16) | 0x0100).to_s(16).rjust(4, "0") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       fields.join(";") | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-08 14:00:44 +00:00
										 |  |  |     def release!(download_path: nil) | 
					
						
							|  |  |  |       return unless detect(download_path) | 
					
						
							| 
									
										
										
										
											2018-08-31 13:16:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-08 14:00:44 +00:00
										 |  |  |       odebug "Releasing #{download_path} from quarantine" | 
					
						
							| 
									
										
										
										
											2018-08-31 13:16:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-26 20:55:54 +00:00
										 |  |  |       quarantiner = system_command(xattr, | 
					
						
							| 
									
										
										
										
											2018-11-02 17:18:07 +00:00
										 |  |  |                                    args:         [ | 
					
						
							| 
									
										
										
										
											2018-09-14 15:48:16 +00:00
										 |  |  |                                      "-d", | 
					
						
							|  |  |  |                                      QUARANTINE_ATTRIBUTE, | 
					
						
							|  |  |  |                                      download_path, | 
					
						
							|  |  |  |                                    ], | 
					
						
							|  |  |  |                                    print_stderr: false) | 
					
						
							| 
									
										
										
										
											2018-08-31 13:16:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-08 14:00:44 +00:00
										 |  |  |       return if quarantiner.success? | 
					
						
							| 
									
										
										
										
											2018-08-31 13:16:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-08 14:00:44 +00:00
										 |  |  |       raise CaskQuarantineReleaseError.new(download_path, quarantiner.stderr) | 
					
						
							|  |  |  |     end | 
					
						
							| 
									
										
										
										
											2018-09-07 15:37:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-08 14:00:44 +00:00
										 |  |  |     def cask!(cask: nil, download_path: nil, action: true) | 
					
						
							|  |  |  |       return if cask.nil? || download_path.nil? | 
					
						
							| 
									
										
										
										
											2018-09-07 15:37:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-08 14:00:44 +00:00
										 |  |  |       return if detect(download_path) | 
					
						
							| 
									
										
										
										
											2018-09-07 15:37:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-08 14:00:44 +00:00
										 |  |  |       odebug "Quarantining #{download_path}" | 
					
						
							| 
									
										
										
										
											2018-09-07 15:37:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-08 14:00:44 +00:00
										 |  |  |       quarantiner = system_command(swift, | 
					
						
							| 
									
										
										
										
											2018-11-02 17:18:07 +00:00
										 |  |  |                                    args:         [ | 
					
						
							| 
									
										
										
										
											2018-09-14 15:48:16 +00:00
										 |  |  |                                      QUARANTINE_SCRIPT, | 
					
						
							|  |  |  |                                      download_path, | 
					
						
							|  |  |  |                                      cask.url.to_s, | 
					
						
							|  |  |  |                                      cask.homepage.to_s, | 
					
						
							|  |  |  |                                    ], | 
					
						
							|  |  |  |                                    print_stderr: false) | 
					
						
							| 
									
										
										
										
											2018-09-07 15:37:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-08 14:00:44 +00:00
										 |  |  |       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) | 
					
						
							| 
									
										
										
										
											2018-08-31 13:16:11 +00:00
										 |  |  |       end | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-04 21:11:29 +00:00
										 |  |  |     def propagate(from: nil, to: nil) | 
					
						
							| 
									
										
										
										
											2018-08-31 13:16:11 +00:00
										 |  |  |       return if from.nil? || to.nil? | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       raise CaskError, "#{from} was not quarantined properly." unless detect(from) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       odebug "Propagating quarantine from #{from} to #{to}" | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-08 20:20:25 +00:00
										 |  |  |       quarantine_status = toggle_no_translocation_bit(status(from)) | 
					
						
							| 
									
										
										
										
											2018-09-04 21:11:29 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-15 18:32:37 +02:00
										 |  |  |       resolved_paths = Pathname.glob(to/"**/*", File::FNM_DOTMATCH).reject(&:symlink?) | 
					
						
							| 
									
										
										
										
											2018-09-04 21:11:29 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-08 01:39:52 +00:00
										 |  |  |       system_command!("/usr/bin/xargs", | 
					
						
							| 
									
										
										
										
											2018-11-02 17:18:07 +00:00
										 |  |  |                       args:  [ | 
					
						
							| 
									
										
										
										
											2018-10-08 01:39:52 +00:00
										 |  |  |                         "-0", | 
					
						
							|  |  |  |                         "--", | 
					
						
							|  |  |  |                         "/bin/chmod", | 
					
						
							|  |  |  |                         "-h", | 
					
						
							|  |  |  |                         "u+w", | 
					
						
							|  |  |  |                       ], | 
					
						
							| 
									
										
										
										
											2018-10-08 18:23:21 +00:00
										 |  |  |                       input: resolved_paths.join("\0")) | 
					
						
							| 
									
										
										
										
											2018-10-08 01:39:52 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-04 21:11:29 +00:00
										 |  |  |       quarantiner = system_command("/usr/bin/xargs", | 
					
						
							| 
									
										
										
										
											2018-11-02 17:18:07 +00:00
										 |  |  |                                    args:         [ | 
					
						
							| 
									
										
										
										
											2018-09-04 21:11:29 +00:00
										 |  |  |                                      "-0", | 
					
						
							|  |  |  |                                      "--", | 
					
						
							| 
									
										
										
										
											2018-09-26 20:55:54 +00:00
										 |  |  |                                      xattr, | 
					
						
							| 
									
										
										
										
											2018-09-04 21:11:29 +00:00
										 |  |  |                                      "-w", | 
					
						
							|  |  |  |                                      QUARANTINE_ATTRIBUTE, | 
					
						
							|  |  |  |                                      quarantine_status, | 
					
						
							|  |  |  |                                    ], | 
					
						
							| 
									
										
										
										
											2018-11-02 17:18:07 +00:00
										 |  |  |                                    input:        resolved_paths.join("\0"), | 
					
						
							| 
									
										
										
										
											2018-09-04 21:11:29 +00:00
										 |  |  |                                    print_stderr: false) | 
					
						
							| 
									
										
										
										
											2018-08-31 13:16:11 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |       return if quarantiner.success? | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       raise CaskQuarantinePropagationError.new(to, quarantiner.stderr) | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  |   end | 
					
						
							|  |  |  | end |