krypted.com

Tiny Deathstars of Foulness

OpenBSM is a subsystem that has been installed on the Mac for some time. OpenBSM provides that ability to create and read audit logs based on the Common Criteria standards.

Audit Logs

The quick and easy way to see what OpenBSM is auditing is to cat the /etc/security/audit_control file:

cat /etc/security/audit_control

The output displays the directory of audit logs, as well as what is currently being audited. By default the configuration is as follows:

#
# $P4: //depot/projects/trustedbsd/openbsm/etc/audit_control#8 $
#
dir:/var/audit
flags:lo,aa
minfree:5
naflags:lo,aa
policy:cnt,argv
filesz:2M
expire-after:10M
superuser-set-sflags-mask:has_authenticated,has_console_access
superuser-clear-sflags-mask:has_authenticated,has_console_access
member-set-sflags-mask:
member-clear-sflags-mask:has_authenticated

You can then see all of the files in your audit log, using a standard ls of those 

ls /var/audit

As you can see, the files are then stored with a date/time stamp naming convention. 

20180119012009.crash_recovery 20180407065646.20180407065716 20180407073931.20180407074018
20180119022233.crash_recovery 20180407065716.20180407065747 20180407074018.20180407074050
20180119043338.crash_recovery 20180407065747.20180407065822 20180407074050.20180511030725
20180119134354.crash_recovery 20180407065822.20180407065853 20180511030725.crash_recovery
20180208172535.crash_recovery 20180407065853.20180407065928 20180616025641.crash_recovery
20180219133137.crash_recovery 20180407065928.20180407070004 20180624022028.crash_recovery
20180312153634.crash_recovery 20180407070004.20180407070036 20180718235941.crash_recovery
20180312160131.crash_recovery 20180407070036.20180407071722 20180720031150.crash_recovery
20180322141701.crash_recovery 20180407071722.20180407072215 20180724021901.crash_recovery
20180330190040.crash_recovery 20180407072215.20180407072259 20180728173033.crash_recovery
20180330191420.20180407064622 20180407072259.20180407073747 20180907031058.crash_recovery
20180407064622.20180407065616 20180407073747.20180407073836 20180911021141.not_terminated
20180407065616.20180407065646 20180407073836.20180407073931 current

The files are binary and so cannot be read properly without the use of a tool to interpret the output. In the next section we will review how to read the logs. 

Using praudit

Binary files aren’t easy to read. Using the praudit binary, you can dump audit logs into XML using the -x flag followed by the path of the log. For example, the following command would read a given log in the above /var/audit example directory:

praudit -x 20180407065747.20180407065822

One record of the output would look as follows

<record version="11" event="session start" modifier="0" time="Sat Apr 7 01:58:22 2018" msec=" + 28 msec" >
<argument arg-num="1" value="0x0" desc="sflags" />
<argument arg-num="2" value="0x0" desc="am_success" />
<argument arg-num="3" value="0x0" desc="am_failure" />
<subject audit-uid="-1" uid="root" gid="wheel" ruid="root" rgid="wheel" pid="0" sid="100645" tid="0 0.0.0.0" />
<return errval="success" retval="0" />
</record>

In the above output, you’ll find the time that an event was logged, as well as the type of event. This could be parsed for specific events, and, as an example, just dump the time and event in a simple json or xml for tracking in another tool. For example, if you’re doing statistical analysis for how many times privileges were escalated as a means of detecting a bad actor on a system.

You can also use the auditreduce command to filter records. Once filtered, results are still in binary and must be converted using praudit.

September 18th, 2018

Posted In: Mac OS X, Mac Security

Tags: , , , ,

