Package list mozc / e68cc98
Support packaged desktop apps on Windows Currently Mozc for Windows does not work for Windows store apps that are converted and packaged with DAC (Desktop App Converter) from Win32 applications. Anecdotally this seems to be because accesses to files under LocalLow folder are virtualized and redirected to app's own copy of LocalLow folder, rather than the real LocalLow folder where Mozc server should put session.ipc file that stores randomized Mozc server pipe name. Here, the reason why Mozc has used this approach (randomize named pipe end point and pass that name via IPC file under LocalLow folder) is to avoid so-called named pipe squatting attacks. This had been critical on Windows XP, but on Windows Vista and later OSes we can make sure that the server of the named pile is actually Mozc server by using GetNamedPipeServerProcessId() API, before sending any keystroke data. This means that using predictable pipe name is not that unsafe any more. To support packaged desktop apps, we decided to stop using random pipe name. With this change, even if an IME client could not read the session.ipc file, it can then try to connect the named pipe directly. Although malicious server may still be able to do some sort of DOS, Mozc client still doesn't allow they to steal data including key events. There is no behavior change in other platforms. Closes #435. BUG=#435 TEST=Manually done REF_BUG=71338191 REF_CL=186285602 REF_TIME=2018-02-20T21:17:51+09:00 REF_TIME_RAW=1519129071 +0900 Hiroyuki Komatsu 3 years ago
3 changed file(s) with 44 addition(s) and 27 deletion(s). Raw diff Collapse all Expand all
2929
3030 MAJOR=2
3131 MINOR=23
32 BUILD=2810
32 BUILD=2811
3333 REVISION=102
3434 # This version represents the version of Mozc IME engine (converter, predictor,
3535 # etc.). This version info is included both in the Mozc server and in the Mozc
5454 'sources!': [
5555 'ipc_path_manager.cc',
5656 'process_watch_dog.cc',
57 ],
58 }],
59 ['target_platform=="Windows"', {
60 'dependencies': [
61 '../base/base.gyp:obfuscator_support',
5762 ],
5863 }],
5964 ],
5656 #include "base/const.h"
5757 #include "base/file_stream.h"
5858 #include "base/file_util.h"
59 #ifdef OS_WIN
60 #include "base/unverified_sha1.h"
61 #endif // OS_WIN
5962 #include "base/logging.h"
6063 #include "base/mac_util.h"
6164 #include "base/mutex.h"
107110 return true;
108111 }
109112
110 void CreateIPCKey(char *value) {
111 char buf[16]; // key is 128 bit
112
113 #ifdef OS_WIN
114 // LUID guaranties uniqueness
115 LUID luid = { 0 }; // LUID is 64bit value
116
117 DCHECK_EQ(sizeof(luid), sizeof(uint64));
118
119 // first 64 bit is random sequence and last 64 bit is LUID
120 if (::AllocateLocallyUniqueId(&luid)) {
121 Util::GetRandomSequence(buf, sizeof(buf) / 2);
122 ::memcpy(buf + sizeof(buf) / 2, &luid, sizeof(buf) / 2);
123 } else {
124 // use random value for failsafe
125 Util::GetRandomSequence(buf, sizeof(buf));
113 string CreateIPCKey() {
114 char buf[16] = {}; // key is 128 bit
115 char value[kKeySize + 1] = {};
116
117 #ifdef OS_WIN
118 const string sid = SystemUtil::GetUserSidAsString();
119 const string sha1 = internal::UnverifiedSHA1::MakeDigest(sid);
120 for (int i = 0; i < sizeof(buf) && i < sha1.size(); ++i) {
121 buf[i] = sha1.at(i);
126122 }
127123 #else
128124 // get 128 bit key: Note that collision will happen.
138134 }
139135
140136 value[kKeySize] = '\0';
137 return string(value);
141138 }
142139
143140 class IPCPathManagerMap {
190187 bool IPCPathManager::CreateNewPathName() {
191188 scoped_lock l(mutex_.get());
192189 if (ipc_path_info_->key().empty()) {
193 char ipc_key[kKeySize + 1];
194 CreateIPCKey(ipc_key);
195 ipc_path_info_->set_key(ipc_key);
190 ipc_path_info_->set_key(CreateIPCKey());
196191 }
197192 return true;
198193 }
243238 // On Windows, ShouldReload() always returns false.
244239 // On other platform, it returns true when timestamp of the file is different
245240 // from that of previous one.
246 if (ShouldReload() || ipc_path_info_->key().empty()) {
247 if (!LoadPathNameInternal()) {
248 LOG(ERROR) << "LoadPathName failed";
249 return false;
250 }
251 }
252 return true;
241 const bool should_load = (ShouldReload() || ipc_path_info_->key().empty());
242 if (!should_load) {
243 return true;
244 }
245
246 if (LoadPathNameInternal()) {
247 return true;
248 }
249
250 #if defined(OS_WIN)
251 // Fill the default values as fallback.
252 // Applications conerted by Desktop App Converter (DAC) does not read
253 // a file of ipc session name in the LocalLow directory.
254 // For a workaround, let applications to connect the named pipe directly.
255 // See: b/71338191.
256 CreateNewPathName();
257 DCHECK(!ipc_path_info_->key().empty());
258 ipc_path_info_->set_protocol_version(IPC_PROTOCOL_VERSION);
259 ipc_path_info_->set_product_version(Version::GetMozcVersion());
260 return true;
261 #else
262 LOG(ERROR) << "LoadPathName failed";
263 return false;
264 #endif
253265 }
254266
255267 bool IPCPathManager::GetPathName(string *ipc_name) const {