]> git.saurik.com Git - apple/security.git/blob - OSX/libsecurity_codesigning/lib/requirement.cpp
Security-59306.61.1.tar.gz
[apple/security.git] / OSX / libsecurity_codesigning / lib / requirement.cpp
1 /*
2 * Copyright (c) 2006-2012 Apple Inc. All Rights Reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
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
11 * file.
12 *
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.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23
24 //
25 // requirement - Code Requirement Blob description
26 //
27 #include "requirement.h"
28 #include "reqinterp.h"
29 #include "codesigning_dtrace.h"
30 #include <security_utilities/errors.h>
31 #include <security_utilities/unix++.h>
32 #include <security_utilities/logging.h>
33 #include <security_utilities/cfutilities.h>
34 #include <security_utilities/hashing.h>
35
36 #ifdef DEBUGDUMP
37 #include "reqdumper.h"
38 #endif
39
40 namespace Security {
41 namespace CodeSigning {
42
43
44 //
45 // Canonical names for requirement types
46 //
47 const char *const Requirement::typeNames[] = {
48 "invalid",
49 "host",
50 "guest",
51 "designated",
52 "library",
53 "plugin",
54 };
55
56
57 //
58 // validate a requirement against a code context
59 //
60 void Requirement::validate(const Requirement::Context &ctx, OSStatus failure /* = errSecCSReqFailed */) const
61 {
62 if (!this->validates(ctx, failure))
63 MacOSError::throwMe(failure);
64 }
65
66 bool Requirement::validates(const Requirement::Context &ctx, OSStatus failure /* = errSecCSReqFailed */) const
67 {
68 CODESIGN_EVAL_REQINT_START((void*)this, (int)this->length());
69 switch (kind()) {
70 case exprForm:
71 if (Requirement::Interpreter(this, &ctx).evaluate()) {
72 CODESIGN_EVAL_REQINT_END(this, 0);
73 return true;
74 } else {
75 CODESIGN_EVAL_REQINT_END(this, failure);
76 return false;
77 }
78 default:
79 CODESIGN_EVAL_REQINT_END(this, errSecCSReqUnsupported);
80 MacOSError::throwMe(errSecCSReqUnsupported);
81 }
82 }
83
84
85 //
86 // Retrieve one certificate from the cert chain.
87 // Positive and negative indices can be used:
88 // [ leaf, intermed-1, ..., intermed-n, anchor ]
89 // 0 1 ... -2 -1
90 // Returns NULL if unavailable for any reason.
91 //
92 SecCertificateRef Requirement::Context::cert(int ix) const
93 {
94 if (certs) {
95 if (ix < 0)
96 ix += certCount();
97 if (ix >= CFArrayGetCount(certs))
98 return NULL;
99 if (CFTypeRef element = CFArrayGetValueAtIndex(certs, ix))
100 return SecCertificateRef(element);
101 }
102 return NULL;
103 }
104
105 unsigned int Requirement::Context::certCount() const
106 {
107 if (certs)
108 return (unsigned int)CFArrayGetCount(certs);
109 else
110 return 0;
111 }
112
113
114 //
115 // Produce the hash of a fake Apple root (only if compiled for internal testing)
116 //
117 #if defined(TEST_APPLE_ANCHOR)
118
119 const char Requirement::testAppleAnchorEnv[] = "TEST_APPLE_ANCHOR";
120
121 const SHA1::Digest &Requirement::testAppleAnchorHash()
122 {
123 static bool tried = false;
124 static SHA1::Digest testHash;
125 if (!tried) {
126 // see if we have one configured
127 if (const char *path = getenv(testAppleAnchorEnv))
128 try {
129 UnixPlusPlus::FileDesc fd(path);
130 char buffer[2048]; // arbitrary limit
131 size_t size = fd.read(buffer, sizeof(buffer));
132 SHA1 hash;
133 hash(buffer, size);
134 hash.finish(testHash);
135 Syslog::alert("ACCEPTING TEST AUTHORITY %s FOR APPLE CODE IDENTITY", path);
136 } catch (...) { }
137 tried = true;
138 }
139 return testHash; // will be zeroes (no match) if not configured
140 }
141
142 #endif //TEST_APPLE_ANCHOR
143
144 //
145 // Debug dump support
146 //
147 #if TARGET_OS_OSX
148 #ifdef DEBUGDUMP
149
150 void Requirement::dump() const
151 {
152 Debug::dump("%s\n", Dumper::dump(this).c_str());
153 }
154
155 #endif //DEBUGDUMP
156 #endif
157
158
159 } // CodeSigning
160 } // Security