32
32
# include < windows.h>
33
33
# define SECURITY_WIN32 1
34
34
# include < security.h>
35
+ # include " mozilla/WinDllServices.h"
35
36
#endif // XP_WIN
36
37
37
38
namespace mozilla ::contentanalysis {
@@ -53,6 +54,7 @@ const char* kIsDLPEnabledPref = "browser.contentanalysis.enabled";
53
54
const char * kIsPerUserPref = " browser.contentanalysis.is_per_user" ;
54
55
const char * kPipePathNamePref = " browser.contentanalysis.pipe_path_name" ;
55
56
const char * kDefaultAllowPref = " browser.contentanalysis.default_allow" ;
57
+ const char * kClientSignature = " browser.contentanalysis.client_signature" ;
56
58
57
59
nsresult MakePromise (JSContext* aCx, RefPtr<mozilla::dom::Promise>* aPromise) {
58
60
nsIGlobalObject* go = xpc::CurrentNativeGlobal (aCx);
@@ -179,8 +181,9 @@ ContentAnalysisRequest::GetWindowGlobalParent(
179
181
return NS_OK;
180
182
}
181
183
182
- nsresult ContentAnalysis::CreateContentAnalysisClient (nsCString&& aPipePathName,
183
- bool aIsPerUser) {
184
+ nsresult ContentAnalysis::CreateContentAnalysisClient (
185
+ nsCString&& aPipePathName, nsString&& aClientSignatureSetting,
186
+ bool aIsPerUser) {
184
187
MOZ_ASSERT (!NS_IsMainThread());
185
188
// This method should only be called once
186
189
MOZ_ASSERT (!mCaClientPromise ->IsResolved ());
@@ -189,6 +192,30 @@ nsresult ContentAnalysis::CreateContentAnalysisClient(nsCString&& aPipePathName,
189
192
content_analysis::sdk::Client::Create ({aPipePathName.Data (), aIsPerUser})
190
193
.release ());
191
194
LOGD (" Content analysis is %s" , client ? " connected" : " not available" );
195
+ #ifdef XP_WIN
196
+ if (client && !aClientSignatureSetting.IsEmpty ()) {
197
+ std::string agentPath = client->GetAgentInfo ().binary_path ;
198
+ nsString agentWidePath = NS_ConvertUTF8toUTF16(agentPath);
199
+ UniquePtr<wchar_t []> orgName =
200
+ mozilla::DllServices::Get ()->GetBinaryOrgName (agentWidePath.Data ());
201
+ bool signatureMatches = false ;
202
+ if (orgName) {
203
+ auto dependentOrgName = nsDependentString (orgName.get ());
204
+ LOGD (" Content analysis client signed with organization name \" %S\" " ,
205
+ static_cast <const wchar_t *>(dependentOrgName.get ()));
206
+ signatureMatches = aClientSignatureSetting.Equals (dependentOrgName);
207
+ } else {
208
+ LOGD (" Content analysis client has no signature" );
209
+ }
210
+ if (!signatureMatches) {
211
+ LOGE (
212
+ " Got mismatched content analysis client signature! All content "
213
+ " analysis operations will fail." );
214
+ mCaClientPromise ->Reject (NS_ERROR_INVALID_SIGNATURE, __func__);
215
+ return NS_OK;
216
+ }
217
+ }
218
+ #endif // XP_WIN
192
219
mCaClientPromise ->Resolve (client, __func__);
193
220
194
221
return NS_OK;
@@ -709,12 +736,15 @@ ContentAnalysis::GetIsActive(bool* aIsActive) {
709
736
return rv;
710
737
}
711
738
bool isPerUser = Preferences::GetBool (kIsPerUserPref );
739
+ nsString clientSignature;
740
+ // It's OK if this fails, we will default to the empty string
741
+ Preferences::GetString (kClientSignature , clientSignature);
712
742
rv = NS_DispatchBackgroundTask(NS_NewCancelableRunnableFunction(
713
743
" ContentAnalysis::CreateContentAnalysisClient" ,
714
744
[owner = RefPtr{this }, pipePathName = std::move (pipePathName),
715
- isPerUser]() mutable {
716
- owner->CreateContentAnalysisClient (std::move (pipePathName),
717
- isPerUser);
745
+ clientSignature = std::move (clientSignature), isPerUser]() mutable {
746
+ owner->CreateContentAnalysisClient (
747
+ std::move (pipePathName), std::move (clientSignature), isPerUser);
718
748
}));
719
749
if (NS_WARN_IF(NS_FAILED(rv))) {
720
750
mCaClientPromise ->Reject (rv, __func__);
0 commit comments