]>
git.saurik.com Git - apple/libsecurity_codesigning.git/blob - lib/reqdumper.cpp
33867de03af8df2b235d800f9cc76b4f9328d02f
2 * Copyright (c) 2006-2007 Apple Inc. All Rights Reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
21 * @APPLE_LICENSE_HEADER_END@
25 // reqdumper - Requirement un-parsing (disassembly)
27 #include "reqdumper.h"
31 namespace CodeSigning
{
33 using namespace UnixPlusPlus
;
37 // Printf to established output channel
39 void Dumper::print(const char *format
, ...)
43 va_start(args
, format
);
44 vsnprintf(buffer
, sizeof(buffer
), format
, args
);
51 // Dump the underlying Requirement program
57 // remove any initial space
58 if (mOutput
[0] == ' ')
59 mOutput
= mOutput
.substr(1);
64 // Dump an entire Requirements set, using temporary Dumper objects.
66 // This detects single Requirement inputs and dumps them successfully (using
67 // single-requirement syntax). No indication of error is returned in this case.
69 string
Dumper::dump(const Requirements
*reqs
, bool debug
/* = false */)
72 return "# no requirement(s)";
73 } else if (reqs
->magic() == Requirement::typeMagic
) { // single requirement
74 return dump((const Requirement
*)reqs
) + "\n";
77 for (unsigned n
= 0; n
< reqs
->count(); n
++) {
79 if (reqs
->type(n
) < kSecRequirementTypeCount
)
80 snprintf(prefix
, sizeof(prefix
),
81 "%s => ", Requirement::typeNames
[reqs
->type(n
)]);
83 snprintf(prefix
, sizeof(prefix
), "/*unknown type*/ %d => ", reqs
->type(n
));
84 Dumper
dumper(reqs
->blob
<Requirement
>(n
), debug
);
86 result
+= prefix
+ dumper
.value() + "\n";
92 string
Dumper::dump(const Requirement
*req
, bool debug
/* = false */)
94 Dumper
dumper(req
, debug
);
98 } catch (const CommonError
&err
) {
101 snprintf(errstr
, sizeof(errstr
), " !! error %ld !!", err
.osStatus());
102 return dumper
.value() + errstr
;
108 string
Dumper::dump(const BlobCore
*req
, bool debug
/* = false */)
110 switch (req
->magic()) {
111 case Requirement::typeMagic
:
112 return dump(static_cast<const Requirement
*>(req
), debug
);
114 case Requirements::typeMagic
:
115 return dump(static_cast<const Requirements
*>(req
), debug
);
118 return "invalid data type";
124 // Element dumpers. Output accumulates in internal buffer.
126 void Dumper::expr(SyntaxLevel level
)
129 print("/*@0x%x*/", pc());
130 ExprOp op
= ExprOp(get
<uint32_t>());
131 switch (op
& ~opFlagMask
) {
139 print("identifier ");
143 print("anchor apple");
146 print("anchor"); certSlot(); print(" = "); hashData();
151 print("info["); dotString(); print("] = "); data();
180 print("info["); dotString(); print("]"); match();
183 print("certificate"); certSlot(); print("["); dotString(); print("]"); match();
186 print("certificate"); certSlot(); print("trusted");
189 print("anchor trusted");
192 if (op
& opGenericFalse
) {
193 print(" false /* opcode %d */", op
& ~opFlagMask
);
195 } else if (op
& opGenericSkip
) {
196 print(" /* opcode %d */", op
& ~opFlagMask
);
199 print("OPCODE %d NOT UNDERSTOOD (ending print)", op
);
205 void Dumper::certSlot()
207 switch (uint32_t slot
= get
<uint32_t>()) {
208 case Requirement::anchorCert
:
211 case Requirement::leafCert
:
222 switch (MatchOperation op
= MatchOperation(get
<uint32_t>())) {
224 print(" /* exists */");
227 print(" = "); data();
230 print(" ~ "); data();
233 print("MATCH OPCODE %d NOT UNDERSTOOD", op
);
238 void Dumper::hashData()
241 const unsigned char *data
; size_t length
;
242 getData(data
, length
);
243 printBytes(data
, length
);
247 void Dumper::data(PrintMode bestMode
/* = isSimple */, bool dotOkay
/* = false */)
249 const unsigned char *data
; size_t length
;
250 getData(data
, length
);
251 for (unsigned n
= 0; n
< length
; n
++)
252 if ((isalnum(data
[n
]) || (data
[n
] == '.' && dotOkay
))) { // simple
253 if (n
== 0 && isdigit(data
[n
])) // unquoted idents can't start with a digit
254 bestMode
= isPrintable
;
255 } else if (isgraph(data
[n
]) || isspace(data
[n
])) {
256 if (bestMode
== isSimple
)
257 bestMode
= isPrintable
;
262 if (length
== 0 && bestMode
== isSimple
)
263 bestMode
= isPrintable
; // force quotes for empty string
267 print("%.*s", length
, data
);
270 print("\"%.*s\"", length
, data
);
274 printBytes(data
, length
);
279 void Dumper::printBytes(const Byte
*data
, size_t length
)
281 for (unsigned n
= 0; n
< length
; n
++)
282 print("%02.2x", data
[n
]);