Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/dom/plugins/ipc/FunctionBroker.cpp
Line
Count
Source (jump to first uncovered line)
1
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
3
/* This Source Code Form is subject to the terms of the Mozilla Public
4
 * License, v. 2.0. If a copy of the MPL was not distributed with this
5
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6
7
#include "FunctionBroker.h"
8
#include "FunctionBrokerParent.h"
9
#include "PluginQuirks.h"
10
11
#if defined(XP_WIN)
12
#include <commdlg.h>
13
#include <schannel.h>
14
#include <sddl.h>
15
#endif // defined(XP_WIN)
16
17
using namespace mozilla;
18
using namespace mozilla::ipc;
19
using namespace mozilla::plugins;
20
21
namespace mozilla {
22
namespace plugins {
23
24
template <int QuirkFlag>
25
static bool CheckQuirks(int aQuirks)
26
{
27
  return static_cast<bool>(aQuirks & QuirkFlag);
28
}
29
30
0
void FreeDestructor(void* aObj) { free(aObj); }
31
32
#if defined(XP_WIN)
33
34
// Specialization of EndpointHandlers for Flash file dialog brokering.
35
struct FileDlgEHContainer
36
{
37
  template<Endpoint e> struct EndpointHandler;
38
};
39
40
template<>
41
struct FileDlgEHContainer::EndpointHandler<CLIENT> :
42
  public BaseEndpointHandler<CLIENT, FileDlgEHContainer::EndpointHandler<CLIENT>>
43
{
44
  using BaseEndpointHandler<CLIENT, EndpointHandler<CLIENT>>::Copy;
45
46
  inline static void Copy(OpenFileNameIPC& aDest, const LPOPENFILENAMEW& aSrc)
47
  {
48
    aDest.CopyFromOfn(aSrc);
49
  }
50
  inline static void Copy(LPOPENFILENAMEW& aDest, const OpenFileNameRetIPC& aSrc)
51
  {
52
    aSrc.AddToOfn(aDest);
53
  }
54
};
55
56
template<>
57
struct FileDlgEHContainer::EndpointHandler<SERVER> :
58
  public BaseEndpointHandler<SERVER, FileDlgEHContainer::EndpointHandler<SERVER>>
59
{
60
  using BaseEndpointHandler<SERVER, EndpointHandler<SERVER>>::Copy;
61
62
  inline static void Copy(OpenFileNameRetIPC& aDest, const LPOPENFILENAMEW& aSrc)
63
  {
64
    aDest.CopyFromOfn(aSrc);
65
  }
66
  inline static void Copy(ServerCallData* aScd, LPOPENFILENAMEW& aDest, const OpenFileNameIPC& aSrc)
67
  {
68
    MOZ_ASSERT(!aDest);
69
    ServerCallData::DestructorType* destructor =
70
      [](void* aObj) {
71
      OpenFileNameIPC::FreeOfnStrings(static_cast<LPOPENFILENAMEW>(aObj));
72
      DeleteDestructor<OPENFILENAMEW>(aObj);
73
    };
74
    aDest = aScd->Allocate<OPENFILENAMEW>(destructor);
75
    aSrc.AllocateOfnStrings(aDest);
76
    aSrc.AddToOfn(aDest);
77
  }
78
};
79
80
// FunctionBroker type that uses FileDlgEHContainer
81
template <FunctionHookId functionId, typename FunctionType>
82
using FileDlgFunctionBroker = FunctionBroker<functionId, FunctionType, FileDlgEHContainer>;
83
84
// Specialization of EndpointHandlers for Flash SSL brokering.
85
struct SslEHContainer {
86
  template<Endpoint e> struct EndpointHandler;
87
};
88
89
template<>
90
struct SslEHContainer::EndpointHandler<CLIENT> :
91
  public BaseEndpointHandler<CLIENT, SslEHContainer::EndpointHandler<CLIENT>>
92
{
93
  using BaseEndpointHandler<CLIENT, EndpointHandler<CLIENT>>::Copy;
94
95
  inline static void Copy(uint64_t& aDest, const PSecHandle& aSrc)
96
  {
97
    MOZ_ASSERT((aSrc->dwLower == aSrc->dwUpper) && IsOdd(aSrc->dwLower));
98
    aDest = static_cast<uint64_t>(aSrc->dwLower);
99
  }
100
  inline static void Copy(PSecHandle& aDest, const uint64_t& aSrc)
101
  {
102
    MOZ_ASSERT(IsOdd(aSrc));
103
    aDest->dwLower = static_cast<ULONG_PTR>(aSrc);
104
    aDest->dwUpper = static_cast<ULONG_PTR>(aSrc);
105
  }
106
  inline static void Copy(IPCSchannelCred& aDest, const PSCHANNEL_CRED& aSrc)
107
  {
108
    if (aSrc) {
109
      aDest.CopyFrom(aSrc);
110
    }
111
  }
112
  inline static void Copy(IPCInternetBuffers& aDest, const LPINTERNET_BUFFERSA& aSrc)
113
  {
114
    aDest.CopyFrom(aSrc);
115
  }
116
};
117
118
template<>
119
struct SslEHContainer::EndpointHandler<SERVER> :
120
  public BaseEndpointHandler<SERVER, SslEHContainer::EndpointHandler<SERVER>>
121
{
122
  using BaseEndpointHandler<SERVER, EndpointHandler<SERVER>>::Copy;
123
124
  // PSecHandle is the same thing as PCtxtHandle and PCredHandle.
125
  inline static void Copy(uint64_t& aDest, const PSecHandle& aSrc)
126
  {
127
    // If the SecHandle was an error then don't store it.
128
    if (!aSrc) {
129
      aDest = 0;
130
      return;
131
    }
132
133
    static uint64_t sNextVal = 1;
134
    UlongPair key(aSrc->dwLower, aSrc->dwUpper);
135
    // Fetch val by reference to update the value in the map
136
    uint64_t& val = sPairToIdMap[key];
137
    if (val == 0) {
138
      MOZ_ASSERT(IsOdd(sNextVal));
139
      val = sNextVal;
140
      sIdToPairMap[val] = key;
141
      sNextVal += 2;
142
    }
143
    aDest = val;
144
  }
145
146
  // HANDLEs and HINTERNETs marshal with obfuscation (for return values)
147
  inline static void Copy(uint64_t& aDest, void* const & aSrc)
148
  {
149
    // If the HANDLE/HINTERNET was an error then don't store it.
150
    if (!aSrc) {
151
      aDest = 0;
152
      return;
153
    }
154
155
    static uint64_t sNextVal = 1;
156
    // Fetch val by reference to update the value in the map
157
    uint64_t& val = sPtrToIdMap[aSrc];
158
    if (val == 0) {
159
      MOZ_ASSERT(IsOdd(sNextVal));
160
      val = sNextVal;
161
      sIdToPtrMap[val] = aSrc;
162
      sNextVal += 2;
163
    }
164
    aDest = val;
165
  }
166
167
  // HANDLEs and HINTERNETs unmarshal with obfuscation
168
  inline static void Copy(void*& aDest, const uint64_t& aSrc)
169
  {
170
    aDest = nullptr;
171
    MOZ_RELEASE_ASSERT(IsOdd(aSrc));
172
173
    // If the src is not found in the map then we get aDest == 0
174
    void* ptr = sIdToPtrMap[aSrc];
175
    aDest = reinterpret_cast<void*>(ptr);
176
    MOZ_RELEASE_ASSERT(aDest);
177
  }
178
179
  inline static void Copy(PSCHANNEL_CRED& aDest, const IPCSchannelCred& aSrc)
180
  {
181
    if (aDest) {
182
      aSrc.CopyTo(aDest);
183
    }
184
  }
185
186
  inline static void Copy(ServerCallData* aScd, PSecHandle& aDest, const uint64_t& aSrc)
187
  {
188
    MOZ_ASSERT(!aDest);
189
    MOZ_RELEASE_ASSERT(IsOdd(aSrc));
190
191
    // If the src is not found in the map then we get the pair { 0, 0 }
192
    aDest = aScd->Allocate<SecHandle>();
193
    const UlongPair& pair = sIdToPairMap[aSrc];
194
    MOZ_RELEASE_ASSERT(pair.first || pair.second);
195
    aDest->dwLower = pair.first;
196
    aDest->dwUpper = pair.second;
197
  }
198
199
  inline static void Copy(ServerCallData* aScd, PSCHANNEL_CRED& aDest, const IPCSchannelCred& aSrc)
200
  {
201
    MOZ_ASSERT(!aDest);
202
    aDest = aScd->Allocate<SCHANNEL_CRED>();
203
    Copy(aDest, aSrc);
204
  }
205
206
  inline static void Copy(ServerCallData* aScd, LPINTERNET_BUFFERSA& aDest, const IPCInternetBuffers& aSrc)
207
  {
208
    MOZ_ASSERT(!aDest);
209
    aSrc.CopyTo(aDest);
210
    ServerCallData::DestructorType* destructor =
211
      [](void* aObj) {
212
      LPINTERNET_BUFFERSA inetBuf = static_cast<LPINTERNET_BUFFERSA>(aObj);
213
      IPCInternetBuffers::FreeBuffers(inetBuf);
214
      FreeDestructor(inetBuf);
215
    };
216
    aScd->PostDestructor(aDest, destructor);
217
  }
218
};
219
220
// FunctionBroker type that uses SslEHContainer
221
template <FunctionHookId functionId, typename FunctionType>
222
using SslFunctionBroker = FunctionBroker<functionId, FunctionType, SslEHContainer>;
223
224
/* GetKeyState */
225
226
typedef FunctionBroker<ID_GetKeyState, decltype(GetKeyState)> GetKeyStateFB;
227
228
template<>
229
ShouldHookFunc* const
230
GetKeyStateFB::BaseType::mShouldHook = &CheckQuirks<QUIRK_FLASH_HOOK_GETKEYSTATE>;
231
232
/* SetCursorPos */
233
234
typedef FunctionBroker<ID_SetCursorPos,
235
                       decltype(SetCursorPos)> SetCursorPosFB;