Just some little one-liners to grab the version of a few common Apple services/built-in apps you might need the version of for another project I’m working on kinda’:
  • cups: cups-config –version
  • Finder: mdls -name kMDItemVersion /System/Library/CoreServices/Finder.app | cut -d ‘”‘ -f2
  • Help Viewer: mdls -name kMDItemVersion /System/Library/CoreServices/HelpViewer.app | cut -d ‘”‘ -f2
  • iBooks Author: mdls -name kMDItemVersion /Application/iTunes\ Author.app | cut -d ‘”‘ -f2
  • ical/Calendar: mdls -name kMDItemVersion /Applications/Calendar.app/ | cut -d ‘”‘ -f2
  • ichat/Messages: mdls -name kMDItemVersion /Applications/Calendar.app/ | cut -d ‘”‘ -f2
  • iMovie: mdls -name kMDItemVersion /Applications/iMovie.app | cut -d ‘”‘ -f2
  • installer: /usr/sbin/installer -vers
  • Photos/iPhoto: mdls -name kMDItemVersion /Applications/Photos.app | cut -d ‘”‘ -f2 
  • iTunes: mdls -name kMDItemVersion /Applications/iTunes.app | cut -d ‘”‘ -f2 
  • Java: /usr/bin/java -version
  • Keynote: mdls -name kMDItemVersion /Applications/Keynote.app | cut -d ‘”‘ -f2
  • macOS: sw_vers -productVersion
  • macOS Server: mdls -name kMDItemVersion /Applications/Server.app | cut -d ‘”‘ -f2
  • Mail: mdls -name kMDItemVersion /Applications/Mail.app | cut -d ‘”‘ -f2
  • mdnsresponder
  • Motion: mdls -name kMDItemVersion /Applications/Motion.app | cut -d ‘”‘ -f2
  • Numbers: mdls -name kMDItemVersion /Applications/Numbers.app | cut -d ‘”‘ -f2
  • Pages Required mdls -name kMDItemVersion /Applications/Pages.app | cut -d ‘”‘ -f2
  • Preview: mdls -name kMDItemVersion /Applications/Preview.app | cut -d ‘”‘ -f2
  • Quicktime: mdls -name kMDItemVersion /Applications/Quicktime\ Player.app | cut -d ‘”‘ -f2 quicktime_broadcaster No (Darwin Stream Server deprecated) N/A quicktime_darwin_mp3_broadcaster No (deprecated service) N/A quicktime_pictureviewer No (for QuickTime for Windows) N/A quicktime_streaming_server No (deprecated service) N/A
  • Remote Desktop: defaults read /System/Library/CoreServices/RemoteManagement/ARDAgent.app/Contents/version.plist CFBundleShortVersionString
  • Safari: mdls -name kMDItemVersion /Applications/Safari.app | cut -d ‘”‘ -f2 server_manager No (deprecated in 2006ish) N/A software_update tcp_ip_configuration_utility No (Laserwriter vuln from 2002) N/A terminal Required mdls -name kMDItemVersion /Applications/Utilities/Terminal.app | cut -d ‘”‘ -f2
  • Textedit Required mdls -name kMDItemVersion /Applications/TextEdit.app | cut -d ‘”‘ -f2
  • Transporter: /Applications/Xcode.app/Contents/Applications/Application Loader.app/Contents/itms/bin/itsmtransporter
  • Xcode: mdls -name kMDItemVersion /Applications/Xcode.app | cut -d ‘”‘ -f2
  • Xsan: /usr/sbin/cvversions
  • openSSL: openssl -version
  • Apache: httpd -v
If you notice, a lot of the built-in apps can be scanned with the same mdls command. There are certainly better ways for some, but when it comes to runtime cost, spotlight can respond quicker than a lot of other tools (other than purpose-built open source tools of course, who already have a smaller amount of data specific to the task). 3rd party software can be checked the same way. Let’s take Microsoft Outlook as an example:

mdls -name kMDItemVersion /Applications/Microsoft\ Outlook.app | cut -d ‘”‘ -f2

Additionally, Frameworks work a little differently. If I wanted to get the WebKit Framework version programmatically, I will need the system_profiler command along with the SPFrameworksDataType option. This will show me the version of WebKit, but strictly piping the output into grep won’t find the WebKit version. Instead I actually need to use an option I don’t use often with grep. Note that -A will allow you to define a number of lines to output following the pattern in question, so here I’m saying constrain my output to what you find that’s WebKit + the next ten lines, then constrain further for just the version number. 

