]> git.saurik.com Git - apple/libsecurity_codesigning.git/blob - lib/filediskrep.cpp
9fefe6a5575ac9d3b07577f5ddd5685096dd5a0b
[apple/libsecurity_codesigning.git] / lib / filediskrep.cpp
1 /*
2 * Copyright (c) 2006-2007 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 #include "filediskrep.h"
24 #include "StaticCode.h"
25 #include "macho++.h" // may perhaps move into security_utilities...
26 #include <cstring>
27
28
29 namespace Security {
30 namespace CodeSigning {
31
32 using namespace UnixPlusPlus;
33
34
35 //
36 // Everything's lazy in here
37 //
38 FileDiskRep::FileDiskRep(const char *path)
39 : SingleDiskRep(path)
40 {
41 }
42
43
44 //
45 // Produce an extended attribute name from a canonical slot name
46 //
47 string FileDiskRep::attrName(const char *name)
48 {
49 static const char prefix[] = "com.apple.cs.";
50 return string(prefix) + name;
51 }
52
53
54 //
55 // Retrieve an extended attribute by name
56 //
57 CFDataRef FileDiskRep::getAttribute(const char *name)
58 {
59 string aname = attrName(name);
60 ssize_t length = fd().getAttrLength(aname);
61 if (length < 0)
62 return NULL; // no such attribute
63 CFMallocData buffer(length);
64 fd().getAttr(aname, buffer, length);
65 return buffer;
66 }
67
68
69 //
70 // Extract and return a component by slot number.
71 // If we have a Mach-O binary, use embedded components.
72 // Otherwise, look for and return the extended attribute, if any.
73 //
74 CFDataRef FileDiskRep::component(CodeDirectory::SpecialSlot slot)
75 {
76 if (const char *name = CodeDirectory::canonicalSlotName(slot))
77 return getAttribute(name);
78 else
79 return NULL;
80 }
81
82
83 //
84 // Generate a suggested set of internal requirements.
85 // We don't really have to say much. However, if we encounter a file that
86 // starts with the magic "#!" script marker, we do suggest that this should
87 // be a valid host if we can reasonably make out what that is.
88 //
89 const Requirements *FileDiskRep::defaultRequirements(const Architecture *)
90 {
91 // read start of file
92 char buffer[256];
93 size_t length = fd().read(buffer, sizeof(buffer), 0);
94 if (length > 3 && buffer[0] == '#' && buffer[1] == '!' && buffer[2] == '/') {
95 // isolate (full) path element in #!/full/path -some -other -stuff
96 if (length == sizeof(buffer))
97 length--;
98 buffer[length] = '\0';
99 char *path = buffer + 2;
100 path[strcspn(path, " \t\n\r\f")] = '\0';
101 secdebug("filediskrep", "looks like a script for %s", path);
102 if (path[1])
103 try {
104 // find path on disk, get designated requirement (if signed)
105 if (RefPointer<DiskRep> rep = DiskRep::bestFileGuess(path))
106 if (SecPointer<SecStaticCode> code = new SecStaticCode(rep))
107 if (const Requirement *req = code->designatedRequirement()) {
108 // package up as host requirement and return that
109 Requirements::Maker maker;
110 maker.add(kSecHostRequirementType, req->clone());
111 secdebug("filediskrep", "made a scripting host requirement");
112 return maker.make();
113 }
114 } catch (...) {
115 secdebug("filediskrep", "exception getting host requirement (ignored)");
116 }
117 }
118 return NULL;
119 }
120
121
122 string FileDiskRep::format()
123 {
124 return "generic";
125 }
126
127
128 //
129 // FileDiskRep::Writers
130 //
131 DiskRep::Writer *FileDiskRep::writer()
132 {
133 return new Writer(this);
134 }
135
136
137 //
138 // Write a component.
139 // Note that this isn't concerned with Mach-O writing; this is handled at
140 // a much higher level. If we're called, it's extended attribute time.
141 //
142 void FileDiskRep::Writer::component(CodeDirectory::SpecialSlot slot, CFDataRef data)
143 {
144 fd().setAttr(attrName(CodeDirectory::canonicalSlotName(slot)),
145 CFDataGetBytePtr(data), CFDataGetLength(data));
146 }
147
148
149 //
150 // We are NOT the preferred store for components because our approach
151 // (extended attributes) suffers from some serious limitations.
152 //
153 bool FileDiskRep::Writer::preferredStore()
154 {
155 return false;
156 }
157
158
159 } // end namespace CodeSigning
160 } // end namespace Security