236
237
/* GetSaveFileNameW */
238
239
typedef FileDlgFunctionBroker<ID_GetSaveFileNameW,
240
                              decltype(GetSaveFileNameW)> GetSaveFileNameWFB;
241
242
// Remember files granted access in the chrome process
243
static void GrantFileAccess(base::ProcessId aClientId, LPOPENFILENAME& aLpofn,
244
                            bool isSave)
245
{
246
#if defined(MOZ_SANDBOX)
247
  if (aLpofn->Flags & OFN_ALLOWMULTISELECT) {
248
    // We only support multiselect with the OFN_EXPLORER flag.
249
    // This guarantees that ofn.lpstrFile follows the pattern below.
250
    MOZ_ASSERT(aLpofn->Flags & OFN_EXPLORER);
251
252
    // lpstrFile is one of two things:
253
    // 1. A null terminated full path to a file, or
254
    // 2. A path to a folder, followed by a NULL, followed by a
255
    // list of file names, each NULL terminated, followed by an
256
    // additional NULL (so it is also double-NULL terminated).
257
    std::wstring path = std::wstring(aLpofn->lpstrFile);
258
    MOZ_ASSERT(aLpofn->nFileOffset > 0);
259
    // For condition #1, nFileOffset points to the file name in the path.
260
    // It will be preceeded by a non-NULL character from the path.
261
    if (aLpofn->lpstrFile[aLpofn->nFileOffset-1] != L'\0') {
262
      FunctionBrokerParent::GetSandboxPermissions()->GrantFileAccess(aClientId, path.c_str(), isSave);
263
    }
264
    else {
265
      // This is condition #2
266
      wchar_t* nextFile = aLpofn->lpstrFile + path.size() + 1;
267
      while (*nextFile != L'\0') {
268
        std::wstring nextFileStr(nextFile);
269
        std::wstring fullPath =
270
          path + std::wstring(L"\\") + nextFileStr;
271
        FunctionBrokerParent::GetSandboxPermissions()->GrantFileAccess(aClientId, fullPath.c_str(), isSave);
272
        nextFile += nextFileStr.size() + 1;
273
      }
274
    }
275
  }
276
  else {
277
    FunctionBrokerParent::GetSandboxPermissions()->GrantFileAccess(aClientId, aLpofn->lpstrFile, isSave);
278
  }
279
#else
280
  MOZ_ASSERT_UNREACHABLE("GetFileName IPC message is only available on "
281
                         "Windows builds with sandbox.");
282
#endif
283
}
284
285
template<> template<>
286
BOOL GetSaveFileNameWFB::RunFunction(GetSaveFileNameWFB::FunctionType* aOrigFunction,
287
                                    base::ProcessId aClientId,
288
                                    LPOPENFILENAMEW& aLpofn) const
289
{
290
  BOOL result = aOrigFunction(aLpofn);
291
  if (result) {
292
    // Record any file access permission that was just granted.
293
    GrantFileAccess(aClientId, aLpofn, true);
294
  }
295
  return result;
296
}
297
298
template<> template<>
299
struct GetSaveFileNameWFB::Response::Info::ShouldMarshal<0> { static const bool value = true; };
300
301
/* GetOpenFileNameW */
302
303
typedef FileDlgFunctionBroker<ID_GetOpenFileNameW,
304
                              decltype(GetOpenFileNameW)> GetOpenFileNameWFB;
305
306
template<> template<>
307
BOOL GetOpenFileNameWFB::RunFunction(GetOpenFileNameWFB::FunctionType* aOrigFunction,
308
                                    base::ProcessId aClientId,
309
                                    LPOPENFILENAMEW& aLpofn) const
310
{
311
  BOOL result = aOrigFunction(aLpofn);
312
  if (result) {
313
    // Record any file access permission that was just granted.
314
    GrantFileAccess(aClientId, aLpofn, false);
315
  }
316
  return result;
317
}
318
319
template<> template<>
320
struct GetOpenFileNameWFB::Response::Info::ShouldMarshal<0> { static const bool value = true; };
321
322
/* InternetOpenA */
323
324
typedef SslFunctionBroker<ID_InternetOpenA,
325
                          decltype(InternetOpenA)> InternetOpenAFB;
326
327
template<>
328
ShouldHookFunc* const
329
InternetOpenAFB::BaseType::mShouldHook = &CheckQuirks<QUIRK_FLASH_HOOK_SSL>;
330
331
/* InternetConnectA */
332
333
typedef SslFunctionBroker<ID_InternetConnectA,
334
                          decltype(InternetConnectA)> InternetConnectAFB;
335
336
template<>
337
ShouldHookFunc* const
338
InternetConnectAFB::BaseType::mShouldHook = &CheckQuirks<QUIRK_FLASH_HOOK_SSL>;
339
340
typedef InternetConnectAFB::Request ICAReqHandler;
341
342
template<>
343
bool ICAReqHandler::ShouldBroker(Endpoint endpoint, const HINTERNET& h,
344
                                  const LPCSTR& srv, const INTERNET_PORT& port,
345
                                  const LPCSTR& user, const LPCSTR& pass,
346
                                  const DWORD& svc, const DWORD& flags,
347
                                  const DWORD_PTR& cxt)
348
{
349
  return (endpoint == SERVER) || IsOdd(reinterpret_cast<uint64_t>(h));
350
}
351
352
/* InternetCloseHandle */
353
354
typedef SslFunctionBroker<ID_InternetCloseHandle,
355
                          decltype(InternetCloseHandle)> InternetCloseHandleFB;
356
357
template<>
358
ShouldHookFunc* const
359
InternetCloseHandleFB::BaseType::mShouldHook = &CheckQuirks<QUIRK_FLASH_HOOK_SSL>;
360
361
typedef InternetCloseHandleFB::Request ICHReqHandler;
362
363
template<>
364
bool ICHReqHandler::ShouldBroker(Endpoint endpoint, const HINTERNET& h)
365
{
366
  // If we are server side then we were already validated since we had to be
367
  // looked up in the "uint64_t <-> HINTERNET" hashtable.
368
  // In the client, we check that this is a dummy handle.
369
  return (endpoint == SERVER) || IsOdd(reinterpret_cast<uint64_t>(h));
370
}
371
372
/* InternetQueryDataAvailable */
373
374
typedef SslFunctionBroker<ID_InternetQueryDataAvailable,
375
                          decltype(InternetQueryDataAvailable)> InternetQueryDataAvailableFB;
