krypted.com

Tiny Deathstars of Foulness

The next release of iOS (10.3), macOS (10.12.4), and tvOS (10.2) bring us a host of new management features. These include DEP configuration, remote wipe, single app mode, conference room mode, and remote reboot for Apple TVs. The next evolution of iOS brings us sounds in lost mode, the ability to prevent users from connecting to unmanaged wireless networks (just make sure to push that policy after sending down the actual managed wireless networks – or eek), the option to remotely shut down and reboot devices,

The Mac options includes some of the above but also restricting the feature to unlock macOS devices with Touch ID, restrict documents and desktop syncing with Apple’s iCloud service. Shared iPad environments also get new passcode policies.

Jamf Pro 9.98 has also comes with Symantec PKI integration and lots, and lots, and lots of resolutions to product issues. For more, see https://www.jamf.com/blog/are-you-ready-for-apples-next-release/. For a full run-down of profile options and MDM commands: http://docs.jamf.com/9.98/casper-suite/release-notes/What’s_New_in_This_Release.html.

Keeping with Apple’s evolving standards, Managed Preferences and Provisioning Profiles are being deprecated: http://docs.jamf.com/9.98/casper-suite/release-notes/Deprecations_and_Removals.html (which isn’t to say you can’t still deploy these kinds of things using your own scripts, etc).

Finally, if you have a problem in your environment and want to see if it’s been fixed, for a list of defects and product improvements – see http://docs.jamf.com/9.98/casper-suite/release-notes/Bug_Fixes_and_Enhancements.html

March 23rd, 2017

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

Tags: , , , ,

Leave a Comment

You search for items in macOS using compound conditions in a number of ways. One way is with awk. Here, we’re going to grab the output of a simple ls command. That gets piped into an awk statement. Then we’re going to look at the expression to evaluate. Basically, we’re going to say anything that contains com. as well as apple and .plist. Because it’s ls, we’re looking for names of files that match those patterns. Each pattern is listed in brackets. And then there’s the {print} to lay out the action of printing to the files that match the pattern to the screen:

ls |awk '/[com.][apple][.plist]/ {print}'

Note: I know you’re not supposed to use ls in scripts. Don’t care. If it were dates and such, I’d of used stat…

March 14th, 2017

Posted In: Mac OS X, Mac OS X Server

Tags: , , , ,

One Comment

If you happen to be tweaking the macOS subsystems for logging, I’ve put them into a little python class. If you need it, find it at this gist:

https://gist.github.com/krypted/495e48a995b2c08d25dc4f67358d1983

Could use an array of all the levels, TTLs, and options. But I’ll get to that when I get some time. If this is all you need, though:

class Logging(object):

__name__ = 'logger.info(1)'
plist = '/System/Library/Preferences/Logging/Subsystems/'

def __init__(__name__, plist, *args, **kwargs):
super(getLogger/, self).__init__()

