Blocking specific USB drives on MacOS - macos

I need to block specific USB drives on MacOS. I found two methods.
Use Disk Arbitration framework and register approval callback.(user mode)
Use MAC policy API in kernel extension and register mpo_mount_check_mount callback.(kernel mode)
In user mode, I can get a kDADiskDescriptionDeviceVendorKey which is the vender id of USB drive. I'm wondering how I can get the same information in mpo_mount_check_mount callback or some other API I don't know. The MAC policy API is undocumented and browsing the XNU source code is extremely challenging for a new MacOS developer.
This is a screenshot from IORegistryExplorer. Could I get this information from a kernel extension using MACF or other APIs? Thanks!
I can use DiskArbitration and IOKit frameworks to get vender id in user mode, but I cannot use the same code in kernel extension.
This is my code.
int GetVenderId(DADiskRef dsk, int *vid)
{
io_service_t ioService;
CFTypeRef vendorid;
ioService = DADiskCopyIOMedia(dsk);
if (0 != ioService)
{
vendorid = IORegistryEntrySearchCFProperty(ioService, kIOServicePlane, CFSTR("idVendor"), NULL, kIORegistryIterateParents | kIORegistryIterateRecursively);
if(0 != vendorid)
{
if (CFNumberGetValue(vendorid, kCFNumberIntType, vid))
{
return 0;
}
CFRelease(vendorid);
}
IOObjectRelease(ioService);
}
return 1;
}

Related

Win32:- How to set an IMMDevice as default communication device only under the context of WIn32 app

I've a simple win32 forms app and I'm using the following
code to set an IMMDevice as default communication device for the app. But it is getting reflected through out the system. Is there a way I could just set as default communication device only under the context of current app ?
public void SetDefaultAudioDevice(IMMDevice device, AudioDeviceRole role)
{
var config = new PolicyConfig();
int hr;
if (config is IPolicyConfig2 config2)
{
device.GetId(out string result)
hr = config2.SetDefaultEndpoint(result, role);
}
}

Getting SSID of the connected wifi network in Xamarin.iOS, iOS 13

After passing from iOS 12 to 13 I am no more able to get the SSID of the connected wifi network.
I tried the solution for iOS 13 proposed in
this question
but with no result.
My previous successful code for iOS 12 (moreover 'CaptiveNetwork' is deprecated now):
if (CaptiveNetwork.TryGetSupportedInterfaces(out string[] supportedInterfaces) == StatusCode.OK)
{
foreach (var item in supportedInterfaces)
{
if (CaptiveNetwork.TryCopyCurrentNetworkInfo(item, out NSDictionary info) == StatusCode.OK)
{
var ssid = info[CaptiveNetwork.NetworkInfoKeySSID].ToString();
return ssid;
}
}
}
Any suggestion?
Updated for iOS 13: Apple announced that iOS 13, the CNCopyCurrentNetworkInfo API will no longer return valid Wi-Fi SSID and BSSID information.
If your app requires valid Wi-Fi SSID and BSSID information to function, you can do the following: · For accessory setup apps, use the NEHotSpotConfiguration API, which now has the option to pass a prefix of the SSID hotspot your app expects to connect to. · For other types of apps, use the CoreLocation API to request the user’s consent to access location information.
So, I updated the above solution in the following way:
Add this key to your info.plist:
<key>NSLocationWhenInUseUsageDescription</key>
<string>Your Description</string>
Use the CoreLocation API to request the user’s consent to access location information.
private void GetLocationConsent()
{
var manager = new CLLocationManager();
manager.AuthorizationChanged += (sender, args) => {
Console.WriteLine("Authorization changed to: {0}", args.Status);
};
if (UIDevice.CurrentDevice.CheckSystemVersion(8, 0))
manager.RequestWhenInUseAuthorization();
}
Call the GetLocationConsent() function before calling the "CaptiveNetwork".

Unique ID for mobile device FMX

What is a good way to create a unique ID for mobile devices (iOS and Android) in a C++Builder FMX app?
In my case, I just want to let my app users vote, but only once per device (even if they delete the app and reinstall it). They stay anonymous, but just can't vote more than once.
I know Apple came out with DeviceCheck for Swift, but I don't know how to use it in C++.
iOS 11: The DeviceCheck API
DeviceCheck API - Unique Identifier for the iOS Devices
Update: This solution targets Android devices. I have no experience with iOS devices.
Original answer: It may be way too late but here's my solution using _di_JTelephonyManager
_di_JObject obj;
_di_JTelephonyManager tm;
UnicodeString id;
try {
obj = SharedActivityContext()->getSystemService(TJContext::JavaClass>TELEPHONY_SERVICE);
if (obj) {
tm = TJTelephonyManager::Wrap(static_cast<_di_ILocalObject>(obj)->GetObjectID());
if (tm) {
//only if SIM Card is in device:
//id = JStringToString(tm->getSubscriberId());
//will get IMEI or MEID number
id = JStringToString(TJSettings_Secure::JavaClass->getString
(SharedActivity()->getContentResolver(),
TJSettings_Secure::JavaClass->ANDROID_ID));
}
}
}
catch (Exception &e) {
//catch exceptions
}
Hope it is helpful :)

Getting the SSID of the CONNECTED WIFI on IOS 12- Xamarin (Updated for iOS 13)

