daemon.devin
daemon.devin

Reputation: 138

NSIS !finalize catch error

I'm trying to catch an error if !finalize doesn't successfully sign the OUTFILE.

In my research, I found that it is possible by reading this NSIS closed/fixed SourceForge bug #1148 that I could check for a return error code; basically anything other than 0 for an unsuccessful return.

So what I'm actually trying to accomplish is I want to be able to check if !finalize was unsuccessful; which in this particular case will most likely be because the user doesn't have access to the internet because I'm having it use a timestamp service first and if not than sign the OUTFILE without using a timestamp.

Here's my current logic using the !finalize instruction:

!define TimestampSHA1
!define TimestampSHA256
!define CERT    `Contrib\crt\${DEVELOPER}.${CERT_EXT}`
!define SIGN    `Contrib\bin\signtool.exe`
!define CMD     `"${SIGN}" sign /f "${CERT}" /p ""`
!define SHA1    `${CMD} /t "${TimestampSHA1}" /v "${PACKAGE}\${OUTFILE}"`
!define SHA256  `${CMD} /fd sha256 /tr "${TimestampSHA256}" /td sha256 /as /v "${PACKAGE}\${OUTFILE}"`

#
# There's a lot more Timestamp services for this next
# !if/!else conditional check but I kept it short
# and sweet as I'm only sharing what's necessary. 
#
!if "${TIMESTAMP_SVC}" == "Comodo"

    !define /REDEF TimestampSHA1 "http://timestamp.comodoca.com"
    !define /REDEF TimestampSHA256 "http://timestamp.comodoca.com/?td=sha256"

!else if "${TIMESTAMP_SVC}" == "Verisign"

    !define /REDEF TimestampSHA1 "http://timestamp.verisign.com/scripts/timstamp.dll"
    !define /REDEF TimestampSHA256 "http://sha256timestamp.ws.symantec.com/sha256/timestamp"

!endif

#
# Sign only if we can locate the certificate..
#
!if /FileExists "${CERT}"


    !ifdef TIMESTAMP_SVC
        #
        # Sign using dual signature hashing 
        # algorithm standards (SHA256 and SHA1)
        # along with a timestamping service.
        #
        !finalize `${SHA1}`
        !finalize `${SHA256}`
        #
        # TODO: Figure out how to catch an error or
        # an unsuccessful signing in order to sign
        # OUTFILE without using a timestamp.
        #
        # The following is just me theoretically 
        # coding as I cannot figure out how to check
        # the return of 'signtool.exe'
        #
        !if ! "${ERRORLEVEL}" == 0

            !finalize `${CMD} /v "%1"`
            !finalize `${CMD} /fd sha256 /td sha256 /as /v "%1"`

        !endif

    !else 

        #
        # If we're here than the end-user didn't 
        # declare a timestamping service so we'll
        # sign it without giving it a timestamp.
        #
        !finalize `${CMD} /v "%1"`
        !finalize `${CMD} /fd sha256 /td sha256 /as /v "%1"`

    !endif

!else # Cannot find the certificate..

    !warning "Cannot find a certificate to code sign with. Please \
              check the spelling and/or the path to your certificate \
              are correct and recompile to sign ${OUTFILE}!"

!endif

I'm well aware about the documentation on !finalize which shows an example using a .bat script but I'd like to avoid having to do that as I've already got the logic in place using NSIS.

Can someone give me a helping hand please?

Upvotes: 2

Views: 1109

Answers (1)

kichik
kichik

Reputation: 34744

!finalize happens after the executable generation is done. So that !if ! "${ERRORLEVEL}" == 0 will actually be evaluated before your command is even executed. You can have the entire script fail with:

!finalize `${CMD} /v "%1"` = 0
!finalize `${CMD} /fd sha256 /td sha256 /as /v "%1"` = 0

If you want to also try to resign without a timestamp, it might be easier to just create a batch file that handles all this logic and call that file with !finalize.

Upvotes: 4

Related Questions