system_profiler SPFrameworksDataType | grep -A10 WebKit: | grep Version

Anyway, more on all this soon.

September 13th, 2018

Posted In: Mac OS X, Mac Security

Tags: , , , , , ,

The Mac comes with a number of tools for querying version numbers of things like apps and operating systems. First, let’s look at operating systems. The quickest way to derive the version of an operating system would be 

sw_vers -productVersion

It then becomes trivial to pipe these into other language provided you can reach them from within a script. For example, if you import os into a python script, you can use the sw_vers command:

import os
os.system('sw_vers -productVersion')


Or to grab the version of the OS you could import a function just for that:

version = platform.mac_ver()

So in the following example, we’ll 

#!/usr/bin/python import sys, urllib, json, platform
if len(sys.argv) > 1: url = 'https://cve.circl.lu/api/search/apple/mac_os_x:{}'.format(sys.argv[1]) print([j['id'] for j in json.loads(urllib.urlopen(url).read().decode('utf-8'))]) else: version = platform.mac_ver() url = 'https://cve.circl.lu/api/search/apple/mac_os_x:{}'.format(version[0]) print([j['id'] for j in json.loads(urllib.urlopen(url).read().decode('utf-8'))])

This can be found at https://github.com/krypted/maccvecheck

So what might I want to do with it next? Well, you can also read the index of an app using mdls, using the -name option and the kMDItemVersion attribute, as follows for iTunes:

mdls -name kMDItemVersion /Applications/iTunes.app

And then you can lookup that up in the CVE database as well:

curl https://cve.circl.lu/api/search/apple/itunes:12.5

Or to merge the version check and the cve check:

curl -s https://cve.circl.lu/api/search/apple/itunes:`mdls -name kMDItemVersion /Applications/iTunes.app | cut -d '"' -f2`

Ultimately, Apple has a number of products that are tracked in the cve database and a library of each could easily be built and parsed to produce all cve hits encountered on a Mac. Obviously, you might not want to trust some random site from Luxembourg (those Luxembourgians are troublesome after all) and you can do this directly against the zip from NIST or create your own microservice that responds similarly to this site. 

Note: Special thanks to Yuresko for fixing my else statement.

September 12th, 2018

Posted In: Mac OS X, Mac Security

My session from MacTech 2017.

September 10th, 2018

Posted In: Mac OS X, Mac OS X Server, Mac Security

Tags: , , ,


Original comic borrowed from the classic: https://xkcd.com/149/

August 31st, 2018

Posted In: Mac OS X

Ever wonder what binaries have dependencies on a given binary? The otool command allows you to look up what dependencies a binary has, but there’s some extra work to get to reversing it. So looto.sh. 

https://github.com/krypted/looto
https://github.com/krypted/looto.git


August 22nd, 2018

Posted In: Mac OS X, Mac OS X Server, Mac Security

Tags: , , ,

In this article, we’ll cover how to use Zapier to connect data from your Jamf Account to a Google sheet. Once you build a WebHooks receiver in Zapier, you don’t have to use Google as the third party service that your WebHook triggers. You could use any other service that Zapier integrates as well, including Mailchimp, WordPress, Shopify, Todoist, ZenDesk, SurveyMonkey, Freshdesk, Quickbooks, Basecamp, and about 1,200 other solutions. In other words, you can link a WebHook from Jamf Pro into pretty much any automated service that you can think of!

So what’s a WebHook? A WebHook is an HTTP callback, or an HTTP POST that is fired when an event happens. The goal of WebHooks is that they are simple event notifications, typically sending a small amount of json to a destination web server that’s then ; a simple event-notification via HTTP POST. A web application listening for that event will then receive the WebHooks and perform a task in the background. Zapier is a great little tool that connects web apps. For modern software apps, most of this is done via acting as a WebHooks receiver and sending an API call to another tool. 

To follow along with this article, you will need a Zapier account, Jamf account and a Google account. Since we’ll be using Zapier to connect Jamf Pro and Google. 

