indygreg / apple-platform-rs

Rust crates supporting Apple platform development
595 stars 49 forks source link

--shallow flag doesn't work #148

Closed CendioOssman closed 2 weeks ago

CendioOssman commented 3 months ago

The --shallow flag doesn't seem like it actually works. When we use it, we see that it initially skips the nested bundle:

1 nested bundles will be copied instead of signed because shallow signing enabled:
Contents/lib/tlclient/vncviewer.app
entering nested bundle Contents/lib/tlclient/vncviewer.app
shallow signing enabled; bundle will be copied instead of signed
leaving nested bundle Contents/lib/tlclient/vncviewer.app

compared to a normal run:

signing 1 nested bundles in the following order:
Contents/lib/tlclient/vncviewer.app
entering nested bundle Contents/lib/tlclient/vncviewer.app
signing bundle at ThinLinc Client Signed.app/Contents/lib/tlclient/vncviewer.app into ThinLinc Client Signed.app/Contents/lib/tlclient/vncviewer.app
signing main executable Contents/MacOS/vncviewer
creating cryptographic signature with certificate Developer ID Application: Cendio AB (PHUT6TWL4H)
leaving nested bundle Contents/lib/tlclient/vncviewer.app

However, it still decides to sign those files unconditionally later in the process:

signing Mach-O file Contents/lib/tlclient/vncviewer.app/Contents/MacOS/vncviewer

Overwriting any existing signature on that file that has been carefully created.

The workaround has been to --exclude the nested bundle instead.

indygreg commented 3 weeks ago

Thanks for the report.

The first log snippet you posted looks reasonable to me. I'm scratching my head why it later says signing Mach-O file Contents/lib/tlclient/vncviewer.app/Contents/MacOS/vncviewer. It shouldn't be processing a file in a nested bundle. This implies that it is descending into the nested bundle as part of signing the main bundle.

I'll need more info to reproduce and debug.

Could you please follow the instructions at https://gregoryszorc.com/docs/apple-codesign/stable/apple_codesign_debugging.html to provide more details?

CendioOssman commented 3 weeks ago

I'm a bit unclear what you need, but I've emailed you with hopefully enough detail.

indygreg commented 3 weeks ago

Thanks for the email.

The contents of the email seemingly point to the bug. We properly detect the nested bundle and correctly ignore it. But when signing the main bundle it signs a Mach-O binary in the nested bundle.

I'm not sure why things are doing what they are. But it is a bug.

indygreg commented 3 weeks ago

Here's the relevant layout of the bundle being signed:

Contents/Info.plist
Contents/MacOS/tlclient
Contents/Resources/<many files>
Contents/lib/tlclient/opensc-pkcs11.dylib
Contents/lib/tlclient/<many files>
Contents/lib/tlclient/vncviewer.app/Contents/Info.plist
Contents/lib/tlclient/vncviewer.app/Contents/MacOS/vncviewer

Clearly there is a bundle at Contents/lib/tlclient/vncviewer.app.

However, this bundle is in a directory that isn't annotated in the CodeResources file as nested. This means that from the context of the outer / main bundle, this directory is just a bunch of normal files and not a bundle.

This project handles this correctly the same as Apple's codesign: it descends into the directory and records the digest of every file in the CodeResources file. (As opposed to recording the nested bundle's signature in the CodeResources file.) So that part is working correctly.

What's behaving differently is that rcodesign will sign additional Mach-O files in the bundle when --shallow is specified.

If we compare the results of codesign and rcodesign --shallow, we see:

Since Contents/lib/tlclient/vncviewer.app is being treated as regular files (not a bundle), the Mach-O inside is recognized as a Mach-O and summarily signed, just like the other Mach-O binaries.

If we want rcodesign --shallow to behave like Apple's codesign, I think the change is to no longer sign Mach-O binaries (outside the main executable) when --shallow is used. This would reduce rcodesign --shallow to just populating CodeResources and signing the main executable.

CendioOssman commented 3 weeks ago

If we want rcodesign --shallow to behave like Apple's codesign, I think the change is to no longer sign Mach-O binaries (outside the main executable) when --shallow is used. This would reduce rcodesign --shallow to just populating CodeResources and signing the main executable.

Indeed, in our current setup using Apple's codesign, we have to recurse the bundle and explicitly sign all those extra binaries.

This is not something we want, though, just what we were forced to do.

In the same spirit, we're not really that interested in --shallow. The ideal for us would be if #149 was resolved so we could just sign the entire complex thing in a single invocation. --shallow was just the workaround we tried.

indygreg commented 2 weeks ago

Thanks for clarifying @CendioOssman!

One of the reasons --shallow exists is to provide compatibility with Apple codesign workflows. So I'm going to make the change to Mach-O signing in --shallow mode.

We'll address #149 separately, as it feels like its own bug.