toolkit/components/maintenanceservice/registrycertificates.cpp

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

     1 /* This Source Code Form is subject to the terms of the Mozilla Public
     2  * License, v. 2.0. If a copy of the MPL was not distributed with this
     3  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     5 #include <stdio.h>
     6 #include <stdlib.h>
     7 #include <windows.h>
     9 #include "registrycertificates.h"
    10 #include "pathhash.h"
    11 #include "nsWindowsHelpers.h"
    12 #include "servicebase.h"
    13 #include "updatehelper.h"
    14 #define MAX_KEY_LENGTH 255
    16 /**
    17  * Verifies if the file path matches any certificate stored in the registry.
    18  *
    19  * @param  filePath The file path of the application to check if allowed.
    20  * @return TRUE if the binary matches any of the allowed certificates.
    21  */
    22 BOOL
    23 DoesBinaryMatchAllowedCertificates(LPCWSTR basePathForUpdate, LPCWSTR filePath)
    24 { 
    25   WCHAR maintenanceServiceKey[MAX_PATH + 1];
    26   if (!CalculateRegistryPathFromFilePath(basePathForUpdate, 
    27                                          maintenanceServiceKey)) {
    28     return FALSE;
    29   }
    31   // We use KEY_WOW64_64KEY to always force 64-bit view.
    32   // The user may have both x86 and x64 applications installed
    33   // which each register information.  We need a consistent place
    34   // to put those certificate attributes in and hence why we always
    35   // force the non redirected registry under Wow6432Node.
    36   // This flag is ignored on 32bit systems.
    37   HKEY baseKeyRaw;
    38   LONG retCode = RegOpenKeyExW(HKEY_LOCAL_MACHINE, 
    39                                maintenanceServiceKey, 0, 
    40                                KEY_READ | KEY_WOW64_64KEY, &baseKeyRaw);
    41   if (retCode != ERROR_SUCCESS) {
    42     LOG_WARN(("Could not open key.  (%d)", retCode));
    43     // Our tests run with a different apply directory for each test.
    44     // We use this registry key on our test slaves to store the 
    45     // allowed name/issuers.
    46     retCode = RegOpenKeyExW(HKEY_LOCAL_MACHINE, 
    47                             TEST_ONLY_FALLBACK_KEY_PATH, 0,
    48                             KEY_READ | KEY_WOW64_64KEY, &baseKeyRaw);
    49     if (retCode != ERROR_SUCCESS) {
    50       LOG_WARN(("Could not open fallback key.  (%d)", retCode));
    51       return FALSE;
    52     }
    53   }
    54   nsAutoRegKey baseKey(baseKeyRaw);
    56   // Get the number of subkeys.
    57   DWORD subkeyCount = 0;
    58   retCode = RegQueryInfoKeyW(baseKey, nullptr, nullptr, nullptr, &subkeyCount,
    59                              nullptr, nullptr, nullptr, nullptr, nullptr,
    60                              nullptr, nullptr);
    61   if (retCode != ERROR_SUCCESS) {
    62     LOG_WARN(("Could not query info key.  (%d)", retCode));
    63     return FALSE;
    64   }
    66   // Enumerate the subkeys, each subkey represents an allowed certificate.
    67   for (DWORD i = 0; i < subkeyCount; i++) { 
    68     WCHAR subkeyBuffer[MAX_KEY_LENGTH];
    69     DWORD subkeyBufferCount = MAX_KEY_LENGTH;  
    70     retCode = RegEnumKeyExW(baseKey, i, subkeyBuffer, 
    71                             &subkeyBufferCount, nullptr, 
    72                             nullptr, nullptr, nullptr); 
    73     if (retCode != ERROR_SUCCESS) {
    74       LOG_WARN(("Could not enum certs.  (%d)", retCode));
    75       return FALSE;
    76     }
    78     // Open the subkey for the current certificate
    79     HKEY subKeyRaw;
    80     retCode = RegOpenKeyExW(baseKey, 
    81                             subkeyBuffer, 
    82                             0, 
    83                             KEY_READ | KEY_WOW64_64KEY, 
    84                             &subKeyRaw);
    85     nsAutoRegKey subKey(subKeyRaw);
    86     if (retCode != ERROR_SUCCESS) {
    87       LOG_WARN(("Could not open subkey.  (%d)", retCode));
    88       continue; // Try the next subkey
    89     }
    91     const int MAX_CHAR_COUNT = 256;
    92     DWORD valueBufSize = MAX_CHAR_COUNT * sizeof(WCHAR);
    93     WCHAR name[MAX_CHAR_COUNT] = { L'\0' };
    94     WCHAR issuer[MAX_CHAR_COUNT] = { L'\0' };
    96     // Get the name from the registry
    97     retCode = RegQueryValueExW(subKey, L"name", 0, nullptr, 
    98                                (LPBYTE)name, &valueBufSize);
    99     if (retCode != ERROR_SUCCESS) {
   100       LOG_WARN(("Could not obtain name from registry.  (%d)", retCode));
   101       continue; // Try the next subkey
   102     }
   104     // Get the issuer from the registry
   105     valueBufSize = MAX_CHAR_COUNT * sizeof(WCHAR);
   106     retCode = RegQueryValueExW(subKey, L"issuer", 0, nullptr, 
   107                                (LPBYTE)issuer, &valueBufSize);
   108     if (retCode != ERROR_SUCCESS) {
   109       LOG_WARN(("Could not obtain issuer from registry.  (%d)", retCode));
   110       continue; // Try the next subkey
   111     }
   113     CertificateCheckInfo allowedCertificate = {
   114       name, 
   115       issuer, 
   116     };
   118     retCode = CheckCertificateForPEFile(filePath, allowedCertificate);
   119     if (retCode != ERROR_SUCCESS) {
   120       LOG_WARN(("Error on certificate check.  (%d)", retCode));
   121       continue; // Try the next subkey
   122     }
   124     retCode = VerifyCertificateTrustForFile(filePath);
   125     if (retCode != ERROR_SUCCESS) {
   126       LOG_WARN(("Error on certificate trust check.  (%d)", retCode));
   127       continue; // Try the next subkey
   128     }
   130     // Raise the roof, we found a match!
   131     return TRUE; 
   132   }
   134   // No certificates match, :'(
   135   return FALSE;
   136 }

mercurial