376
377
template<>
378
ShouldHookFunc* const
379
InternetQueryDataAvailableFB::BaseType::mShouldHook = &CheckQuirks<QUIRK_FLASH_HOOK_SSL>;
380
381
typedef InternetQueryDataAvailableFB::Request IQDAReq;
382
typedef InternetQueryDataAvailableFB::RequestDelegate<BOOL HOOK_CALL (HINTERNET)> IQDADelegateReq;
383
384
template<>
385
void IQDAReq::Marshal(IpdlTuple& aTuple, const HINTERNET& file,
386
                      const LPDWORD& nBytes, const DWORD& flags,
387
                      const DWORD_PTR& cxt)
388
{
389
  IQDADelegateReq::Marshal(aTuple, file);
390
}
391
392
template<>
393
bool IQDAReq::Unmarshal(ServerCallData& aScd, const IpdlTuple& aTuple, HINTERNET& file,
394
                        LPDWORD& nBytes, DWORD& flags, DWORD_PTR& cxt)
395
{
396
  bool success = IQDADelegateReq::Unmarshal(aScd, aTuple, file);
397
  if (!success) {
398
    return false;
399
  }
400
  flags = 0;
401
  cxt = 0;
402
  nBytes = aScd.Allocate<DWORD>();
403
  return true;
404
}
405
406
template<>
407
bool IQDAReq::ShouldBroker(Endpoint endpoint, const HINTERNET& file,
408
                           const LPDWORD& nBytes, const DWORD& flags,
409
                           const DWORD_PTR& cxt)
410
{
411
  // If we are server side then we were already validated since we had to be
412
  // looked up in the "uint64_t <-> HINTERNET" hashtable.
413
  // In the client, we check that this is a dummy handle.
414
  return (endpoint == SERVER) ||
415
         ((flags == 0) && (cxt == 0) &&
416
          IsOdd(reinterpret_cast<uint64_t>(file)));
417
}
418
419
template<> template<>
420
struct InternetQueryDataAvailableFB::Response::Info::ShouldMarshal<1> { static const bool value = true; };
421
422
/* InternetReadFile */
423
424
typedef SslFunctionBroker<ID_InternetReadFile,
425
                          decltype(InternetReadFile)> InternetReadFileFB;
426
427
template<>
428
ShouldHookFunc* const
429
InternetReadFileFB::BaseType::mShouldHook = &CheckQuirks<QUIRK_FLASH_HOOK_SSL>;
430
431
typedef InternetReadFileFB::Request IRFRequestHandler;
432
typedef InternetReadFileFB::RequestDelegate<BOOL HOOK_CALL (HINTERNET, DWORD)> IRFDelegateReq;
433
434
template<>
435
void IRFRequestHandler::Marshal(IpdlTuple& aTuple, const HINTERNET& h,
436
                                const LPVOID& buf, const DWORD& nBytesToRead,
437
                                const LPDWORD& nBytesRead)
438
{
439
  IRFDelegateReq::Marshal(aTuple, h, nBytesToRead);
440
}
441
442
443
template<>
444
bool IRFRequestHandler::Unmarshal(ServerCallData& aScd, const IpdlTuple& aTuple, HINTERNET& h,
445
                                  LPVOID& buf, DWORD& nBytesToRead,
446
                                  LPDWORD& nBytesRead)
447
{
448
  bool ret = IRFDelegateReq::Unmarshal(aScd, aTuple, h, nBytesToRead);
449
  if (!ret) {
450
    return false;
451
  }
452
453
  nBytesRead = aScd.Allocate<DWORD>();
454
  MOZ_ASSERT(nBytesToRead > 0);
455
  aScd.AllocateMemory(nBytesToRead, buf);
456
  return true;
457
}
458
459
template<>
460
bool IRFRequestHandler::ShouldBroker(Endpoint endpoint, const HINTERNET& h,
461
                                     const LPVOID& buf, const DWORD& nBytesToRead,
462
                                     const LPDWORD& nBytesRead)
463
{
464
  // For server-side validation, the HINTERNET deserialization will have
465
  // required it to already be looked up in the IdToPtrMap.  At that point,
466
  // any call is valid.
467
  return (endpoint == SERVER) || IsOdd(reinterpret_cast<uint64_t>(h));
468
}
469
470
typedef InternetReadFileFB::Response IRFResponseHandler;
471
typedef InternetReadFileFB::ResponseDelegate<BOOL HOOK_CALL (nsDependentCSubstring)> IRFDelegateResponseHandler;
472
473
// Marshal the output parameter that we sent to the response delegate.
474
template<> template<>
475
struct IRFResponseHandler::Info::ShouldMarshal<0> { static const bool value = true; };
476
477
template<>
478
void IRFResponseHandler::Marshal(IpdlTuple& aTuple, const BOOL& ret, const HINTERNET& h,
479
                                 const LPVOID& buf, const DWORD& nBytesToRead,
480
                                 const LPDWORD& nBytesRead)
481
{
482
  nsDependentCSubstring str;
483
  if (*nBytesRead) {
484
    str.Assign(static_cast<const char*>(buf), *nBytesRead);
485
  }
486
  IRFDelegateResponseHandler::Marshal(aTuple, ret, str);
487
}
488
489
template<>
490
bool IRFResponseHandler::Unmarshal(const IpdlTuple& aTuple, BOOL& ret, HINTERNET& h,
491
                                   LPVOID& buf, DWORD& nBytesToRead,
492
                                   LPDWORD& nBytesRead)
493
{
494
  nsDependentCSubstring str;
495
  bool success =
496
    IRFDelegateResponseHandler::Unmarshal(aTuple, ret, str);
497
  if (!success) {
498
    return false;
499
  }
500
501
  if (str.Length()) {
502
    memcpy(buf, str.Data(), str.Length());
503
    *nBytesRead = str.Length();
504
  }
505
  return true;
506
}
507
508
/* InternetWriteFile */
509
510
typedef SslFunctionBroker<ID_InternetWriteFile,
511
                          decltype(InternetWriteFile)> InternetWriteFileFB;
512
513
template<>
514
ShouldHookFunc* const
515
InternetWriteFileFB::BaseType::mShouldHook = &CheckQuirks<QUIRK_FLASH_HOOK_SSL>;
516
517
typedef InternetWriteFileFB::Request IWFReqHandler;
518
typedef InternetWriteFileFB::RequestDelegate<int HOOK_CALL (HINTERNET, nsDependentCSubstring)> IWFDelegateReqHandler;
519
520
template<>
521
void IWFReqHandler::Marshal(IpdlTuple& aTuple, const HINTERNET& file, const LPCVOID& buf,
522
                            const DWORD& nToWrite, const LPDWORD& nWritten)
523
{
524
  MOZ_ASSERT(nWritten);
525
  IWFDelegateReqHandler::Marshal(aTuple, file,
526
                                  nsDependentCSubstring(static_cast<const char*>(buf), nToWrite));
527
}
528
529
template<>
530
bool IWFReqHandler::Unmarshal(ServerCallData& aScd, const IpdlTuple& aTuple, HINTERNET& file,
531
                              LPCVOID& buf, DWORD& nToWrite, LPDWORD& nWritten)
532
{
533
  nsDependentCSubstring str;
534
  if (!IWFDelegateReqHandler::Unmarshal(aScd, aTuple, file, str)) {
535
    return false;
536
  }
537
538
  aScd.AllocateString(str, buf, false);
539
  nToWrite = str.Length();
540
  nWritten = aScd.Allocate<DWORD>();
541
  return true;
542
}
543
544
template<>
545
bool IWFReqHandler::ShouldBroker(Endpoint endpoint, const HINTERNET& file,
546
                                 const LPCVOID& buf, const DWORD& nToWrite,
547
                                 const LPDWORD& nWritten)
548
{
549
  // For server-side validation, the HINTERNET deserialization will have
550
  // required it to already be looked up in the IdToPtrMap.  At that point,
551
  // any call is valid.
552
  return (endpoint == SERVER) || IsOdd(reinterpret_cast<uint64_t>(file));
553
}
554
555
template<> template<>
556
struct InternetWriteFileFB::Response::Info::ShouldMarshal<3> { static const bool value = true; };
557
558
/* InternetSetOptionA */
559
560
typedef SslFunctionBroker<ID_InternetSetOptionA,
561
                          decltype(InternetSetOptionA)> InternetSetOptionAFB;
