Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Parse addon id from mozilla.rsa file

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++?

like image 755
Jayesh Avatar asked Jan 08 '19 10:01

Jayesh


1 Answers

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.

like image 101
void Avatar answered Nov 02 '22 17:11

void