| 75 | |
| 76 | |
| 77 | class WindowsSignTool(SigningTool): |
| 78 | def __init__(self, certificate_file=None): |
| 79 | super().__init__( |
| 80 | os.environ.get("CONSTRUCTOR_SIGNTOOL_PATH", "signtool"), |
| 81 | certificate_file=certificate_file, |
| 82 | ) |
| 83 | |
| 84 | def _get_signing_params(self): |
| 85 | """Get non-secret signing parameters from environment.""" |
| 86 | return { |
| 87 | "timestamp_server": os.environ.get( |
| 88 | "CONSTRUCTOR_SIGNTOOL_TIMESTAMP_SERVER_URL", "http://timestamp.sectigo.com" |
| 89 | ), |
| 90 | "timestamp_digest": os.environ.get("CONSTRUCTOR_SIGNTOOL_TIMESTAMP_DIGEST", "sha256"), |
| 91 | "file_digest": os.environ.get("CONSTRUCTOR_SIGNTOOL_FILE_DIGEST", "sha256"), |
| 92 | } |
| 93 | |
| 94 | def get_signing_command(self) -> str: |
| 95 | params = self._get_signing_params() |
| 96 | command = ( |
| 97 | f"{win_str_esc(self.executable)} sign /f {win_str_esc(self.certificate_file)} " |
| 98 | f"/tr {win_str_esc(params['timestamp_server'])} /td {params['timestamp_digest']} " |
| 99 | f"/fd {params['file_digest']}" |
| 100 | ) |
| 101 | if "CONSTRUCTOR_PFX_CERTIFICATE_PASSWORD" in os.environ: |
| 102 | # signtool can get the password from the env var on its own |
| 103 | command += ' /p "%CONSTRUCTOR_PFX_CERTIFICATE_PASSWORD%"' |
| 104 | return command |
| 105 | |
| 106 | def verify_signing_tool(self): |
| 107 | super()._verify_tool_is_available() |
| 108 | if not Path(self.certificate_file).exists(): |
| 109 | raise FileNotFoundError(f"Could not find certificate file {self.certificate_file}.") |
| 110 | check_call([self.executable, "/?"], stdout=PIPE, stderr=PIPE) |
| 111 | |
| 112 | def verify_signature(self, installer_file: str | Path): |
| 113 | proc = run( |
| 114 | [self.executable, "verify", "/v", str(installer_file)], |
| 115 | stdout=PIPE, |
| 116 | stderr=STDOUT, |
| 117 | text=True, |
| 118 | ) |
| 119 | logger.info(proc.stdout) |
| 120 | if "SignTool Error: No signature found" in proc.stdout: |
| 121 | # This is a signing error! |
| 122 | proc.check_returncode() |
| 123 | elif proc.returncode: |
| 124 | # we had errors but maybe not critical ones |
| 125 | logger.error( |
| 126 | f"SignTool could find a signature in {installer_file} but detected errors. " |
| 127 | "This is expected for untrusted (development) certificates. " |
| 128 | "If it is supposed to be trusted, please check your certificate!" |
| 129 | ) |
| 130 | |
| 131 | |
| 132 | class AzureSignTool(SigningTool): |
no outgoing calls
no test coverage detected