Google Sheet Setup

  1. Signup/Login to your google account at https://docs.google.com/spreadsheets.
  2. Create new spreadsheet.
  3. Add any column names of fields you will want to store on your google sheet about your device—i.e. Date, Group, Name, Mac Address, IP Address, Make, Model, etc. We will use these columns in the Zap to map our data to the correct column.

Zapier Setup

  1. Signup/Login to your Zapier account at https://zapier.com
  2. Click “Make a Zap!” button in top right-hand corner.
  3. You will start my setting up the webhook for catching the smart group change.

Catching Smart Group Membership Change Zap

  1. Name your Zap
  2. Add Note (optional) – Optionally it might be good to add some details about what you zap does. You can do this by clicking the link “Add Note” under the name.
  3. Example Note:Catches POST from Smart Group Change Zap and gets the Id of the computer added and/or removed from the group, to get all the computer details and save to Google Sheet.
  4. Setup your trigger step. Choose Webhooks under Built-In Apps.
  5. Select Catch Hook.
  6. Continue pass the “Pick Off a Child Key” as there is nothing specific we need to select off the hook.
  7. Zapier will provide an URL to send requests to. This URL will need to be copied and pasted in your webhook settings in Jamf.
  8. Open up a new window to begin setup of Jamf webhook, leave this zap open as you will return to it.

Jamf Setup of Webhook

  1. After copying the URL from the zap. Open up a new window and login to your Jamf account.
  2. Click the cog in the top right corner and go to your settings.
  3. Under Global Management click on the Webhooks icon.
  4. Click “New” button.
  5. Add a Display Name.
  6. Check “Enabled”.
  7. Paste the URL from the previous zap to the Webhook URL input.
  8. Set Authentication Type to “None”
  9. Fill in your preferred connection and read timeout
  10. Set Content Type to “JSON”
  11. Select the Webhook event from the dropdown – Set to “SmartGroupComputerMembershipChange”
  12. Set up the target smart computer group. You can select a group or apply to all groups.
  13. Save and return to your Zapier window with your previous zap.

Catching Smart Group Membership Change Zap (continued)

  1. After completing setup of Jamf webhook. Click “Ok, I did this” to begin a test and pull in a test sample. Then return to your Jamf window and trigger the webhook. The webhook can be triggered in two ways.
    1. Trigger the webhook by going to Computers – > Search Inventory -> (Select a computer) -> Edit -> Update site to a new site that is in a different computer group and Save
    2. Trigger the webhook by going to Computers -> Smart Computer Groups – > (Select a Group) -> Update site to a new site that is in a different computer group and Save.
  2. If the event is triggered correctly you will see a test result/message like below:

  1. Next setup an action step. Select Code under Built-In Apps.
  2. Select “Run Javascript”
  3. Use the following Input Data Parameters
    1. eventName : Select “Event Name” from Field Options
    2. addedComputers: Select “Event Group Added Device Ids” from Field Options
    3. removedComputers: Select “Event Group Removed Device Ids” from Field Options
  4. In the code section. Copy and paste the following code:

** The highlighted url will be replaced by another url in a later zap.

var added = [];
var removed = [];
if(inputData.addedComputers) {
added = inputData.addedComputers.split(',');
}
if(inputData.removedComputers) {
removed = inputData.removedComputers.split(',');
}
 
var otherZapURL = "https://hooks.zapier.com/hooks/catch/3491337/wk7qh8/";
for(var i = 0; i< added.length; i++) {
var addedBody = JSON.stringify({
computer: added[i],
status: "added",
eventname:inputData.eventName
});
await fetch(otherZapURL, {method:'POST', body:addedBody});
}
for(var i = 0; i< removed.length; i++) {
var removedBody = JSON.stringify({
computer: removed[i],
status: "removed",
eventname:inputData.eventName
});
await fetch(otherZapURL, {method:'POST', body:removedBody});
}
return [{status: 'ok'}];

  1. This zap is done.

