Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(434)

Side by Side Diff: third_party/omaha/base/extractor.cc

Issue 423293004: Move app_installer into chromium. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Change app_installer.gypi to app_installer.gyp Created 6 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright 2005-2009 Google Inc.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 // ========================================================================
15
16 #include "omaha/base/extractor.h"
17
18 #include <windows.h>
19 #include <wintrust.h>
20 #include <crtdbg.h>
21 #pragma warning(push)
22 // C4100: unreferenced formal parameter
23 // C4310: cast truncates constant value
24 // C4548: expression before comma has no effect
25 #pragma warning(disable : 4100 4310 4548)
26 #include "base/basictypes.h"
27 #pragma warning(pop)
28
29 namespace omaha {
30
31 #define AFFILIATE_ID_MAGIC "Gact"
32
33 TagExtractor::TagExtractor()
34 : file_handle_(INVALID_HANDLE_VALUE),
35 file_mapping_(NULL),
36 file_base_(NULL),
37 file_length_(0),
38 cert_length_(0),
39 cert_dir_base_(NULL) {
40 }
41
42 TagExtractor::~TagExtractor() {
43 CloseFile();
44 }
45
46 bool TagExtractor::OpenFile(const TCHAR* filename) {
47 CloseFile();
48 file_handle_ = CreateFile(filename, GENERIC_READ, FILE_SHARE_READ, NULL,
49 OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
50 if (IsFileOpen()) {
51 file_mapping_ = CreateFileMapping(file_handle_, NULL, PAGE_READONLY,
52 0, 0, NULL);
53 if (file_mapping_ != NULL) {
54 file_base_ = MapViewOfFile(file_mapping_, FILE_MAP_READ, 0, 0, 0);
55 if (file_base_ != NULL) {
56 MEMORY_BASIC_INFORMATION info = {0};
57 if (::VirtualQuery(file_base_, &info, sizeof(info))) {
58 file_length_ = info.RegionSize;
59 return true;
60 }
61 }
62 CloseHandle(file_mapping_);
63 }
64 CloseFile();
65 }
66 return false;
67 }
68
69 bool TagExtractor::IsFileOpen() const {
70 return file_handle_ != INVALID_HANDLE_VALUE;
71 }
72
73 void TagExtractor::CloseFile() {
74 if (file_base_ != NULL) {
75 UnmapViewOfFile(file_base_);
76 file_base_ = NULL;
77 }
78 if (file_mapping_ != NULL) {
79 CloseHandle(file_mapping_);
80 file_mapping_ = NULL;
81 }
82 if (IsFileOpen()) {
83 CloseHandle(file_handle_);
84 file_handle_ = INVALID_HANDLE_VALUE;
85 }
86 }
87
88 bool TagExtractor::ExtractTag(const char* binary_file,
89 size_t binary_file_length,
90 char* tag_buffer,
91 int* tag_buffer_len) {
92 file_length_ = binary_file_length;
93 return InternalExtractTag(binary_file, tag_buffer, tag_buffer_len);
94 }
95
96 bool TagExtractor::ExtractTag(char* tag_buffer, int* tag_buffer_len) {
97 if (tag_buffer_len == NULL) {
98 return false;
99 }
100 if (!IsFileOpen()) {
101 return false;
102 }
103
104 return InternalExtractTag(static_cast<char*>(file_base_),
105 tag_buffer,
106 tag_buffer_len);
107 }
108
109 bool TagExtractor::InternalReadCertificate(const char* file_buffer) {
110 if (!file_buffer) {
111 return false;
112 }
113
114 const void* certificate_directory_pointer =
115 GetCertificateDirectoryPointer(file_buffer);
116 if (NULL == certificate_directory_pointer) {
117 return false;
118 }
119 const void* asn1_signature_pointer =
120 GetASN1SignaturePointer(certificate_directory_pointer);
121 if (NULL == asn1_signature_pointer) {
122 return false;
123 }
124 DWORD asn1_signature_length =
125 GetASN1SignatureLength(asn1_signature_pointer);
126 if (0 == asn1_signature_length) {
127 return false;
128 }
129
130 cert_length_ = asn1_signature_length;
131 cert_dir_base_ = certificate_directory_pointer;
132
133 return true;
134 }
135
136 bool TagExtractor::InternalExtractTag(const char* file_buffer,
137 char* tag_buffer,
138 int* tag_buffer_len) {
139 if (!file_buffer) {
140 return false;
141 }
142
143 if (!InternalReadCertificate(file_buffer)) {
144 return false;
145 }
146
147 const char* read_base = static_cast<const char*>(cert_dir_base_) +
148 cert_length_;
149 if (read_base >= file_buffer + file_length_) {
150 // The file is not tagged.
151 return false;
152 }
153
154 return ReadTag(read_base, tag_buffer, tag_buffer_len);
155 }
156
157 bool TagExtractor::ReadTag(const char* tag_pointer,
158 char* tag_buffer,
159 int* tag_buffer_len) const {
160 int mc = memcmp(tag_pointer,
161 AFFILIATE_ID_MAGIC,
162 arraysize(AFFILIATE_ID_MAGIC) - 1);
163 if (0 != mc) {
164 return false;
165 }
166 tag_pointer += arraysize(AFFILIATE_ID_MAGIC) - 1;
167
168 uint16 id_len = 0;
169 const unsigned char* id_len_serialized =
170 reinterpret_cast<const unsigned char*>(tag_pointer);
171 id_len = id_len_serialized[0] << 8;
172 // unsigned char and uint16 get promoted to int.
173 id_len = static_cast<uint16>(id_len + id_len_serialized[1]);
174
175 int buffer_size_required = id_len + 1;
176 if (tag_buffer == NULL) {
177 *tag_buffer_len = buffer_size_required;
178 return true;
179 }
180 if (*tag_buffer_len < buffer_size_required) {
181 return false;
182 }
183 tag_pointer += sizeof(id_len);
184 memcpy(tag_buffer, tag_pointer, id_len);
185 tag_buffer[id_len] = '\0';
186 return true;
187 }
188
189 const void* TagExtractor::GetCertificateDirectoryPointer(
190 const void* base) const {
191 const char* image_base = reinterpret_cast<const char*>(base);
192
193 // Is this a PEF?
194 const IMAGE_DOS_HEADER* dos_header =
195 reinterpret_cast<const IMAGE_DOS_HEADER *>(image_base);
196 if (dos_header->e_magic != IMAGE_DOS_SIGNATURE) {
197 return NULL;
198 }
199
200 // Get PE header.
201 const IMAGE_NT_HEADERS* nt_headers = reinterpret_cast<const IMAGE_NT_HEADERS*>
202 (image_base + dos_header->e_lfanew);
203
204 // Again, is this a PEF? This code should get an F for not being endian-
205 // safe, but it gets an A for working in the real world.
206 if (nt_headers->Signature != IMAGE_NT_SIGNATURE) {
207 return NULL;
208 }
209
210 const IMAGE_DATA_DIRECTORY* idd =
211 reinterpret_cast<const IMAGE_DATA_DIRECTORY *>
212 (&nt_headers->
213 OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_SECURITY]);
214 if (idd->VirtualAddress != NULL) {
215 return image_base + idd->VirtualAddress;
216 }
217 return NULL;
218 }
219
220 const void* TagExtractor::GetASN1SignaturePointer(const void* base) const {
221 const WIN_CERTIFICATE* cert =
222 reinterpret_cast<const WIN_CERTIFICATE *>(base);
223 return cert->bCertificate;
224 }
225
226 int TagExtractor::GetASN1SignatureLength(const void* base) const {
227 const unsigned char* sig_base =
228 reinterpret_cast<const unsigned char*>(base);
229
230 // No, this isn't a full ASN.1 parser. We're just doing the very bare
231 // minimum to extract a length.
232 if (*sig_base++ == 0x30 && *sig_base++ == 0x82) {
233 int len = (*sig_base++ << 8);
234 len += *sig_base++;
235 // Windows pads the certificate directory to align at a 8-byte boundary.
236 // This piece of code it trying to replicate the logic that is used to
237 // calculate the padding to be added to the certificate. It returns
238 // the entire length of the certificate directory from the windows
239 // certificate directory start to the end of padding.
240 // The windows certificate directory has the following structure
241 // <WIN_CERTIFICATE><Certificate><Padding>.
242 // WIN_CERTIFICATE is the windows certificate directory structure.
243 // <Certificate> has the following format:
244 // <Magic(2 bytes)><Cert length(2 bytes)><Certificate Data>
245 // Note that the "Cert length" does not include the magic bytes or
246 // the length.
247 //
248 // Hence the total length of the certificate is:
249 // cert_length + "WIN_CERTIFICATE header size" + magic + length
250 // + padding = (cert length + 8 + 2 + 2 + 7) & (0-8)
251 return (len + 8 + 2 + 2 + 7) & 0xffffff8;
252 }
253 return 0;
254 }
255
256 } // namespace omaha
257
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698