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/. */
11 #include "registrycertificates.hxx"
13 #include "servicebase.hxx"
14 #include "updatehelper.h"
15 #define MAX_KEY_LENGTH 255
31 void releaseKey(HKEY key
)
50 * Verifies if the file path matches any certificate stored in the registry.
52 * @param filePath The file path of the application to check if allowed.
53 * @return TRUE if the binary matches any of the allowed certificates.
56 DoesBinaryMatchAllowedCertificates(LPCWSTR basePathForUpdate
, LPCWSTR filePath
)
58 WCHAR maintenanceServiceKey
[MAX_PATH
+ 1];
59 if (!CalculateRegistryPathFromFilePath(basePathForUpdate
,
60 maintenanceServiceKey
))
65 // We use KEY_WOW64_64KEY to always force 64-bit view.
66 // The user may have both x86 and x64 applications installed
67 // which each register information. We need a consistent place
68 // to put those certificate attributes in and hence why we always
69 // force the non redirected registry under Wow6432Node.
70 // This flag is ignored on 32bit systems.
72 LONG retCode
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
73 maintenanceServiceKey
, 0,
74 KEY_READ
| KEY_WOW64_64KEY
, &baseKeyRaw
);
75 if (retCode
!= ERROR_SUCCESS
)
77 LOG_WARN(("Could not open key. (%d)", retCode
));
78 // Our tests run with a different apply directory for each test.
79 // We use this registry key on our test slaves to store the
80 // allowed name/issuers.
81 retCode
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
82 TEST_ONLY_FALLBACK_KEY_PATH
, 0,
83 KEY_READ
| KEY_WOW64_64KEY
, &baseKeyRaw
);
84 if (retCode
!= ERROR_SUCCESS
)
86 LOG_WARN(("Could not open fallback key. (%d)", retCode
));
90 AutoRegKey
baseKey(baseKeyRaw
);
92 // Get the number of subkeys.
93 DWORD subkeyCount
= 0;
94 retCode
= RegQueryInfoKeyW(baseKey
.get(), nullptr, nullptr, nullptr, &subkeyCount
,
95 nullptr, nullptr, nullptr, nullptr, nullptr,
97 if (retCode
!= ERROR_SUCCESS
)
99 LOG_WARN(("Could not query info key. (%d)", retCode
));
103 // Enumerate the subkeys, each subkey represents an allowed certificate.
104 for (DWORD i
= 0; i
< subkeyCount
; i
++)
106 WCHAR subkeyBuffer
[MAX_KEY_LENGTH
];
107 DWORD subkeyBufferCount
= MAX_KEY_LENGTH
;
108 retCode
= RegEnumKeyExW(baseKey
.get(), i
, subkeyBuffer
,
109 &subkeyBufferCount
, nullptr,
110 nullptr, nullptr, nullptr);
111 if (retCode
!= ERROR_SUCCESS
)
113 LOG_WARN(("Could not enum certs. (%d)", retCode
));
117 // Open the subkey for the current certificate
119 retCode
= RegOpenKeyExW(baseKey
.get(),
122 KEY_READ
| KEY_WOW64_64KEY
,
124 AutoRegKey
subKey(subKeyRaw
);
125 if (retCode
!= ERROR_SUCCESS
)
127 LOG_WARN(("Could not open subkey. (%d)", retCode
));
128 continue; // Try the next subkey
131 const int MAX_CHAR_COUNT
= 256;
132 DWORD valueBufSize
= MAX_CHAR_COUNT
* sizeof(WCHAR
);
133 WCHAR name
[MAX_CHAR_COUNT
] = { L
'\0' };
134 WCHAR issuer
[MAX_CHAR_COUNT
] = { L
'\0' };
136 // Get the name from the registry
137 retCode
= RegQueryValueExW(subKey
.get(), L
"name", 0, nullptr,
138 (LPBYTE
)name
, &valueBufSize
);
139 if (retCode
!= ERROR_SUCCESS
)
141 LOG_WARN(("Could not obtain name from registry. (%d)", retCode
));
142 continue; // Try the next subkey
145 // Get the issuer from the registry
146 valueBufSize
= MAX_CHAR_COUNT
* sizeof(WCHAR
);
147 retCode
= RegQueryValueExW(subKey
.get(), L
"issuer", 0, nullptr,
148 (LPBYTE
)issuer
, &valueBufSize
);
149 if (retCode
!= ERROR_SUCCESS
)
151 LOG_WARN(("Could not obtain issuer from registry. (%d)", retCode
));
152 continue; // Try the next subkey
155 CertificateCheckInfo allowedCertificate
=
161 retCode
= CheckCertificateForPEFile(filePath
, allowedCertificate
);
162 if (retCode
!= ERROR_SUCCESS
)
164 LOG_WARN(("Error on certificate check. (%d)", retCode
));
165 continue; // Try the next subkey
168 retCode
= VerifyCertificateTrustForFile(filePath
);
169 if (retCode
!= ERROR_SUCCESS
)
171 LOG_WARN(("Error on certificate trust check. (%d)", retCode
));
172 continue; // Try the next subkey
175 // Raise the roof, we found a match!
179 // No certificates match, :'(