1 /* $ANTLR 2.7.7 (20120228): "requirements.grammar" -> "RequirementParser.cpp"$ */
2 #include "RequirementParser.hpp"
3 #include <antlr/NoViableAltException.hpp>
4 #include <antlr/SemanticException.hpp>
5 #include <antlr/ASTFactory.hpp>
7 #include "requirement.h"
9 #include "csutilities.h"
10 #include <security_utilities/cfutilities.h>
11 #include <security_utilities/hashing.h>
12 #include <security_cdsa_utilities/cssmdata.h> // OID coding
13 using namespace CodeSigning
;
14 typedef Requirement::Maker Maker
;
16 ANTLR_BEGIN_NAMESPACE(Security_CodeSigning
)
19 // Collect error messages.
20 // Note that the immediate caller takes the absence of collected error messages
21 // to indicate compilation success.
23 void RequirementParser::reportError(const antlr::RecognitionException
&ex
)
25 errors
+= ex
.toString() + "\n";
28 void RequirementParser::reportError(const std::string
&s
)
35 // Parser helper functions
37 string
RequirementParser::hexString(const string
&s
)
40 throw antlr::SemanticException("odd number of digits");
41 const char *p
= s
.data();
43 for (unsigned n
= 0; n
< s
.length(); n
+= 2) {
45 sscanf(p
+n
, "%2hhx", &c
);
51 void RequirementParser::hashString(const string
&s
, SHA1::Digest hash
)
53 if (s
.size() != 2 * SHA1::digestLength
)
54 throw antlr::SemanticException("invalid hash length");
55 memcpy(hash
, hexString(s
).data(), SHA1::digestLength
);
58 static const char *matchPrefix(const string
&key
, const char *prefix
)
60 unsigned pLength
= strlen(prefix
);
61 if (!key
.compare(0, pLength
, prefix
, 0, pLength
))
62 return key
.c_str() + pLength
;
67 void RequirementParser::certMatchOperation(Maker
&maker
, int32_t slot
, string key
)
69 if (matchPrefix(key
, "subject.")) {
70 maker
.put(opCertField
);
73 } else if (const char *oids
= matchPrefix(key
, "field.")) {
74 maker
.put(opCertGeneric
);
76 CssmAutoData
oid(Allocator::standard()); oid
.fromOid(oids
);
77 maker
.putData(oid
.data(), oid
.length());
78 } else if (const char *oids
= matchPrefix(key
, "extension.")) {
79 maker
.put(opCertGeneric
);
81 CssmAutoData
oid(Allocator::standard()); oid
.fromOid(oids
);
82 maker
.putData(oid
.data(), oid
.length());
83 } else if (const char *oids
= matchPrefix(key
, "policy.")) {
84 maker
.put(opCertPolicy
);
86 CssmAutoData
oid(Allocator::standard()); oid
.fromOid(oids
);
87 maker
.putData(oid
.data(), oid
.length());
89 throw antlr::SemanticException(key
+ ": unrecognized certificate field");
93 RequirementParser::RequirementParser(antlr::TokenBuffer
& tokenBuf
, int k
)
94 : antlr::LLkParser(tokenBuf
,k
)
98 RequirementParser::RequirementParser(antlr::TokenBuffer
& tokenBuf
)
99 : antlr::LLkParser(tokenBuf
,2)
103 RequirementParser::RequirementParser(antlr::TokenStream
& lexer
, int k
)
104 : antlr::LLkParser(lexer
,k
)
108 RequirementParser::RequirementParser(antlr::TokenStream
& lexer
)
109 : antlr::LLkParser(lexer
,2)
113 RequirementParser::RequirementParser(const antlr::ParserSharedInputState
& state
)
114 : antlr::LLkParser(state
,2)
118 BlobCore
* RequirementParser::autosense() {
119 BlobCore
*result
= NULL
;
121 try { // for error handling
129 case LITERAL_identifier
:
132 case LITERAL_certificate
:
135 case LITERAL_entitlement
:
137 result
=requirement();
142 case LITERAL_designated
:
143 case LITERAL_library
:
147 result
=requirementSet();
152 throw antlr::NoViableAltException(LT(1), getFilename());
156 catch (antlr::RecognitionException
& ex
) {
158 recover(ex
,_tokenSet_0
);
163 Requirement
* RequirementParser::requirement() {
164 Requirement
*result
= NULL
;
166 try { // for error handling
167 result
=requirementElement();
168 match(antlr::Token::EOF_TYPE
);
170 catch (antlr::RecognitionException
& ex
) {
172 recover(ex
,_tokenSet_0
);
177 Requirements
* RequirementParser::requirementSet() {
178 Requirements
*result
= NULL
;
179 Requirements::Maker maker
;
181 try { // for error handling
185 if (((LA(1) >= LITERAL_guest
&& LA(1) <= INTEGER
))) {
186 uint32_t t
; Requirement
*req
;
189 req
=requirementElement();
193 if ( _cnt4
>=1 ) { goto _loop4
; } else {throw antlr::NoViableAltException(LT(1), getFilename());}
200 result
= errors
.empty() ? maker() : NULL
;
201 match(antlr::Token::EOF_TYPE
);
203 catch (antlr::RecognitionException
& ex
) {
205 recover(ex
,_tokenSet_0
);
210 uint32_t RequirementParser::requirementType() {
211 uint32_t type
= kSecInvalidRequirementType
;
212 antlr::RefToken stype
= antlr::nullToken
;
214 try { // for error handling
218 match(LITERAL_guest
);
219 type
= kSecGuestRequirementType
;
225 type
= kSecHostRequirementType
;
228 case LITERAL_designated
:
230 match(LITERAL_designated
);
231 type
= kSecDesignatedRequirementType
;
234 case LITERAL_library
:
236 match(LITERAL_library
);
237 type
= kSecLibraryRequirementType
;
242 match(LITERAL_plugin
);
243 type
= kSecPluginRequirementType
;
250 type
= atol(stype
->getText().c_str());
255 throw antlr::NoViableAltException(LT(1), getFilename());
259 catch (antlr::RecognitionException
& ex
) {
261 recover(ex
,_tokenSet_1
);
266 Requirement
* RequirementParser::requirementElement() {
267 Requirement
*result
= NULL
;
268 Requirement::Maker maker
;
270 try { // for error handling
275 if ((LA(1) == SEMI
)) {
286 catch (antlr::RecognitionException
& ex
) {
288 recover(ex
,_tokenSet_2
);
293 void RequirementParser::expr(
296 Maker::Label
label(maker
);
298 try { // for error handling
302 if ((LA(1) == LITERAL_or
)) {
304 maker
.insert
<ExprOp
>(label
) = opOr
;
315 catch (antlr::RecognitionException
& ex
) {
317 recover(ex
,_tokenSet_3
);
321 void RequirementParser::fluff() {
323 try { // for error handling
326 catch (antlr::RecognitionException
& ex
) {
328 recover(ex
,_tokenSet_4
);
332 void RequirementParser::term(
335 Maker::Label
label(maker
);
337 try { // for error handling
341 if ((LA(1) == LITERAL_and
)) {
343 maker
.insert
<ExprOp
>(label
) = opAnd
;
354 catch (antlr::RecognitionException
& ex
) {
356 recover(ex
,_tokenSet_5
);
360 void RequirementParser::primary(
364 try { // for error handling
380 match(LITERAL_always
);
390 throw antlr::NoViableAltException(LT(1), getFilename());
404 match(LITERAL_never
);
409 match(LITERAL_false
);
414 throw antlr::NoViableAltException(LT(1), getFilename());
422 case LITERAL_certificate
:
433 case LITERAL_entitlement
:
435 entitlementspec(maker
);
438 case LITERAL_identifier
:
440 match(LITERAL_identifier
);
443 code
=identifierString();
449 match(LITERAL_cdhash
);
453 maker
.cdhash(digest
);
457 if ((LA(1) == LPAREN
) && (_tokenSet_6
.member(LA(2)))) {
462 else if ((LA(1) == LPAREN
) && (LA(2) == DOTKEY
|| LA(2) == STRING
)) {
465 name
=identifierString();
467 maker
.put(opNamedCode
); maker
.put(name
);
470 throw antlr::NoViableAltException(LT(1), getFilename());
474 catch (antlr::RecognitionException
& ex
) {
476 recover(ex
,_tokenSet_7
);
480 void RequirementParser::certspec(
484 try { // for error handling
485 if ((LA(1) == LITERAL_anchor
) && (LA(2) == LITERAL_apple
)) {
486 match(LITERAL_anchor
);
487 match(LITERAL_apple
);
490 else if ((LA(1) == LITERAL_anchor
) && (LA(2) == LITERAL_generic
)) {
491 match(LITERAL_anchor
);
492 match(LITERAL_generic
);
493 match(LITERAL_apple
);
494 maker
.put(opAppleGenericAnchor
);
496 else if ((LA(1) == LITERAL_anchor
|| LA(1) == LITERAL_certificate
|| LA(1) == LITERAL_cert
) && (LA(2) == LITERAL_trusted
)) {
499 case LITERAL_certificate
:
501 match(LITERAL_certificate
);
511 match(LITERAL_anchor
);
516 throw antlr::NoViableAltException(LT(1), getFilename());
520 match(LITERAL_trusted
);
521 maker
.trustedAnchor();
523 else if ((LA(1) == LITERAL_certificate
|| LA(1) == LITERAL_cert
) && (_tokenSet_8
.member(LA(2)))) {
526 case LITERAL_certificate
:
528 match(LITERAL_certificate
);
538 throw antlr::NoViableAltException(LT(1), getFilename());
554 certslotspec(maker
, slot
);
557 case LITERAL_trusted
:
559 match(LITERAL_trusted
);
560 maker
.trustedAnchor(slot
);
565 throw antlr::NoViableAltException(LT(1), getFilename());
570 else if ((LA(1) == LITERAL_anchor
) && (_tokenSet_9
.member(LA(2)))) {
571 match(LITERAL_anchor
);
572 certslotspec(maker
, Requirement::anchorCert
);
575 throw antlr::NoViableAltException(LT(1), getFilename());
579 catch (antlr::RecognitionException
& ex
) {
581 recover(ex
,_tokenSet_7
);
585 void RequirementParser::infospec(
590 try { // for error handling
593 maker
.put(opInfoKeyField
); maker
.put(key
);
596 catch (antlr::RecognitionException
& ex
) {
598 recover(ex
,_tokenSet_7
);
602 void RequirementParser::entitlementspec(
607 try { // for error handling
608 match(LITERAL_entitlement
);
610 maker
.put(opEntitlementField
); maker
.put(key
);
613 catch (antlr::RecognitionException
& ex
) {
615 recover(ex
,_tokenSet_7
);
619 void RequirementParser::eql() {
621 try { // for error handling
643 throw antlr::NoViableAltException(LT(1), getFilename());
647 catch (antlr::RecognitionException
& ex
) {
649 recover(ex
,_tokenSet_10
);
653 string
RequirementParser::identifierString() {
655 antlr::RefToken dk
= antlr::nullToken
;
656 antlr::RefToken s
= antlr::nullToken
;
658 try { // for error handling
664 result
= dk
->getText();
671 result
= s
->getText();
676 throw antlr::NoViableAltException(LT(1), getFilename());
680 catch (antlr::RecognitionException
& ex
) {
682 recover(ex
,_tokenSet_7
);
687 void RequirementParser::hash(
690 antlr::RefToken hash
= antlr::nullToken
;
692 try { // for error handling
695 hashString(hash
->getText(), digest
);
697 catch (antlr::RecognitionException
& ex
) {
699 recover(ex
,_tokenSet_7
);
703 void RequirementParser::appleanchor(
707 try { // for error handling
709 case antlr::Token::EOF_TYPE
:
712 case LITERAL_designated
:
713 case LITERAL_library
:
722 maker
.put(opAppleAnchor
);
725 case LITERAL_generic
:
727 match(LITERAL_generic
);
728 maker
.put(opAppleGenericAnchor
);
735 name
=identifierString();
736 maker
.put(opNamedAnchor
); maker
.put(name
);
741 throw antlr::NoViableAltException(LT(1), getFilename());
745 catch (antlr::RecognitionException
& ex
) {
747 recover(ex
,_tokenSet_7
);
751 int32_t RequirementParser::certSlot() {
753 antlr::RefToken s
= antlr::nullToken
;
754 antlr::RefToken ss
= antlr::nullToken
;
756 try { // for error handling
762 slot
= atol(s
->getText().c_str());
770 slot
= -atol(ss
->getText().c_str());
776 slot
= Requirement::leafCert
;
782 slot
= Requirement::anchorCert
;
787 throw antlr::NoViableAltException(LT(1), getFilename());
791 catch (antlr::RecognitionException
& ex
) {
793 recover(ex
,_tokenSet_11
);
798 void RequirementParser::certslotspec(
799 Maker
&maker
, int32_t slot
803 try { // for error handling
814 certificateDigest(digest
);
815 maker
.anchor(slot
, digest
);
821 certMatchOperation(maker
, slot
, key
);
827 throw antlr::NoViableAltException(LT(1), getFilename());
831 catch (antlr::RecognitionException
& ex
) {
833 recover(ex
,_tokenSet_7
);
837 void RequirementParser::empty() {
839 try { // for error handling
841 catch (antlr::RecognitionException
& ex
) {
843 recover(ex
,_tokenSet_12
);
847 void RequirementParser::certificateDigest(
851 try { // for error handling
864 if (CFRef
<CFDataRef
> certData
= cfLoadFile(path
))
865 hashOfCertificate(CFDataGetBytePtr(certData
), CFDataGetLength(certData
), digest
);
867 throw antlr::SemanticException(path
+ ": not found");
873 throw antlr::NoViableAltException(LT(1), getFilename());
877 catch (antlr::RecognitionException
& ex
) {
879 recover(ex
,_tokenSet_7
);
883 string
RequirementParser::bracketKey() {
886 try { // for error handling
891 catch (antlr::RecognitionException
& ex
) {
893 recover(ex
,_tokenSet_13
);
898 void RequirementParser::match_suffix(
902 try { // for error handling
904 case antlr::Token::EOF_TYPE
:
907 case LITERAL_designated
:
908 case LITERAL_library
:
922 match(LITERAL_exists
);
925 case antlr::Token::EOF_TYPE
:
928 case LITERAL_designated
:
929 case LITERAL_library
:
941 throw antlr::NoViableAltException(LT(1), getFilename());
945 maker
.put(matchExists
);
965 throw antlr::NoViableAltException(LT(1), getFilename());
969 MatchOperation mop
= matchEqual
; string value
;
986 throw antlr::NoViableAltException(LT(1), getFilename());
996 mop
= (mop
== matchEndsWith
) ? matchContains
: matchBeginsWith
;
999 case antlr::Token::EOF_TYPE
:
1002 case LITERAL_designated
:
1003 case LITERAL_library
:
1004 case LITERAL_plugin
:
1015 throw antlr::NoViableAltException(LT(1), getFilename());
1019 maker
.put(mop
); maker
.put(value
);
1027 maker
.put(matchContains
); maker
.put(value
);
1035 maker
.put(matchLessThan
); maker
.put(value
);
1043 maker
.put(matchGreaterThan
); maker
.put(value
);
1051 maker
.put(matchLessEqual
); maker
.put(value
);
1059 maker
.put(matchGreaterEqual
); maker
.put(value
);
1064 throw antlr::NoViableAltException(LT(1), getFilename());
1068 catch (antlr::RecognitionException
& ex
) {
1070 recover(ex
,_tokenSet_7
);
1074 string
RequirementParser::datavalue() {
1076 antlr::RefToken hex
= antlr::nullToken
;
1078 try { // for error handling
1083 result
=stringvalue();
1090 result
= hexString(hex
->getText());
1095 throw antlr::NoViableAltException(LT(1), getFilename());
1099 catch (antlr::RecognitionException
& ex
) {
1101 recover(ex
,_tokenSet_14
);
1106 string
RequirementParser::stringvalue() {
1108 antlr::RefToken dk
= antlr::nullToken
;
1109 antlr::RefToken s
= antlr::nullToken
;
1111 try { // for error handling
1117 result
= dk
->getText();
1124 result
= s
->getText();
1129 throw antlr::NoViableAltException(LT(1), getFilename());
1133 catch (antlr::RecognitionException
& ex
) {
1135 recover(ex
,_tokenSet_15
);
1140 string
RequirementParser::pathstring() {
1142 antlr::RefToken dk
= antlr::nullToken
;
1143 antlr::RefToken s
= antlr::nullToken
;
1144 antlr::RefToken pn
= antlr::nullToken
;
1146 try { // for error handling
1152 result
= dk
->getText();
1159 result
= s
->getText();
1166 result
= pn
->getText();
1171 throw antlr::NoViableAltException(LT(1), getFilename());
1175 catch (antlr::RecognitionException
& ex
) {
1177 recover(ex
,_tokenSet_7
);
1182 void RequirementParser::initializeASTFactory( antlr::ASTFactory
& )
1185 const char* RequirementParser::tokenNames
[] = {
1189 "NULL_TREE_LOOKAHEAD",
1246 const unsigned long RequirementParser::_tokenSet_0_data_
[] = { 2UL, 0UL, 0UL, 0UL };
1248 const antlr::BitSet
RequirementParser::_tokenSet_0(_tokenSet_0_data_
,4);
1249 const unsigned long RequirementParser::_tokenSet_1_data_
[] = { 16UL, 0UL, 0UL, 0UL };
1251 const antlr::BitSet
RequirementParser::_tokenSet_1(_tokenSet_1_data_
,4);
1252 const unsigned long RequirementParser::_tokenSet_2_data_
[] = { 2018UL, 0UL, 0UL, 0UL };
1253 // EOF "guest" "host" "designated" "library" "plugin" INTEGER
1254 const antlr::BitSet
RequirementParser::_tokenSet_2(_tokenSet_2_data_
,4);
1255 const unsigned long RequirementParser::_tokenSet_3_data_
[] = { 18402UL, 131072UL, 0UL, 0UL };
1256 // EOF "guest" "host" "designated" "library" "plugin" INTEGER RPAREN SEMI
1257 const antlr::BitSet
RequirementParser::_tokenSet_3(_tokenSet_3_data_
,4);
1258 const unsigned long RequirementParser::_tokenSet_4_data_
[] = { 2018UL, 131072UL, 0UL, 0UL };
1259 // EOF "guest" "host" "designated" "library" "plugin" INTEGER SEMI
1260 const antlr::BitSet
RequirementParser::_tokenSet_4(_tokenSet_4_data_
,4);
1261 const unsigned long RequirementParser::_tokenSet_5_data_
[] = { 20450UL, 131072UL, 0UL, 0UL };
1262 // EOF "guest" "host" "designated" "library" "plugin" INTEGER "or" RPAREN
1264 const antlr::BitSet
RequirementParser::_tokenSet_5(_tokenSet_5_data_
,4);
1265 const unsigned long RequirementParser::_tokenSet_6_data_
[] = { 914333696UL, 0UL, 0UL, 0UL };
1266 // LPAREN NOT "always" "true" "never" "false" "identifier" "cdhash" "anchor"
1267 // "certificate" "cert" "info" "entitlement"
1268 const antlr::BitSet
RequirementParser::_tokenSet_6(_tokenSet_6_data_
,4);
1269 const unsigned long RequirementParser::_tokenSet_7_data_
[] = { 24546UL, 131072UL, 0UL, 0UL };
1270 // EOF "guest" "host" "designated" "library" "plugin" INTEGER "or" "and"
1272 const antlr::BitSet
RequirementParser::_tokenSet_7(_tokenSet_7_data_
,4);
1273 const unsigned long RequirementParser::_tokenSet_8_data_
[] = { 1024UL, 3584UL, 0UL, 0UL };
1274 // INTEGER NEG "leaf" "root"
1275 const antlr::BitSet
RequirementParser::_tokenSet_8(_tokenSet_8_data_
,4);
1276 const unsigned long RequirementParser::_tokenSet_9_data_
[] = { 2147483648UL, 118913UL, 0UL, 0UL };
1277 // EQL EQQL LBRACK HASHCONSTANT DOTKEY STRING PATHNAME
1278 const antlr::BitSet
RequirementParser::_tokenSet_9(_tokenSet_9_data_
,4);
1279 const unsigned long RequirementParser::_tokenSet_10_data_
[] = { 0UL, 118784UL, 0UL, 0UL };
1280 // HASHCONSTANT DOTKEY STRING PATHNAME
1281 const antlr::BitSet
RequirementParser::_tokenSet_10(_tokenSet_10_data_
,4);
1282 const unsigned long RequirementParser::_tokenSet_11_data_
[] = { 2281701376UL, 118913UL, 0UL, 0UL };
1283 // "trusted" EQL EQQL LBRACK HASHCONSTANT DOTKEY STRING PATHNAME
1284 const antlr::BitSet
RequirementParser::_tokenSet_11(_tokenSet_11_data_
,4);
1285 const unsigned long RequirementParser::_tokenSet_12_data_
[] = { 1073766370UL, 249856UL, 0UL, 0UL };
1286 // EOF "guest" "host" "designated" "library" "plugin" INTEGER "or" "and"
1287 // RPAREN "exists" HASHCONSTANT DOTKEY STRING PATHNAME SEMI
1288 const antlr::BitSet
RequirementParser::_tokenSet_12(_tokenSet_12_data_
,4);
1289 const unsigned long RequirementParser::_tokenSet_13_data_
[] = { 3221250018UL, 131197UL, 0UL, 0UL };
1290 // EOF "guest" "host" "designated" "library" "plugin" INTEGER "or" "and"
1291 // RPAREN "exists" EQL EQQL SUBS LESS GT LE GE SEMI
1292 const antlr::BitSet
RequirementParser::_tokenSet_13(_tokenSet_13_data_
,4);
1293 const unsigned long RequirementParser::_tokenSet_14_data_
[] = { 24546UL, 131074UL, 0UL, 0UL };
1294 // EOF "guest" "host" "designated" "library" "plugin" INTEGER "or" "and"
1296 const antlr::BitSet
RequirementParser::_tokenSet_14(_tokenSet_14_data_
,4);
1297 const unsigned long RequirementParser::_tokenSet_15_data_
[] = { 24546UL, 131330UL, 0UL, 0UL };
1298 // EOF "guest" "host" "designated" "library" "plugin" INTEGER "or" "and"
1299 // RPAREN STAR RBRACK SEMI
1300 const antlr::BitSet
RequirementParser::_tokenSet_15(_tokenSet_15_data_
,4);