-
-
Notifications
You must be signed in to change notification settings - Fork 4k
fix(bundler): sign DLLs #11676
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
fix(bundler): sign DLLs #11676
Changes from all commits
9e3ac6e
f3ce45a
fecf91a
abeb34c
41aa9e7
37b4ca1
ab1d91b
39b259b
a651401
f973a77
88336f8
855ac68
06b2209
1d6d939
7f05af7
415af22
1f8dd28
c3c091b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| --- | ||
| 'tauri-bundler': 'patch:enhance' | ||
| --- | ||
|
|
||
| Sign NSIS and WiX DLLs when bundling |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| --- | ||
| 'tauri-bundler': 'patch:enhance' | ||
| --- | ||
|
|
||
| Sign DLLs from resources. |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -55,11 +55,18 @@ const NSIS_REQUIRED_FILES: &[&str] = &[ | |
| "Include/nsDialogs.nsh", | ||
| "Include/WinMessages.nsh", | ||
| ]; | ||
| const NSIS_PLUGIN_FILES: &[&str] = &[ | ||
| "NSISdl.dll", | ||
| "StartMenu.dll", | ||
| "System.dll", | ||
| "nsDialogs.dll", | ||
| "additional/nsis_tauri_utils.dll", | ||
| ]; | ||
| #[cfg(not(target_os = "windows"))] | ||
| const NSIS_REQUIRED_FILES: &[&str] = &["Plugins/x86-unicode/nsis_tauri_utils.dll"]; | ||
| const NSIS_REQUIRED_FILES: &[&str] = &["Plugins/x86-unicode/additional/nsis_tauri_utils.dll"]; | ||
|
|
||
| const NSIS_REQUIRED_FILES_HASH: &[(&str, &str, &str, HashAlgorithm)] = &[( | ||
| "Plugins/x86-unicode/nsis_tauri_utils.dll", | ||
| "Plugins/x86-unicode/additional/nsis_tauri_utils.dll", | ||
| NSIS_TAURI_UTILS_URL, | ||
| NSIS_TAURI_UTILS_SHA1, | ||
| HashAlgorithm::Sha1, | ||
|
|
@@ -96,7 +103,10 @@ pub fn bundle_project(settings: &Settings, updater: bool) -> crate::Result<Vec<P | |
| log::warn!("NSIS directory contains mis-hashed files. Redownloading them."); | ||
| for (path, url, hash, hash_algorithm) in mismatched { | ||
| let data = download_and_verify(url, hash, *hash_algorithm)?; | ||
| fs::write(nsis_toolset_path.join(path), data)?; | ||
| let out_path = nsis_toolset_path.join(path); | ||
| std::fs::create_dir_all(out_path.parent().context("output path has no parent")?) | ||
| .context("failed to create file output directory")?; | ||
| fs::write(out_path, data).with_context(|| format!("failed to save {path}"))?; | ||
| } | ||
| } | ||
| } | ||
|
|
@@ -116,6 +126,7 @@ fn get_and_extract_nsis(nsis_toolset_path: &Path, _tauri_tools_path: &Path) -> c | |
| fs::rename(_tauri_tools_path.join("nsis-3.08"), nsis_toolset_path)?; | ||
| } | ||
|
|
||
| // download additional plugins | ||
| let nsis_plugins = nsis_toolset_path.join("Plugins"); | ||
|
|
||
| let data = download_and_verify( | ||
|
|
@@ -124,7 +135,7 @@ fn get_and_extract_nsis(nsis_toolset_path: &Path, _tauri_tools_path: &Path) -> c | |
| HashAlgorithm::Sha1, | ||
| )?; | ||
|
|
||
| let target_folder = nsis_plugins.join("x86-unicode"); | ||
| let target_folder = nsis_plugins.join("x86-unicode").join("additional"); | ||
| fs::create_dir_all(&target_folder)?; | ||
| fs::write(target_folder.join("nsis_tauri_utils.dll"), data)?; | ||
|
|
||
|
|
@@ -156,7 +167,7 @@ fn try_add_numeric_build_number(version_str: &str) -> anyhow::Result<String> { | |
|
|
||
| fn build_nsis_app_installer( | ||
| settings: &Settings, | ||
| _nsis_toolset_path: &Path, | ||
| #[allow(unused_variables)] nsis_toolset_path: &Path, | ||
| tauri_tools_path: &Path, | ||
| updater: bool, | ||
| ) -> crate::Result<Vec<PathBuf>> { | ||
|
|
@@ -180,19 +191,83 @@ fn build_nsis_app_installer( | |
| } | ||
| fs::create_dir_all(&output_path)?; | ||
|
|
||
| // we make a copy of the NSIS directory if we're going to sign its DLLs | ||
| // because we don't want to change the DLL hashes so the cache can reuse it | ||
| let maybe_plugin_copy_path = if settings.can_sign() { | ||
| // find nsis path | ||
| #[cfg(target_os = "linux")] | ||
| let system_nsis_toolset_path = std::env::var_os("NSIS_PATH") | ||
| .map(PathBuf::from) | ||
| .unwrap_or_else(|| PathBuf::from("/usr/share/nsis")); | ||
| #[cfg(target_os = "macos")] | ||
| let system_nsis_toolset_path = std::env::var_os("NSIS_PATH") | ||
| .map(PathBuf::from) | ||
| .ok_or_else(|| anyhow::anyhow!("failed to resolve NSIS path")) | ||
| .or_else(|_| { | ||
| let mut makensis_path = | ||
| which::which("makensis").context("failed to resolve `makensis`; did you install nsis? See https://tauri.app/distribute/windows-installer/#install-nsis for more information")?; | ||
| // homebrew installs it as a symlink | ||
| if makensis_path.is_symlink() { | ||
| // read_link might return a path relative to makensis_path so we must use join() and canonicalize | ||
| makensis_path = makensis_path | ||
| .parent() | ||
| .context("missing makensis parent")? | ||
| .join(std::fs::read_link(&makensis_path).context("failed to resolve makensis symlink")?) | ||
| .canonicalize() | ||
| .context("failed to resolve makensis path")?; | ||
| } | ||
| // file structure: | ||
| // ├── bin | ||
| // │ ├── makensis | ||
| // ├── share | ||
| // │ ├── nsis | ||
| let bin_folder = makensis_path.parent().context("missing makensis parent")?; | ||
| let root_folder = bin_folder.parent().context("missing makensis root")?; | ||
| crate::Result::Ok(root_folder.join("share").join("nsis")) | ||
| })?; | ||
| #[cfg(windows)] | ||
| let system_nsis_toolset_path = nsis_toolset_path.to_path_buf(); | ||
|
|
||
| let plugins_path = output_path.join("Plugins"); | ||
| // copy system plugins (we don't want to modify system installed DLLs, and on some systems there will even be permission errors if we try) | ||
| crate::utils::fs_utils::copy_dir( | ||
| &system_nsis_toolset_path.join("Plugins").join("x86-unicode"), | ||
| &plugins_path.join("x86-unicode"), | ||
| ) | ||
| .context("failed to copy system NSIS Plugins folder to local copy")?; | ||
| // copy our downloaded DLLs | ||
| crate::utils::fs_utils::copy_dir( | ||
| &nsis_toolset_path | ||
| .join("Plugins") | ||
| .join("x86-unicode") | ||
| .join("additional"), | ||
| &plugins_path.join("x86-unicode").join("additional"), | ||
| ) | ||
| .context("failed to copy additional NSIS Plugins folder to local copy")?; | ||
| Some(plugins_path) | ||
| } else { | ||
| // in this case plugin_copy_path can be None, we'll use the system default path | ||
| None | ||
| }; | ||
|
|
||
| let mut data = BTreeMap::new(); | ||
|
|
||
| let bundle_id = settings.bundle_identifier(); | ||
| let manufacturer = settings | ||
| .publisher() | ||
| .unwrap_or_else(|| bundle_id.split('.').nth(1).unwrap_or(bundle_id)); | ||
|
|
||
| #[cfg(not(target_os = "windows"))] | ||
| { | ||
| let mut dir = dirs::cache_dir().unwrap(); | ||
| dir.extend(["tauri", "NSIS", "Plugins", "x86-unicode"]); | ||
| data.insert("additional_plugins_path", to_json(dir)); | ||
| } | ||
| let additional_plugins_path = maybe_plugin_copy_path | ||
| .clone() | ||
| .unwrap_or_else(|| nsis_toolset_path.join("Plugins")) | ||
| .join("x86-unicode") | ||
| .join("additional"); | ||
|
|
||
| data.insert( | ||
| "additional_plugins_path", | ||
| // either our Plugins copy (when signing) or the cache/Plugins/x86-unicode path | ||
| to_json(&additional_plugins_path), | ||
| ); | ||
|
|
||
| data.insert("arch", to_json(arch)); | ||
| data.insert("bundle_id", to_json(bundle_id)); | ||
|
|
@@ -526,13 +601,29 @@ fn build_nsis_app_installer( | |
| )); | ||
| fs::create_dir_all(nsis_installer_path.parent().unwrap())?; | ||
|
|
||
| log::info!(action = "Running"; "makensis.exe to produce {}", display_path(&nsis_installer_path)); | ||
| if settings.can_sign() { | ||
| log::info!("Signing NSIS plugins"); | ||
| for dll in NSIS_PLUGIN_FILES { | ||
| let path = additional_plugins_path.join(dll); | ||
| if path.exists() { | ||
| try_sign(&path, settings)?; | ||
| } else { | ||
| log::warn!("Could not find {}, skipping signing", path.display()); | ||
| } | ||
| } | ||
| } | ||
|
|
||
| log::info!(action = "Running"; "makensis to produce {}", display_path(&nsis_installer_path)); | ||
|
|
||
| #[cfg(target_os = "windows")] | ||
| let mut nsis_cmd = Command::new(_nsis_toolset_path.join("makensis.exe")); | ||
| let mut nsis_cmd = Command::new(nsis_toolset_path.join("makensis.exe")); | ||
| #[cfg(not(target_os = "windows"))] | ||
| let mut nsis_cmd = Command::new("makensis"); | ||
|
|
||
| if let Some(plugins_path) = &maybe_plugin_copy_path { | ||
| nsis_cmd.env("NSISPLUGINS", plugins_path); | ||
| } | ||
|
|
||
| nsis_cmd | ||
| .args(["-INPUTCHARSET", "UTF8", "-OUTPUTCHARSET", "UTF8"]) | ||
| .arg(match settings.log_level() { | ||
|
|
@@ -628,6 +719,9 @@ fn generate_resource_data(settings: &Settings) -> crate::Result<ResourcesMap> { | |
| let loader_path = | ||
| dunce::simplified(&settings.project_out_directory().join("WebView2Loader.dll")).to_path_buf(); | ||
| if loader_path.exists() { | ||
| if settings.can_sign() { | ||
| try_sign(&loader_path, settings)?; | ||
| } | ||
| added_resources.push(loader_path.clone()); | ||
| resources.insert( | ||
| loader_path, | ||
|
|
@@ -650,6 +744,10 @@ fn generate_resource_data(settings: &Settings) -> crate::Result<ResourcesMap> { | |
| } | ||
| added_resources.push(resource_path.clone()); | ||
|
|
||
| if settings.can_sign() { | ||
| try_sign(&resource_path, settings)?; | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ...
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. you already identified the code so are you open to creating a PR as well? |
||
| } | ||
|
|
||
| let target_path = resource.target(); | ||
| resources.insert( | ||
| resource_path, | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.