+++ /dev/null
-/*
- * Copyright (c) 2006-2007 Apple Inc. All Rights Reserved.
- *
- * @APPLE_LICENSE_HEADER_START@
- *
- * This file contains Original Code and/or Modifications of Original Code
- * as defined in and that are subject to the Apple Public Source License
- * Version 2.0 (the 'License'). You may not use this file except in
- * compliance with the License. Please obtain a copy of the License at
- * http://www.opensource.apple.com/apsl/ and read it before using this
- * file.
- *
- * The Original Code and all software distributed under the License are
- * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
- * Please see the License for the specific language governing rights and
- * limitations under the License.
- *
- * @APPLE_LICENSE_HEADER_END@
- */
-
-//
-// reqdumper - Requirement un-parsing (disassembly)
-//
-#include "reqdumper.h"
-#include <security_cdsa_utilities/cssmdata.h> // OID encoder
-#include <cstdarg>
-
-namespace Security {
-namespace CodeSigning {
-
-using namespace UnixPlusPlus;
-
-
-//
-// Table of reserved words (keywords), generated by ANTLR
-//
-static const char * const keywords[] = {
-#include "RequirementKeywords.h"
- "",
- NULL
-};
-
-
-//
-// Printf to established output channel
-//
-void Dumper::print(const char *format, ...)
-{
- char buffer[256];
- va_list args;
- va_start(args, format);
- vsnprintf(buffer, sizeof(buffer), format, args);
- va_end(args);
- mOutput += buffer;
-}
-
-
-//
-// Dump the underlying Requirement program
-//
-void Dumper::dump()
-{
- this->expr();
-
- // remove any initial space
- if (mOutput[0] == ' ')
- mOutput = mOutput.substr(1);
-}
-
-
-//
-// Dump an entire Requirements set, using temporary Dumper objects.
-//
-// This detects single Requirement inputs and dumps them successfully (using
-// single-requirement syntax). No indication of error is returned in this case.
-//
-string Dumper::dump(const Requirements *reqs, bool debug /* = false */)
-{
- if (!reqs) {
- return "# no requirement(s)";
- } else if (reqs->magic() == Requirement::typeMagic) { // single requirement
- return dump((const Requirement *)reqs) + "\n";
- } else {
- string result;
- for (unsigned n = 0; n < reqs->count(); n++) {
- char prefix[200];
- if (reqs->type(n) < kSecRequirementTypeCount)
- snprintf(prefix, sizeof(prefix),
- "%s => ", Requirement::typeNames[reqs->type(n)]);
- else
- snprintf(prefix, sizeof(prefix), "/*unknown type*/ %d => ", reqs->type(n));
- Dumper dumper(reqs->blob<Requirement>(n), debug);
- dumper.expr();
- result += prefix + dumper.value() + "\n";
- }
- return result;
- }
-}
-
-string Dumper::dump(const Requirement *req, bool debug /* = false */)
-{
- Dumper dumper(req, debug);
- try {
- dumper.dump();
- return dumper;
- } catch (const CommonError &err) {
- if (debug) {
- char errstr[80];
- snprintf(errstr, sizeof(errstr), " !! error %ld !!", (unsigned long)err.osStatus());
- return dumper.value() + errstr;
- }
- throw;
- }
-}
-
-string Dumper::dump(const BlobCore *req, bool debug /* = false */)
-{
- switch (req->magic()) {
- case Requirement::typeMagic:
- return dump(static_cast<const Requirement *>(req), debug);
- break;
- case Requirements::typeMagic:
- return dump(static_cast<const Requirements *>(req), debug);
- break;
- default:
- return "invalid data type";
- }
-}
-
-
-//
-// Element dumpers. Output accumulates in internal buffer.
-//
-void Dumper::expr(SyntaxLevel level)
-{
- if (mDebug)
- print("/*@0x%x*/", pc());
- ExprOp op = ExprOp(get<uint32_t>());
- switch (op & ~opFlagMask) {
- case opFalse:
- print("never");
- break;
- case opTrue:
- print("always");
- break;
- case opIdent:
- print("identifier ");
- data();
- break;
- case opAppleAnchor:
- print("anchor apple");
- break;
- case opAppleGenericAnchor:
- print("anchor apple generic");
- break;
- case opAnchorHash:
- print("certificate"); certSlot(); print(" = "); hashData();
- break;
- case opInfoKeyValue:
- if (mDebug)
- print("/*legacy*/");
- print("info["); dotString(); print("] = "); data();
- break;
- case opAnd:
- if (level < slAnd)
- print("(");
- expr(slAnd);
- print(" and ");
- expr(slAnd);
- if (level < slAnd)
- print(")");
- break;
- case opOr:
- if (level < slOr)
- print("(");
- expr(slOr);
- print(" or ");
- expr(slOr);
- if (level < slOr)
- print(")");
- break;
- case opNot:
- print("! ");
- expr(slPrimary);
- break;
- case opCDHash:
- print("cdhash ");
- hashData();
- break;
- case opInfoKeyField:
- print("info["); dotString(); print("]"); match();
- break;
- case opEntitlementField:
- print("entitlement["); dotString(); print("]"); match();
- break;
- case opCertField:
- print("certificate"); certSlot(); print("["); dotString(); print("]"); match();
- break;
- case opCertGeneric:
- print("certificate"); certSlot(); print("[");
- {
- const unsigned char *data; size_t length;
- getData(data, length);
- print("field.%s", CssmOid((unsigned char *)data, length).toOid().c_str());
- }
- print("]"); match();
- break;
- case opCertPolicy:
- print("certificate"); certSlot(); print("[");
- {
- const unsigned char *data; size_t length;
- getData(data, length);
- print("policy.%s", CssmOid((unsigned char *)data, length).toOid().c_str());
- }
- print("]"); match();
- break;
- case opTrustedCert:
- print("certificate"); certSlot(); print("trusted");
- break;
- case opTrustedCerts:
- print("anchor trusted");
- break;
- case opNamedAnchor:
- print("anchor apple "); data();
- break;
- case opNamedCode:
- print("("); data(); print(")");
- break;
- default:
- if (op & opGenericFalse) {
- print(" false /* opcode %d */", op & ~opFlagMask);
- break;
- } else if (op & opGenericSkip) {
- print(" /* opcode %d */", op & ~opFlagMask);
- break;
- } else {
- print("OPCODE %d NOT UNDERSTOOD (ending print)", op);
- return;
- }
- }
-}
-
-void Dumper::certSlot()
-{
- switch (int32_t slot = get<int32_t>()) {
- case Requirement::anchorCert:
- print(" root");
- break;
- case Requirement::leafCert:
- print(" leaf");
- break;
- default:
- print(" %d", slot);
- break;
- }
-}
-
-void Dumper::match()
-{
- switch (MatchOperation op = MatchOperation(get<uint32_t>())) {
- case matchExists:
- print(" /* exists */");
- break;
- case matchEqual:
- print(" = "); data();
- break;
- case matchContains:
- print(" ~ "); data();
- break;
- case matchBeginsWith:
- print(" = "); data(); print("*");
- break;
- case matchEndsWith:
- print(" = *"); data();
- break;
- case matchLessThan:
- print(" < "); data();
- break;
- case matchGreaterEqual:
- print(" >= "); data();
- break;
- case matchLessEqual:
- print(" <= "); data();
- break;
- case matchGreaterThan:
- print(" > "); data();
- break;
- default:
- print("MATCH OPCODE %d NOT UNDERSTOOD", op);
- break;
- }
-}
-
-void Dumper::hashData()
-{
- print("H\"");
- const unsigned char *data; size_t length;
- getData(data, length);
- printBytes(data, length);
- print("\"");
-}
-
-void Dumper::data(PrintMode bestMode /* = isSimple */, bool dotOkay /* = false */)
-{
- const unsigned char *data; size_t length;
- getData(data, length);
- for (unsigned n = 0; n < length; n++)
- if ((isalnum(data[n]) || (data[n] == '.' && dotOkay))) { // simple
- if (n == 0 && isdigit(data[n])) // unquoted idents can't start with a digit
- bestMode = isPrintable;
- } else if (isgraph(data[n]) || isspace(data[n])) {
- if (bestMode == isSimple)
- bestMode = isPrintable;
- } else {
- bestMode = isBinary;
- break; // pessimal
- }
-
- if (bestMode == isSimple) {
- string s((const char *)data, length);
- for (const char * const * k = keywords; *k; k++)
- if (s == *k) {
- bestMode = isPrintable; // reserved word; need quotes
- break;
- }
- }
-
- switch (bestMode) {
- case isSimple:
- print("%.*s", length, data);
- break;
- case isPrintable:
- print("\"%.*s\"", length, data);
- break;
- default:
- print("0x");
- printBytes(data, length);
- break;
- }
-}
-
-void Dumper::printBytes(const Byte *data, size_t length)
-{
- for (unsigned n = 0; n < length; n++)
- print("%02.2x", data[n]);
-}
-
-
-} // CodeSigning
-} // Security