I am writing a driverkit extension whose goal is to block USB devices, such as flash drives. As a starting point, I chose example project at https://developer.apple.com/documentation/driverkit/communicating_between_a_driverkit_extension_and_a_client_app?language=objc
In effort not to disable a keyboard or a mouse, firstly I am trying to match my dext with a single concrete USB drive, whose vendorId I found in the registry (being aware of hexa to decimal conversions). The problem is that when the flash drive is plugged in, the system doesn't match my dext and continues with the system one.
What's wrong? Is a provisioning profile required for this? Is it even possible to match any device this way?
Driver's entitlement file:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.security.app-sandbox</key>
<true/>
<key>com.apple.developer.driverkit</key>
<true/>
<key>com.apple.developer.driverkit.transport.usb</key>
<array>
<dict>
<key>idVendor</key>
<integer>9128</integer>
</dict>
</array>
</dict>
</plist>
Info.plist:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>$(DEVELOPMENT_LANGUAGE)</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>
<string>$(PRODUCT_BUNDLE_PACKAGE_TYPE)</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleVersion</key>
<string>1</string>
<key>IOKitPersonalities</key>
<dict>
<key>DeviceControlDriver</key>
<dict>
<key>idVendor</key>
<integer>9128</integer>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleIdentifierKernel</key>
<string>com.apple.kpi.iokit</string>
<key>IOClass</key>
<string>IOUserService</string>
<key>IOProviderClass</key>
<string>IOUSBHostDevice</string>
<key>IOUserClass</key>
<string>DeviceControlDriver</string>
<key>IOUserServerName</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>UserClientProperties</key>
<dict>
<key>IOClass</key>
<string>IOUserUserClient</string>
<key>IOUserClass</key>
<string>DeviceControlDriver</string>
</dict>
</dict>
</dict>
<key>OSBundleUsageDescription</key>
<string></string>
</dict>
</plist>
There are a few sub-questions here, and I'll try to address them individually:
In effort not to disable a keyboard or a mouse, firstly I am trying to match my dext with a single concrete USB drive, whose vendorId I found in the registry (being aware of hexa to decimal conversions). The problem is that when the flash drive is plugged in, the system doesn't match my dext and continues with the system one.
[…]
<key>idVendor</key>
<integer>9128</integer>
…
<key>IOProviderClass</key>
<string>IOUSBHostDevice</string>
Matching USB devices on macOS follows very specific rules. If you do not follow one of the matching patterns outlined in this documentation from Apple, matching will generally fail.
You're attempting to match on idVendor alone; this will not work, you will need to match on either idVendor + idProduct or one of the other patterns listed.
What's wrong? Is a provisioning profile required for this?
Is it even possible to match any device this way?
If you wish to distribute your driver, or even run it locally with SIP enabled, you will require a provisioning profile. Note that Apple generally issues entitlements for specific requested vendor IDs only; if your needs go beyond that you'll need to get in touch with Apple directly.
For local testing without valid code signing, you can disable SIP; you will still require valid embedded entitlements in the signature, but you can use a provisioning profile which doesn't match the entitlements.
I am writing a driverkit extension whose goal is to block USB devices, such as flash drives.
Note that this will be of somewhat limited effectiveness, as 3rd party kexts and DriverKit extensions are not considered for matching during early system boot. This means that any devices which can be claimed by Apple's drivers and which are already connected at the time macOS starts up will always match Apple's own drivers, not yours.
For USB, you can to some extent work around this by forcing re-enumeration using the USBDeviceReEnumerate function. Note that this simulates a hard unplug, so for mounted storage devices, you should unmount cleanly first, for example.
Related
I am crating files of Microsoft office word, excel and powerpoint using apple script in Mac OS app. I need an AppleScript in my app with enabled sandbox. I found example code on apple developer side but How can use same code for Microsoft office.
<key>com.apple.security.scripting-targets</key>
<dict>
<key>com.apple.mail</key>
<array>
<string>com.apple.mail.compose</string>
</array>
</dict>
Is anybody know the correct entitlements record in XCode for Microsoft office?
What should i set in <array> </array> tags?
<key>com.apple.security.scripting-targets</key>
<dict>
<key>com.microsoft.Word</key>
<array></array>
<key>com.microsoft.Excel</key>
<array></array>
<key>com.microsoft.Powerpoint</key>
<array></array>
</dict>
For me it only works with
com.apple.security.temporary-exception.apple-events
even if "scripting-target" should be the preferred way according to apple docs
The values in your example are correct.
There are quite a few hints about how to keep programs alive, and restart them when they crash:
By using a shell script
By using launchd
They all have one restriction in common, though: They all need to be run before the to-be-monitored program.
In my case, though, I have a faceless background app that has to decide on its own whether it wants to be restarted in case it crashes. So, my app would be launched first and cannot be quit to become a child of a monitoring process (for explanation see below).
I've tried the launchd solution by writing a plist file like this:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>KeepAlive</key>
<dict>
<key>SuccessfulExit</key>
<false/>
</dict>
<key>Label</key>
<string>com.mydomain.myapp.restartAfterCrash</string>
<key>ProgramArguments</key>
<array>
<string>/Applications/MyApp.app/Contents/MacOS/MyApp</string>
</array>
</dict>
</plist>
It nearly does what I need, but in order to activate it from my app, by invoking it with launchctl load /path/to/file.plist, it wants to launch my app once more, so that my originally running app would have to quit to let the new instance run.
However, I cannot pass control to another instance of my app, because it's causing several new problems if the app was launched by double clicking a document the Finder or if it was launched by an AppleScript that wants to communicate further with my app. In those cases, my originally launched app must keep running, and thus the launchd method is not viable, nor is any other method that requires my app to run a new instance instead.
In short, are there other tested (reliable) methods that a Mac application can use to have itself restarted only if it crashes?
The only method I can think of is launching another faceless background application that monitors the first program's lifetime, e.g. via its PID.
I also wonder if it can be done with a simple shell command invocation that would periodically check whether my app is still alive, as those always run as a child process and would die along with the primary app, won't they?
I'm working on kext driver for my USB device on OS X. In this driver I have a pointer to object IOUSBDevice *device (it can be received in start() and probe() functions) and I have a problem: it is possible to open device (device->open(this, kIOServiceSeize)) in probe() function, but in other functions open()return false, because it seems like classic driver take the control on device.
I found article User-Mode USB Device Arbitration and tried to create "skeleton" kext to set "ClassicMustNotSeize" property to true, but it seems like it is not working, I still can't open the device.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>English</string>
<key>CFBundleIconFile</key>
<string></string>
<key>CFBundleIdentifier</key>
<string>com.sample.iokit.ClassicNotSeizeDriver</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundlePackageType</key>
<string>KEXT</string>
<key>CFBundleShortVersionString</key>
<string>1.0.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>1.0.0</string>
<key>IOKitPersonalities</key>
<dict>
<key>MyUSBDevice</key>
<dict>
<key>CFBundleIdentifier</key>
<string>com.apple.driver.AppleUSBMergeNub</string>
<key>IOClass</key>
<string>AppleUSBMergeNub</string>
<key>IOProviderClass</key>
<string>IOUSBDevice</string>
<key>IOProviderMergeProperties</key>
<dict>
<key>ClassicMustNotSeize</key>
<true/>
</dict>
<key>idProduct</key>
<integer>1</integer>
<key>idVendor</key>
<integer>10978</integer>
</dict>
</dict>
<key>OSBundleLibraries</key>
<dict>
<key>com.apple.driver.AppleUSBMergeNub</key>
<string>1.8.3b1</string>
<key>com.apple.iokit.IOUSBFamily</key>
<string>1.8</string>
</dict>
</dict>
</plist>
Is it possible to set "ClassicMustNotSeize" property programmatically, for example in probe() function of my driver?
I tried:
device->setProperty("ClassicMustNotSeize", true);
and it seems like it also doesn't work.
Other kexts will not claim a service if yours has successfully matched and probe()d. If you don't successfully start(), it might get matched by another kext later if something re-initiates matching. So something isn't right, and it's not possible to tell from your question alone what it is because you haven't provided the relevant code, info.plist and ioreg excerpt, let alone your code's debug output…
So I can only guess:
Why do you think you need to use kIOServiceSeize? If your kext matches the device, has the highest probe score and returns non-null from probe(), no other driver will have grabbed the device (yet). If you want to ensure exclusive access to USB devices, use the kUSBOptionBitOpenExclusivelyMask option to open().
If you open() during probe(), make sure you close() before returning, no matter what value you return. Re-open() in start(). (Overriding probe() is usually not needed anyway, it will return this by default.)
Are you setting a match category in your I/O kit personality? Unless you have a very good reason, don't.
Are you matching an IOUSBInterface instead of the IOUSBDevice in your actual driver personality, and then traversing the service graph? Or somehow otherwise trying to claim the device other than by I/O kit matching?
Is your kext in /Library/Extensions (or /System/Library/Extensions if there's a good reason it can't be in /LE)? If not, it won't participate in matching.
I very much doubt this has anything to do with "Classic" which as far as I'm aware was a way of running Mac OS 8 & 9 applications in early versions of OS X. So unless you're targeting 10.1 or so, ClassicMustNotSeize does nothing.
In my OSX app I have a WebView that goes to a page with Silverlight content. Everything works well in non-sandboxed mode, but as soon as I "sandbox" it the Silverlight content does not load... just a blank WebView. Has anyone else noticed this?
I have played around with the entitlement file and have enabled everything possible. Regular web content works fine, but not Silverlight content. Here are my settings, perhaps someone can offer any suggestions.
<key>com.apple.security.app-sandbox</key>
<true/>
<key>com.apple.security.network.client</key>
<true/>
<key>com.apple.security.network.server</key>
<true/>
<!-- Here I tried using the temporary-exception entitlement to point to the Silverlight plugin, but it did not work :( -->
<key>com.apple.security.temporary-exception.files.absolute-path.read-write</key>
<array>
<string>/Library/Internet Plug-Ins/Silverlight.plugin/Contents/</string>
<string>/Library/Internet Plug-Ins/Silverlight.plugin/Contents/MacOS/agcore</string>
<string>/Library/Internet Plug-Ins/Silverlight.plugin/</string>
<string>/Library/Internet Plug-Ins/Silverlight.plugin</string>
<string>/Library/Internet Plug-Ins/</string>
<string>/Library/Internet Plug-Ins</string>
</array>
<key>com.apple.security.temporary-exception.files.home-relative-path.read-write</key>
<array>
<string>/Library/Internet Plug-Ins/</string>
</array>
<!-- I read somewhere online to try this but it did not work :( -->
<key>com.apple.security.temporary-exception.mach-lookup.global-name</key>
<array>
<string>com.apple.WebKit.PluginAgent</string>
</array>
Do I need to do anything with my code so the Webview sees (and loads) the Silverlight content? I'm puzzled because it works just fine without sandboxing, but I can't Submit to the Mac App Store unless it works in a sandbox. Any help would be greatly appreciated... thanks!!!
I have done it in windows, how do i register a protocol on mac osx. I want to click links in firefox (a href="somename://mylinkAndData") and launch a binary?
Have a look at Apple's Launch Services Programming Guide. You have to add CFBundleURLTypes to your apps Info.plist and register your app with LSRegisterURL().
Excerpt from Firefox.app/Contents/Info.plist:
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleURLIconFile</key>
<string>document.icns</string>
<key>CFBundleURLName</key>
<string>http URL</string>
<key>CFBundleURLSchemes</key>
<array>
<string>http</string>
</array>
</dict>
....
EDIT: See Handling URL schemes in Cocoa for a how-to article