562
563
template<>
564
ShouldHookFunc* const
565
InternetSetOptionAFB::BaseType::mShouldHook = &CheckQuirks<QUIRK_FLASH_HOOK_SSL>;
566
567
typedef InternetSetOptionAFB::Request ISOAReqHandler;
568
typedef InternetSetOptionAFB::RequestDelegate<BOOL HOOK_CALL (HINTERNET, DWORD, nsDependentCSubstring)> ISOADelegateReqHandler;
569
570
template<>
571
void ISOAReqHandler::Marshal(IpdlTuple& aTuple, const HINTERNET& h, const DWORD& opt,
572
                             const LPVOID& buf, const DWORD& bufLen)
573
{
574
  ISOADelegateReqHandler::Marshal(aTuple, h, opt,
575
                                  nsDependentCSubstring(static_cast<const char*>(buf), bufLen));
576
}
577
578
template<>
579
bool ISOAReqHandler::Unmarshal(ServerCallData& aScd, const IpdlTuple& aTuple, HINTERNET& h,
580
                               DWORD& opt, LPVOID& buf, DWORD& bufLen)
581
{
582
  nsDependentCSubstring str;
583
  if (!ISOADelegateReqHandler::Unmarshal(aScd, aTuple, h, opt, str)) {
584
    return false;
585
  }
586
587
  aScd.AllocateString(str, buf, false);
588
  bufLen = str.Length();
589
  return true;
590
}
591
592
template<>
593
bool ISOAReqHandler::ShouldBroker(Endpoint endpoint, const HINTERNET& h, const DWORD& opt,
594
                                  const LPVOID& buf, const DWORD& bufLen)
595
{
596
  // For server-side validation, the HINTERNET deserialization will have
597
  // required it to already be looked up in the IdToPtrMap.  At that point,
598
  // any call is valid.
599
  return (endpoint == SERVER) || IsOdd(reinterpret_cast<uint64_t>(h));
600
}
601
602
/* HttpAddRequestHeadersA */
603
604
typedef SslFunctionBroker<ID_HttpAddRequestHeadersA,
605
                          decltype(HttpAddRequestHeadersA)> HttpAddRequestHeadersAFB;
606
607
template<>
608
ShouldHookFunc* const
609
HttpAddRequestHeadersAFB::BaseType::mShouldHook = &CheckQuirks<QUIRK_FLASH_HOOK_SSL>;
610
611
typedef HttpAddRequestHeadersAFB::Request HARHAReqHandler;
612
613
template<>
614
bool HARHAReqHandler::ShouldBroker(Endpoint endpoint, const HINTERNET& h,
615
                                   const LPCSTR& head, const DWORD& headLen,
616
                                   const DWORD& mods)
617
{
618
  // For server-side validation, the HINTERNET deserialization will have
619
  // required it to already be looked up in the IdToPtrMap.  At that point,
620
  // any call is valid.
621
  return (endpoint == SERVER) || IsOdd(reinterpret_cast<uint64_t>(h));
622
}
623
624
/* HttpOpenRequestA */
625
626
typedef SslFunctionBroker<ID_HttpOpenRequestA,
627
                          decltype(HttpOpenRequestA)> HttpOpenRequestAFB;
628
629
template<>
630
ShouldHookFunc* const
631
HttpOpenRequestAFB::BaseType::mShouldHook = &CheckQuirks<QUIRK_FLASH_HOOK_SSL>;
632
633
typedef HttpOpenRequestAFB::Request HORAReqHandler;
634
typedef HttpOpenRequestAFB::RequestDelegate<HINTERNET HOOK_CALL (HINTERNET, LPCSTR, LPCSTR, LPCSTR, LPCSTR, nsTArray<nsCString>, DWORD, DWORD_PTR)> HORADelegateReqHandler;
635
636
template<>
637
void HORAReqHandler::Marshal(IpdlTuple& aTuple, const HINTERNET& h,
638
                             const LPCSTR& verb, const LPCSTR& obj,
639
                             const LPCSTR& ver, const LPCSTR& ref,
640
                             LPCSTR * const & acceptTypes, const DWORD& flags,
641
                             const DWORD_PTR& cxt)
642
{
643
  nsTArray<nsCString> arrayAcceptTypes;
644
  LPCSTR * curAcceptType = acceptTypes;
645
  if (curAcceptType) {
646
    while (*curAcceptType) {
647
      arrayAcceptTypes.AppendElement(nsCString(*curAcceptType));
648
      ++curAcceptType;
649
    }
650
  }
651
  HORADelegateReqHandler::Marshal(aTuple, h, verb, obj, ver, ref,
652
                                  arrayAcceptTypes, flags, cxt);
653
}
654
655
template<>
656
bool HORAReqHandler::Unmarshal(ServerCallData& aScd, const IpdlTuple& aTuple, HINTERNET& h,
657
                               LPCSTR& verb, LPCSTR& obj, LPCSTR& ver,
658
                               LPCSTR& ref, LPCSTR *& acceptTypes,
659
                               DWORD& flags, DWORD_PTR& cxt)
660
{
661
  nsTArray<nsCString> arrayAcceptTypes;
662
  if (!HORADelegateReqHandler::Unmarshal(aScd, aTuple, h, verb, obj, ver, ref, arrayAcceptTypes, flags, cxt)) {
663
    return false;
664
  }
665
  if (arrayAcceptTypes.Length() == 0) {
666
    acceptTypes = nullptr;
667
  } else {
668
    aScd.AllocateMemory((arrayAcceptTypes.Length() + 1) * sizeof(LPCSTR), acceptTypes);
669
    for (size_t i = 0; i < arrayAcceptTypes.Length(); ++i) {
670
      aScd.AllocateString(arrayAcceptTypes[i], acceptTypes[i]);
671
    }
672
    acceptTypes[arrayAcceptTypes.Length()] = nullptr;
673
  }
674
  return true;
675
}
676
677
template<>
678
bool HORAReqHandler::ShouldBroker(Endpoint endpoint, const HINTERNET& h,
679
                                  const LPCSTR& verb, const LPCSTR& obj,
680
                                  const LPCSTR& ver, const LPCSTR& ref,
681
                                  LPCSTR * const & acceptTypes,
682
                                  const DWORD& flags, const DWORD_PTR& cxt)
683
{
684
  // For the server-side test, the HINTERNET deserialization will have
685
  // required it to already be looked up in the IdToPtrMap.  At that point,
686
  // any call is valid.
687
  return (endpoint == SERVER) || IsOdd(reinterpret_cast<uint64_t>(h));
688
}
689
690
/* HttpQueryInfoA */
691
692
typedef SslFunctionBroker<ID_HttpQueryInfoA,
693
                          decltype(HttpQueryInfoA)> HttpQueryInfoAFB;
694
695
template<>
696
ShouldHookFunc* const
697
HttpQueryInfoAFB::BaseType::mShouldHook = &CheckQuirks<QUIRK_FLASH_HOOK_SSL>;
698
699
typedef HttpQueryInfoAFB::Request HQIARequestHandler;
700
typedef HttpQueryInfoAFB::RequestDelegate<BOOL HOOK_CALL (HINTERNET, DWORD, BOOL, DWORD, BOOL, DWORD)> HQIADelegateRequestHandler;
701
702
template<>
703
void HQIARequestHandler::Marshal(IpdlTuple& aTuple, const HINTERNET& h,
704
                                 const DWORD& lvl, const LPVOID& buf, const LPDWORD& bufLen,
705
                                 const LPDWORD& idx)
706
{
707
  HQIADelegateRequestHandler::Marshal(aTuple, h, lvl,
708
                                      bufLen != nullptr, bufLen ? *bufLen : 0,
709
                                      idx != nullptr, idx ? *idx : 0);
710
}
711
712
template<>
713
bool HQIARequestHandler::Unmarshal(ServerCallData& aScd, const IpdlTuple& aTuple, HINTERNET& h,
714
                                   DWORD& lvl, LPVOID& buf, LPDWORD& bufLen,
715
                                   LPDWORD& idx)