Saving Computer Details to Google Sheet

  1. Start a new zap.
  2. Add Note (optional) – Optionally it might be good to add some details about what you zap does. You can do this by clicking the link “Add Note” under the name.
  3. Example Note:Catches POST from Smart Group Change Zap and gets the Id of the computer added and/or removed from the group, to get all the computer details and save to Google Sheet.
  4. Setup your trigger step. Choose Webhooks under Built-In Apps.
  5. Select Catch Hook.
  6. Continue pass the “Pick Off a Child Key” as there is nothing specific we need to select off the hook.
  7. Zapier will provide an URL to send requests to. This URL will need to be copied and pasted in your previous zap in the code section where the highlighted url was listed.
  8. Setup an action step. Select Webhooks under “Built-In Apps”
  9. Select “GET” action type.
  10. Fill in the following input:
    1. URL : Copy and Paste https://kryptedjamf.jamfcloud.com/JSSResource/computers/id/(replace your kryptedjamf.jamfcloud.com with your role)
      1. Select “Computer” from field options
      2. See below as sample:

  1. Query String Params – leave blank
  2. Send As JSON – Select Yes
  3. JSON key – enter “json”
  4. Unflatten – Select Yes
  5. Basic Auth –separate your username and password with a pipe character
    1. i.e. USERNAME|PASSWORD
  6. Headers – leave blank
  1. Continue to through to Test Step and make sure data was received about the computer.
  2. If successful, continue to add a third action step by clicking the plus icon under you previous step and selection Action.
  3. Search for Google sheets in Search for Apps.
  4. Select Google Sheets and select the action type “Create Spreadsheet Row”.
  5. Connect your Google Account you used to create your Google sheet in the previous steps. See Google Sheets Setup section earlier in this document.
  6. Select Spreadsheet you set up under Spreadsheet input.
  7. Select the worksheet that has your columns names.
  8. After the worksheet is selected, each column will appear as an input option to map fields to. You will need to map each column to the appropriate field by selecting the field from the field options menu to the right of the input.
  9. After you’ve finished the mapping, select Continue to Test the step. If the test was successful, you should see your new record on your google sheet.
  10. Turn both of your zaps on and you are ready to automatically record all your smart group changes!

This was written for a specific use case, but because it’s useful for a number of apps and many of those can be hooked to other apps providing a nearly infinite number of use cases to link Jamf Pro Smart Group changes (one of the most valuable things that Jamf does) to other solutions!

 

August 17th, 2018

Posted In: JAMF, Mac OS X, Mac OS X Server

Tags: , , , , , ,

I’ve seen a few issues now where ApplePay and Health stopped working properly on a Mac and iOS device and when you fixed one, it seemed to wreck the connection with the other. Turns out that the information on a local system is managed with the new(ish) ckksctl command. Using ckksctl is pretty straight forward. First, let’s look at what’s on the Mac, using the ckksctl command with the status verb:

/usr/sbin/ckksctl status

There will be a section for ApplePay and another for Health. Here, if the services are configured, you should see the following in that section:

CloudKit account: logged in

Now, let’s force a pull of what’s in iCloud using the fetch verb:

/usr/sbin/ckksctl fetch

A successful sync will simply exit. However, that doesn’t mean that the keys are actually working. So if the issues persist, what we’re going to do is reset what’s in the local system and then pull the information from CloudKit again and show the status:

/usr/sbin/ckksctl reset; /usr/sbin/ckksctl status

Additionally, if you feel the local system is correct and the CloudKit data is incorrect then you could do the opposite and push a fresh config from the client to CloudKit:

/usr/sbin/ckksctl reset-cloudkit; /usr/sbin/ckksctl status

This has resolved issues I’ve seen. The status is also useful to track what a client has been configured to access. Please feel free to comment if you’ve had other experiences as I’ve found practically no information on this command.

August 10th, 2018

Posted In: cloud, Mac OS X, Mac Security

Tags: , ,

