]> git.saurik.com Git - apple/libsecurity_codesigning.git/blame - lib/requirement.cpp
libsecurity_codesigning-55037.15.tar.gz
[apple/libsecurity_codesigning.git] / lib / requirement.cpp
CommitLineData
7d31e928 1/*
62e4ed3d 2 * Copyright (c) 2006-2012 Apple Inc. All Rights Reserved.
7d31e928
A
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"
d1c1ab47 29#include "codesigning_dtrace.h"
7d31e928
A
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 <security_codesigning/reqdumper.h>
38#endif
39
40namespace Security {
41namespace CodeSigning {
42
43
44//
45// The (SHA-1) hash of the canonical Apple certificate root anchor
46//
47static const SHA1::Digest gAppleAnchorHash =
48 { 0x61, 0x1e, 0x5b, 0x66, 0x2c, 0x59, 0x3a, 0x08, 0xff, 0x58,
49 0xd1, 0x4a, 0xe2, 0x24, 0x52, 0xd1, 0x98, 0xdf, 0x6c, 0x60 };
50
51
52//
53// Canonical names for requirement types
54//
55const char *const Requirement::typeNames[] = {
56 "invalid",
57 "host",
58 "guest",
59 "designated",
f60086fc
A
60 "library",
61 "plugin",
7d31e928
A
62};
63
64
65//
66// validate a requirement against a code context
67//
68void Requirement::validate(const Requirement::Context &ctx, OSStatus failure /* = errSecCSReqFailed */) const
f60086fc
A
69{
70 if (!this->validates(ctx, failure))
71 MacOSError::throwMe(failure);
72}
73
74bool Requirement::validates(const Requirement::Context &ctx, OSStatus failure /* = errSecCSReqFailed */) const
d1c1ab47
A
75{
76 CODESIGN_EVAL_REQINT_START((void*)this, this->length());
7d31e928
A
77 switch (kind()) {
78 case exprForm:
d1c1ab47 79 if (Requirement::Interpreter(this, &ctx).evaluate()) {
f60086fc
A
80 CODESIGN_EVAL_REQINT_END(this, 0);
81 return true;
d1c1ab47 82 } else {
f60086fc
A
83 CODESIGN_EVAL_REQINT_END(this, failure);
84 return false;
d1c1ab47 85 }
7d31e928 86 default:
f60086fc 87 CODESIGN_EVAL_REQINT_END(this, errSecCSReqUnsupported);
7d31e928
A
88 MacOSError::throwMe(errSecCSReqUnsupported);
89 }
90}
91
92
93//
94// Retrieve one certificate from the cert chain.
95// Positive and negative indices can be used:
96// [ leaf, intermed-1, ..., intermed-n, anchor ]
97// 0 1 ... -2 -1
98// Returns NULL if unavailable for any reason.
99//
100SecCertificateRef Requirement::Context::cert(int ix) const
101{
102 if (certs) {
103 if (ix < 0)
104 ix += certCount();
62e4ed3d
A
105 if (ix >= CFArrayGetCount(certs))
106 return NULL;
7d31e928
A
107 if (CFTypeRef element = CFArrayGetValueAtIndex(certs, ix))
108 return SecCertificateRef(element);
109 }
110 return NULL;
111}
112
113unsigned int Requirement::Context::certCount() const
114{
115 if (certs)
116 return CFArrayGetCount(certs);
117 else
118 return 0;
119}
120
121
122//
123// Return the hash of the canonical Apple certificate root (anchor).
124// In a special test mode, also return an alternate root hash for testing.
125//
126const SHA1::Digest &Requirement::appleAnchorHash()
127{
128 return gAppleAnchorHash;
129}
130
131#if defined(TEST_APPLE_ANCHOR)
132
133const char Requirement::testAppleAnchorEnv[] = "TEST_APPLE_ANCHOR";
134
135const SHA1::Digest &Requirement::testAppleAnchorHash()
136{
137 static bool tried = false;
138 static SHA1::Digest testHash;
139 if (!tried) {
140 // see if we have one configured
141 if (const char *path = getenv(testAppleAnchorEnv))
142 try {
143 UnixPlusPlus::FileDesc fd(path);
144 char buffer[2048]; // arbitrary limit
145 size_t size = fd.read(buffer, sizeof(buffer));
146 SHA1 hash;
147 hash(buffer, size);
148 hash.finish(testHash);
149 Syslog::alert("ACCEPTING TEST AUTHORITY %s FOR APPLE CODE IDENTITY", path);
150 } catch (...) { }
151 tried = true;
152 }
153 return testHash; // will be zeroes (no match) if not configured
154}
155
156#endif //TEST_APPLE_ANCHOR
157
158
7d31e928
A
159//
160// Debug dump support
161//
162#ifdef DEBUGDUMP
163
164void Requirement::dump() const
165{
166 Debug::dump("%s\n", Dumper::dump(this).c_str());
167}
168
169#endif //DEBUGDUMP
170
171
172} // CodeSigning
173} // Security