716
{
717
  BOOL hasBufLen, hasIdx;
718
  DWORD tempBufLen, tempIdx;
719
  bool success =
720
    HQIADelegateRequestHandler::Unmarshal(aScd, aTuple, h, lvl, hasBufLen, tempBufLen, hasIdx, tempIdx);
721
  if (!success) {
722
    return false;
723
  }
724
725
  bufLen = nullptr;
726
  if (hasBufLen) {
727
    aScd.AllocateMemory(tempBufLen, buf, bufLen);
728
  }
729
730
  idx = nullptr;
731
  if (hasIdx) {
732
    idx = aScd.Allocate<DWORD>(tempIdx);
733
  }
734
735
  return true;
736
}
737
738
template<>
739
bool HQIARequestHandler::ShouldBroker(Endpoint endpoint, const HINTERNET& h,
740
                                      const DWORD& lvl, const LPVOID& buf,
741
                                      const LPDWORD& bufLen, const LPDWORD& idx)
742
{
743
  return (endpoint == SERVER) || IsOdd(reinterpret_cast<uint64_t>(h));
744
}
745
746
// Marshal all of the output parameters that we sent to the response delegate.
747
template<> template<>
748
struct HttpQueryInfoAFB::Response::Info::ShouldMarshal<0> { static const bool value = true; };
749
template<> template<>
750
struct HttpQueryInfoAFB::Response::Info::ShouldMarshal<1> { static const bool value = true; };
751
template<> template<>
752
struct HttpQueryInfoAFB::Response::Info::ShouldMarshal<2> { static const bool value = true; };
753
754
typedef HttpQueryInfoAFB::Response HQIAResponseHandler;
755
typedef HttpQueryInfoAFB::ResponseDelegate<BOOL HOOK_CALL (nsDependentCSubstring, DWORD, DWORD)> HQIADelegateResponseHandler;
756
757
template<>
758
void HQIAResponseHandler::Marshal(IpdlTuple& aTuple, const BOOL& ret, const HINTERNET& h,
759
                                 const DWORD& lvl, const LPVOID& buf, const LPDWORD& bufLen,
760
                                 const LPDWORD& idx)
761
{
762
  nsDependentCSubstring str;
763
  if (buf && ret) {
764
    MOZ_ASSERT(bufLen);
765
    str.Assign(static_cast<const char*>(buf), *bufLen);
766
  }
767
  // Note that we send the bufLen separately to handle the case where buf wasn't
768
  // allocated or large enough to hold the entire return value.  bufLen is then
769
  // the required buffer size.
770
  HQIADelegateResponseHandler::Marshal(aTuple, ret, str,
771
                                       bufLen ? *bufLen : 0, idx ? *idx : 0);
772
}
773
774
template<>
775
bool HQIAResponseHandler::Unmarshal(const IpdlTuple& aTuple, BOOL& ret, HINTERNET& h,
776
                                   DWORD& lvl, LPVOID& buf, LPDWORD& bufLen,
777
                                   LPDWORD& idx)
778
{
779
  DWORD totalBufLen = *bufLen;
780
  nsDependentCSubstring str;
781
  DWORD tempBufLen, tempIdx;
782
  bool success =
783
    HQIADelegateResponseHandler::Unmarshal(aTuple, ret, str, tempBufLen, tempIdx);
784
  if (!success) {
785
    return false;
786
  }
787
788
  if (bufLen) {
789
    *bufLen = tempBufLen;
790
  }
791
  if (idx) {
792
    *idx = tempIdx;
793
  }
794
795
  if (buf && ret) {
796
    // When HttpQueryInfo returns strings, the buffer length will not include
797
    // the null terminator.  Rather than (brittle-y) trying to determine if the
798
    // return buffer is a string, we always tack on a null terminator if the
799
    // buffer has room for it.
800
    MOZ_ASSERT(str.Length() == *bufLen);
801
    memcpy(buf, str.Data(), str.Length());
802
    if (str.Length() < totalBufLen) {
803
      char* cbuf = static_cast<char*>(buf);
804
      cbuf[str.Length()] = '\0';
805
    }
806
  }
807
  return true;
808
}
809
810
/* HttpSendRequestA */
811
812
typedef SslFunctionBroker<ID_HttpSendRequestA,
813
                          decltype(HttpSendRequestA)> HttpSendRequestAFB;
814
815
template<>
816
ShouldHookFunc* const
817
HttpSendRequestAFB::BaseType::mShouldHook = &CheckQuirks<QUIRK_FLASH_HOOK_SSL>;
818
819
typedef HttpSendRequestAFB::Request HSRARequestHandler;
820
typedef HttpSendRequestAFB::RequestDelegate<BOOL HOOK_CALL (HINTERNET, nsDependentCSubstring, nsDependentCSubstring)> HSRADelegateRequestHandler;
821
822
template<>
823
void HSRARequestHandler::Marshal(IpdlTuple& aTuple, const HINTERNET& h,
824
                                 const LPCSTR& head, const DWORD& headLen,
825
                                 const LPVOID& opt, const DWORD& optLen)
826
{
827
  nsDependentCSubstring headStr;
828
  headStr.SetIsVoid(head == nullptr);
829
  if (head) {
830
    // HttpSendRequest allows headLen == -1L for length of a null terminated string.
831
    DWORD ncHeadLen = headLen;
832
    if (ncHeadLen == -1L) {
833
      ncHeadLen = strlen(head);
834
    }
835
    headStr.Rebind(head, ncHeadLen);
836
  }
837
  nsDependentCSubstring optStr;
838
  optStr.SetIsVoid(opt == nullptr);
839
  if (opt) {
840
    optStr.Rebind(static_cast<const char*>(opt), optLen);
841
  }
842
  HSRADelegateRequestHandler::Marshal(aTuple, h, headStr, optStr);
843
}
844
845
template<>
846
bool HSRARequestHandler::Unmarshal(ServerCallData& aScd, const IpdlTuple& aTuple, HINTERNET& h,
847
                                   LPCSTR& head, DWORD& headLen, LPVOID& opt,
848
                                   DWORD& optLen)
849
{
850
  nsDependentCSubstring headStr;
851
  nsDependentCSubstring optStr;
852
  bool success = HSRADelegateRequestHandler::Unmarshal(aScd, aTuple, h, headStr, optStr);
853
  if (!success) {
854
    return false;
855
  }
856
857
  if (headStr.IsVoid()) {
858
    head = nullptr;
859
    MOZ_ASSERT(headLen == 0);
860
  } else {
861
    aScd.AllocateString(headStr, head, false);
862
    headLen = headStr.Length();
863
  }
864
865
  if (optStr.IsVoid()) {
866
    opt = nullptr;
867
    MOZ_ASSERT(optLen == 0);
868
  } else {
869
    aScd.AllocateString(optStr, opt, false);
870
    optLen = optStr.Length();
871
  }
872
  return true;
873
}
874
875
template<>
876
bool HSRARequestHandler::ShouldBroker(Endpoint endpoint, const HINTERNET& h,
877
                                       const LPCSTR& head, const DWORD& headLen,
878
                                       const LPVOID& opt, const DWORD& optLen)
879
{
880
  // If we are server side then we were already validated since we had to be
881
  // looked up in the "uint64_t <-> HINTERNET" hashtable.
882
  // In the client, we check that this is a dummy handle.
883
  return (endpoint == SERVER) || IsOdd(reinterpret_cast<uint64_t>(h));
884
}
885
886
/* HttpSendRequestExA */
887
888
typedef SslFunctionBroker<ID_HttpSendRequestExA,
889
                          decltype(HttpSendRequestExA)> HttpSendRequestExAFB;
890
891
template<>
892
ShouldHookFunc* const
893
HttpSendRequestExAFB::BaseType::mShouldHook = &CheckQuirks<QUIRK_FLASH_HOOK_SSL>;
894
895
typedef RequestInfo<ID_HttpSendRequestExA> HSRExAReqInfo;
896
897
template<> template<>
898
struct HSRExAReqInfo::FixedValue<2> { static const LPINTERNET_BUFFERSA value; };
899
const LPINTERNET_BUFFERSA HSRExAReqInfo::FixedValue<2>::value = nullptr;
900
901
// Docs for HttpSendRequestExA say this parameter 'must' be zero but Flash
902
// passes other values.
903
// template<> template<>
904
// struct HSRExAReqInfo::FixedValue<3> { static const DWORD value = 0; };
905
906
template<> template<>
907
struct HSRExAReqInfo::FixedValue<4> { static const DWORD_PTR value; };
908
const DWORD_PTR HSRExAReqInfo::FixedValue<4>::value = 0;
909
910
/* HttpEndRequestA */
911
912
typedef SslFunctionBroker<ID_HttpEndRequestA,
913
  decltype(HttpEndRequestA)> HttpEndRequestAFB;
