Ported app to M2 and need advice to notarize

Hi,

I am totally unaware of the new notarize mechanism and generally starting to sign my application after having ported it to M2.

I want to distribute the app without App Store - yet.

My application is an open source tool or better a more complex tool for the software development that contains dylibs and frameworks all within an app bundle.

I am using wxWidgets and stumbled upon the build process using install_name_tool temporary for each bundle and probably all libraries that I place into the application bundle to have an @executable_path and not an absolute path.

That works so far, but the notarize tool or better checking it with spctl rejects it.

A further test with spctl --assess or the like, I have the command lost, shows that are resources missing and I have a hint to use @rpath entries to be added.

I am using makefiles and a custom make system where I build up the make commands for each target. I won't modify the rules for each target type, if I could do this in a post build step for all the contents of the app bundle.

I have therefore a shell script that handles that additional task yet until code signing and it looks like as follows:

#!/bin/sh
# Copies together files for the Mac OS X application bundle and created a disk image

export prefix=$1

export VERSION=1.3.4

cp ../../../Database/*.sql wxWrapper.app/Contents/Resources
cp splash.png wxWrapper.app/Contents/Resources

mkdir wxWrapper.app/Contents/Resources/XSLT
cp -R ../../../AppDevelopmentDemo/DynamicApp/XSLT_Templates/include            wxWrapper.app/Contents/Resources/XSLT/include
cp -R ../../../AppDevelopmentDemo/DynamicApp/XSLT_Templates/DMFToXMI           wxWrapper.app/Contents/Resources/XSLT/DMFToXMI
cp -R ../../../AppDevelopmentDemo/DynamicApp/XSLT_Templates/XMIToDMF           wxWrapper.app/Contents/Resources/XSLT/XMIToDMF
cp -R ../../../AppDevelopmentDemo/DynamicApp/XSLT_Templates/lbDMFDataViewModel wxWrapper.app/Contents/Resources/XSLT/lbDMFDataViewModel
cp -R ../../../AppDevelopmentDemo/DynamicApp/XSLT_Templates/lbDMFFixedFormular wxWrapper.app/Contents/Resources/XSLT/lbDMFFixedFormular
cp -R ../../../AppDevelopmentDemo/DynamicApp/XSLT_Templates/TurboVision        wxWrapper.app/Contents/Resources/XSLT/TurboVision
cp -R ../../../AppDevelopmentDemo/DynamicApp/XSLT_Templates/wxActiveRecords    wxWrapper.app/Contents/Resources/XSLT/wxActiveRecords
cp -R ../../../AppDevelopmentDemo/DynamicApp/XSLT_Templates/wxLua              wxWrapper.app/Contents/Resources/XSLT/wxLua

cp ../../../AppDevelopmentDemo/DynamicApp/XSLT_Templates/include/XMISettingsTemplate.xsl wxWrapper.app/Contents/Resources/XSLT/XMIToDMF/XMISettings.xsl
cp -R ../../../AppDevelopmentDemo/DynamicApp/UMLSamples wxWrapper.app/Contents/Resources

mkdir wxWrapper.app/Contents/Resources/toolbarimages
# UGLY! Using environment that also is properly defined while jenkins build is better
cp -R $prefix/lib wxWrapper.app/Contents
cp -R $prefix/plugins wxWrapper.app/Contents/Resources
# How to access them?
cp toolbarimages/*.xpm wxWrapper.app/Contents/Resources/toolbarimages
cp toolbarimages/*.png wxWrapper.app/Contents/Resources/toolbarimages
#cp -R `wx-config --prefix`/lib/lib`wx-config --basename`-`wx-config --release`.0.6.0.dylib wxWrapper.app/Contents/lib
#cp -R `wx-config --prefix`/lib/lib`wx-config --basename`-`wx-config --release`.0.dylib wxWrapper.app/Contents/lib
cp -R `wx-config --prefix`/lib/lib`wx-config --basename`-`wx-config --release`.*.dylib wxWrapper.app/Contents/lib
cp -R `wx-config --prefix`/lib/lib`wx-config --basename`-`wx-config --release`.dylib wxWrapper.app/Contents/lib

cp Info.plist wxWrapper.app/Contents

codesign -f -v -s "Lothar Behrens" wxWrapper.app/Contents/Frameworks/lbHook.framework/Versions/A/lbHook
codesign -f -v -s "Lothar Behrens" wxWrapper.app/Contents/Frameworks/wxJson.framework/Versions/A/wxJson
codesign -f -v -s "Lothar Behrens" wxWrapper.app/Contents/Frameworks/wxWrapperDLL.framework/Versions/A/wxWrapperDLL
codesign -f -v -s "Lothar Behrens" wxWrapper.app/Contents/lib/*
codesign -f -v -s "Lothar Behrens" wxWrapper.app/Contents/Resources/plugins/*
xattr -cr wxWrapper.app
codesign -f -v -s "Lothar Behrens" wxWrapper.app/Contents/MacOS/wxWrapper
#codesign -dvv wxWrapper.app
codesign -f -v -s "Lothar Behrens" wxWrapper.app
#spctl -a -t exec -vvvv wxWrapper.app
#codesign -dvv wxWrapper.app
#codesign -vv --deep-verify wxWrapper.app 

# Creating a new diskimage

hdiutil create -ov -size 200m -volname lbDMF-$VERSION lbDMF-$VERSION-`uname -p`.dmg -fs HFS+

sleep 5

hdiutil attach lbDMF-$VERSION-`uname -p`.dmg

# Copy stuff

#mkdir /Volumes/lbDMF-$VERSION/`uname -p`

#cp -R wxWrapper.app /Volumes/lbDMF-$VERSION/`uname -p`
cp -R wxWrapper.app /Volumes/lbDMF-$VERSION
mkdir /Volumes/lbDMF-$VERSION/toolbarimages
cp toolbarimages/*.xpm /Volumes/lbDMF-$VERSION/toolbarimages
cp toolbarimages/*.png /Volumes/lbDMF-$VERSION/toolbarimages

cp ../../../COPYING /Volumes/lbDMF-$VERSION
cp ../../../license-bindist.txt /Volumes/lbDMF-$VERSION

cp ../../../AppDevelopmentDemo/DynamicApp/Doc/ApplicationprototypingDokumentation.pdf /Volumes/lbDMF-$VERSION/

# Copying templates to an accessable place

cp -R wxWrapper.app/Contents/Resources/XSLT /Volumes/lbDMF-$VERSION/
cp -R wxWrapper.app/Contents/Resources/UMLSamples /Volumes/lbDMF-$VERSION/

mkdir /Volumes/lbDMF-$VERSION/.lbDMF
cp -R wxWrapper.app/Contents/Resources/*.sql /Volumes/lbDMF-$VERSION/.lbDMF


cat <<EOF >> /Volumes/lbDMF-$VERSION/Readme.txt
Dear Mac user!

...

Thanks

Lothar Behrens
EOF

rm -rf `find /Volumes/lbDMF-$VERSION -name CVS -print`

hdiutil detach /Volumes/lbDMF-$VERSION
rm lbDMF-$VERSION lbDMF-$VERSION-`uname -p`.dmg.zip
zip lbDMF.dmg.zip lbDMF-$VERSION lbDMF-$VERSION-`uname -p`.dmg
mv lbDMF.dmg.zip lbDMF-$VERSION-`uname -p`.dmg.zip
code-block

Testing the app bundle shows this:

spctl --assess -vvvvv --type execute wxWrapper.app wxWrapper.app: rejected origin=Apple Development: Lothar Behrens (********)

I need some help where to insert a proper notary tool command and a proper check before uploading that I can see, if I could do so.

Despite that I haven't had an active developer ID, I have that now and need to setup the Developer ID Distribution certificate into the keychain.

So I plan to add the @rpath values per framework/dylib/so as additional commands into the shell script above.

But how can I best verify for successful usage of notary tool?

Any help?

Thanks,

Lothar

I have it got far beyond the notarization! I always ask and then I Digg deeper. I had missed using the correct Developer ID Application certificate. Issuing that with a CSR and addressing that as my signing certificate got me to a next error, I was able to solve by the mentioned option. Hardening runtime was not enabled.

Now I can notarize my app and staple it. Now I have some library loading issues, I have due to the hardening enabled. I may miss some dependencies no longer loadable and will investigate into that.

I may have found the reason for nt being able to load a library within my application bundle. Are the two libraries starting with /usr/lib/libc++.1.dylib the cause, I cannot load the library?

I have added an entitlement to disable com.apple.security.cs.disable-library-validation and added the runtime option --option=library and passed the entitlements file. But the entitlements seem not being reported:

lothar@macm2 wxWrapper % codesign -d -v --entitlements - wxwrapper.app                               
Executable=/Users/lothar/develop/Projects/lbdmf/Test/GUI/wxWrapper/wxWrapper.app/Contents/MacOS/wxWrapper
Identifier=info.wxwrapper
Format=app bundle with Mach-O thin (arm64)
CodeDirectory v=20500 size=3002 flags=0x10000(runtime) hashes=87+3 location=embedded
Signature size=8977
Timestamp=28. Jul 2024 at 18:02:20
Info.plist entries=14
TeamIdentifier=3MPMMGXYRY
Runtime Version=14.2.0
Sealed Resources version=2 rules=13 files=640
Internal requirements count=1 size=176
lothar@macm2 wxWrapper % codesign -d -v --entitlements - wxwrapper.app/Contents/lib/lbModule.so
Executable=/Users/lothar/develop/Projects/lbdmf/Test/GUI/wxWrapper/wxWrapper.app/Contents/lib/lbModule.so.0.0.1
Identifier=lbModule.so.0
Format=Mach-O thin (arm64)
CodeDirectory v=20500 size=2713 flags=0x10000(runtime) hashes=79+2 location=embedded
Signature size=8977
Timestamp=28. Jul 2024 at 18:02:14
Info.plist=not bound
TeamIdentifier=3MPMMGXYRY
Runtime Version=14.2.0
Sealed Resources=none
Internal requirements count=1 size=176

Ill post the second analysis in another answer...

Any further ideas?

Thanks, Lothar

Here is the second part:

Here is the lbModule.so shared object.

wxWrapper.app/Contents/lib/lbModule.so:
Load command 0
      cmd LC_SEGMENT_64
  cmdsize 712
  segname __TEXT
   vmaddr 0x0000000000000000
   vmsize 0x0000000000034000
  fileoff 0
 filesize 212992
  maxprot 0x00000005
 initprot 0x00000005
   nsects 8
    flags 0x0
Section
  sectname __text
   segname __TEXT
      addr 0x0000000000002634
      size 0x000000000002d260
    offset 9780
     align 2^2 (4)
    reloff 0
    nreloc 0
     flags 0x80000400
 reserved1 0
 reserved2 0
Section
  sectname __stubs
   segname __TEXT
      addr 0x000000000002f894
      size 0x0000000000000624
    offset 194708
     align 2^2 (4)
    reloff 0
    nreloc 0
     flags 0x80000408
 reserved1 0 (index into indirect symbol table)
 reserved2 12 (size of stubs)
Section
  sectname __init_offsets
   segname __TEXT
      addr 0x000000000002feb8
      size 0x000000000000000c
    offset 196280
     align 2^2 (4)
    reloff 0
    nreloc 0
     flags 0x00000016
 reserved1 0
 reserved2 0
Section
  sectname __gcc_except_tab
   segname __TEXT
      addr 0x000000000002fec4
      size 0x0000000000000e34
    offset 196292
     align 2^2 (4)
    reloff 0
    nreloc 0
     flags 0x00000000
 reserved1 0
 reserved2 0
Section
  sectname __cstring
   segname __TEXT
      addr 0x0000000000030cf8
      size 0x0000000000002477
    offset 199928
     align 2^0 (1)
    reloff 0
    nreloc 0
     flags 0x00000002
 reserved1 0
 reserved2 0
Section
  sectname __const
   segname __TEXT
      addr 0x000000000003316f
      size 0x0000000000000659
    offset 209263
     align 2^0 (1)
    reloff 0
    nreloc 0
     flags 0x00000000
 reserved1 0
 reserved2 0
Section
  sectname __unwind_info
   segname __TEXT
      addr 0x00000000000337c8
      size 0x0000000000000800
    offset 210888
     align 2^2 (4)
    reloff 0
    nreloc 0
     flags 0x00000000
 reserved1 0
 reserved2 0
Section
  sectname __eh_frame
   segname __TEXT
      addr 0x0000000000033fc8
      size 0x0000000000000038
    offset 212936
     align 2^3 (8)
    reloff 0
    nreloc 0
     flags 0x6800000b
 reserved1 0
 reserved2 0
Load command 1
      cmd LC_SEGMENT_64
  cmdsize 232
  segname __DATA_CONST
   vmaddr 0x0000000000034000
   vmsize 0x0000000000004000
  fileoff 212992
 filesize 16384
  maxprot 0x00000003
 initprot 0x00000003
   nsects 2
    flags 0x10
Section
  sectname __got
   segname __DATA_CONST
      addr 0x0000000000034000
      size 0x0000000000000438
    offset 212992
     align 2^3 (8)
    reloff 0
    nreloc 0
     flags 0x00000006
 reserved1 131 (index into indirect symbol table)
 reserved2 0
Section
  sectname __const
   segname __DATA_CONST
      addr 0x0000000000034438
      size 0x0000000000001368
    offset 214072
     align 2^3 (8)
    reloff 0
    nreloc 0
     flags 0x00000000
 reserved1 0
 reserved2 0
Load command 2
      cmd LC_SEGMENT_64
  cmdsize 232
  segname __DATA
   vmaddr 0x0000000000038000
   vmsize 0x0000000000004000
  fileoff 0
 filesize 0
  maxprot 0x00000003
 initprot 0x00000003
   nsects 2
    flags 0x0
Section
  sectname __common
   segname __DATA
      addr 0x0000000000038000
      size 0x0000000000000030
    offset 0
     align 2^3 (8)
    reloff 0
    nreloc 0
     flags 0x00000001
 reserved1 0
 reserved2 0
Section
  sectname __bss
   segname __DATA
      addr 0x0000000000038030
      size 0x00000000000003e8
    offset 0
     align 2^0 (1)
    reloff 0
    nreloc 0
     flags 0x00000001
 reserved1 0
 reserved2 0
Load command 3
      cmd LC_SEGMENT_64
  cmdsize 72
  segname __LINKEDIT
   vmaddr 0x000000000003c000
   vmsize 0x000000000001c000
  fileoff 229376
 filesize 112128
  maxprot 0x00000001
 initprot 0x00000001
   nsects 0
    flags 0x0
Load command 4
      cmd LC_DYLD_CHAINED_FIXUPS
  cmdsize 16
  dataoff 229376
 datasize 4872
Load command 5
      cmd LC_DYLD_EXPORTS_TRIE
  cmdsize 16
  dataoff 234248
 datasize 10680
Load command 6
     cmd LC_SYMTAB
 cmdsize 24
  symoff 245632
   nsyms 2941
  stroff 293752
 strsize 26816
Load command 7
            cmd LC_DYSYMTAB
        cmdsize 80
      ilocalsym 0
      nlocalsym 2499
     iextdefsym 2499
     nextdefsym 375
      iundefsym 2874
      nundefsym 67
         tocoff 0
           ntoc 0
      modtaboff 0
        nmodtab 0
   extrefsymoff 0
    nextrefsyms 0
 indirectsymoff 292688
  nindirectsyms 266
      extreloff 0
        nextrel 0
      locreloff 0
        nlocrel 0
Load command 8
     cmd LC_UUID
 cmdsize 24
    uuid 2A4D2901-8DC0-3AD1-969D-A13D19E01AF4
Load command 9
      cmd LC_BUILD_VERSION
  cmdsize 32
 platform 1
    minos 13.0
      sdk 14.2
   ntools 1
     tool 3
  version 1022.1
Load command 10
      cmd LC_SOURCE_VERSION
  cmdsize 16
  version 0.0
Load command 11
          cmd LC_LOAD_DYLIB
      cmdsize 96
         name @executable_path/../Frameworks/lbHook.framework/Versions/A/lbHook (offset 24)
   time stamp 2 Thu Jan  1 01:00:02 1970
      current version 1.0.0
compatibility version 1.0.0
Load command 12
          cmd LC_LOAD_DYLIB
      cmdsize 48
         name /usr/lib/libc++.1.dylib (offset 24)
   time stamp 2 Thu Jan  1 01:00:02 1970
      current version 1600.157.0
compatibility version 1.0.0
Load command 13
          cmd LC_LOAD_DYLIB
      cmdsize 56
         name /usr/lib/libSystem.B.dylib (offset 24)
   time stamp 2 Thu Jan  1 01:00:02 1970
      current version 1336.61.1
compatibility version 1.0.0
Load command 14
      cmd LC_FUNCTION_STARTS
  cmdsize 16
  dataoff 244928
 datasize 704
Load command 15
      cmd LC_DATA_IN_CODE
  cmdsize 16
  dataoff 245632
 datasize 0
Load command 16
      cmd LC_CODE_SIGNATURE
  cmdsize 16
  dataoff 320576
 datasize 20928

Hope that gives me an answer.

Thanks, Lothar

I got so far over the first loading of a so with dlopen. My main plugin, lbModule.so could be loaded after I have set entitlements. Then I was able to load another module from the lib directory, where lbModule.so is located, but that then does not be able to loaf my real plugins:

Pid 59583	:lbHook.cpp:992 Kann SO module './wxWrapper.app/Contents/Resources/plugins/lbVisitorOperations.so' nicht laden.
Pid 59583	:lbHook.cpp:992 Kann SO module './wxWrapper.app/Contents/Resources/plugins/lbBasicEventHandlers.so' nicht laden.
Pid 59583	:lbHook.cpp:992 Kann SO module './wxWrapper.app/Contents/Resources/plugins/lbFileOperationsPlugin.so' nicht laden.
Pid 59583	:lbHook.cpp:992 Kann SO module './wxWrapper.app/Contents/Resources/plugins/lbCryptoStream.so' nicht laden.
Pid 59583	:lbHook.cpp:992 Kann SO module './wxWrapper.app/Contents/Resources/plugins/lbDMFXslt.so' nicht laden.
Pid 59583	:lbHook.cpp:992 Kann SO module './wxWrapper.app/Contents/Resources/plugins/lbwxUpdateChecker.so' nicht laden.
Pid 59583	:lbHook.cpp:992 Kann SO module './wxWrapper.app/Contents/Resources/plugins/lbDMFBasicActionSteps.so' nicht laden.
Pid 59583	:lbHook.cpp:992 Kann SO module './wxWrapper.app/Contents/Resources/plugins/UserFeedback.so' nicht laden.
Pid 59583	:lbHook.cpp:992 Kann SO module './wxWrapper.app/Contents/Resources/plugins/DatabaseLayerGateway.so' nicht laden.
Pid 59583	:lbHook.cpp:992 Kann SO module './wxWrapper.app/Contents/Resources/plugins/lbXSLTTransformer.so' nicht laden.
Pid 59583	:lbHook.cpp:992 Kann SO module './wxWrapper.app/Contents/Resources/plugins/lbDMFDataModel.so' nicht laden.
Pid 59583	:lbHook.cpp:992 Kann SO module './wxWrapper.app/Contents/Resources/plugins/lbLoginWizard.so' nicht laden.
Pid 59583	:lbHook.cpp:992 Kann SO module './wxWrapper.app/Contents/Resources/plugins/lbANTLR3.so' nicht laden.
Pid 59583	:lbHook.cpp:992 Kann SO module './wxWrapper.app/Contents/Resources/plugins/lbDatabaseReport.so' nicht laden.
Pid 59583	:lbHook.cpp:992 Kann SO module './wxWrapper.app/Contents/Resources/plugins/lbDynamicAppStorage.so' nicht laden.
Pid 59583	:lbHook.cpp:992 Kann SO module './wxWrapper.app/Contents/Resources/plugins/lbDatabaseForm.so' nicht laden.
Pid 59583	:lbHook.cpp:992 Kann SO module './wxWrapper.app/Contents/Resources/plugins/lbwxSFDesigner.so' nicht laden.
Pid 59583	:lbHook.cpp:992 Kann SO module './wxWrapper.app/Contents/Resources/plugins/TestPlugin.so' nicht laden.
Pid 59583	:lbHook.cpp:992 Kann SO module './wxWrapper.app/Contents/Resources/plugins/lbwxPropertyForm.so' nicht laden.
Pid 59583	:lbHook.cpp:992 Kann SO module './wxWrapper.app/Contents/Resources/plugins/lbUILanguage.so' nicht laden.
Pid 59583	:2024. 7.28 - 19:27:30 Datei: lbMetaApplication.cpp Zeile: 1363 Message: Error: Could not load stream operator classes!

Should I move the plugin folder out of Resources beside the lib folder?

Two examples. The first does not load but the second:

Executable=/Users/lothar/develop/Projects/lbdmf/Test/GUI/wxWrapper/wxWrapper.app/Contents/Resources/plugins/lbVisitorOperations.so.0.0.1
Identifier=lbVisitorOperations.so.0
Format=Mach-O thin (arm64)
CodeDirectory v=20500 size=7716 flags=0x10000(runtime) hashes=232+5 location=embedded
Signature size=8978
Timestamp=28. Jul 2024 at 19:26:26
Info.plist=not bound
TeamIdentifier=3MPMMGXYRY
Runtime Version=14.2.0
Sealed Resources=none
Internal requirements count=1 size=184
[Dict]
	[Key] com.apple.security.cs.disable-library-validation
	[Value]
		[Bool] true
lothar@macm2 wxWrapper % codesign -d -v --entitlements - wxwrapper.app/Contents/lib/lbModule.so
Executable=/Users/lothar/develop/Projects/lbdmf/Test/GUI/wxWrapper/wxWrapper.app/Contents/lib/lbModule.so.0.0.1
Identifier=lbModule.so.0
Format=Mach-O thin (arm64)
CodeDirectory v=20500 size=2809 flags=0x10000(runtime) hashes=79+5 location=embedded
Signature size=8977
Timestamp=28. Jul 2024 at 19:26:21
Info.plist=not bound
TeamIdentifier=3MPMMGXYRY
Runtime Version=14.2.0
Sealed Resources=none
Internal requirements count=1 size=176
[Dict]
	[Key] com.apple.security.cs.disable-library-validation
	[Value]
		[Bool] true
lothar@macm2 wxWrapper % 

For today, I have tried enough. I should rename the title and the topic. It is no longer notarization.

Regards, Lothar

Wow, that’s a lot of info. I’m not really sure where to start here, so lemme just point you at some docs. Or, more accurate, some forums posts with links to documentation:

Beyond that, check out An Apple Library Primer which, in turn, links to Dynamic Library Identification and Embedding nonstandard code structures in a bundle.

I’m not sure where you’re at right now, but I see you’re aiming to disable library validation and I want to caution you against doing that unnecessarily [1]. It’s the leading cause of Gatekeeper problems, as I explain in Resolving Gatekeeper Problems Caused by Dangling Load Command Paths.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

[1] There are very few good reasons to disable library validation. Loading in-process plug-ins created by other developers is the only common one.

Hi,

I have got it so far, that I can load my main shared objects (*.so) within my application bundle within Contents/lib.

But I didn't have found any documentation where to locate plugins that I want NOT to be located in the same directory. This is because I scan the directory and use a loose coupled system for my software.

My plugins directory was at Contents/Resources/plugins and I was unable to load any of these by the following module name for dlopen. For example ./Contents/Resources/plugins/fooPlugin.so

After moving the plugins beside the Contents/lib directory and adopted my path for the parameter to ./Contents/plugins/fooPlugin.so it failed as well.

While reading the @rpath install_name_tool, I did not found an example for other than the lib folder . regardless id local/lib ~/lib or whet ever was mentioned.

So far, I think, I have gone through the code signing steps with applying entitlements and through notarizing. I think, I miss something around the custom plugin path.

Thanks, Lothar

The canonical place for plug-ins is Contents/PlugIns. Note the capitalisation. See Placing Content in a Bundle for more on this.

If you only load plug-ins from within your bundle, you shouldn’t disable library validation. Rather, leave library validation enabled and make sure all your plug-ins are signed by you.

You will need to sign each plug-in as a separate code item. For detailed instructions on how to sign Mac code manually, see Creating distribution-signed code for macOS.

As your plug-ins are loaded from within your bundle, I recommend that you use the rpath model described in Dynamic Library Standard Setup for Apps.

If you still can’t get dlopen to work, call dlerror to get the actual error and post that here.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

Ported app to M2 and need advice to notarize
 
 
Q