logger.info('Input parameters:\n'
'accessibility: "{com.apple.Accessibility.plist}"\n'
'StandaloneHIDFudPlugins: "{com.apple.StandaloneHIDFudPlugins.plist}"\n'
'duetactivityscheduler: "{com.apple.duetactivityscheduler.plist}"\n'
'passkit: "{com.apple.passkit.plist}"\n'
'AppKit: "{com.apple.AppKit.plist}"\n'
'SystemConfiguration: "{com.apple.SystemConfiguration.plist}"\n'
'eapol: "{com.apple.eapol.plist}"\n'
'persona: "{com.apple.persona.plist}"\n'
'AppleIR: "{com.apple.AppleIR.plist}"\n'
'TCC: "{com.apple.TCC.plist}"\n'
'icloudpreferences: "{com.apple.icloudpreferences.plist}"\n'
'apple.pf: "{com.apple.pf.plist}"\n'
'AssetCache: "{com.apple.AssetCache.plist}"\n'
'TimeMachine: "{com.apple.TimeMachine.plist}"\n'
'internetAccounts: "{com.apple.internetAccounts.plist}"\n'
'photoanalysisd.graph: "{com.apple.photoanalysisd.graph.plist}"\n'
'AssetCacheServices: "{com.apple.AssetCacheServices.plist}"\n'
'Transport: "{com.apple.Transport.plist}"\n'
'libsqlite3: "{com.apple.libsqlite3.plist}"\n'
'photoanalysisd.job: "{com.apple.photoanalysisd.job.plist}"\n'
'BezelServices: "{com.apple.BezelServices.plist}"\n'
'accounts: "{com.apple.accounts.plist}"\n'
'locationd.Core: "{com.apple.locationd.Core.plist}"\n'
'photoanalysisd: "{com.apple.photoanalysisd.plist}"\n'
'DesktopServices: "{com.apple.DesktopServices.plist}"\n'
'amp.MediaServices: "{com.apple.amp.MediaServices.plist}"\n'
'locationd.Legacy: "{com.apple.locationd.Legacy.plist}"\n'
'pluginkit: "{com.apple.pluginkit.plist}"\n'
'ExchangeWebServices: "{com.apple.ExchangeWebServices.plist}"\n'
'authkit: "{com.apple.authkit.plist}"\n'
'locationd.Motion: "{com.apple.locationd.Motion.plist}"\n'
'sandbox.reporting: "{com.apple.sandbox.reporting.plist}"\n'
'FaceTime: "{com.apple.FaceTime.plist}"\n'
'avfaudio: "{com.apple.avfaudio.plist}"\n'
'locationd.Position: "{com.apple.locationd.Position.plist}"\n'
'sbd: "{com.apple.sbd.plist}"\n'
'Finder: "{com.apple.Finder.plist}"\n'
'awd.awdd: "{com.apple.awd.awdd.plist}"\n'
'locationd.Utility: "{com.apple.locationd.Utility.plist}"\n'
'securityd: "{com.apple.securityd.plist}"\n'
'HTTPServer: "{com.apple.HTTPServer.plist}"\n'
'awd.framework: "{com.apple.awd.framework.plist}"\n'
'mDNSResponder: "{com.apple.mDNSResponder.plist}"\n'
'sharing: "{com.apple.sharing.plist}"\n'
'IDS: "{com.apple.IDS.plist}"\n'
'bluetooth: "{com.apple.bluetooth.plist}"\n'
'mac.install: "{com.apple.mac.install.plist}"\n'
'siri: "{com.apple.siri.plist}"\n'
'IPConfiguration: "{com.apple.IPConfiguration.plist}"\n'
'calendar: "{com.apple.calendar.plist}"\n'
'mail: "{com.apple.mail.plist}"\n'
'social: "{com.apple.social.plist}"\n'
'ManagedClient: "{com.apple.ManagedClient.plist}"\n'
'captive: "{com.apple.captive.plist}"\n'
'mediaremote: "{com.apple.mediaremote.plist}"\n'
'socialpushagent: "{com.apple.socialpushagent.plist}"\n'
'Messages: "{com.apple.Messages.plist}"\n'
'catalyst: "{com.apple.catalyst.plist}"\n'
'multipeerconnectivity: "{com.apple.multipeerconnectivity.plist}"\n'
'symptomsd: "{com.apple.symptomsd.plist}"\n'
'MessagesEvents: "{com.apple.MessagesEvents.plist}"\n'
'cdp: "{com.apple.cdp.plist}"\n'
'network: "{com.apple.network.plist}"\n'
'syncdefaults: "{com.apple.syncdefaults.plist}"\n'
'NetworkSharing: "{com.apple.NetworkSharing.plist}"\n'
'clouddocs: "{com.apple.clouddocs.plist}"\n'
'networkextension: "{com.apple.networkextension.plist}"\n'
'useractivity: "{com.apple.useractivity.plist}"\n'
'ProtectedCloudStorage: "{com.apple.ProtectedCloudStorage.plist}"\n'
'coreanimation: "{com.apple.coreanimation.plist}"\n'
'networkserviceproxy: "{com.apple.networkserviceproxy.plist}"\n'
'Registration: "{com.apple.Registration.plist}"\n'
'coreaudio: "{com.apple.coreaudio.plist}"\n'
'nlcd: "{com.apple.nlcd.plist}"\n'
'SkyLight: "{com.apple.SkyLight.plist}"\n'
'coredata: "{com.apple.coredata.plist}"\n'
'notes: "{com.apple.notes.plist}"\n'

try:
plist()
except Exception as e:
logger.error(e)

March 13th, 2017

Posted In: Mac OS X

Tags: , , , , , , , ,

Leave a Comment

One of my favorite things about grabbing things with scripts is just how many ways (and sometimes how needfully or needlessly convoluted you can make them) to grab the same pieces of information. For example, something as simple as what hosts you use to resolve names on a Mac. There are a number of ways to grab what DNS server a device is using in macOS. So when you’re running a script you might choose to grab DNS information one way or another, according to what you’re after. Some of this might seem more complicated than it should be. And that’s correct…

resolv.conf

The /etc/resolv.conf file is updated automatically to look at what servers are used to resolve names used for DNS. The easiest way to see theses to simply cat it and grep for nameserver:

cat /etc/resolv.conf | grep nameserver

scutil

The next way we’ll grab DNS information is using scutil. Here, we use the –dns option, which outputs a lot of DNS stuffs, including all the built-in resolvers:

scutil --dns

To just grab the name servers:

scutil --dns | grep nameserver

We can also simplify the output to just the servers with awk:

scutil --dns | grep nameserver | awk '{print$3}'

networksetup

The second way is using networksetup. This command has an option to get a DNS server in (shocker) -getdnsservers. However, you have to list the interface for each. So below we’ll dump all interfaces into an array using -listallhardwareports and then read them in using a for loop and querying the name servers.

interfaces=( "$(networksetup -listallhardwareports | grep Hardware | cut -c 16-900)" )
for i in "${interfaces[@]}"
do
networksetup -getdnsservers $i
done

The one tricky thing in this one is I initially forgot to quote the interfaces as they went into the array, which meant each word of the interface was an item in the array and therefore the -getdnsservers option failed. Once I quoted, it was all happy. The other thing I can point out is I used cut instead of sed because it was easier to quote; however, it seems unlikely the name can be more than 890 characters, so I think it’s fine…

dig

You can also use dig. Here, you’ll query for a name without using an @ option, but omit everything but the line with the server that responded:

dig google.com | grep SERVER:

The output is kinda’ fug:

;; SERVER: 4.2.2.2#53(4.2.2.2)

For simpler output, we’ll use sed to constrain the output to just what’s between the parenthesis:

dig google.com | grep SERVER: | sed 's/^.*(//;s/)$//'

nslookup

nslookup is a tool similar to dig, used for querying names. We’ll basically do the same thing as above, just using awk as it’s just a standard position in a line:

nslookup google.com | grep Server: | awk '{print$2}'

system_profiler

Then there’s system_profiler, the command line interface for System Profiler. Here, we can query the SPNetworkDataType. This is going to produce a lot of output, so we can limit it to just the DNS servers using grep to constrain to just the lines we want and awk for just the columns in those lines, as follows:

system_profiler SPNetworkDataType | grep "Domain Name Servers:" | awk '{print$4}'

hosts

@knapjack added to use hosts. I had to use verbose mode to pull the local name server as follows:

host -v -t ns google.com | grep Received | awk '{print $5}'

ipconfig

Thanks to the lovely Allister (@sacrilicious), we also have ipconfig to add to the list:

/usr/sbin/ipconfig getpacket en0 2> /dev/null | grep name_ | cut -d' ' -f3-

There are tons of ways to find things in macOS. Do you have a way to find a DNS server that I didn’t think of here?

March 6th, 2017

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

Tags: , , , , , , ,

4 Comments

According to @johnkitzmiller, you can’t spell function without fun. So let’s have some fun! What’s a function? Think of it as a script inside a script. Define functions at the beginning of the script instead of making repeated calls to the same task within a script. The other nice thing about functions is that the act of compartmentalization makes them simple to insert into a number of different scripts. For example, if you do a lot of curl commands to pull down something in a lot of different scripts, having the grabbing of the data as a function, then the parsing of it into an array as a function and ultimately the writing of it or dealing with an stderr as another might make it simpler to then port it into the next script and the next.

Functions are simple to define. Just use (yes, you guessed it) the function command. So let’s look at the most basic function. Here, we’ll wrap a simple echo line inside curly brackets. So the syntax is function followed by the name of the function, followed by a curly bracket to introduce it. Then, I like to put a curly bracket on a line at the end of the function. Then I have a line where I just call the function. Note, there’s no special indicator, like a $ in front of the name of it or anything like that (unless you maybe variabalized it):

#!/bin/bash
function hellokitzy {
echo "Hello Kitzy"
}
hellokitzy

OK, so when you call it, it says hellokitzy. Obviously it could have nested if/thens, whiles, cases, etc. Now, let’s have two functions. In this example, we’ll basically just split the single echo statement into two; then call them in separate lines:

#!/bin/bash
function hello {
echo "Hello"
}
function kitzy {
echo "Kitzy"
}
hello
kitzy

As with shell scripts, you can also push a positional parameter into the function. Here, we pass a positional parameter into the script and it echos a hello to that parameter. You know, making our scripts a bit more personal and all… Then we call the function twice. In the first instance, we just pass the same parameter, but in the second, we actually replace it. We do this to show that the function overwrites the $1 inside that function, but if we did another call to the function we’d just get the original $1 as it doesn’t persist outside of the function:

#!/bin/bash
function term {
exit
}
function hello {
echo "Hello" $1
}
hello $1
hello all
echo "bye"
term

When run with a parameter of Kitzy, the above would simply output:

Hello Kitzy
Hello all
bye

That’s just for positional parameters that you’re feeding into a script though. If you have a variable (let’s call it a) and you update it in a function, then it will be the updated variable after the function. So in the following example, a echos out as two in the end:

#!/bin/bash
a=1
function quit {
a=2
exit
}
echo $a

Overall, functions are easy to use and make your code more modular. The only things that get a little complicated is that unless you know functions, you aren’t sure what’s going on in the beginning and when you are editing variables throughout the script you wanna’ make sure you know what changed things and when.

OK, now you – have fun with functions, and feel free to use the comments to post some you wrote!

February 28th, 2017

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

Tags: , , , ,

I’ve written about SQLite databases here and there over the years. A number of Apple tools and third party tools for the platform run on SQLite and it’s usually a pretty straight forward process to get into a database and inspect what’s there and how you might programmatically interact with tools that store data in SQLite. And I’ll frequently use a tool like Navicat to quickly and visually hop in and look at what happens when I edit data that then gets committed to the database.

But I don’t always have tools like that around. So when I want to inspect new databases, or at least those new to me, I need to use the sqlite3 command. First, I need to find the databases, which are .db files, usually stored somewhere that a user has rights to alter the file. For example,  /Library/Application Support/My Product. In that folder, you’ll usually find a db file, which for this process, we’ll use the example of Data.db.

To access that file, you’d simply run sqlite3 with the path of the database, as follows:

sqlite3 /Library/Application\ Support/My\ Product/Data.db

To see a list of tables in the database, use .tables (note that a tool like Postgress would use commands like /tr but in SQLite we can run commands with a . in front and statements like select do not use those):

.tables

To then see a list of columns, use .schema followed by the name of a table. In this case, we’ll look at iOS_devices, which tracks the basic devices stored on the server:

.schema iOS_devices

The output shows us a limited set of fields, meaning that the UDID is used to link information from other tables to the device. I like to enable column headers, unless actually doing an export (and then I usually do it as well):

.headers ON

Then, you can run a standard select to see what is in each field, which in the below example would be listing all information from all rows in the myapptable table:

select * from myapptable;

The output might be as follows:

GUID|last_modified|Field3|Field4
abcdefg|2017-01-26T17:02:39Z|Contents of field 3|Contents of field four

Another thing to consider is that a number of apps will use multiple .db files. For example, one might contain tables about users, another for groups, and another for devices in a simple asset tracking system. This doesn’t seem great at first, but I’ve never really judged it, as I don’t know what kind of design considerations they were planning for that I don’t know. If so, finding that key (likely GUID in the above example) will likely be required if you’re doing this type of reverse engineer to find a way to programmatically inject information into or extract information out of a tool that doesn’t otherwise allow you to do so.

February 24th, 2017

Posted In: Mac OS X, SQL

Tags: , , , , , , , , ,

To tell curl that you can read and write cookies, first we’ll start the engine using an empty cookie jar, using the -b option, which always reads cookies into memory:

curl -b newcookiejar http://krypted.com

If your site can set cookies you can then read them with the -L option

curl -L -b newcookiejar http://krypted.com

The response should be similar to the following:

Reading cookies from file

Curl also supports reading cookies in from the Netscape cookie format, used by defining a cookies.txt file instead:

curl -L -b cookies.txt http://krypted.com

If the server updates the cookies in a response, curl would update that cookie in memory but unless you write something that looks for a new cookie, the next use will read the original cookie again.

To create that file, use the -c option (short for –cookie-jar) as follows:

curl -c cookie-jar.txt http://krypted.com

This will save save all types of cookies (including session cookies). To differentiate, curl supports junk, or session cookies using the –junk-session-cookies options, or -j for short. The following can read these expiring cookies:

curl -j -b cookie-jar.txt http://krypted.com

Use that to start a session and then that same -c to call them on your next use. This could be as simple as the following:

CURL=/usr/bin/curl
COOKIEJAR=cookie-jar.txt
SITE=http://krypted.com
$CURL -j -b $COOKIEJAR $site

You can also add a username and password to the initial request and then store the cookie. This type of authentication and session management is used frequently, for example in the Munkireport API, as you can see here:

For converting, the -b detects if a file is a Netscape formatted cookie file, parses, then rewrites using the -c option at the end of a line:

curl -b cookie.txt -c cookie-jar.txt http://krypted.com

February 20th, 2017

Posted In: Mac OS X, Mac Security

Tags: , , , , , ,

You can quickly and easily back up your Filewave databases using the fwcontrol command to stop a Filewave server (thus preserving the integrity of the data you are backing up) and then backing up the database using the /fwxserver directory.

To get started, we’ll first down the server. This is done using the fwcontrol command along with the server option and the stop verb, as follows:

sudo fwcontrol server stop

Now that there won’t be data trying to commit into the database, let’s make a backup of the database directory using the cp command:

cp -rp /fwxserver/DB ~/Desktop/Databasebak

To start the database, use the decontrol command with the server option and the start verb, as follows:

fwcontrol server start

Note, if you will be moving to a new Filewave server, you would want to lock clients during this transition, so before restarting your server, use the sqlite3 command to set the status to 1 in the user table:

sqlite3 /fwxserver/DB/server.sqlite 'update user set status = 1;'

February 15th, 2017

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

Tags: ,

So I comment a lot of lines out in my /etc/hosts file. This usually means that I end up with a lot of cruft at the top of my file. And while I write comments into files and scripts here and there, I don’t always want to see them. So I can grep them out by piping the output of the file to grep as follows:

cat /etc/hosts | grep -v "^#"

You could also do the same, eliminating all lines that start with a “v” instead:

cat !$ | grep -v "^v"

February 13th, 2017

Posted In: Mac OS X, Unix

Tags: , , , , , ,

I originally wrote this back in 2015 as an article for troubleshooting APNs traffic on a Profile Manager server. But it turns out that troubleshooting push notification communications between macOS Server and Apple’s Push Notification is basically the same as troubleshooting the apsd client on macOS. Basically, we’re gonna’ put the APNs daemon, apsd, into debug mode. To enable APNS debug logging, run these commands:

defaults write /Library/Preferences/com.apple.apsd APSLogLevel -int 7
defaults write /Library/Preferences/com.apple.apsd APSWriteLogs -bool TRUE
killall apsd

Then use tail -f to watch the apsd.log file at /Library/Logs/apsd.log. Be wary, as this can fill up your system. So to disable, use these commands:

defaults write /Library/Preferences/com.apple.apsd APSWriteLogs -bool FALSE
defaults delete /Library/Preferences/com.apple.apsd APSLogLevel
killall apsd

February 9th, 2017

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

Tags: , , , ,

Next Page »