I could get the ssid of the connected wifi to my iPhone. After Installing Xcode 10 and Updating Visual Studio for Mac and Visual Studio 2017, it returns me an empty ssid.
This is my piece of code for getting the ssid:
public override string GetCurrentWiFi()
{
String ssid = "";
try
{
string[] supportedInterfaces;
StatusCode status;
if ((status = CaptiveNetwork.TryGetSupportedInterfaces(out supportedInterfaces)) != StatusCode.OK)
{
}
else
{
foreach (var item in supportedInterfaces)
{
NSDictionary info;
status = CaptiveNetwork.TryCopyCurrentNetworkInfo(item, out info);
if (status != StatusCode.OK)
{
continue;
}
ssid = info[CaptiveNetwork.NetworkInfoKeySSID].ToString();
}
}
}
catch
{
}
return ssid;
}
I tried to add "Access WiFi Information" entitlement for iOS 12 app as it is mentioned here but the app still get an empty ssid:https://forums.xamarin.com/discussion/139476/adding-access-wifi-information-entitlement-for-ios-12-apps
I would be thankful if anyone could help.
RESOLVED: I applied Access WIFI Information for my Apple ID. Then I regenerated my Provisioning profile again and open it in my Xcode. Do not forget to add Entitlements.plist in the Custom Entertainments in the ios Bundle Signing. Now it works correctly.
Updated for iOS 13: Apple announced that iOS 13, the CNCopyCurrentNetworkInfo API will no longer return valid Wi-Fi SSID and BSSID information.
If your app requires valid Wi-Fi SSID and BSSID information to function, you can do the following:
· For accessory setup apps, use the NEHotSpotConfiguration API, which now has the option to pass a prefix of the SSID hotspot your app expects to connect to.
· For other types of apps, use the CoreLocation API to request the user’s consent to access location information.
So, I updated the above solution in the following way:
Add this key to your info.plist:
<key>NSLocationWhenInUseUsageDescription</key>
<string>Your Description</string>
Use the CoreLocation API to request the user’s consent to access location information.
private void GetLocationConsent()
{
var manager = new CLLocationManager();
manager.AuthorizationChanged += (sender, args) => {
Console.WriteLine("Authorization changed to: {0}", args.Status);
};
if (UIDevice.CurrentDevice.CheckSystemVersion(8, 0))
manager.RequestWhenInUseAuthorization();
}
Call the GetLocationConsent() function before calling the "CaptiveNetwork".
To use this function in iOS 12 and later, enable the Access WiFi Information capability for your app .
So you have to check Access WiFi Infomation in appid.

Multiple device driver? (KMDF/WDF)

I've just written a KMDF USB driver. Now I want to connect several (up to at least four) devices to the PC. Where do I start? I've noted that when I connect the second device to the PC it use the very same instance of the driver as for the first connected device. EvtDeviceAdd(...) runs one time per device and since I don't have any handling for several devices things get weird... Right now my EvtDeviceAdd looks like this:
NTSTATUS EvtDeviceAdd(IN WDFDRIVER Driver, IN PWDFDEVICE_INIT DeviceInit) {
WDF_PNPPOWER_EVENT_CALLBACKS pnpPowerCallbacks;
WDF_OBJECT_ATTRIBUTES attributes;
NTSTATUS status;
WDFDEVICE device;
WDF_DEVICE_PNP_CAPABILITIES pnpCaps;
WDF_IO_QUEUE_CONFIG ioQueueConfig;
PDEVICE_CONTEXT pDevContext;
WDFQUEUE queue;
PWSTR driverRegistryPath;
UNREFERENCED_PARAMETER(Driver);
PAGED_CODE();
DbgPrint("New device was added\n");
WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnpPowerCallbacks);
pnpPowerCallbacks.EvtDevicePrepareHardware = EvtDevicePrepareHardware;
WdfDeviceInitSetPnpPowerEventCallbacks(DeviceInit, &pnpPowerCallbacks);
WdfDeviceInitSetIoType(DeviceInit, WdfDeviceIoBuffered);
WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, DEVICE_CONTEXT);
status = WdfDeviceCreate(&DeviceInit, &attributes, &device);
if (!NT_SUCCESS(status)) {
DbgPrint("WdfDeviceCreate failed with Status code %!STATUS!\n", status);
return status;
}
pDevContext = GetDeviceContext(device);
WDF_DEVICE_PNP_CAPABILITIES_INIT(&pnpCaps);
pnpCaps.SurpriseRemovalOK = WdfTrue;
WdfDeviceSetPnpCapabilities(device, &pnpCaps);
WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE(&ioQueueConfig, WdfIoQueueDispatchParallel);
ioQueueConfig.EvtIoRead = EvtIoRead;
ioQueueConfig.EvtIoWrite = EvtIoWrite;
ioQueueConfig.EvtIoDeviceControl = EvtIoDeviceControl;
ioQueueConfig.PowerManaged = WdfTrue;
status = WdfIoQueueCreate(device, &ioQueueConfig, WDF_NO_OBJECT_ATTRIBUTES, &queue);
if (!NT_SUCCESS(status)) {
DbgPrint("WdfIoQueueCreate failed %!STATUS!\n", status);
return status;
}
pDevContext->DeviceIOControlQueue = queue;
status = WdfDeviceCreateDeviceInterface(device, (LPGUID) &GUID_DEVINTERFACE_MYDEVICE, NULL);
if (!NT_SUCCESS(status)) {
DbgPrint("WdfDeviceCreateDeviceInterface failed %!STATUS!\n", status);
return status;
}
}
Where do I start? Is there any good examples?
There is only one instance of the driver in memory for all the connected devices (it's a singleton). The OS calls to the driver are accompanied with the relevant device context and from that point the devices shouldn't interfere with each other operation. The problems begin if non-constant global/static variables are being used. Since the Kernel space is shared, such variables will be actually shared and accessible from all attached devices. For this reason global/static data shouldn't be device-specific and should be guarded since it's shared resource. There are some samples in the WDK demonstrating multi-device drivers.

Resources