914
915
template<>
916
ShouldHookFunc* const
917
HttpEndRequestAFB::BaseType::mShouldHook = &CheckQuirks<QUIRK_FLASH_HOOK_SSL>;
918
919
typedef RequestInfo<ID_HttpEndRequestA> HERAReqInfo;
920
921
template<> template<>
922
struct HERAReqInfo::FixedValue<1> { static const LPINTERNET_BUFFERSA value; };
923
const LPINTERNET_BUFFERSA HERAReqInfo::FixedValue<1>::value = nullptr;
924
925
template<> template<>
926
struct HERAReqInfo::FixedValue<2> { static const DWORD value; };
927
const DWORD HERAReqInfo::FixedValue<2>::value = 0;
928
929
template<> template<>
930
struct HERAReqInfo::FixedValue<3> { static const DWORD_PTR value; };
931
const DWORD_PTR HERAReqInfo::FixedValue<3>::value = 0;
932
933
/* InternetQueryOptionA */
934
935
typedef SslFunctionBroker<ID_InternetQueryOptionA,
936
                          decltype(InternetQueryOptionA)> InternetQueryOptionAFB;
937
938
template<>
939
ShouldHookFunc* const
940
InternetQueryOptionAFB::BaseType::mShouldHook = &CheckQuirks<QUIRK_FLASH_HOOK_SSL>;
941
942
typedef InternetQueryOptionAFB::Request IQOARequestHandler;
943
typedef InternetQueryOptionAFB::RequestDelegate<BOOL HOOK_CALL (HINTERNET, DWORD, DWORD)> IQOADelegateRequestHandler;
944
945
template<>
946
void IQOARequestHandler::Marshal(IpdlTuple& aTuple, const HINTERNET& h,
947
                                 const DWORD& opt, const LPVOID& buf, const LPDWORD& bufLen)
948
{
949
  MOZ_ASSERT(bufLen);
950
  IQOADelegateRequestHandler::Marshal(aTuple, h, opt, buf ? *bufLen : 0);
951
}
952
953
template<>
954
bool IQOARequestHandler::Unmarshal(ServerCallData& aScd, const IpdlTuple& aTuple, HINTERNET& h,
955
                                   DWORD& opt, LPVOID& buf, LPDWORD& bufLen)
956
{
957
  DWORD tempBufLen;
958
  bool success =
959
    IQOADelegateRequestHandler::Unmarshal(aScd, aTuple, h, opt, tempBufLen);
960
  if (!success) {
961
    return false;
962
  }
963
964
  aScd.AllocateMemory(tempBufLen, buf, bufLen);
965
  return true;
966
}
967
968
template<>
969
bool IQOARequestHandler::ShouldBroker(Endpoint endpoint, const HINTERNET& h,
970
                                       const DWORD& opt, const LPVOID& buf,
971
                                       const LPDWORD& bufLen)
972
{
973
  // If we are server side then we were already validated since we had to be
974
  // looked up in the "uint64_t <-> HINTERNET" hashtable.
975
  // In the client, we check that this is a dummy handle.
976
  return (endpoint == SERVER) || IsOdd(reinterpret_cast<uint64_t>(h));
977
}
978
979
// Marshal all of the output parameters that we sent to the response delegate.
980
template<> template<>
981
struct InternetQueryOptionAFB::Response::Info::ShouldMarshal<0> { static const bool value = true; };
982
template<> template<>
983
struct InternetQueryOptionAFB::Response::Info::ShouldMarshal<1> { static const bool value = true; };
984
985
typedef InternetQueryOptionAFB::Response IQOAResponseHandler;
986
typedef InternetQueryOptionAFB::ResponseDelegate<BOOL HOOK_CALL (nsDependentCSubstring, DWORD)> IQOADelegateResponseHandler;
987
988
template<>
989
void IQOAResponseHandler::Marshal(IpdlTuple& aTuple, const BOOL& ret, const HINTERNET& h,
990
                                  const DWORD& opt, const LPVOID& buf, const LPDWORD& bufLen)
991
{
992
  nsDependentCSubstring str;
993
  if (buf && ret) {
994
    MOZ_ASSERT(*bufLen);
995
    str.Assign(static_cast<const char*>(buf), *bufLen);
996
  }
997
  IQOADelegateResponseHandler::Marshal(aTuple, ret, str, *bufLen);
998
}
999
1000
template<>
1001
bool IQOAResponseHandler::Unmarshal(const IpdlTuple& aTuple, BOOL& ret, HINTERNET& h,
1002
                                   DWORD& opt, LPVOID& buf, LPDWORD& bufLen)
1003
{
1004
  nsDependentCSubstring str;
1005
  bool success =
1006
    IQOADelegateResponseHandler::Unmarshal(aTuple, ret, str, *bufLen);
1007
  if (!success) {
1008
    return false;
1009
  }
1010
1011
  if (buf && ret) {
1012
    MOZ_ASSERT(str.Length() == *bufLen);
1013
    memcpy(buf, str.Data(), str.Length());
1014
  }
1015
  return true;
1016
}
1017
1018
/* InternetErrorDlg */
1019
1020
typedef SslFunctionBroker<ID_InternetErrorDlg,
1021
                          decltype(InternetErrorDlg)> InternetErrorDlgFB;
1022
1023
template<>
1024
ShouldHookFunc* const
1025
InternetErrorDlgFB::BaseType::mShouldHook = &CheckQuirks<QUIRK_FLASH_HOOK_SSL>;
1026
1027
typedef RequestInfo<ID_InternetErrorDlg> IEDReqInfo;
1028
1029
template<> template<>
1030
struct IEDReqInfo::FixedValue<4> { static LPVOID* const value; };
1031
LPVOID* const IEDReqInfo::FixedValue<4>::value = nullptr;
1032
1033
typedef InternetErrorDlgFB::Request IEDReqHandler;
1034
1035
template<>
1036
bool IEDReqHandler::ShouldBroker(Endpoint endpoint, const HWND& hwnd,
1037
                                 const HINTERNET& h, const DWORD& err,
1038
                                 const DWORD& flags, LPVOID* const & data)
1039
{
1040
  const DWORD SUPPORTED_FLAGS =
1041
    FLAGS_ERROR_UI_FILTER_FOR_ERRORS | FLAGS_ERROR_UI_FLAGS_CHANGE_OPTIONS |
1042
    FLAGS_ERROR_UI_FLAGS_GENERATE_DATA | FLAGS_ERROR_UI_FLAGS_NO_UI;
1043
1044
  // We broker if (1) the handle h is brokered (odd in client),
1045
  // (2) we support the requested action flags and (3) there is no user
1046
  // data, which wouldn't make sense for our supported flags anyway.
1047
  return ((endpoint == SERVER) || IsOdd(reinterpret_cast<uint64_t>(h))) &&
1048
         (!(flags & ~SUPPORTED_FLAGS)) && (data == nullptr);
1049
}
1050
1051
/* AcquireCredentialsHandleA */
1052
1053
typedef SslFunctionBroker<ID_AcquireCredentialsHandleA,
1054
                          decltype(AcquireCredentialsHandleA)> AcquireCredentialsHandleAFB;
