Skip to content
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

8293462: [macos] app image signature invalid when creating DMG or PKG from post processed signed image #10316

Closed
wants to merge 3 commits into from
Closed
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -271,19 +271,18 @@ public void prepareApplicationFiles(Map<String, ? super Object> params)
// Mark app image as signed, before we signing it.
AppImageFile appImageFile =
AppImageFile.load(predefinedAppImage);
appImageFile.setIsSigned(true);
AppImageFile.save(predefinedAppImage, null, appImageFile);
if (!appImageFile.isSigned()) {
appImageFile.copyAsSigned().save(predefinedAppImage);
} else {
appImageFile = null;
}

boolean markUnsigned = false;
try {
markUnsigned = !doSigning(params);
doSigning(params);
} catch (Exception ex) {
markUnsigned = true;
} finally {
// Undo marking image as signed if needed.
if (markUnsigned) {
appImageFile.setIsSigned(false);
AppImageFile.save(predefinedAppImage, null, appImageFile);
// Restore original app image file if signing failed
if (appImageFile != null) {
appImageFile.save(predefinedAppImage);
}
}

@@ -382,7 +381,7 @@ private void copyRuntimeFiles(Map<String, ? super Object> params)
}
}

private boolean doSigning(Map<String, ? super Object> params)
private void doSigning(Map<String, ? super Object> params)
throws IOException {

if (Optional.ofNullable(
@@ -406,10 +405,7 @@ private boolean doSigning(Map<String, ? super Object> params)
// Calling signAppBundle() without signingIdentity will result in
// unsigning app bundle
signAppBundle(params, root, null, null, null);
return false; // Since we unsigned app image
}

return true;
}

private static String getLauncherName(Map<String, ? super Object> params) {
Original file line number Diff line number Diff line change
@@ -77,7 +77,7 @@ protected void copyApplication(Map<String, ? super Object> params)
appLayout.appDirectory());
}

AppImageFile.save(root, params, null);
AppImageFile.save(root, params);

