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

Side by Side Diff: base/apply_tag.cc

Issue 624713003: Keep only base/extractor.[cc|h]. (Closed) Base URL: https://chromium.googlesource.com/external/omaha.git@master
Patch Set: Created 6 years, 2 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
« no previous file with comments | « base/apply_tag.h ('k') | base/atl_regexp.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright 2006-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 // Applies a tag to a signed file.
17
18 #include "omaha/base/apply_tag.h"
19 #include <atlrx.h>
20 #include <vector>
21 #include "base/scoped_ptr.h"
22 #include "omaha/base/utils.h"
23 #include "omaha/base/extractor.h"
24
25 namespace omaha {
26
27 const char kMagicBytes[] = "Gact";
28 const uint32 kPEHeaderOffset = 60;
29
30 ApplyTag::ApplyTag()
31 : prev_tag_string_length_(0),
32 prev_cert_length_(0),
33 append_(0) {}
34
35 bool ApplyTag::IsValidTagString(const char* tag_string) {
36 ASSERT1(tag_string);
37
38 CAtlRegExp<CAtlRECharTraitsA> regex;
39 REParseError error = regex.Parse(kValidTagStringRegEx);
40 if (error != REPARSE_ERROR_OK) {
41 return false;
42 }
43
44 CAtlREMatchContext<CAtlRECharTraitsA> context;
45 return !!regex.Match(tag_string, &context);
46 }
47
48 HRESULT ApplyTag::Init(const TCHAR* signed_exe_file,
49 const char* tag_string,
50 int tag_string_length,
51 const TCHAR* tagged_file,
52 bool append) {
53 ASSERT1(signed_exe_file);
54 ASSERT1(tag_string);
55 ASSERT1(tagged_file);
56
57 signed_exe_file_ = signed_exe_file;
58 tagged_file_ = tagged_file;
59 append_ = append;
60
61 // Check the tag_string for invalid characters.
62 if (!IsValidTagString(tag_string)) {
63 return E_INVALIDARG;
64 }
65
66 for (int i = 0; i < tag_string_length; ++i) {
67 tag_string_.push_back(tag_string[i]);
68 }
69
70 return S_OK;
71 }
72
73 HRESULT ApplyTag::EmbedTagString() {
74 std::vector<byte> input_file_buffer;
75 HRESULT hr = ReadEntireFile(signed_exe_file_, 0, &input_file_buffer);
76 if (FAILED(hr)) {
77 return hr;
78 }
79
80 ASSERT1(!input_file_buffer.empty());
81 VERIFY1(ReadExistingTag(&input_file_buffer));
82 if (!append_ && prev_tag_string_length_) {
83 // If there is a previous tag and the append flag is not set, then
84 // we should error out.
85 return APPLYTAG_E_ALREADY_TAGGED;
86 }
87
88 if (!CreateBufferToWrite()) {
89 return E_FAIL;
90 }
91
92 // The input_file_buffer might contain the previously read tag, in which
93 // case the buffer_data_ is larger than the actual output buffer length.
94 // The real output buffer length is returned by the ApplyTagToBuffer
95 // method.
96 buffer_data_.resize(input_file_buffer.size() + tag_buffer_.size());
97
98 copy(input_file_buffer.begin(),
99 input_file_buffer.end(),
100 buffer_data_.begin());
101
102 int output_length = 0;
103 if (!ApplyTagToBuffer(&output_length))
104 return E_FAIL;
105
106 std::vector<byte> output_buffer(output_length);
107 ASSERT1(static_cast<size_t>(output_length) <= buffer_data_.size());
108 copy(buffer_data_.begin(),
109 buffer_data_.begin() + output_length,
110 output_buffer.begin());
111 return WriteEntireFile(tagged_file_, output_buffer);
112 }
113
114 uint32 ApplyTag::GetUint32(const void* p) {
115 ASSERT1(p);
116
117 const uint32* pu = reinterpret_cast<const uint32*>(p);
118 return *pu;
119 }
120
121 void ApplyTag::PutUint32(uint32 i, void* p) {
122 ASSERT1(p);
123
124 uint32* pu = reinterpret_cast<uint32*>(p);
125 *pu = i;
126 }
127
128 bool ApplyTag::ReadExistingTag(std::vector<byte>* binary) {
129 ASSERT1(binary);
130
131 int len = 0;
132 TagExtractor tag;
133 char* bin = reinterpret_cast<char*>(&binary->front());
134 ASSERT1(bin);
135 if (tag.ExtractTag(bin, binary->size(), NULL, &len)) {
136 prev_tag_string_.resize(len);
137 if (tag.ExtractTag(bin, binary->size(), &prev_tag_string_.front(), &len)) {
138 // The extractor returns the actual length
139 // of the string + 1 for the terminating null.
140 prev_tag_string_length_ = len - 1;
141 }
142 }
143
144 // Set the existing certificate length even if previous
145 // tag does not exist.
146 prev_cert_length_ = tag.cert_length();
147 return true;
148 }
149
150 bool ApplyTag::CreateBufferToWrite() {
151 ASSERT1(!append_ && !prev_tag_string_length_ || append_);
152 ASSERT1(!tag_string_.empty());
153 ASSERT1(!prev_tag_string_.size() ||
154 prev_tag_string_.size() ==
155 static_cast<size_t>(prev_tag_string_length_ + 1));
156
157 // Build the tag buffer.
158 // The format of the tag buffer is:
159 // 000000-000003: 4-byte magic (big-endian)
160 // 000004-000005: unsigned 16-bit int string length (big-endian)
161 // 000006-??????: ASCII string
162 int tag_string_len = tag_string_.size() + prev_tag_string_length_;
163 int kMagicBytesLen = ::lstrlenA(kMagicBytes);
164 int tag_header_len = kMagicBytesLen + 2;
165 int unpadded_tag_buffer_len = tag_string_len + tag_header_len;
166 // The tag buffer should be padded to multiples of 8, otherwise it will
167 // break the signature of the executable file.
168 int padded_tag_buffer_length = (unpadded_tag_buffer_len + 15) & (-8);
169
170 tag_buffer_.clear();
171 tag_buffer_.resize(padded_tag_buffer_length, 0);
172 memcpy(&tag_buffer_.front(), kMagicBytes, kMagicBytesLen);
173 tag_buffer_[kMagicBytesLen] =
174 static_cast<char>((tag_string_len & 0xff00) >> 8);
175 tag_buffer_[kMagicBytesLen+1] = static_cast<char>(tag_string_len & 0xff);
176
177 if (prev_tag_string_length_ > 0) {
178 copy(prev_tag_string_.begin(),
179 prev_tag_string_.end(),
180 tag_buffer_.begin() + tag_header_len);
181 }
182
183 copy(tag_string_.begin(),
184 tag_string_.end(),
185 tag_buffer_.begin() + tag_header_len + prev_tag_string_length_);
186 ASSERT1(static_cast<int>(tag_buffer_.size()) == padded_tag_buffer_length);
187
188 return true;
189 }
190
191 bool ApplyTag::ApplyTagToBuffer(int* output_len) {
192 ASSERT1(output_len);
193
194 uint32 original_data_len = buffer_data_.size() - tag_buffer_.size();
195 uint32 peheader = GetUint32(&buffer_data_.front() + kPEHeaderOffset);
196 uint32 kCertDirAddressOffset = 152;
197 uint32 kCertDirInfoSize = 4 + 4;
198
199 ASSERT1(peheader + kCertDirAddressOffset + kCertDirInfoSize <=
200 original_data_len);
201
202 // Read certificate directory info.
203 uint32 cert_dir_offset = GetUint32(&buffer_data_.front() + peheader +
204 kCertDirAddressOffset);
205 if (cert_dir_offset == 0)
206 return false;
207 uint32 cert_dir_len = GetUint32(&buffer_data_.front() + peheader +
208 kCertDirAddressOffset + 4);
209 ASSERT1(cert_dir_offset + cert_dir_len <= original_data_len);
210
211 // Calculate the new output length.
212 int prev_pad_length = cert_dir_len - prev_cert_length_ -
213 prev_tag_string_length_;
214 ASSERT1(prev_pad_length >= 0);
215 int orig_dir_len = cert_dir_len - prev_tag_string_length_ -
216 prev_pad_length;
217 ASSERT1(orig_dir_len == prev_cert_length_);
218 int output_length = original_data_len - prev_tag_string_length_ -
219 prev_pad_length + tag_buffer_.size();
220 *output_len = output_length;
221 ASSERT1(static_cast<size_t>(output_length) <= buffer_data_.size());
222 ASSERT1(output_length >= orig_dir_len);
223
224 // Increase the size of certificate directory.
225 int new_cert_len = prev_cert_length_ + tag_buffer_.size();
226 PutUint32(new_cert_len,
227 &buffer_data_.front() + peheader + kCertDirAddressOffset + 4);
228
229 // Read certificate struct info.
230 uint32 cert_struct_len = GetUint32(&buffer_data_.front() + cert_dir_offset);
231 ASSERT1(!(cert_struct_len > cert_dir_len ||
232 cert_struct_len < cert_dir_len - 8));
233
234 // Increase the certificate struct size.
235 PutUint32(new_cert_len, &buffer_data_.front() + cert_dir_offset);
236
237 // Copy the tag buffer.
238 copy(tag_buffer_.begin(), tag_buffer_.end(),
239 buffer_data_.begin() + cert_dir_offset + prev_cert_length_);
240
241 return true;
242 }
243
244 } // namespace omaha
OLDNEW
« no previous file with comments | « base/apply_tag.h ('k') | base/atl_regexp.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698