1055
1056
template<>
1057
ShouldHookFunc* const
1058
AcquireCredentialsHandleAFB::BaseType::mShouldHook = &CheckQuirks<QUIRK_FLASH_HOOK_SSL>;
1059
1060
typedef RequestInfo<ID_AcquireCredentialsHandleA> ACHAReqInfo;
1061
1062
template<> template<>
1063
struct ACHAReqInfo::FixedValue<0> { static const LPSTR value; };
1064
const LPSTR ACHAReqInfo::FixedValue<0>::value = nullptr;
1065
1066
template<> template<>
1067
struct ACHAReqInfo::FixedValue<1> { static const LPSTR value; };
1068
const LPSTR ACHAReqInfo::FixedValue<1>::value = UNISP_NAME_A;
1069
1070
template<> template<>
1071
struct ACHAReqInfo::FixedValue<2> { static const unsigned long value; };
1072
const unsigned long ACHAReqInfo::FixedValue<2>::value = SECPKG_CRED_OUTBOUND;
1073
1074
template<> template<>
1075
struct ACHAReqInfo::FixedValue<3> { static void* const value; };
1076
void* const ACHAReqInfo::FixedValue<3>::value = nullptr;
1077
1078
template<> template<>
1079
struct ACHAReqInfo::FixedValue<5> { static const SEC_GET_KEY_FN value; };
1080
const SEC_GET_KEY_FN ACHAReqInfo::FixedValue<5>::value = nullptr;
1081
1082
template<> template<>
1083
struct ACHAReqInfo::FixedValue<6> { static void* const value; };
1084
void* const ACHAReqInfo::FixedValue<6>::value = nullptr;
1085
1086
typedef AcquireCredentialsHandleAFB::Request ACHARequestHandler;
1087
typedef AcquireCredentialsHandleAFB::RequestDelegate<SECURITY_STATUS HOOK_CALL (LPSTR, LPSTR, unsigned long, void*, PSCHANNEL_CRED, SEC_GET_KEY_FN, void*)> ACHADelegateRequestHandler;
1088
1089
template<>
1090
void ACHARequestHandler::Marshal(IpdlTuple& aTuple, const LPSTR& principal,
1091
                                 const LPSTR& pkg, const unsigned long& credUse,
1092
                                 const PVOID& logonId, const PVOID& auth,
1093
                                 const SEC_GET_KEY_FN& getKeyFn,
1094
                                 const PVOID& getKeyArg, const PCredHandle& cred,
1095
                                 const PTimeStamp& expiry)
1096
{
1097
  const PSCHANNEL_CRED& scCred = reinterpret_cast<const PSCHANNEL_CRED&>(auth);
1098
  ACHADelegateRequestHandler::Marshal(aTuple, principal, pkg, credUse, logonId,
1099
                                      scCred, getKeyFn, getKeyArg);
1100
}
1101
1102
template<>
1103
bool ACHARequestHandler::Unmarshal(ServerCallData& aScd, const IpdlTuple& aTuple, LPSTR& principal,
1104
                                   LPSTR& pkg, unsigned long& credUse,
1105
                                   PVOID& logonId, PVOID& auth, SEC_GET_KEY_FN& getKeyFn,
1106
                                   PVOID& getKeyArg, PCredHandle& cred, PTimeStamp& expiry)
1107
{
1108
  PSCHANNEL_CRED& scCred = reinterpret_cast<PSCHANNEL_CRED&>(auth);
1109
  if (!ACHADelegateRequestHandler::Unmarshal(aScd, aTuple, principal, pkg, credUse,
1110
                                             logonId, scCred, getKeyFn, getKeyArg)) {
1111
    return false;
1112
  }
1113
1114
  cred = aScd.Allocate<CredHandle>();
1115
  expiry = aScd.Allocate<::TimeStamp>();
1116
  return true;
1117
}
1118
1119
typedef ResponseInfo<ID_AcquireCredentialsHandleA> ACHARspInfo;
1120
1121
// Response phase must send output parameters
1122
template<> template<>
1123
struct ACHARspInfo::ShouldMarshal<7> { static const bool value = true; };
1124
template<> template<>
1125
struct ACHARspInfo::ShouldMarshal<8> { static const bool value = true; };
1126
1127
/* QueryCredentialsAttributesA */
1128
1129
typedef SslFunctionBroker<ID_QueryCredentialsAttributesA,
1130
                          decltype(QueryCredentialsAttributesA)> QueryCredentialsAttributesAFB;
1131
1132
template<>
1133
ShouldHookFunc* const
1134
QueryCredentialsAttributesAFB::BaseType::mShouldHook = &CheckQuirks<QUIRK_FLASH_HOOK_SSL>;
1135
1136
/* FreeCredentialsHandle */
1137
1138
typedef SslFunctionBroker<ID_FreeCredentialsHandle,
1139
                          decltype(FreeCredentialsHandle)> FreeCredentialsHandleFB;
1140
1141
template<>
1142
ShouldHookFunc* const
1143
FreeCredentialsHandleFB::BaseType::mShouldHook = &CheckQuirks<QUIRK_FLASH_HOOK_SSL>;
1144
1145
typedef FreeCredentialsHandleFB::Request FCHReq;
1146
1147
template<>
1148
bool FCHReq::ShouldBroker(Endpoint endpoint, const PCredHandle& h)
1149
{
1150
  // If we are server side then we were already validated since we had to be
1151
  // looked up in the "uint64_t <-> CredHandle" hashtable.
1152
  // In the client, we check that this is a dummy handle.
1153
  return (endpoint == SERVER) ||
1154
         ((h->dwLower == h->dwUpper) && IsOdd(static_cast<uint64_t>(h->dwLower)));
1155
}
1156
1157
/* CreateMutexW */
1158
1159
// Get the user's SID as a string.  Returns an empty string on failure.
1160
static std::wstring GetUserSid()
1161
{
1162
  std::wstring ret;
1163
  // Get user SID from process token information
1164
  HANDLE token;
1165
  BOOL success = ::OpenProcessToken(::GetCurrentProcess(), TOKEN_QUERY, &token);
1166
  if (!success) {
1167
    return ret;
1168
  }
1169
  DWORD bufLen;
1170
  success = ::GetTokenInformation(token, TokenUser, nullptr, 0, &bufLen);
1171
  if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
1172
    return ret;
1173
  }
1174
  void* buf = malloc(bufLen);
1175
  success = ::GetTokenInformation(token, TokenUser, buf, bufLen, &bufLen);
1176
  MOZ_ASSERT(success);
1177
  if (success) {
1178
    TOKEN_USER* tokenUser = static_cast<TOKEN_USER*>(buf);
1179
    PSID sid = tokenUser->User.Sid;
1180
    LPWSTR sidStr;
1181
    success = ::ConvertSidToStringSid(sid, &sidStr);
1182
    if (success) {
1183
      ret = sidStr;
1184
      ::LocalFree(sidStr);
1185
    }
1186
  }
1187
  free(buf);
1188
  ::CloseHandle(token);
1189
  return ret;
1190
}
1191
1192
// Get the name Windows uses for the camera mutex.  Returns an empty string
1193
// on failure.
1194
// The camera mutex is identified in Windows code using a hard-coded GUID string,
1195
// "eed3bd3a-a1ad-4e99-987b-d7cb3fcfa7f0", and the user's SID.  The GUID
1196
// value was determined by investigating Windows code.  It is referenced in
1197
// CCreateSwEnum::CCreateSwEnum(void) in devenum.dll.
1198
static std::wstring GetCameraMutexName()
1199
{
1200
  std::wstring userSid = GetUserSid();
1201
  if (userSid.empty()) {
1202
    return userSid;
1203
  }
1204
  return std::wstring(L"eed3bd3a-a1ad-4e99-987b-d7cb3fcfa7f0 - ") + userSid;
1205
}
1206
1207
typedef FunctionBroker<ID_CreateMutexW, decltype(CreateMutexW)> CreateMutexWFB;
1208
1209
template<>
1210
ShouldHookFunc* const
1211
CreateMutexWFB::BaseType::mShouldHook = &CheckQuirks<QUIRK_FLASH_HOOK_CREATEMUTEXW>;
1212
1213
typedef CreateMutexWFB::Request CMWReqHandler;
1214
typedef CMWReqHandler::Info CMWReqInfo;
1215
typedef CreateMutexWFB::Response CMWRspHandler;
1216
1217
template<>
1218
bool CMWReqHandler::ShouldBroker(Endpoint endpoint,
1219
                                 const LPSECURITY_ATTRIBUTES& aAttribs,
1220
                                 const BOOL& aOwner,
1221
                                 const LPCWSTR& aName)