Migrating file services from a macOS Server to a macOS Client can be a bit traumatic at first. Mostly because the thought itself can be a bit daunting. But once you get started, it’s pretty simple. Mostly because there’s less to do. And that can be a challenge. While there are ways to hack together solutions for network homes and other more advanced features, if you’re doing that, then you’re missing a key point here. 

Let’s start by documenting our existing share points. We’ll do this with the serveradmin command and using the settings verb for the sharing service as follows:

sudo serveradmin settings sharing

Each share is an item in the sharePointList array, with the following:

sharing:sharePointList:_array_id:/Users/charles.edge/Public:nfsExportRecord = _empty_array sharing:sharePointList:_array_id:/Users/charles.edge/Public:smbName = “Charles Edge’s Public Folder” sharing:sharePointList:_array_id:/Users/charles.edge/Public:name = “Charles Edge’s Public Folder” sharing:sharePointList:_array_id:/Users/charles.edge/Public:afpIsGuestAccessEnabled = yes sharing:sharePointList:_array_id:/Users/charles.edge/Public:isIndexingEnabled = no sharing:sharePointList:_array_id:/Users/charles.edge/Public:dsAttrTypeNative\:sharepoint_group_id = “6C37A421-C506-4523-8769-1AF6EA245B68” sharing:sharePointList:_array_id:/Users/charles.edge/Public:mountedOnPath = “/” sharing:sharePointList:_array_id:/Users/charles.edge/Public:dsAttrTypeNative\:sharepoint_account_uuid = “C0405AE4-6CBE-40C7-9584-174687C80C07” sharing:sharePointList:_array_id:/Users/charles.edge/Public:path = “/Users/charles.edge/Public” sharing:sharePointList:_array_id:/Users/charles.edge/Public:smbIsShared = yes sharing:sharePointList:_array_id:/Users/charles.edge/Public:smbIsGuestAccessEnabled = yes sharing:sharePointList:_array_id:/Users/charles.edge/Public:afpName = “Charles Edge’s Public Folder” sharing:sharePointList:_array_id:/Users/charles.edge/Public:dsAttrTypeStandard\:GeneratedUID = “5C13E2AA-A86D-45D0-80B4-00CA86DE2253” sharing:sharePointList:_array_id:/Users/charles.edge/Public:smbDirectoryMask = “755” sharing:sharePointList:_array_id:/Users/charles.edge/Public:afpIsShared = yes sharing:sharePointList:_array_id:/Users/charles.edge/Public:smbCreateMask = “644” sharing:sharePointList:_array_id:/Users/charles.edge/Public:ftpName = “Charles Edge’s Public Folder”

Once you’ve removed the Server app, you’ll be left with using the sharing command. Using that command, you can list shares using the -l option:

sharing -l

That same share then appears as follows:

List of Share Points
name: Charles Edge’s Public Folder
path: /Users/charles.edge/Public
afp: {
name: Charles Edge’s Public Folder
shared: 1
guest access: 1
inherit perms: 0
}
smb: {
name: Charles Edge’s Public Folder
shared: 1
guest access: 1
read-only: 0
sealed: 0
}


Or from the Sharing System Preference Pane.

Now you just have to loop through and create each share (although they should co-exist between tools). To create a share, click on the plus sign under Shared Folders.

You can then browse to the folder you’d like to share. Next, we’ll give access to the directory. Use the plus sign on the right side of the screen and then select the user or group you’d like to add to the list that has access to the directory (while the directory is highlighted in the list on the left).

Once the user is in the list, use the permissions on the right side of the user list to select what level each user or group gets.

You have additional controls for file and folder security that can be set at either the directory that is shared or those below it hierarchically. To do so, highlight the directory and use the Get Info option under the File menu in the Finder.

Note: You can also check the Shared Folder box on these folders to share them, meaning you have one less step once you get used to the workflow!

April 25th, 2018

Posted In: Mac OS X

Tags: , , , , , ,

