7

I am trying to read mozilla.rsa file and parse the addon Id using C++.

My effort:

std::string rsaPath = xpiDir + "\\META-INF\\mozilla.rsa";

int rets = system(("CertUtil " + rsaPath + " | findstr " + "S=CA").c_str());

//
.....
My additional logic.............
.....
///

It's working fine on Windows 7 and later versions. But, there is no on Windows xp.

CertUtil

Is there any way to read addon id from mozilla.rsa file using C or C++?

Duck Dodgers
  • 3,409
  • 8
  • 29
  • 43
Jayesh
  • 4,755
  • 9
  • 32
  • 62
  • What specifically is working on Win7 and not on XP? – Ben T Feb 07 '19 at 23:36
  • Have you tried moving the certutil.exe and required dlls over to XP? I'd guess it would still work fine. Otherwise, you might install and use openssl to parse the cert info. I using openssl.exe instead of certutil.exe acceptable? – ThatOneDude Feb 08 '19 at 21:25
  • try `certutil -dump mozilla.rsa` – HariUserX Feb 11 '19 at 06:09
  • Does [this post](https://stackoverflow.com/questions/42566076/extract-extension-id-from-asn1-mozilla-rsa-file) answer your question. – Jatinder Kumar Feb 11 '19 at 09:01

1 Answers1

4

Indeed, the file can be read and parsed with Windows CryptoAPI.

The file mozilla.rsa of Mozilla extension is a PKCS#7 signature. On Linux it can be viewed with the following command:

openssl pkcs7 -print -inform der -in META-INF/mozilla.rsa.

The signature file contains a chain of certificates. One of them has addon ID in its CN component of Subject field.

This Stack Overflow answer explains how to parse PKCS#7 data using CryptoAPI CryptQueryObject() function.

For reference Microsoft Support has also more elaborate example of parsing: https://support.microsoft.com/en-us/help/323809/how-to-get-information-from-authenticode-signed-executables.

Using all these sources, one can compile the following code which would print the required ID:

#include <windows.h>
#include <wincrypt.h>
#pragma comment(lib, "crypt32.lib")

...

std::string rsaPath = xpiDir + "\\META-INF\\mozilla.rsa";
std::wstring wRsaPath(rsaPath.begin(), rsaPath.end());

HCERTSTORE hStore = NULL;
HCRYPTMSG hMsg = NULL;
BOOL res = CryptQueryObject(
    CERT_QUERY_OBJECT_FILE,
    wRsaPath.c_str(),
    CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED,
    CERT_QUERY_FORMAT_FLAG_BINARY,
    0,
    NULL,
    NULL,
    NULL,
    &hStore,
    &hMsg,
    NULL
);
if (!res) {
    std::cout << "Error decoding PKCS#7 file: " << GetLastError() << std::endl;
    return -1;
}

PCCERT_CONTEXT next_cert = NULL;
while ((next_cert = CertEnumCertificatesInStore(hStore, next_cert)) != NULL)
{
    WCHAR szName[1024];
    // Get subject name
    if (!CertGetNameString(
        next_cert,
        CERT_NAME_SIMPLE_DISPLAY_TYPE,
        0,
        NULL,
        szName,
        1024
    )) {
        std::cout << "CertGetNameString failed.\n";
        return -1;
    }

    // only process names looking like IDs, e.g. "CN={212b458b-a608-452b-be1f-a09658163cbf}"
    if (szName[0] == L'{') {
        std::wcout << szName << std::endl;
    }
}

CryptMsgClose(hMsg);
CertCloseStore(hStore, 0);

The comparison szName[0] == L'{' is not very reliable, it is only used for the sake of code simplicity. One might want to use better way of detecting addon ID value, e.g. regex.

Ashish
  • 2,026
  • 17
  • 19
void
  • 2,759
  • 12
  • 28
  • 1
    Thank you so much. I really appreciate your effort. – Jayesh Feb 12 '19 at 09:49
  • Thank you for the praise, but does the answer work for you? If there are still some glitches on XP then I can follow up, to make the answer really useful for everyone. – void Feb 12 '19 at 10:02