keytool -v -list -keystore /System/Library/Java/Support/CoreDeploy.bundle/Contents/Home/lib/security/cacertsThe default password is 'changeit'.
Friday, June 29, 2012
JAVA CA store on OS X
To get the list of CAs trusted by Java on OS X:
Thursday, June 28, 2012
Ruby foo: flatten a hash into a string
Flatten a ruby hash into a string. In this case the comma is the key value delimiter and the semicolon is the entry delimiter.
irb(main):016:0> a={'sdfs'=>['aaa','bbb'], 'ppp'=>['aa','a']} => {"ppp"=>["aa", "a"], "sdfs"=>["aaa", "bbb"]} => ["ppp:aa,a", "sdfs:aaa,bbb"] irb(main):018:0> b=a.map { |k, v| "#{k}:#{v.join(',')}" }.join(";") => "ppp:aa,a;sdfs:aaa,bbb"
Tuesday, June 26, 2012
Ruby Dir.glob to provides some of the python os.walk functionality
The ruby Dir.glob command is pretty nice. It provides some of what os.walk provides for python and is a reasonable choice for working with files and directories. Double * gets you recursion.
Quick and dirty way to list user home directories and user-level global environment file:
Dir.glob("/Users/**/.MacOSX/environment")More comprehensive is to use dscl, but it is more work, first get a list of users:
dscl . -list /UsersThen iterate over each of those:
dscl . -read /Users/myuser NFSHomeDirectoryTo get a rough list of Applications and their plists (note getting a list of everything installed is more complicated):
Dir.glob("/Applications/**/**app/Contents/Info.plist")
Thursday, June 21, 2012
Ruby string manipulation: struct, split, join
Every time I write ruby it seems like I have to re-learn everything. To shortcut the process for next time here is a snippet that demonstrates some string handling by parsing the output of lsof (OS X format).
Ruby structs are the equivalent of python namedtuple, very handy for splitting up strings in a sane way.
def parse_lsof(lsof_out) net_listener = Struct.new(:command, :pid, :user, :fd, :type, :device, :size, :node, :name, :status) output = [] # strip header line lsof_lines = lsof_out.split("\n")[1..-1] lsof_lines.each { |line| line_array = line.split("\s") listener_o = net_listener.new(*line_array) output.push("#{listener_o.command},#{listener_o.user},#{listener_o.type},#{listener_o.node},#{listener_o.name}") } return output.join(" ") end
Thursday, June 14, 2012
Adjust log level of python logger in a library (pyactiveresource)
My logging was being polluted by pyactiveresource that was writing a lot of useless logs at the 'INFO' level. I wanted my own logging set at INFO, so how can you change pyactiveresource?
As described in the python doco, you can access the logger with getLogger and adjust the level like this:
noisy_logger = logging.getLogger('pyactiveresource') noisy_logger.setLevel(logging.WARN)Then just set your own logger as normal, something like:
syslog = logging.handlers.SysLogHandler('/var/run/syslog') syslog.setFormatter(logging.Formatter('%(name)s: %(message)s')) syslog.setLevel(logging.INFO) logging.getLogger().addHandler(syslog)
Wednesday, June 6, 2012
Mac OS X pkg, bom files, package installation and utilities
List all installed packages:
PKG files are just XAR files that contain a bunch of metadata files and the app itself inside a zipped cpio.
To extract the files on OS X, use (note tempdir will be created and can't exist prior to running the command):
Use lsbom to inspect bill of materials files (note apple says "The files and directories where receipts are stored are subject to change. Always use pkgutil to query or modify them"). These options are more readable than the defaults:
On installation the package app directory is copied to the installation dir (usually /Applications/) and the BOM is written with a plist of installation metadata to the Receipts directory:
pkgutil --pkgs --volume /What files does this package install?
pkgutil --files com.vmware.fusionVerify file permissions and owner/group is the same as listed in the package BOM in /private/var/db/receipts/ (actually calls repair_packages). See the end of this post for how to verify the file content.
pkgutil --verify com.vmware.fusionThere isn't any uninstall functionality on OS X, this command just drops the metadata out of the receipts directory, which is handy if you want to re-install:
pkgutil --forget com.vmware.fusionpkgutil has a code signing check feature, but it looks like it is broken or doesn't work how I expected it to:
$ pkgutil --check-signature com.apple.pkg.Safari Package does not exist: com.apple.pkg.Safari $ pkgutil --check-signature /Applications/Safari.app/ Package "Safari": Status: no signature $ codesign -d -vvv /Applications/Safari.app/ Executable=/Applications/Safari.app/Contents/MacOS/Safari Identifier=com.apple.Safari Format=bundle with Mach-O universal (i386 x86_64) CodeDirectory v=20100 size=185 flags=0x0(none) hashes=3+3 location=embedded Hash type=sha1 size=20 CDHash=66615ae53cb89ac254e4efc6d3eb2f93fa6a4a85 Signature size=4064 Authority=Software Signing Authority=Apple Code Signing Certification Authority Authority=Apple Root CA Info.plist entries=37 Sealed Resources rules=11 files=393 Internal requirements count=1 size=108
PKG files
PKG files are just XAR files that contain a bunch of metadata files and the app itself inside a zipped cpio.
To extract the files on OS X, use (note tempdir will be created and can't exist prior to running the command):
pkgutil --expand my.pkg tempdirHere is a manual unpacking sequence (if you just want metadata use the pkgutil commands to avoid all this unpacking). tar understands xar on OS X but on linux you'll need to install the xar package and use 'xar -xf helloworld.pkg':
$ tar zxvf helloworld.pkg x com.totallylegit.helloworld.pkg x com.totallylegit.helloworld.pkg/Bom x com.totallylegit.helloworld.pkg/Payload x com.totallylegit.helloworld.pkg/PackageInfo x Distribution $ cd com.totallylegit.helloworld.pkg/ $ ls Bom PackageInfo Payload $ mv Payload Payload.gz $ gunzip Payload $ cpio -iv < Payload . ./helloworld.app ./helloworld.app/Contents ./helloworld.app/Contents/Info.plist ./helloworld.app/Contents/MacOS ./helloworld.app/Contents/MacOS/helloworld ./helloworld.app/Contents/PkgInfo ./helloworld.app/Contents/Resources ./helloworld.app/Contents/Resources/en.lproj ./helloworld.app/Contents/Resources/en.lproj/Credits.rtf ./helloworld.app/Contents/Resources/en.lproj/InfoPlist.strings ./helloworld.app/Contents/Resources/en.lproj/MainMenu.nib 87 blocks
BOM files
Use lsbom to inspect bill of materials files (note apple says "The files and directories where receipts are stored are subject to change. Always use pkgutil to query or modify them"). These options are more readable than the defaults:
$ lsbom -p MUGsf /private/var/db/receipts/com.vmware.fusion.bom drwxr-xr-x root admin . drwxrwxr-x root admin ./Applications -rwxr-xr-x root admin 82 ./Applications/._VMware Fusion.app [snip]While pkgutil/repair_packages could check file content hasn't changed by calculating the CRC32 and comparing that with the one in the BOM, it doesn't. It would be fairly simple to do. The BOM content for a simple package looks like this (path, octal mode, UID/GID, size, CRC32):
$ lsbom Bom . 0 0/0 ./helloworld.app 40755 0/0 ./helloworld.app/Contents 40755 0/0 ./helloworld.app/Contents/Info.plist 100644 0/0 1429 3178638052 ./helloworld.app/Contents/MacOS 40755 0/0 ./helloworld.app/Contents/MacOS/helloworld 100755 0/0 13488 1649029420 ./helloworld.app/Contents/PkgInfo 100644 0/0 8 742937289 ./helloworld.app/Contents/Resources 40755 0/0 ./helloworld.app/Contents/Resources/en.lproj 40755 0/0 ./helloworld.app/Contents/Resources/en.lproj/Credits.rtf 100644 0/0 436 2072274354 ./helloworld.app/Contents/Resources/en.lproj/InfoPlist.strings 100644 0/0 92 2769355950 ./helloworld.app/Contents/Resources/en.lproj/MainMenu.nib 100644 0/0 27463 4224082203and the checksum can be calculated with cksum which prints the size in bytes and the CRC32:
$ cksum helloworld 1649029420 13488 helloworld
Installation
On installation the package app directory is copied to the installation dir (usually /Applications/) and the BOM is written with a plist of installation metadata to the Receipts directory:
$ ls -1 /private/var/db/receipts/com.vmware* /private/var/db/receipts/com.vmware.fusion.bom /private/var/db/receipts/com.vmware.fusion.plist
Gatekeeper, XProtect and the Quarantine attribute
Apps can opt-in to Gatekeeper and Xprotect protection by adding LSFileQuarantineEnabled to their Contents/Info.plist. This means that any files created by that app will get tagged with the apple quarantine HFS+ extended attribute.
For example, here's what chrome looks like when downloaded with Safari:
$ ls -l@eOd Downloads/googlechrome.dmg -rw-r--r--@ 1 user group - 39937778 Apr 16 11:31 Downloads/googlechrome.dmg com.apple.diskimages.fsck 20 com.apple.diskimages.recentcksum 79 com.apple.metadata:kMDItemDownloadedDate 53 com.apple.metadata:kMDItemWhereFroms 210 com.apple.quarantine 57and the same file downloaded with curl (which isn't a cocoa app and hence can't opt-in):
$ curl -o chrome_curl.dmg -L https://dl.google.com/chrome/mac/stable/GGRO/googlechrome.dmg % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 100 38.0M 100 38.0M 0 0 15.7M 0 0:00:02 0:00:02 --:--:-- 18.2M $ ls -l@eOd chrome_curl.dmg -rw-r--r-- 1 user group - 39937627 Apr 20 14:47 chrome_curl.dmgLooking at the contents of the extended attributes we see a bunch of interesting metadata, including the HTTP referrer in a binary plist inside 'com.apple.metadata:kMDItemWhereFroms' and the quaratine attribute in 'com.apple.quarantine'.
$ xattr -l Downloads/googlechrome.dmg com.apple.diskimages.fsck: |?W??\<!* ?#Z???r??u com.apple.diskimages.recentcksum: i:325165 on 3A5356B1-31CB-32FB-AFC7-DBE23A5C1547 @ 1334601060 - CRC32:$AE7BD4AF com.apple.metadata:kMDItemDownloadedDate: 00000000 62 70 6C 69 73 74 30 30 A1 01 33 41 B5 42 0E 78 |bplist00..3A.B.x| 00000010 17 F3 17 08 0A 00 00 00 00 00 00 01 01 00 00 00 |................| 00000020 00 00 00 00 02 00 00 00 00 00 00 00 00 00 00 00 |................| 00000030 00 00 00 00 13 |.....| 00000035 com.apple.metadata:kMDItemWhereFroms: 00000000 62 70 6C 69 73 74 30 30 A2 01 02 5F 10 3D 68 74 |bplist00..._.=ht| 00000010 74 70 73 3A 2F 2F 64 6C 2E 67 6F 6F 67 6C 65 2E |tps://dl.google.| 00000020 63 6F 6D 2F 63 68 72 6F 6D 65 2F 6D 61 63 2F 73 |com/chrome/mac/s| 00000030 74 61 62 6C 65 2F 47 47 52 4D 2F 67 6F 6F 67 6C |table/GGRM/googl| 00000040 65 63 68 72 6F 6D 65 2E 64 6D 67 5F 10 61 68 74 |echrome.dmg_.aht| 00000050 74 70 73 3A 2F 2F 77 77 77 2E 67 6F 6F 67 6C 65 |tps://www.google| 00000060 2E 63 6F 6D 2F 63 68 72 6F 6D 65 3F 26 62 72 61 |.com/chrome?&bra| 00000070 6E 64 3D 43 48 4D 41 26 75 74 6D 5F 63 61 6D 70 |nd=CHMA&utm_camp| 00000080 61 69 67 6E 3D 65 6E 26 75 74 6D 5F 73 6F 75 72 |aign=en&utm_sour| 00000090 63 65 3D 65 6E 2D 68 61 2D 6E 61 2D 75 73 2D 62 |ce=en-ha-na-us-b| 000000A0 6B 26 75 74 6D 5F 6D 65 64 69 75 6D 3D 68 61 08 |k&utm_medium=ha.| 000000B0 0B 4B 00 00 00 00 00 00 01 01 00 00 00 00 00 00 |.K..............| 000000C0 00 03 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 000000D0 00 AF |..| 000000d2 com.apple.quarantine: 0002;4f91d6f8;Safari;A89FCF40-0748-46BE-9C5E-1599A280E9D6Breaking down this string based on the description in:
/System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/LaunchServices.framework/Versions/A/Headers/LSQuarantine.h
- 0002: kLSQuarantineType (I think), one of:
- kLSQuarantineTypeWebDownload
- kLSQuarantineTypeOtherDownload
- kLSQuarantineTypeEmailAttachment
- kLSQuarantineTypeInstantMessageAttachment
- kLSQuarantineTypeCalendarEventAttachment
- kLSQuarantineTypeOtherAttachment
- 4f91d6f8: LSQuarantineTimeStamp, seconds since epoch timestamp in hex, print with 'date -r 0x4f91d6f8'
- Safari: kLSQuarantineAgentName, the name of the process that wrote the file, or whatever the process sets via the API.
- A89FCF40-0748-46BE-9C5E-1599A280E9D6: a UUID. The key (LSQuarantineEventIdentifier) used for entries in the SQLite DB.
$ sqlite3 /Users/auser/Library/Preferences/com.apple.LaunchServices.QuarantineEventsV2 sqlite> .dump PRAGMA foreign_keys=OFF; BEGIN TRANSACTION; CREATE TABLE LSQuarantineEvent ( LSQuarantineEventIdentifier TEXT PRIMARY KEY NOT NULL, LSQuarantineTimeStamp REAL, LSQuarantineAgentBundleIdentifier TEXT, LSQuarantineAgentName TEXT, LSQuarantineDataURLString TEXT, LSQuarantineSenderName TEXT, LSQuarantineSenderAddress TEXT, LSQuarantineTypeNumber INTEGER, LSQuarantineOriginTitle TEXT, LSQuarantineOriginURLString TEXT, LSQuarantineOriginAlias BLOB ); INSERT INTO "LSQuarantineEvent" VALUES('A89FCF40-0748-46BE-9C5E-1599A280E9D6',356650616.054473,'com.apple.Safari','Safari','https://dl.google.com/chrome/mac/stable/GGRO/googlechrome.dmg',NULL,NULL,0,NULL,'https://www.google.com/',NULL); CREATE INDEX LSQuarantineEventIndex ON LSQuarantineEvent ( LSQuarantineEventIdentifier ); COMMIT;Note the NULL fields, which are optional fields that can be filled in by the developer who writes the file. The OS writes LSQuarantineAgentNameKey, LSQuarantineAgentBundleIdentifierKey, and LSQuarantineTimeStampKey by default. Chrome adds LSQuarantineDataURLString and LSQuarantineOriginURLString. Apple said in the Leopard Launch Services release notes:
When the Launch Services API is used to open a quarantined file and the file appears to be an application, script, or other executable file type, Launch Services will display an alert to confirm the user understands the file is some kind of application. If the file is opened, the quarantine properties are automatically cleared by Launch Services if the user has write access to the file.So translating this to the Gatekeeper world, with the default settings Gatekeeper will block execution and fire an alert if:
- The file is opened with Launch Services (e.g. from the finder via user action, from another cocoa app, or as a mime handler). Excludes executables/installers run from the commandline, or programmatically via POSIX APIs. 'UnsafeExecutable' may play a role here (needs checking).
- The file has the quarantine xattr set.
- The file is not signed by apple or an apple developer cert.
/System/Library/CoreServices/CoreTypes.bundle/Contents/Resources/XProtect.plistto determine if the file is known-bad.
Subscribe to:
Posts (Atom)