1222
{
1223
  // Statically hold the camera mutex name so that we dont recompute it for
1224
  // every CreateMutexW call in the client process.
1225
  static std::wstring camMutexName = GetCameraMutexName();
1226
1227
  // Only broker if we are requesting the camera mutex.  Note that we only
1228
  // need to check that the client is actually requesting the camera.  The
1229
  // command is always valid on the server as long as we can construct the
1230
  // mutex name.
1231
  if (endpoint == SERVER) {
1232
    return !camMutexName.empty();
1233
  }
1234
1235
  return (!aOwner) && aName && (!camMutexName.empty()) && (camMutexName == aName);
1236
}
1237
1238
// We dont need to marshal any parameters.  We construct all of them server-side.
1239
template<> template<>
1240
struct CMWReqInfo::ShouldMarshal<0> { static const bool value = false; };
1241
template<> template<>
1242
struct CMWReqInfo::ShouldMarshal<1> { static const bool value = false; };
1243
template<> template<>
1244
struct CMWReqInfo::ShouldMarshal<2> { static const bool value = false; };
1245
1246
template<> template<>
1247
HANDLE CreateMutexWFB::RunFunction(CreateMutexWFB::FunctionType* aOrigFunction,
1248
                                   base::ProcessId aClientId,
1249
                                   LPSECURITY_ATTRIBUTES& aAttribs,
1250
                                   BOOL& aOwner,
1251
                                   LPCWSTR& aName) const
1252
{
1253
  // Use CreateMutexW to get the camera mutex and DuplicateHandle to open it
1254
  // for use in the child process.
1255
  // Recall that aAttribs, aOwner and aName are all unmarshaled so they are
1256
  // unassigned garbage.
1257
  SECURITY_ATTRIBUTES mutexAttrib =
1258
    { sizeof(SECURITY_ATTRIBUTES), nullptr /* ignored */, TRUE };
1259
  std::wstring camMutexName = GetCameraMutexName();
1260
  if (camMutexName.empty()) {
1261
    return 0;
1262
  }
1263
  HANDLE serverMutex = ::CreateMutexW(&mutexAttrib, FALSE, camMutexName.c_str());
1264
  if (serverMutex == 0) {
1265
    return 0;
1266
  }
1267
  ScopedProcessHandle clientProcHandle;
1268
  if (!base::OpenProcessHandle(aClientId, &clientProcHandle.rwget())) {
1269
    return 0;
1270
  }
1271
  HANDLE ret;
1272
  if (!::DuplicateHandle(::GetCurrentProcess(), serverMutex, clientProcHandle,
1273
                         &ret, SYNCHRONIZE, FALSE, DUPLICATE_CLOSE_SOURCE)) {
1274
    return 0;
1275
  }
1276
  return ret;
1277
}
1278
1279
#endif // defined(XP_WIN)
1280
1281
/*****************************************************************************/
1282
1283
#define FUN_HOOK(x) static_cast<FunctionHook*>(x)
1284
void
1285
AddBrokeredFunctionHooks(FunctionHookArray& aHooks)
1286
0
{
1287
0
  // We transfer ownership of the FunctionHook objects to the array.
1288
#if defined(XP_WIN)
1289
  aHooks[ID_GetKeyState] =
1290
    FUN_HOOK(new GetKeyStateFB("user32.dll", "GetKeyState", &GetKeyState));
1291
  aHooks[ID_SetCursorPos] =
1292
    FUN_HOOK(new SetCursorPosFB("user32.dll", "SetCursorPos", &SetCursorPos));
1293
  aHooks[ID_GetSaveFileNameW] =
1294
    FUN_HOOK(new GetSaveFileNameWFB("comdlg32.dll", "GetSaveFileNameW",
1295
                                    &GetSaveFileNameW));
1296
  aHooks[ID_GetOpenFileNameW] =
1297
    FUN_HOOK(new GetOpenFileNameWFB("comdlg32.dll", "GetOpenFileNameW",
1298
                                    &GetOpenFileNameW));
1299
  aHooks[ID_InternetOpenA] =
1300
    FUN_HOOK(new InternetOpenAFB("wininet.dll", "InternetOpenA", &InternetOpenA));
1301
  aHooks[ID_InternetConnectA] =
1302
    FUN_HOOK(new InternetConnectAFB("wininet.dll", "InternetConnectA",
1303
                                    &InternetConnectA));
1304
  aHooks[ID_InternetCloseHandle] =
1305
    FUN_HOOK(new InternetCloseHandleFB("wininet.dll", "InternetCloseHandle",
1306
                                       &InternetCloseHandle));
1307
  aHooks[ID_InternetQueryDataAvailable] =
1308
    FUN_HOOK(new InternetQueryDataAvailableFB("wininet.dll",
1309
                                              "InternetQueryDataAvailable",
1310
                                              &InternetQueryDataAvailable));
1311
  aHooks[ID_InternetReadFile] =
1312
    FUN_HOOK(new InternetReadFileFB("wininet.dll", "InternetReadFile",
1313
                                    &InternetReadFile));
1314
  aHooks[ID_InternetWriteFile] =
1315
    FUN_HOOK(new InternetWriteFileFB("wininet.dll", "InternetWriteFile",
1316
                                     &InternetWriteFile));
1317
  aHooks[ID_InternetSetOptionA] =
1318
    FUN_HOOK(new InternetSetOptionAFB("wininet.dll", "InternetSetOptionA",
1319
                                      &InternetSetOptionA));
1320
  aHooks[ID_HttpAddRequestHeadersA] =
1321
    FUN_HOOK(new HttpAddRequestHeadersAFB("wininet.dll",
1322
                                          "HttpAddRequestHeadersA",
1323
                                          &HttpAddRequestHeadersA));
1324
  aHooks[ID_HttpOpenRequestA] =
1325
    FUN_HOOK(new HttpOpenRequestAFB("wininet.dll", "HttpOpenRequestA",
1326
                                    &HttpOpenRequestA));
1327
  aHooks[ID_HttpQueryInfoA] =
1328
    FUN_HOOK(new HttpQueryInfoAFB("wininet.dll", "HttpQueryInfoA",
1329
                                  &HttpQueryInfoA));
1330
  aHooks[ID_HttpSendRequestA] =
1331
    FUN_HOOK(new HttpSendRequestAFB("wininet.dll", "HttpSendRequestA",
1332
                                    &HttpSendRequestA));
1333
  aHooks[ID_HttpSendRequestExA] =
1334
    FUN_HOOK(new HttpSendRequestExAFB("wininet.dll", "HttpSendRequestExA",
1335
                                      &HttpSendRequestExA));
1336
  aHooks[ID_HttpEndRequestA] =
1337
    FUN_HOOK(new HttpEndRequestAFB("wininet.dll", "HttpEndRequestA",
1338
      &HttpEndRequestA));
1339
  aHooks[ID_InternetQueryOptionA] =
1340
    FUN_HOOK(new InternetQueryOptionAFB("wininet.dll", "InternetQueryOptionA",
1341
                                        &InternetQueryOptionA));
1342
  aHooks[ID_InternetErrorDlg] =
1343
    FUN_HOOK(new InternetErrorDlgFB("wininet.dll", "InternetErrorDlg",
1344
                                    InternetErrorDlg));
1345
  aHooks[ID_AcquireCredentialsHandleA] =
1346
    FUN_HOOK(new AcquireCredentialsHandleAFB("sspicli.dll",
1347
                                             "AcquireCredentialsHandleA",
1348
                                             &AcquireCredentialsHandleA));
1349
  aHooks[ID_QueryCredentialsAttributesA] =
1350
    FUN_HOOK(new QueryCredentialsAttributesAFB("sspicli.dll",
1351
                                               "QueryCredentialsAttributesA",
1352
                                               &QueryCredentialsAttributesA));
1353
  aHooks[ID_FreeCredentialsHandle] =
1354
    FUN_HOOK(new FreeCredentialsHandleFB("sspicli.dll",
1355
                                         "FreeCredentialsHandle",
1356
                                         &FreeCredentialsHandle));
1357
  aHooks[ID_CreateMutexW] =
1358
    FUN_HOOK(new CreateMutexWFB("kernel32.dll", "CreateMutexW", &CreateMutexW));
1359
#endif // defined(XP_WIN)
1360
}
1361
1362
#undef FUN_HOOK
1363
1364
} // namespace plugins
1365
} // namespace mozilla