]> git.saurik.com Git - apple/libsecurity_codesigning.git/blame - lib/csdatabase.cpp
libsecurity_codesigning-55032.tar.gz
[apple/libsecurity_codesigning.git] / lib / csdatabase.cpp
CommitLineData
d1c1ab47
A
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
24//
25// csdb - system-supported Code Signing related database interfaces
26//
27#include "csdatabase.h"
28#include "detachedrep.h"
29
30namespace Security {
31namespace CodeSigning {
32
33using namespace SQLite;
34
35
36//
37// The one and only SignatureDatabase object.
38// It auto-adapts to readonly vs. writable use.
39//
40ModuleNexus<SignatureDatabase> signatureDatabase;
f60086fc 41ModuleNexus<SignatureDatabaseWriter> signatureDatabaseWriter;
d1c1ab47
A
42
43
44//
45// Default path to the signature database.
46//
47const char SignatureDatabase::defaultPath[] = "/var/db/DetachedSignatures";
48
49
50//
51// Creation commands to initialize the system database.
52//
53const char schema[] = "\
54 create table if not exists code ( \n\
55 id integer primary key on conflict replace autoincrement not null, \n\
56 global integer null references global (id), \n\
57 identifier text not null, \n\
58 architecture integer, \n\
59 identification blob not null unique on conflict replace, \n\
60 signature blob not null, \n\
61 created text default current_timestamp \n\
62 ); \n\
63 create index if not exists identifier_index on code (identifier); \n\
64 create index if not exists architecture_index on code (architecture); \n\
65 create index if not exists id_index on code (identification); \n\
66 \n\
67 create table if not exists global ( \n\
68 id integer primary key on conflict replace autoincrement not null, \n\
69 sign_location text not null, \n\
70 signature blob null \n\
71 ); \n\
72 create index if not exists location_index on global (sign_location); \n\
73";
74
75
76
77//
78// Open the database (creating it if necessary and possible).
79// Note that this isn't creating the schema; we do that on first write.
80//
81SignatureDatabase::SignatureDatabase(const char *path, int flags)
82 : SQLite::Database(path, flags)
83{
84}
85
86SignatureDatabase::~SignatureDatabase()
87{ /* virtual */ }
88
89
90//
91// Consult the database to find code by identification blob.
92// Return the signature and (optional) global data blobs.
93//
94FilterRep *SignatureDatabase::findCode(DiskRep *rep)
95{
96 if (CFRef<CFDataRef> identification = rep->identification())
97 if (!this->empty()) {
98 SQLite::Statement query(*this,
99 "select code.signature, global.signature from code, global \
100 where code.identification = ?1 and code.global = global.id;");
101 query.bind(1) = identification.get();
102 if (query.nextRow())
103 return new DetachedRep(query[0].data(), query[1].data(), rep, "system");
104 }
105
106 // no joy
107 return NULL;
108}
109
110
111//
112// Given a unified detached signature blob, store its data in the database.
113// This writes exactly one Global record, plus one Code record per architecture
114// (where non-architectural code is treated as single-architecture).
115//
f60086fc 116void SignatureDatabaseWriter::storeCode(const BlobCore *sig, const char *location)
d1c1ab47
A
117{
118 Transaction xa(*this, Transaction::exclusive); // lock out everyone
119 if (this->empty())
120 this->execute(schema); // initialize schema
121 if (const EmbeddedSignatureBlob *esig = EmbeddedSignatureBlob::specific(sig)) { // architecture-less
122 int64 globid = insertGlobal(location, NULL);
123 insertCode(globid, 0, esig);
124 xa.commit();
125 return;
126 } else if (const DetachedSignatureBlob *dsblob = DetachedSignatureBlob::specific(sig)) {
127 int64 globid = insertGlobal(location, dsblob->find(0));
128 unsigned count = dsblob->count();
129 for (unsigned n = 0; n < count; n++)
130 if (uint32_t arch = dsblob->type(n))
131 insertCode(globid, arch, EmbeddedSignatureBlob::specific(dsblob->blob(n)));
132 xa.commit();
133 return;
134 }
135
136 MacOSError::throwMe(errSecCSSignatureInvalid);
137
138}
139
f60086fc 140int64 SignatureDatabaseWriter::insertGlobal(const char *location, const BlobCore *blob)
d1c1ab47
A
141{
142 Statement insert(*this, "insert into global (sign_location, signature) values (?1, ?2);");
143 insert.bind(1) = location;
144 if (blob)
145 insert.bind(2).blob(blob, blob->length(), true);
146 insert();
147 return lastInsert();
148}
149
f60086fc 150void SignatureDatabaseWriter::insertCode(int64 globid, int arch, const EmbeddedSignatureBlob *sig)
d1c1ab47
A
151{
152 // retrieve binary identifier (was added by signer)
153 const BlobWrapper *ident = BlobWrapper::specific(sig->find(cdIdentificationSlot));
154 assert(ident);
155
156 // extract CodeDirectory to get some information from it
157 const CodeDirectory *cd = CodeDirectory::specific(sig->find(cdCodeDirectorySlot));
158 assert(cd);
159
160 // write the record
161 Statement insert(*this,
162 "insert into code (global, identifier, architecture, identification, signature) values (?1, ?2, ?3, ?4, ?5);");
163 insert.bind(1) = globid;
164 insert.bind(2) = cd->identifier();
165 if (arch)
166 insert.bind(3) = arch;
167 insert.bind(4).blob(ident->data(), ident->length(), true);
168 insert.bind(5).blob(sig, sig->length(), true);
169 insert();
170}
171
172
173
174} // end namespace CodeSigning
175} // end namespace Security