Skip to content

Commit

Permalink
enforce signing of midi 2 components unless in developer mode
Browse files Browse the repository at this point in the history
  • Loading branch information
garydan42 committed Jan 28, 2025
1 parent a57f6f0 commit c9a0bcd
Show file tree
Hide file tree
Showing 10 changed files with 144 additions and 20 deletions.
94 changes: 94 additions & 0 deletions src/api/Inc/midi_utils.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License
// ============================================================================
// This is part of the Windows MIDI Services App API and should be used
// in your Windows application via an official binary distribution.
// Further information: https://aka.ms/midi
// ============================================================================

#pragma once

#include <wincrypt.h>
#include <SoftPub.h>
#include <mscat.h>
#include <wintrust.h>

#define GUID_STRING_LENGTH 39

const wchar_t appModelPath[] = L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\AppModelUnlock";
const wchar_t developerModeKey[] = L"AllowDevelopmentWithoutDevLicense";

namespace WindowsMidiServicesInternal
{
inline bool IsDeveloperModeEnabled()
{
DWORD developerMode {0};
DWORD dataSize = sizeof(DWORD);

// Skip check if developer mode is enabled.
if (ERROR_SUCCESS == RegGetValue(HKEY_LOCAL_MACHINE, appModelPath, developerModeKey, RRF_RT_DWORD, NULL, &developerMode, &dataSize) &&
developerMode == 1)
{
return true;
}

return false;
}

inline std::wstring GetFileNameFromCLSID(const std::wstring& clsidStr)
{
std::wstring subKey = L"CLSID\\" + clsidStr + L"\\InprocServer32";
wchar_t filePath[MAX_PATH] {NULL};
DWORD bufferSize = sizeof(filePath);

if (ERROR_SUCCESS != RegGetValue(HKEY_CLASSES_ROOT, subKey.c_str(), NULL, RRF_RT_REG_SZ, NULL, &filePath, &bufferSize))
{
return L"";
}

return std::wstring(filePath);
}

inline HRESULT IsFileDigitallySigned(const std::wstring& filePath)
{
LONG status;
WINTRUST_FILE_INFO fileData;
WINTRUST_DATA winTrustData;
GUID policyGUID = WINTRUST_ACTION_GENERIC_VERIFY_V2;

memset(&fileData, 0, sizeof(fileData));
fileData.cbStruct = sizeof(WINTRUST_FILE_INFO);
fileData.pcwszFilePath = filePath.c_str();

memset(&winTrustData, 0, sizeof(winTrustData));
winTrustData.cbStruct = sizeof(WINTRUST_DATA);
winTrustData.dwUIChoice = WTD_UI_NONE;
winTrustData.fdwRevocationChecks = WTD_REVOKE_NONE;
winTrustData.dwUnionChoice = WTD_CHOICE_FILE;
winTrustData.dwStateAction = WTD_STATEACTION_VERIFY;
winTrustData.dwProvFlags = WTD_SAFER_FLAG;
winTrustData.pFile = &fileData;

status = WinVerifyTrust(NULL, &policyGUID, &winTrustData);

winTrustData.dwStateAction = WTD_STATEACTION_CLOSE;
WinVerifyTrust(NULL, &policyGUID, &winTrustData);

return HRESULT_FROM_WIN32(status);
}

inline HRESULT IsComponentPermitted(GUID guid)
{
// If we are in developer mode, we allow loading of untrusted components.
RETURN_HR_IF(S_OK, IsDeveloperModeEnabled());

wchar_t guidString[GUID_STRING_LENGTH] {NULL};
RETURN_HR_IF(E_INVALIDARG, 0 == StringFromGUID2(guid, guidString, _countof(guidString)));

// otherwise, confirm the component is trusted.
std::wstring fileName = GetFileNameFromCLSID(std::wstring(guidString));
RETURN_IF_FAILED(IsFileDigitallySigned(fileName.c_str()));

return S_OK;
}
}
44 changes: 24 additions & 20 deletions src/api/Service/Exe/MidiConfigurationManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -327,33 +327,37 @@ std::vector<TRANSPORTMETADATA> CMidiConfigurationManager::GetAllEnabledTransport
wil::com_ptr_nothrow<IMidiTransport> midiTransport;
wil::com_ptr_nothrow<IMidiServiceTransportPluginMetadataProvider> plugin;