List<String> items = APP_CONTENT.fetchFrom(params);
for (String item : items) {
Original file line number Diff line number Diff line change
@@ -61,13 +61,14 @@
public final class AppImageFile {

// These values will be loaded from AppImage xml file.
private final String creatorVersion;
private final String creatorPlatform;
private final Path appImageDir;
private final String appVersion;
private final String launcherName;
private final String mainClass;
private final List<LauncherInfo> addLauncherInfos;
private boolean signed;
private final String creatorVersion;
private final String creatorPlatform;
private final boolean signed;
private final boolean appStore;

private static final String FILENAME = ".jpackage.xml";
@@ -81,11 +82,8 @@ private AppImageFile(Path appImageDir, String appVersion, String launcherName,
String creatorVersion, String creatorPlatform, String signedStr,
String appStoreStr) {
boolean isValid = true;
if (!Objects.equals(getVersion(), creatorVersion)) {
isValid = false;
}

if (!Objects.equals(getPlatform(), creatorPlatform)) {
if (appImageDir == null) {
isValid = false;
}

@@ -107,6 +105,14 @@ private AppImageFile(Path appImageDir, String appVersion, String launcherName,
}
}

if (!Objects.equals(getVersion(), creatorVersion)) {
isValid = false;
}

if (!Objects.equals(getPlatform(), creatorPlatform)) {
isValid = false;
}

if (signedStr == null ||
!("true".equals(signedStr) || "false".equals(signedStr))) {
isValid = false;
@@ -123,6 +129,7 @@ private AppImageFile(Path appImageDir, String appVersion, String launcherName,
AppImageFile.getPathInAppImage(appImageDir)));
}

this.appImageDir = appImageDir;
this.appVersion = appVersion;
this.launcherName = launcherName;
this.mainClass = mainClass;
@@ -142,6 +149,13 @@ List<LauncherInfo> getAddLaunchers() {
return addLauncherInfos;
}

/**
* Returns application image directory. Never returns null.
*/
Path getAppImageDir() {
return appImageDir;
}

/**
* Returns application version. Never returns null or empty value.
*/
@@ -163,10 +177,6 @@ String getMainClass() {
return mainClass;
}

public void setIsSigned(boolean v) {
signed = v;
}

public boolean isSigned() {
return signed;
}
@@ -186,6 +196,27 @@ public static Path getPathInAppImage(Path appImageDir) {
.resolve(FILENAME);
}

/**
* Saves file with application image info in application image using values
* from current instance.
* @param appImageDir - path to application image
* @throws IOException
*/
void save(Path appImageDir) throws IOException {
AppImageFile.save(appImageDir, null, this);
}

/**
* Saves file with application image info in application image.
* @param appImageDir - path to application image
* @param params - parameters used to generate application image
* @throws IOException
*/
static void save(Path appImageDir, Map<String, Object> params)
throws IOException {
AppImageFile.save(appImageDir, params, null);
}

/**
* Saves file with application image info in application image using params
* or appImage. Both params or appImage cannot be valid.
@@ -196,7 +227,7 @@ public static Path getPathInAppImage(Path appImageDir) {
* @throws IllegalArgumentException - If both params and appImage are null or
* If both params and appImage are not null
*/
static void save(Path appImageDir,
private static void save(Path appImageDir,
Map<String, Object> params,
AppImageFile appImage) throws IOException {
if ((params == null && appImage == null) ||
@@ -335,10 +366,20 @@ public static AppImageFile load(Path appImageDir) {
}
}

private static String getAttribute(Node item, String attr) {
NamedNodeMap attrs = item.getAttributes();
Node attrNode = attrs.getNamedItem(attr);
return ((attrNode == null) ? null : attrNode.getNodeValue());
/**
* Returns copy of AppImageFile, but with signed set to true if AppImageFile
* is not marked as signed. If AppImageFile already signed it will return
* instance to itself.
* @return
*/
public AppImageFile copyAsSigned() {
if (isSigned()) {
return this;
}

return new AppImageFile(getAppImageDir(), getAppVersion(),
getLauncherName(), getMainClass(), getAddLaunchers(),
getVersion(), getPlatform(), "true", String.valueOf(isAppStore()));
}

public static Document readXml(Path appImageDir) throws IOException {
@@ -431,6 +472,12 @@ private LauncherInfo(Node node) {
this.service = !"false".equals(getAttribute(node, "service"));
}

private String getAttribute(Node item, String attr) {
NamedNodeMap attrs = item.getAttributes();
Node attrNode = attrs.getNamedItem(attr);
return ((attrNode == null) ? null : attrNode.getNodeValue());
}

public String getName() {
return name;
}
Original file line number Diff line number Diff line change
@@ -169,6 +169,21 @@ public void testMacSign() throws IOException {
Assert.assertTrue(aif.isSigned());
}

@Test
public void testCopyAsSigned() throws IOException {
Map<String, Object> params = new LinkedHashMap<>();
params.put("name", "Foo");
params.put("main-class", "main.Class");
params.put("description", "Duck App Description");
params.put("mac-sign", Boolean.FALSE);

AppImageFile aif = create(params);
Assert.assertFalse(aif.isSigned());

aif = aif.copyAsSigned();
Assert.assertTrue(aif.isSigned());
}

@Test
public void testMacAppStore() throws IOException {
Map<String, Object> params = new LinkedHashMap<>();
@@ -211,7 +226,7 @@ public void testAddLaunchers() throws IOException {
}

private AppImageFile create(Map<String, Object> params) throws IOException {
AppImageFile.save(tempFolder.getRoot().toPath(), params, null);
AppImageFile.save(tempFolder.getRoot().toPath(), params);
return AppImageFile.load(tempFolder.getRoot().toPath());
}