Code View

plugin / plugin-2.2.0.0 / apps / src / dso-verify.cpp
// SPDX-License-Identifier: MIT
// apps/src/dso-verify.cpp
//
// dso-verify — verify a signed DSO and report trust level
//
// Usage:
//   dso-verify addon.so
//   dso-verify addon.so --keys /etc/myapp/trusted-keys.d/
//   dso-verify addon.so --keys /etc/myapp/trusted-keys.d/ --quiet
//
// Exit codes:
//   0  TRUSTED   — valid signature, signer key in trusted-keys directory
//   1  UNKNOWN   — valid signature, signer key NOT in trusted-keys directory
//   2  UNSIGNED  — no manifest/signature sections
//   3  REJECTED  — signature invalid or SHA-256 mismatch
//   4  ERROR     — I/O or format error

#include <sign/Verifier.hh>
#include <sign/TrustLevel.hh>

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <string>

using namespace fedem::sign;

int main( int argc, char** argv )
{
    std::string dsoPath, keysDir;
    bool quiet = false;

    for( int i = 1; i < argc; ++i )
    {
        if(      !std::strcmp(argv[i],"--keys") && i+1<argc ) keysDir = argv[++i];
        else if( !std::strcmp(argv[i],"--quiet") || !std::strcmp(argv[i],"-q") ) quiet = true;
        else if( !std::strcmp(argv[i],"--help")  || !std::strcmp(argv[i],"-h") )
        {
            std::puts("Usage: dso-verify <addon.so> [--keys <trusted-keys.d/>] [--quiet]\n"
                      "Exit: 0=TRUSTED 1=UNKNOWN 2=UNSIGNED 3=REJECTED 4=ERROR");
            return 0;
        }
        else if( argv[i][0] != '-' ) dsoPath = argv[i];
        else { std::fprintf(stderr,"error: unknown argument: %s\n",argv[i]); return 4; }
    }

    if( dsoPath.empty() )
    { std::fputs("error: DSO path required\n",stderr); return 4; }

    // Default trusted-keys search order
    std::string const keysSearch = keysDir.empty() ? "/etc/trusted-keys.d" : keysDir;

    VerifyResult vr = Verifier::verify( dsoPath, keysSearch );

    if( !quiet )
    {
        std::printf("%s: %s\n", trustLevelName(vr.trust), dsoPath.c_str());
        if( vr.hasManifest )
        {
            std::printf("  name:    %s\n", vr.data.name.c_str());
            std::printf("  version: %s\n", vr.data.version.c_str());
            std::printf("  author:  %s\n", vr.data.author.c_str());
            std::printf("  key:     %s\n", vr.data.publicKeyId.c_str());
            std::printf("  signed:  %s\n", vr.data.timestamp.c_str());
        }
        if( !vr.detail.empty() )
            std::printf("  detail:  %s\n", vr.detail.c_str());
    }

    switch( vr.trust )
    {
        case TrustLevel::TRUSTED:  return 0;
        case TrustLevel::UNKNOWN:  return 1;
        case TrustLevel::UNSIGNED: return 2;
        case TrustLevel::REJECTED: return 3;
    }
    return 4;
}