if (SUCCEEDED(CoCreateInstance(transportId, nullptr, CLSCTX_ALL, IID_PPV_ARGS(&midiTransport))))
// Do not load any transports which are untrusted, unless in developer mode.
if (SUCCEEDED(internal::IsComponentPermitted(transportId)))
{
if (SUCCEEDED(midiTransport->Activate(__uuidof(IMidiServiceTransportPluginMetadataProvider), (void**)&plugin)))
if (SUCCEEDED(CoCreateInstance(transportId, nullptr, CLSCTX_ALL, IID_PPV_ARGS(&midiTransport))))
{
plugin->Initialize();
if (SUCCEEDED(midiTransport->Activate(__uuidof(IMidiServiceTransportPluginMetadataProvider), (void**)&plugin)))
{
plugin->Initialize();

TRANSPORTMETADATA metadata;
TRANSPORTMETADATA metadata;

LOG_IF_FAILED(plugin->GetMetadata(&metadata));
LOG_IF_FAILED(plugin->GetMetadata(&metadata));

results.push_back(std::move(metadata));
results.push_back(std::move(metadata));

plugin->Shutdown();
}
else
{
// log that the interface isn't there, but don't terminate or anything
plugin->Shutdown();
}
else
{
// log that the interface isn't there, but don't terminate or anything

TraceLoggingWrite(
MidiSrvTelemetryProvider::Provider(),
MIDI_TRACE_EVENT_ERROR,
TraceLoggingString(__FUNCTION__, MIDI_TRACE_EVENT_LOCATION_FIELD),
TraceLoggingLevel(WINEVENT_LEVEL_ERROR),
TraceLoggingWideString(L"Unable to activate IMidiServiceTransportPlugin", MIDI_TRACE_EVENT_MESSAGE_FIELD),
TraceLoggingGuid(transportId, "transport id"),
TraceLoggingPointer(this, "this")
);
TraceLoggingWrite(
MidiSrvTelemetryProvider::Provider(),
MIDI_TRACE_EVENT_ERROR,
TraceLoggingString(__FUNCTION__, MIDI_TRACE_EVENT_LOCATION_FIELD),
TraceLoggingLevel(WINEVENT_LEVEL_ERROR),
TraceLoggingWideString(L"Unable to activate IMidiServiceTransportPlugin", MIDI_TRACE_EVENT_MESSAGE_FIELD),
TraceLoggingGuid(transportId, "transport id"),
TraceLoggingPointer(this, "this")
);
}
}
}
}
Expand Down
6 changes: 6 additions & 0 deletions src/api/Service/Exe/MidiDeviceManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,12 @@ CMidiDeviceManager::Initialize(
TraceLoggingGuid(TransportLayer, "transport layer")
);

// Do not load any transports which are untrusted, unless in developer mode.
if (FAILED(internal::IsComponentPermitted(TransportLayer)))
{
continue;
}

// changed these from a return-on-fail to just log, so we don't prevent service startup
// due to one bad transport

Expand Down
4 changes: 4 additions & 0 deletions src/api/Service/Exe/MidiDevicePipe.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,10 @@ CMidiDevicePipe::Initialize(
RETURN_HR_IF_NULL(E_INVALIDARG, prop);
m_TransportGuid = winrt::unbox_value<winrt::guid>(prop);

// Confirm that this component is either signed, or we are in developer mode.
// Else, do not use it.
RETURN_IF_FAILED(internal::IsComponentPermitted(m_TransportGuid));

GUID dummySessionId{};

if (MidiFlowBidirectional == creationParams->Flow)
Expand Down
2 changes: 2 additions & 0 deletions src/api/Service/Exe/MidiEndpointProtocolWorker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,8 @@ CMidiEndpointProtocolWorker::Start(

// this is not a good idea, but we don't have a reference to the COM lib here
GUID midi2MidiSrvTransportIID = internal::StringToGuid(L"{2BA15E4E-5417-4A66-85B8-2B2260EFBC84}");

RETURN_IF_FAILED(internal::IsComponentPermitted(midi2MidiSrvTransportIID));
RETURN_IF_FAILED(CoCreateInstance((IID)midi2MidiSrvTransportIID, nullptr, CLSCTX_ALL, IID_PPV_ARGS(&serviceTransport)));
RETURN_IF_NULL_ALLOC(serviceTransport);

Expand Down
4 changes: 4 additions & 0 deletions src/api/Service/Exe/MidiTransformPipe.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,10 @@ CMidiTransformPipe::Initialize(

m_TransformGuid = pipeCreationParams->TransformGuid;

// Confirm that this component is either signed, or we are in developer mode.
// Else, do not use it.
RETURN_IF_FAILED(internal::IsComponentPermitted(m_TransformGuid));

// Transforms are "bidirectional" from the midi pipes perspective,
// so we always initialize the pipe as bidirectional.
RETURN_IF_FAILED(CMidiPipe::Initialize(device, MidiFlowBidirectional));
Expand Down
1 change: 1 addition & 0 deletions src/api/Service/Exe/stdafx.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@
#include "devpkey.h"

// Shared helpers
#include "midi_utils.h"
#include "midi_ump.h"
#include "midi_timestamp.h"
#include "ump_helpers.h"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,10 @@ CMidi2KSAggregateMidiInProxy::Initialize(

auto transformId = __uuidof(Midi2BS2UMPTransform);

// Confirm that this component is either signed, or we are in developer mode.
// Else, do not use it.
RETURN_IF_FAILED(internal::IsComponentPermitted(transformId));

RETURN_IF_FAILED(CoCreateInstance(transformId, nullptr, CLSCTX_ALL, IID_PPV_ARGS(&transformPlugin)));

RETURN_IF_FAILED(transformPlugin->Activate(__uuidof(IMidiDataTransform), (void**)(&m_bs2UmpTransform)));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,10 @@ CMidi2KSAggregateMidiOutProxy::Initialize(

auto transformId = __uuidof(Midi2UMP2BSTransform);

// Confirm that this component is either signed, or we are in developer mode.
// Else, do not use it.
RETURN_IF_FAILED(internal::IsComponentPermitted(transformId));

RETURN_IF_FAILED(CoCreateInstance(transformId, nullptr, CLSCTX_ALL, IID_PPV_ARGS(&transformPlugin)));

RETURN_IF_FAILED(transformPlugin->Activate(__uuidof(IMidiDataTransform), (void**)(&m_ump2BSTransform)));
Expand Down
1 change: 1 addition & 0 deletions src/api/Transport/KSAggregateTransport/pch.h
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ namespace internal = ::WindowsMidiServicesInternal;
#include "MidiDefs.h"
#include "WindowsMidiServices.h"
#include "WindowsMidiServices_i.c"
#include "midi_utils.h"


#undef GetObject
Expand Down

0 comments on commit c9a0bcd

Please sign in to comment.