]>
git.saurik.com Git - apple/security.git/blob - OSX/libsecurity_codesigning/lib/reqdumper.cpp
ea29bdfe7a544528f08b7e08b626530393b3d0aa
2 * Copyright (c) 2006-2007,2011-2013 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"
29 #include <security_cdsa_utilities/cssmdata.h> // OID encoder
34 namespace CodeSigning
{
36 using namespace UnixPlusPlus
;
40 // Table of reserved words (keywords), generated by ANTLR
42 static const char * const keywords
[] = {
43 #include "RequirementKeywords.h"
50 // Printf to established output channel
52 void Dumper::print(const char *format
, ...)
56 va_start(args
, format
);
57 vsnprintf(buffer
, sizeof(buffer
), format
, args
);
64 // Dump the underlying Requirement program
70 // remove any initial space
71 if (mOutput
[0] == ' ')
72 mOutput
= mOutput
.substr(1);
77 // Dump an entire Requirements set, using temporary Dumper objects.
79 // This detects single Requirement inputs and dumps them successfully (using
80 // single-requirement syntax). No indication of error is returned in this case.
82 string
Dumper::dump(const Requirements
*reqs
, bool debug
/* = false */)
85 return "# no requirement(s)";
86 } else if (reqs
->magic() == Requirement::typeMagic
) { // single requirement
87 return dump((const Requirement
*)reqs
) + "\n";
90 for (unsigned n
= 0; n
< reqs
->count(); n
++) {
92 if (reqs
->type(n
) < kSecRequirementTypeCount
)
93 snprintf(prefix
, sizeof(prefix
),
94 "%s => ", Requirement::typeNames
[reqs
->type(n
)]);
96 snprintf(prefix
, sizeof(prefix
), "/*unknown type*/ %d => ", reqs
->type(n
));
97 Dumper
dumper(reqs
->blob
<Requirement
>(n
), debug
);
99 result
+= prefix
+ dumper
.value() + "\n";
105 string
Dumper::dump(const Requirement
*req
, bool debug
/* = false */)
107 Dumper
dumper(req
, debug
);
111 } catch (const CommonError
&err
) {
114 snprintf(errstr
, sizeof(errstr
), " !! error %ld !!", (unsigned long)err
.osStatus());
115 return dumper
.value() + errstr
;
121 string
Dumper::dump(const BlobCore
*req
, bool debug
/* = false */)
123 switch (req
->magic()) {
124 case Requirement::typeMagic
:
125 return dump(static_cast<const Requirement
*>(req
), debug
);
126 case Requirements::typeMagic
:
127 return dump(static_cast<const Requirements
*>(req
), debug
);
129 return "invalid data type";
135 // Element dumpers. Output accumulates in internal buffer.
137 void Dumper::expr(SyntaxLevel level
)
140 print("/*@0x%x*/", pc());
141 ExprOp op
= ExprOp(get
<uint32_t>());
142 switch (op
& ~opFlagMask
) {
150 print("identifier ");
154 print("anchor apple");
156 case opAppleGenericAnchor
:
157 print("anchor apple generic");
160 print("certificate"); certSlot(); print(" = "); hashData();
165 print("info["); dotString(); print("] = "); data();
194 print("info["); dotString(); print("]"); match();
196 case opEntitlementField
:
197 print("entitlement["); dotString(); print("]"); match();
200 print("certificate"); certSlot(); print("["); dotString(); print("]"); match();
202 case opCertFieldDate
:
203 print("certificate"); certSlot(); print("[");
206 const unsigned char *data
; size_t length
;
207 getData(data
, length
);
208 print("timestamp.%s", CssmOid((unsigned char *)data
, length
).toOid().c_str());
212 print("certificate"); certSlot(); print("[");
215 const unsigned char *data
; size_t length
;
216 getData(data
, length
);
217 print("field.%s", CssmOid((unsigned char *)data
, length
).toOid().c_str());
223 print("certificate"); certSlot(); print("[");
226 const unsigned char *data
; size_t length
;
227 getData(data
, length
);
228 print("policy.%s", CssmOid((unsigned char *)data
, length
).toOid().c_str());
234 print("certificate"); certSlot(); print("trusted");
237 print("anchor trusted");
240 print("anchor apple "); data();
243 print("("); data(); print(")");
246 print("platform = %d", get
<int32_t>());
252 if (op
& opGenericFalse
) {
253 print(" false /* opcode %d */", op
& ~opFlagMask
);
255 } else if (op
& opGenericSkip
) {
256 print(" /* opcode %d */", op
& ~opFlagMask
);
259 print("OPCODE %d NOT UNDERSTOOD (ending print)", op
);
265 void Dumper::certSlot()
267 switch (int32_t slot
= get
<int32_t>()) {
268 case Requirement::anchorCert
:
271 case Requirement::leafCert
:
282 switch (MatchOperation op
= MatchOperation(get
<uint32_t>())) {
284 print(" /* exists */");
290 print(" = "); data();
293 print(" ~ "); data();
295 case matchBeginsWith
:
296 print(" = "); data(); print("*");
299 print(" = *"); data();
302 print(" < "); data();
304 case matchGreaterEqual
:
305 print(" >= "); data();
308 print(" <= "); data();
310 case matchGreaterThan
:
311 print(" > "); data();
314 print(" = "); timestamp();
317 print(" < "); timestamp();
320 print(" > "); timestamp();
322 case matchOnOrBefore
:
323 print(" <= "); timestamp();
326 print(" >= "); timestamp();
329 print("MATCH OPCODE %d NOT UNDERSTOOD", op
);
334 void Dumper::hashData()
337 const unsigned char *data
; size_t length
;
338 getData(data
, length
);
339 printBytes(data
, length
);
343 void Dumper::data(PrintMode bestMode
/* = isSimple */, bool dotOkay
/* = false */)
345 const unsigned char *data
; size_t length
;
346 getData(data
, length
);
347 for (unsigned n
= 0; n
< length
; n
++)
348 if ((isalnum(data
[n
]) || (data
[n
] == '.' && dotOkay
))) { // simple
349 if (n
== 0 && isdigit(data
[n
])) // unquoted idents can't start with a digit
350 bestMode
= isPrintable
;
351 } else if (isgraph(data
[n
]) || isspace(data
[n
])) {
352 if (bestMode
== isSimple
)
353 bestMode
= isPrintable
;
359 if (bestMode
== isSimple
) {
360 string
s((const char *)data
, length
);
361 for (const char * const * k
= keywords
; *k
; k
++)
363 bestMode
= isPrintable
; // reserved word; need quotes
370 print("%.*s", (int)length
, data
);
374 for (unsigned n
= 0; n
< length
; n
++)
378 print("\\%c", data
[n
]);
381 print("%c", data
[n
]);
388 printBytes(data
, length
);
393 void Dumper::timestamp()
395 CFAbsoluteTime at
= static_cast<CFAbsoluteTime
>(get
<int64_t>());
396 CFRef
<CFDateRef
> date
= CFDateCreate(NULL
, at
);
398 CFRef
<CFStringRef
> str
= CFCopyDescription(date
);
400 print("<%s>", cfString(str
).c_str());
403 void Dumper::printBytes(const Byte
*data
, size_t length
)
405 for (unsigned n
= 0; n
< length
; n
++)
406 print("%02.2x", data
[n
]);