Awhile back, I wrote a tool to rewrap ipa files that I called ipasign: https://github.com/krypted/ipasign/blob/master/ipasign.py. But I wanted to do something similar for the Mac, and specifically have it run in Linux. So looking at what you’d need to be able to do, let’s start with viewing the contents of a flattened Apple package. This command will show you the files installed as a part of the Node JS package. Why did I choose that package? It was sitting on my desktop…

pkgutil --files org.nodejs.node.pkg

Now, this logic is available because you’re running pkgutil on a Mac. But that can’t run in Linux. So what would you do if you wanted to complete that same operation? If the package hasn’t been flattened then you can simply traverse the files in the package. If it has been flattened (and it must be in order to properly be signed) then that can’t work. So to see the files installed from a Linux system will require a tad bit more work. First, we’ll create a directly to extract our package into:

mkdir node-v8.11.1.pkg

Then cd into that directory and use xar to extract the package:

xar -xf /Users/charles.edge/Downloads/node-v8.11.1.pkg

In there, you’ll see three files: Bom, PackageInfo, and Payload. The contents, which mimic the –files option to some extent are found by first changing the name of payload to Payload.gz:

mv ./node-v8.11.1.pkg/Payload ./node-v8.11.1.pkg/Payload.gz

Then unzipping it:

gunzip Payload

And viewing the contents:

cpio -iv < Payload

Or throw all that into a one-liner:

cpio -o | gzip -c > Payload

You can also use bomutils to traverse and make BOMs: http://bomutils.dyndns.org/tutorial.html

You can also see some metadata about how the package will lay down by catting the distribution file:

<?xml version=”1.0″ encoding=”utf-8″ standalone=”yes”?>
<installer-gui-script minSpecVersion=”1″>
<title>Node.js</title>
<welcome file=”welcome.html”/>
<conclusion file=”conclusion.html”/>
<background alignment=”topleft” file=”osx_installer_logo.png”/>
<pkg-ref id=”org.nodejs.node.pkg” auth=”root”>
<bundle-version/>
</pkg-ref>
<pkg-ref id=”org.nodejs.npm.pkg” auth=”root”>
<bundle-version/>
</pkg-ref>
<options customize=”allow” require-scripts=”false”/>
<license file=”license.rtf”/>
<choices-outline>
<line choice=”org.nodejs.node.pkg”/>
<line choice=”org.nodejs.npm.pkg”/>
</choices-outline>
<choice id=”org.nodejs.node.pkg” visible=”true” title=”Node.js v8.11.1″>
<pkg-ref id=”org.nodejs.node.pkg”/>
</choice>
<pkg-ref id=”org.nodejs.node.pkg” version=”v8.11.1″ onConclusion=”none” installKBytes=”37377″>#node-v8.11.1.pkg</pkg-ref>
<choice id=”org.nodejs.npm.pkg” visible=”true” title=”npm v5.6.0″>
<pkg-ref id=”org.nodejs.npm.pkg”/>
</choice>
<pkg-ref id=”org.nodejs.npm.pkg” version=”v5.6.0″ onConclusion=”none” installKBytes=”20113″>#npm-v5.6.0.pkg</pkg-ref>

If you want to make a package, check out this gist: https://gist.github.com/SchizoDuckie/2a1a1cc71284e6463b9a.

Next up, you frequently want to check the signature of a package. So to see the signature, I can simply use: pkgutil if on a Mac:

pkgutil --check-signature org.nodejs.node.pkg

Or I can use codesign:

codesign -v node-v8.11.1.pkg

The beauty of codesign is that it’s been open sourced by Apple. The bummer about codesign is that it uses multiple CoreFoundation frameworks:

otool -L /usr/bin/codesign

/usr/bin/codesign:

/System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation (compatibility version 150.0.0, current version 1452.23.0)

/System/Library/Frameworks/Security.framework/Versions/A/Security (compatibility version 1.0.0, current version 58286.51.6)

/usr/lib/libc++.1.dylib (compatibility version 1.0.0, current version 400.9.0)

/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1252.50.4)

April 24th, 2018

Posted In: Mac OS X, Mac Security, Mass Deployment

Tags: , , , , , ,

« Previous PageNext Page »