]>
git.saurik.com Git - apple/security.git/blob - OSX/libsecurity_codesigning/lib/reqdumper.cpp
d1cb94a9d7936c3fc5d06b7bbd3681b016bce37d
   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" 
  28 #include <security_cdsa_utilities/cssmdata.h>   // OID encoder 
  32 namespace CodeSigning 
{ 
  34 using namespace UnixPlusPlus
; 
  38 // Table of reserved words (keywords), generated by ANTLR 
  40 static const char * const keywords
[] = { 
  41 #include "RequirementKeywords.h" 
  48 // Printf to established output channel 
  50 void Dumper::print(const char *format
, ...) 
  54         va_start(args
, format
); 
  55         vsnprintf(buffer
, sizeof(buffer
), format
, args
); 
  62 // Dump the underlying Requirement program 
  68         // remove any initial space 
  69         if (mOutput
[0] == ' ') 
  70                 mOutput 
= mOutput
.substr(1); 
  75 // Dump an entire Requirements set, using temporary Dumper objects. 
  77 // This detects single Requirement inputs and dumps them successfully (using 
  78 // single-requirement syntax). No indication of error is returned in this case. 
  80 string 
Dumper::dump(const Requirements 
*reqs
, bool debug 
/* = false */) 
  83                 return "# no requirement(s)"; 
  84         } else if (reqs
->magic() == Requirement::typeMagic
) {   // single requirement 
  85                 return dump((const Requirement 
*)reqs
) + "\n"; 
  88                 for (unsigned n 
= 0; n 
< reqs
->count(); n
++) { 
  90                         if (reqs
->type(n
) < kSecRequirementTypeCount
) 
  91                                 snprintf(prefix
, sizeof(prefix
), 
  92                                         "%s => ", Requirement::typeNames
[reqs
->type(n
)]); 
  94                                 snprintf(prefix
, sizeof(prefix
), "/*unknown type*/ %d => ", reqs
->type(n
)); 
  95                         Dumper 
dumper(reqs
->blob
<Requirement
>(n
), debug
); 
  97                         result 
+= prefix 
+ dumper
.value() + "\n"; 
 103 string 
Dumper::dump(const Requirement 
*req
, bool debug 
/* = false */) 
 105         Dumper 
dumper(req
, debug
); 
 109         } catch (const CommonError 
&err
) { 
 112                         snprintf(errstr
, sizeof(errstr
), " !! error %ld !!", (unsigned long)err
.osStatus()); 
 113                         return dumper
.value() + errstr
; 
 119 string 
Dumper::dump(const BlobCore 
*req
, bool debug 
/* = false */) 
 121         switch (req
->magic()) { 
 122         case Requirement::typeMagic
: 
 123                 return dump(static_cast<const Requirement 
*>(req
), debug
); 
 124         case Requirements::typeMagic
: 
 125                 return dump(static_cast<const Requirements 
*>(req
), debug
); 
 127                 return "invalid data type"; 
 133 // Element dumpers. Output accumulates in internal buffer. 
 135 void Dumper::expr(SyntaxLevel level
) 
 138                 print("/*@0x%x*/", pc()); 
 139         ExprOp op 
= ExprOp(get
<uint32_t>()); 
 140         switch (op 
& ~opFlagMask
) { 
 148                 print("identifier "); 
 152                 print("anchor apple"); 
 154         case opAppleGenericAnchor
: 
 155                 print("anchor apple generic"); 
 158                 print("certificate"); certSlot(); print(" = "); hashData(); 
 163                 print("info["); dotString(); print("] = "); data(); 
 192                 print("info["); dotString(); print("]"); match(); 
 194         case opEntitlementField
: 
 195                 print("entitlement["); dotString(); print("]"); match(); 
 198                 print("certificate"); certSlot(); print("["); dotString(); print("]"); match(); 
 201                 print("certificate"); certSlot(); print("["); 
 203                         const unsigned char *data
; size_t length
; 
 204                         getData(data
, length
); 
 205                         print("field.%s", CssmOid((unsigned char *)data
, length
).toOid().c_str()); 
 210                 print("certificate"); certSlot(); print("["); 
 212                         const unsigned char *data
; size_t length
; 
 213                         getData(data
, length
); 
 214                         print("policy.%s", CssmOid((unsigned char *)data
, length
).toOid().c_str()); 
 219                 print("certificate"); certSlot(); print("trusted"); 
 222                 print("anchor trusted"); 
 225                 print("anchor apple "); data(); 
 228                 print("("); data(); print(")"); 
 231                 print("platform = %d", get
<int32_t>()); 
 234                 if (op 
& opGenericFalse
) { 
 235                         print(" false /* opcode %d */", op 
& ~opFlagMask
); 
 237                 } else if (op 
& opGenericSkip
) { 
 238                         print(" /* opcode %d */", op 
& ~opFlagMask
); 
 241                         print("OPCODE %d NOT UNDERSTOOD (ending print)", op
); 
 247 void Dumper::certSlot() 
 249         switch (int32_t slot 
= get
<int32_t>()) { 
 250         case Requirement::anchorCert
: 
 253         case Requirement::leafCert
: 
 264         switch (MatchOperation op 
= MatchOperation(get
<uint32_t>())) { 
 266                 print(" /* exists */"); 
 269                 print(" = "); data(); 
 272                 print(" ~ "); data(); 
 274         case matchBeginsWith
: 
 275                 print(" = "); data(); print("*"); 
 278                 print(" = *"); data(); 
 281                 print(" < "); data(); 
 283         case matchGreaterEqual
: 
 284                 print(" >= "); data(); 
 287                 print(" <= "); data(); 
 289         case matchGreaterThan
: 
 290                 print(" > "); data(); 
 293                 print("MATCH OPCODE %d NOT UNDERSTOOD", op
); 
 298 void Dumper::hashData() 
 301         const unsigned char *data
; size_t length
; 
 302         getData(data
, length
); 
 303         printBytes(data
, length
); 
 307 void Dumper::data(PrintMode bestMode 
/* = isSimple */, bool dotOkay 
/* = false */) 
 309         const unsigned char *data
; size_t length
; 
 310         getData(data
, length
); 
 311         for (unsigned n 
= 0; n 
< length
; n
++) 
 312                 if ((isalnum(data
[n
]) || (data
[n
] == '.' && dotOkay
))) {        // simple 
 313                         if (n 
== 0 && isdigit(data
[n
])) // unquoted idents can't start with a digit 
 314                                 bestMode 
= isPrintable
; 
 315                 } else if (isgraph(data
[n
]) || isspace(data
[n
])) { 
 316                         if (bestMode 
== isSimple
) 
 317                                 bestMode 
= isPrintable
; 
 323         if (bestMode 
== isSimple
) { 
 324                 string 
s((const char *)data
, length
); 
 325                 for (const char * const * k 
= keywords
; *k
; k
++) 
 327                                 bestMode 
= isPrintable
;         // reserved word; need quotes 
 334                 print("%.*s", length
, data
); 
 338                 for (unsigned n 
= 0; n 
< length
; n
++) 
 342                                 print("\\%c", data
[n
]); 
 345                                 print("%c", data
[n
]); 
 352                 printBytes(data
, length
); 
 357 void Dumper::printBytes(const Byte 
*data
, size_t length
) 
 359         for (unsigned n 
= 0; n 
< length
; n
++) 
 360                 print("%02.2x", data
[n
]);