I have created an encrypted .DMG called ‘Test.dmg’ with a password of ‘password’ and have several SQLite3 databases and some admin level scripts in it. What I want to do is access the files on the .DMG but NOT mount it. I want to be able to write a script (or an XCode interface) which, when it needs to access the data in the databases or run the functions of the admin scripts, will access the .DMG with the password but not save it in the system keychain or mount it so users can access the data manually. I know I can mount it but that, in my mind, defeats the reason I bothered to encrypt and password protect it.
Is something like this possible?
All I have so far is:
property pDongleMounted : false -- Default value
property pDongleName : "Test" -- The name of the .dmg file
set lReply to "USB Dongle not found."
set lParseUSBPorts to (do shell script "system_profiler SPUSBDataType") as text
if lParseUSBPorts contains "0x1607" and lParseUSBPorts contains "0x0951" and lParseUSBPorts contains "001000000000000000000279" then
set lReply to my sMountDongle(pDongleName)
end if
return lReply
--> Mount Dongle image (How do I do this when the .dmg requires a password?)
on sMountDongle(pDongleName)
set lDongleImagePath to "USB_Dongle:" & pDongleName & ".dmg"
do shell script "hdiutil attach " & quoted form of POSIX path of lDongleImagePath
return "Image mounted."
end sMountDongle
--> Unmount Dongle image (Do this AFTER data is accessed)
on sUnMountDongle(pDongleName)
tell application "System Events"
set lDongleImage to (pDongleName is in (get name of disks))
if lDongleImage then set pDongleMounted to true
end tell
if pDongleMounted then do shell script "hdiutil unmount " & quoted form of ("/Volumes/" & pDongleName)
return "Image unmounted."
end sUnMountDongle
which does not even address opening the image using a password , and if you can access the data without mounting the image, can you at least make it invisible?
Actually I got that shell script from other examples on this site so no. I didn’t know that WAS an option, so thanks!
Okay, this works like a charm but I was wondering - While I don’t SEE it mounted on the desktop I can see it is mounted when I open Disk Utility. Does that mean that a user could if they so choose access the contents of the mounted image as long as it remains open or does the -nobrowse option make it inaccessible? By the way, is there a option like -withpassword “password” so you can open a password protected image?
property pDMGMounted : false -- Default value
property pDMGName : "Test" -- The name of the .dmg file
set lReply to "USB Dongle not found."
set lParseUSBPorts to (do shell script "system_profiler SPUSBDataType") as text
if lParseUSBPorts contains "0x1607" and lParseUSBPorts contains "0x0951" and lParseUSBPorts contains "001000000000000000000279" then
set lReply to my sMountDMG(pDMGName)
end if
return lReply
--> Mount Dongle image
on sMountDMG(pDMGName)
set lDMGImage to "USB_Dongle:" & pDMGName & ".dmg"
do shell script ("hdiutil attach " & (quoted form of POSIX path of lDMGImage) & " -nobrowse")
return "Image mounted."
end sMountDMG
--> Unmount Dongle image (Do this AFTER data is accessed)
on sUnMountDMG(pDMGName)
tell application "System Events"
set lDMGImage to (pDMGName is in (get name of disks))
if lDMGImage then set pDMGMounted to true
end tell
if pDMGMounted then do shell script "hdiutil unmount " & quoted form of ("/Volumes/" & pDMGName)
return "Image unmounted."
end sUnMountDMG
As for making it completely unaccessible to the end user I don’t think you can. You can add the nobrowse as I said which hides it, but you can’t really make invisible/locked. The only thing I can think of would maybe be to try doing the following…
Set the owners of the files on the DMG to root and give it permissions of execute only. Then incase they have ignore permissions set you could attach the dmg with the ‘-owners on’ option.
The only problem with all of this is if they have a admin account on the machine anything you do they can pretty much work around.
do shell script ("echo -n " & pDMGPwd & "|hdiutil attach " & (quoted form of POSIX path of lDMGImage) & " -stdinpass -nobrowse")
which translates into do shell script (“echo -n password|hdiutil attach /Volumes/USB_Dongle/Test.dmg -stdinpass -nobrowse”)
To me it looks like the only thing my code was missing was the tilde in from the front of the path, so I added it but now get the error:
What have I done wrong? The full script is below… By the way, I like your ideas regarding the setting of the file owners to root and execute only. I think I will make two versions, give them both a spin, and determine from there which one will be the best fit.
property pDMGMounted : false -- Default value
property pDMGName : "Test" -- The name of the .dmg file
property pDMGPwd : "password" -- The password for the .dmg file
set lParseUSBPorts to (do shell script "system_profiler SPUSBDataType") as text
set lReply to "Default reply." -- Only necessary while testing
if lParseUSBPorts contains "0x1607" and lParseUSBPorts contains "0x0951" and lParseUSBPorts contains "001000000000000000000279" then
my sMountDMG(pDMGName)
-- Do everything with files on the password protected image here
set lReply to my sUnMountDMG(pDMGName)
else
set lReply to "USB Dongle not found."
end if
return lReply
--> Mount Dongle image
on sMountDMG(pDMGName)
set lDMGImage to "USB_Dongle:" & pDMGName & ".dmg"
do shell script ("echo -n " & pDMGPwd & "|hdiutil attach " & (quoted form of POSIX path of lDMGImage) & " -stdinpass -nobrowse")
end sMountDMG
--> Unmount Dongle image (Do this AFTER data is accessed)
on sUnMountDMG(pDMGName)
tell application "System Events"
set lDMGImage to (pDMGName is in (get name of disks))
if lDMGImage then set pDMGMounted to true
end tell
if pDMGMounted then do shell script "hdiutil unmount " & quoted form of ("/Volumes/" & pDMGName)
return "Image unmounted." -- Only necessary while testing
end sUnMountDMG
Also results in hdiutil: attach failed - Authentication error.
HOLD THE PHONE! I just save the script as an application and ran it just for grins, and as an application it DOES mount the .dmg image. What’s with that? As a script it fails - as an application it works…
with -nobrowse removed it mounts the image if run as a script (didn’t try it as an application but assume it works as an app).
I think I MAY have figured out where my mistake was (actually I know WHERE it was , I guess WHY it was occurring is more accurate).
Here is where the problem was:
if lParseUSBPorts contains "0x1607" and lParseUSBPorts contains "0x0951" and lParseUSBPorts contains "001000000000000000000279" then
my sMountDMG(pDMGName)
When I change my sMountDMG(pDMGName) to either set x to my sMountDMG(pDMGName) OR I follow it with delay 2 the problem goes away. I guess it was trying to unmount the image before or while it was in the process of being mounted and setting the result as a variable or adding a bit of delay to the script gives it time to finish up.
Thanks to James and Stefan the following is the script, pared down slightly. This is by no mean the whole project but since this works I will be putting it the time to design a functional application that incorporates a dongle and then test the security of it. If it works and is useful I will post the code and instructions. No promises when I will be done with this though:D
property pDMGName : "Test" -- The name of the .dmg file
property pDMGPwd : "password" -- The password for the .dmg file
set lParseUSBPorts to (do shell script "system_profiler SPUSBDataType") as text
if lParseUSBPorts contains "0x1607" and lParseUSBPorts contains "0x0951" and lParseUSBPorts contains "001000000000000000000279" then
set lReply to my sMountDMG(pDMGName)
set lDMGImagePath to ("Volumes:" & pDMGName)
(* ALL FILE ACTIONS GO BELOW THIS !!! *)
(* ALL FILE ACTIONS GO ABOVE THIS !!! *)
tell application "System Events" to set lDMGImage to (pDMGName is in (get name of disks))
set lReply to my sUnMountDMG(pDMGName, lDMGImage, lDMGImagePath)
--set lReply to sEjectDMG(pDMGName, lDMGImage, lDMGImagePath)
end if
--> Mount Dongle image
on sMountDMG(pDMGName)
set lDMGImage to ("USB_Dongle:" & pDMGName & ".dmg") as text
do shell script ("/bin/echo -n " & quoted form of the pDMGPwd & " | /usr/bin/hdiutil attach -stdinpass " & quoted form of POSIX path of lDMGImage & " -nobrowse")
end sMountDMG
--> Unmount Dongle image (Do this AFTER data is accessed)
on sUnMountDMG(pDMGName, lDMGImage, lDMGImagePath)
if lDMGImage then do shell script ("/usr/bin/hdiutil unmount " & quoted form of POSIX path of lDMGImagePath)
end sUnMountDMG
--> Eject Dongle image
on sEjectDMG(pDMGName, lDMGImage, lDMGImagePath)
if lDMGImage then do shell script ("/usr/bin/hdiutil detach " & quoted form of POSIX path of lDMGImagePath)
end sEjectDMG
I tried your solution, changing only what was relevant to my use, as it was closest to what I want to do. I want to make a dmg that behaves like an Installer. To that end I want to open an encrypted dmg using Applescript (if the User agrees to the Licese Agreement) then run some other suff.
I have all files; Test.dmg Test.scpt Test.app together on the Desktop. But I get: Applescript Error - hdiutil: attach failed - No such file or directory
Did you ever get this working correctly?
property pDMGName : "Test" -- The name of the .dmg file
property pDMGPwd : "Password" -- The password for the .dmg file
--> Confirm
set dialog to display dialog "Mount, Unencrypt, Expand 'Test.dmg' ?
" buttons {"Cancel", "OK"} cancel button 1
set pressed to button returned of dialog
if pressed is equal to "OK" then
set lReply to my sMountDMG(pDMGName)
set lDMGImagePath to ("Volumes:" & pDMGName)
(* ALL FILE ACTIONS GO BELOW THIS !!! *)
(* ALL FILE ACTIONS GO ABOVE THIS !!! *)
tell application "System Events" to set lDMGImage to (pDMGName is in (get name of disks))
set lReply to my sUnMountDMG(pDMGName, lDMGImage, lDMGImagePath)
--set lReply to sEjectDMG(pDMGName, lDMGImage, lDMGImagePath)
end if
--> Mount Dongle image
on sMountDMG(pDMGName)
set lDMGImage to (pDMGName & ".dmg") as text
do shell script ("/bin/echo -n " & quoted form of the pDMGPwd & " | /usr/bin/hdiutil attach -stdinpass " & quoted form of POSIX path of lDMGImage & " -nobrowse")
end sMountDMG
--> Unmount Dongle image (Do this AFTER data is accessed)
on sUnMountDMG(pDMGName, lDMGImage, lDMGImagePath)
if lDMGImage then do shell script ("/usr/bin/hdiutil unmount " & quoted form of POSIX path of lDMGImagePath)
end sUnMountDMG
--> Eject Dongle image
on sEjectDMG(pDMGName, lDMGImage, lDMGImagePath)
if lDMGImage then do shell script ("/usr/bin/hdiutil detach " & quoted form of POSIX path of lDMGImagePath)
end sEjectDMG