jump to navigation

Brother Love September 3, 2009

Posted by bigmaconcampus in Rhinoism.
Tags: ,
add a comment

While observing her brothers hug after beating a video game…

Rhino: “Brother love…. I’ll never know it.”

Advertisements

Wireless Installer – The Next Generation August 27, 2009

Posted by bigmaconcampus in Mac Tech.
Tags: , , , , , , , , , , , , , , , , , , , , ,
25 comments

Ok, after originally posting the code for my wireless installer, I’ve updated the code earlier in the summer and keep promising to post an update. Without further adieu, here it finally is.

*NOTE* 9/29/09
There were some errors in the applescript sections of the original post. These should be correct now. Oops.

*NOTE* 12/21/09
Gave up fighting wordpress to display the code correctly so that it would compile correctly if someone copy/pasted it. Now have a direct link to download the working files at the bottom of this post. Sorry for the delay/problems.

Intro
Since I couldn’t remember specifically what I changed (several bug fixes, some major, some minor), I’ll re-post the entire thing here. It has been tested on over 1700 Macs since the beginning of June 2009, so I consider it fairly solid at this point.

There was an entire section redone in C code since there were certain APIs that could only be addressed that way. This was also the ONLY piece that was a reminant of a GUI based version I’d made a year beforehand. Now, all command line, YEAH. (Thanks Kim!) Also, now moves the newly added wireless network to the top of the preferred list so connection time is quicker (noticed that with users that had 20+ wireless networks, adding it to the end of the list resulted in several minute long connection times).

The only issues I’ve run into is that on occasional runs, the installer will not pickup the wireless username correctly (the main script thinks that the wireless username is blank). I haven’t been able to narrow down what causes it directly (I think it has to do with running the installer partially and quitting at a certain spot, which must be leaving some clutter behind, but haven’t directly proved this yet), but have added code to recognize the problem and exit with an error. Most times, running the installer a second time will work fine. (If anyone happens to figure it out, please let me know in the comments)

The other small issue shows about one in a hundred runs and I consider it an applescript bug. Sometimes the portion that is applescript won’t allow the user to type in the dialog box. A reboot solves this behavior.

This installer basically works the same as before, it is crammed into a PackageMaker .pkg file and runs as a postscript to perfom the setup. The beauty of this is that it can be posted on a website for the user’s to run themselves and doesn’t require a tech to setup their wireless for them. (Makes our lines MUCH shorter). If you are confused by any of the details, refer to the previous post for a deeper description of some portions.

It’s in several scripts in several different languages (Four in all I think, we almost had some perl in it, but I’m a Bash junkie and got it to work in less lines in Bash :P )

Change Log

July 2009
Version 3.6
Fixed bug that caused a blank wireless username in certain situations
Fixed bug with a ‘space’ in the Mac password
Wireless network is now added in the top location of preferred networks to enable faster connection
Added more error codes
Added better error descriptions
Added ‘retry counter’ to dialogs
Lowered number of retries from five to three

April 2009
Version 3.5
Rebuilt Keychain creation mechanism in C to solve several bugs centering around creation of ACL of Keychain and Assistive Devices settings.
Added Mac OS X 10.6 enhancements
Increased speed of installer
Added second wireless password test in case of system outage

March 2009
Version 3.1
Made compatible with Mac OS X 10.6 (Snow Leopard)
Added several exceptions for MacBook Air hardware types due to lack of ethernet port
Streamlined method of fixing certain symbol characters in passwords
Fixed bug with toggling Assistive Devices settings
Modified handling of certain preference files and previous Enterprise level network setups
Added steps to handle a blank Mac Password
Added error code for a corrupt login.keychain that cannot be unlocked

Final Important Info
After wrestling with WordPress attempting to get the code posted correctly, I’ve given up and decided to instead post a link to download the working files so that anyone interested can just download the pieces and package it themselves.

There are three applescripts, used to obtain and test usernames and passwords, and cleanup Keychain Items, that are called by the Main Script. These feed back the variables for username and password to the parent script.

The Mac password cannot be blank (I wouldn’t recommend a user have a blank password anyway) nor can it contain a space (causes problems with the script).

Some items in remove_keychain_items.scpt need to be edited manually (Names of keychain items). Also, if the keychain is locked with a different password than the main user account password, the script will error at this step.

C Programming Section:
This section replaced the part that would actually set the access level for the wireless to get to the keychain item. Before it used GUI Applescript and relied on Assistive Devices to be able to click a single ‘OK’ button. Using C to create the keychain item and set the ACL to allow the eapolclient to access the keychain fixes the issues with doing it the previous way.

This C code should be compiled for both Intel and PowerPC separately and the resulting files should be named:
AddKeychainItem_Intel
AddKeychainItem_PowerPC

The parent script determines the processor type and will run the appropriate version of the executable.

You would need to do a find/replace in this section of code for wirelessnetworkname and put in the name of your particular wireless network.

Download working files
Wireless Installer

Hopefully the new and improved version (which is still not 100% complete, but getting closer) will help someone out there. If so, drop a comment.

But who would be the Best Man? August 25, 2009

Posted by bigmaconcampus in Rhinoism.
Tags: , , , ,
1 comment so far

While making lasagna with Rhino one evening, I let her take a nip at the mozzarella and she commented:

“Mmmmmm, I’m going to have to marry that cheese some day.”

Windows OS installer for Mac August 20, 2009

Posted by bigmaconcampus in Mac Tech.
Tags: , , , , , , , , , , , , , , , , , , ,
add a comment

As part of a group of installers I’ve developed for our University, the one that I thought would be the most difficult, but turned out to be the easiest was the one that will install a Windows OS as a dual-boot on the Mac.

This is not necessarily a fully automated method (like I would use in a lab situation), but rather an easy to use installer that can be posted on a intranet website for student (primarily students), faculty, employee use. It allows us to put Windows on Macs that are not our property and therefore we don’t have admin rights on the machine.

This is a flat-package (.pkg) that contains the necessary scripts to download a Windows image (created with Winclone) via curl, partitions the hard drive (35 GB partition) and then clones the downloaded image onto the second partition that was just created. All the user does is click a few buttons and the installation is fully automated. The installer package is relatively small at around 1 MB. The heavy lifting is done by the script downloading the image file to a /tmp location during the installation.

With the second version, an overlay window was added (using iHook) that allows a progress bar to give the user some feedback as to the status of the installation. We found some people were getting impatient and shutting off their computers thinking that the installation had frozen (Total time for this part was about 20-30 minutes), which was necessitating the need for better user feedback.

Also found that the image for Windows Vista needed to be sysprepped to function with all the varying Apple hardware. Unfortunately, this doubles the installer time. Sysprep takes about 20-30 minutes to do it’s thing. And reboots several times as well. But it is worth it to have a single image work on the varying Apple hardware. The image also had to move through the various hardwares starting from oldest to newest to load all of the bootcamp drivers. Doing it in a different order tended to kill Vista. Hopefully things will be smoother with Windows 7.

We have plans to make the third version use a bit torrent to download the image rather than curling the file from a single webserver. The beating the server takes during student setup workshops is heavy (20-50 user’s all trying to download the same 6.5 GB file at the same time). Switching to a torrent based download should relieve the server strain and speed up the download time for the clients when a large number run it simultaneously.

Here are the main scripts that performs all the tasks. It is kicked off as a postscript from a Packagemaker flat-package that is downloaded from a internal website (on purpose to keep the rest of the world from being able to access it). The package includes the Winclone command-line pieces necessary for cloning, but not the actual image file. That is downloaded separately by the script. iHook is also included in the package for the feedback.

Postscript for Package

#!/bin/sh
PATH=/bin:/usr/bin:/sbin:/usr/sbin export PATH

### This postinstall script will kick start the actual Vista
### Installer script and Feedback window to show progress

/private/tmp/foo/iHook/iHook.app/Contents/MacOS/iHook --no-titlebar --script=/private/tmp/foo/windowsvista/vista_installer.sh

ERROR=`grep ERROR /Library/Logs/Vista_Installer_For_Mac.log | cut -c 1-6`
if [ "$ERROR" != "" ]; then
rm -rf /tmp/clemson
$ERROR
fi

exit 0

The first line engages the main script. The ERROR section is just a test for any errors that might have occurred so that the installer will error properly if there was an error deeper in the other script. Found it was the easiest way to communicate between the installer app, iHook, and the nested scripts. The installer has a tendency to exit successful even when an error occurs if this part is left out.

Main Script referred to in the previous postscript that is run by iHook (vista_installer.sh):

#!/bin/sh
PATH=/bin:/usr/bin:/sbin:/usr/sbin export PATH

### Script created by Bryan Lee,
### April 2008.
### Modified November 2008 for new Apple hardware and
### to add the feedback mechanism.
###
### This postinstall script downloads the Windows image files
### in the proper temp directory and sets the correct permissions.
### Then partition the hard drive into 2 partitions. Finally, clone
### the Windows image onto the 2nd partition.
###
### iHook is used to give feedback to the user during the process.
###
### Requires iHook be installed in the /tmp directory
### Requires Winclone.perl be modified to redirect stderr to
### PROGRESS_FILE path during the restore process
### like the following example:
###
### do_command("=====restoring image======","/usr/bin/gunzip -c \
### "${image_dir}/boot.img.gz\"| \"$ntfstools_dir/ntfsclone\"
### --restore-image --overwrite \"$ntfs_partition\" - 2>&1 >
### /private/tmp/foo/windowsvista/winclone_progress.txt");
###
### Depends on Package installer to download Windows image file
### to /tmp directory
###

# Setup Location of Log file
LOG="/Library/Logs/Vista_Installer_For_Mac.log"

# Setup initial state for iHook Window
echo "%LOG OPEN" $LOG
chmod a+r $LOG
echo "%BECOMEKEY"
# echo "%TITLE Windows Vista Installer for Macintosh"
echo "%WINDOWLEVEL HIGH"
echo "%WINDOWSIZE 800 600"
echo "%WINDOWPOSITION CENTER"
echo "%WINDOWZOOM ENABLE"
echo "%HIDETIMER"
echo "%BACKGROUND /private/tmp/foo/iHook/windowsvistaformac_background.jpg"
echo "%BACKGROUNDSCALING TOFIT"

### Cleanup any possible files leftover from a previous run of the installer
### that would cause issues if present
rm -rf /private/tmp/foo/windowsvista/boot.img.gz
rm -rf /private/tmp/foo/windowsvista/winclone_progress.txt

### Set initial blank variables
PROGRESS=""
IHOOK_PERCENT=""
DOWNLOAD_PERCENT=""
PREVIOUS_FILE_SIZE=""
CURRENT_FILE_SIZE=""
KILL_CURL=""
SECOND_PARTITION_NAME=""

#####################
### FUNCTIONS ###
#####################

# Function for making computer beep three times
BEEP_THREE_TIMES ()
{
LIMIT=3 # Upper limit
a=0
while [ $a -le "$LIMIT" ]; do
a=$(($a+1))
echo "%BEEP"
sleep .5
done
}

### Set PID of iHook (to kill) in case of error
KILL_IHOOK=`ps acx | grep iHook | cut -c 1-5`

### Must set the size of this variable to the size of the image file in Kilobytes
### Using the following command on the image directory
### ls -sk | grep total | cut -c 7-15
### Current values for Vers2 is 6734820. Round down to the nearest MB
TOTAL_SIZE="6734000"

### Must set the path to the file that contains the progress from Winclone
PROGRESS_FILE="/private/tmp/foo/windowsvista/winclone_progress.txt"

#####################
### Initial tests ###
#####################

### Test for Processor type ###
HARDWARETYPE=`system_profiler -detailLevel mini | grep "Processor Name" | awk '{ print $3 }' `
if [ "$HARDWARETYPE" != "Intel" ]; then
BEEP_THREE_TIMES
echo "%WINDOWLEVEL NORMAL"
echo "exit 9, ERROR: Computer Hardware Cannot support Windows"
osascript -e "tell application \"iHook\" to activate"
osascript -e "tell application \"iHook\" to display dialog \"This computer does not support running Windows because is does not have an Intel Processor.\" & return & return & \"This installation will now exit with an error.\" buttons {\"OK\"} default button 1 with icon caution with title \"Windows Vista Installer for Mac\""
osascript -e "tell application \"Installer\" to activate"
kill $KILL_IHOOK
exit 9
fi

# Check to see if a second partition already exists, or some other odd situation
SECOND_PARTITION_NAME=`df | grep /dev/disk0s3`
if [ "$SECOND_PARTITION_NAME" != "" ]; then
BEEP_THREE_TIMES
echo "%WINDOWLEVEL NORMAL"
echo "exit 8, ERROR: Multiple Partitions Exist"
osascript -e "tell application \"iHook\" to activate"
osascript -e "tell application \"iHook\" to display dialog \"Multiple Partitions Already Exist\" & return & \"This installer can not be run on this system without removing the secondary partition\" & return & return & \"Please contact Jenny at 867-5309.\" & return & return & \"This installation will now exit with an error.\" buttons {\"OK\"} default button 1 with icon caution with title \"Windows Vista Installer for Mac\""
osascript -e "tell application \"Installer\" to activate"
kill $KILL_IHOOK
exit 8
fi

### DOWNLOAD STAGE 1 ###

# Start Progress Bar for Downloading Image
echo "%BEGINPOLE"
echo "Downloading Windows Image"

### Change directory to the Windows temp directory created by the installer
### and set the current file size variable

cd /private/tmp/foo/windowsvista/
CURRENT_FILE_SIZE=$(ls -sk | grep total | cut -c 7-15)

### Download image needed for Windows imaging from the Web server
echo "Starting Download of Windows image"
curl -O http://www.foo.edu/windows/vista/version2/boot.img.gz &

### Loop to update download progress constantly until complete
until [ "$CURRENT_FILE_SIZE" -ge "$TOTAL_SIZE" ]; do
sleep 7
DOWNLOAD_PERCENT=`echo "($CURRENT_FILE_SIZE * 100) / $TOTAL_SIZE" | bc`
echo "%$DOWNLOAD_PERCENT"
echo "Download Is $DOWNLOAD_PERCENT Percent Complete"
CURRENT_FILE_SIZE=$(ls -sk | grep total | cut -c 7-15)
if [ "$PREVIOUS_FILE_SIZE" = "$CURRENT_FILE_SIZE" ]; then
BEEP_THREE_TIMES
echo "%ENDPOLE"
echo "%WINDOWLEVEL NORMAL"
echo "exit 1, ERROR: Image file did not download successfully"
osascript -e "tell application \"iHook\" to activate"
osascript -e "tell application \"iHook\" to display dialog \"An error has occurred while attempting to download the Windows Image File.\" & return & return & \"Please verifiy your network connection and try the installation again.\" & return & return & \"This installation will now exit with an error.\" buttons {\"OK\"} default button 1 with icon caution with title \"Windows Vista Installer for Mac\""
osascript -e "tell application \"Installer\" to activate"
KILL_CURL=`ps acx | grep curl | cut -c 1-5`
kill $KILL_CURL
kill $KILL_IHOOK
exit 1
fi
PREVIOUS_FILE_SIZE=$CURRENT_FILE_SIZE
done

echo "%100"
echo "Download Is 100 Percent Finished"
sleep 2

echo "%ENDPOLE"

### Set correct permissions on script files

chmod u+rwx /private/tmp/foo/windowsvista/winclone.perl
chmod u+rwx /private/tmp/foo/windowsvista/gptrefresh
chmod u+rwx /private/tmp/foo/windowsvista/ntfsclone
chmod u+rwx /private/tmp/foo/windowsvista/ntfscp
chmod u+rwx /private/tmp/foo/windowsvista/ntfsresize
chmod u+rwx /private/tmp/foo/windowsvista/size
chmod u+rwx /private/tmp/foo/windowsvista/BCD
chmod u+rwx /private/tmp/foo/windowsvista/boot.mbr
chmod u+rwx /private/tmp/foo/windowsvista/partitionid
chmod u+rwx /private/tmp/foo/windowsvista/description
chmod u+rwx /private/tmp/foo/windowsvista/vista_installer.sh

### PARITIONING STAGE 2 ###

### Properties ###
#
# These items must be modified to suit your environment before
# implementing this script! You do not need to make any other
# modifications to this file than these properties.
# Note: the target disk is determined programatically by finding
# the internal drive that is already partitioned using the GPTFormat
# If you have multiple drives (physical drives, not partitions)
# attached to your client machines that are partitioned using the
# GPTFormat, you will need to specify the target disk manually.

echo "Partitioning Drive. Please be patient."
sleep 2

# Partition the internal disk that is already using the GPT partitioning scheme
tdisk=`diskutil list | awk '/GUID_partition_scheme/ {print $NF}'`
totalSize=`df -m | awk "/$tdisk/"' {total+=$2} END {print total}'`
macSize=$(($totalSize - 35000))
diskutil resizeVolume /dev/$tdisk"s2" ${macSize}M MS-DOS WINDOWS 0b

### Check to see if 2nd parition was created
SECOND_PARTITION_NAME=`df | grep /dev/disk0s3 | grep "WINDOWS"`

if [ "$SECOND_PARTITION_NAME" = "" ]; then
BEEP_THREE_TIMES
echo "%WINDOWLEVEL NORMAL"
echo "exit 2, ERROR: Paritioning failed"
osascript -e "tell application \"iHook\" to activate"
osascript -e "tell application \"iHook\" to display dialog \"Partitioning was not successful! \" & return & return & \"Possible causes include: \" & return & \"More than one partition already exists\" & return & \"An external hard drive is connected\" & return & \"A rare issue with the Partition Map of the hard drive\" & return & return & \"Please try installation again or contact Jenny at 867-5309.\" & return & return & \"This installation will now exit with an error.\" buttons {\"OK\"} default button 1 with icon caution with title \"Windows Vista Installer for Mac\""
osascript -e "tell application \"Installer\" to activate"
kill $KILL_IHOOK
exit 2
fi

echo "Partitioning Completed Successfully"
sleep 1

### CLONING STAGE 3 ###

# Start Progress Bar for Cloning
echo "%BEGINPOLE"
echo "Cloning Process Is Starting"
sleep 1
### Begin the Windows cloning process onto the 2nd partition

/private/tmp/foo/windowsvista/winclone.perl --self-extract &

### Find initial progress from the winclone output
touch $PROGRESS_FILE
PROGRESS=$(tail -1 $PROGRESS_FILE)

### Loop to keep temp file location from showing in feedback window
LIMIT=14 # Upper limit
a=0

while [ $a -le "$LIMIT" ]
do
a=$(($a+1))
echo "Cloning Operation Is Starting"
sleep .5
done

### Loop to update cloning progress constantly until complete
until [ "$PROGRESS" = '100.00 percent completed' ]; do
IHOOK_PERCENT=$(tail -1 $PROGRESS_FILE | cut -c 1-3)
echo "%$IHOOK_PERCENT"
echo "Cloning Operation Is $IHOOK_PERCENT Percent Complete"
PROGRESS=$(tail -1 $PROGRESS_FILE)
sleep 3
done

echo "%100"
echo "Cloning Operation Is 100 Percent Finished"
sleep 5

echo "%ENDPOLE"
echo "Finishing Installation"
sleep 5

echo "Installation of Windows Vista completed"
sleep 5

echo "Cleaning up installation files"
sleep 5

rm -rf /private/tmp/foo
echo "Installation Completed Successfully"
sleep 2

exit

The script checks for Intel-processor, that the initial state has only one partition, that the download completes, and that partitioning was successful or else gives an error dialog and then exits.

There are two odd glitches that occur about 1 in 100 installations, both dealing with partition map issues.

The first will cause the partitioning stage to error. Seems that on the occasional Mac, there is a small error in the partition map that doesn’t rear it’s ugly head until you attempt to change the partitions. The only fix seems to be to boot from a Disk Warrior CD and rebuild. Then the installer will run fine.

The second issue is a little more frustrating and is documented by Apple. The installation will finish without any problems, but upon the first boot while holding down the ‘option’ key, the Mac won’ recognize that the Windows partition is bootable. The Startup Disk Panel will show it, all the files are on the second partition, but the Mac refuses to boot to it. Sometimes removing the partition and re-running the installer will work, sometimes not. Doing a manual clone using Winclone will usually work. Apple’s suggestion is to erase the partition and start over.

Hope this helps someone out there with any deployment problems or if they are just looking for ideas.

Reset Mac Password the Easy Way July 5, 2009

Posted by bigmaconcampus in Mac Tech.
Tags: , , , , , , , ,
247 comments

*** Please Note!!! ***

The instructions in the main post are for Mac OS X 10.5 and 10.6. If you are using Mac OS X 10.7 or higher, you can just reboot and hold down the “R” key while it reboots to enter recovery mode. Then open the terminal and type “resetpassword” to use the password reset utility. Much easier than everything you will read in the post below. Now returning to your ancient post, already in progress…

*** Original Post ***

We are swimming in the middle of summer workshops at our University. We do these a couple of times a week and the purpose is to help introduce the new, incoming students to University specific systems, setup wireless for the school and install software. We even offer Windows for the few that might want it. All this in less than 2 hours.

A good time is had by all…

One of the problems we run into regularly is the one in 50 students that either can’t remember their Mac password (even though we ask them to try and guess it about 10 times). Or better yet, the parental units, being helpful, did the original setup for the child they love instead of letting them gain some independence and do it themselves, thereby screwing them over in their first college experience. But I digress.

When we run into this situation, we need to reset their password quickly and painlessly. Not always having installation discs handy, we resort to doing it in Single-User mode.

To do this, reboot the computer holding down the command (Apple symbol on older Macs) and ‘S’ key at the same time. After about 10 seconds or so, you’ll see a very Unix-y OS loaded. You may want to hit return a couple of times to make sure it has finished loading.

WARNING: Doing the next part will cause you to lose any saved passwords in your Keychain. If you are locked out of the Mac anyway, you really have nothing to lose though.

At this point, you have booted the computer as root and need to run the following commands:

mount -uw /

launchctl load /System/Library/LaunchDaemons/com.apple.DirectoryServices.plist

ls /Users (to get the username to reset if you do not know it)

passwd username (username being the username you are resetting)

reset password (password being the new password)Sorry, realized the wording was confusing. Just type the new password and press return (nothing will show on screen while you are typing. You will need to enter it a second time to verify and ward off typos.

rm -rf /Users/username/Library/Keychains/login.keychain

reboot

After the computer reboots, you should be able to login using the new password now. Be aware, that the system will create a new login.keychain for you with no passwords in it. You can force this creation immediately by opening Safari.

p.s. This method only works on Leopard 10.5.x. or higher.

iPhone Sent Items Issue with Entourage 2008 July 2, 2009

Posted by bigmaconcampus in Mac Tech.
Tags: , , , , , , , ,
1 comment so far

UPDATE 8-20-2009:
Seems that the iPhone OS 3.1 update fixed this issue. So the following info might be moot at this point.

Ever since using my iPhone with Exchange (since the iPhone 2.0 Beta program), I’d had an issue with how the Sent Items from the iPhone device show in the Exchange Sent Items when viewed from Entourage 2008 (think it’s a problem with Entourage 2004 also, if I’m remembering correctly). Messages that are sent, show with no subject and the message content displays in HTML code or MIME encoded making it unreadable by the user.

After originally blaming the iPhone for this new behavior at the time (issue wasn’t present when connecting to Exchange via IMAP), I narrowed it down to an issue between ActiveSync and Entourage (wonderfully, both being Microsoft Products). I’ve since seen the issue with a Palm Treo running Windows CE that also uses ActiveSync to connect to Exchange and the user uses Entourage 2008.

Anyway, never having seen the problem fixed, about a year ago I came up with a work-around to make Entourage at least ‘seem’ to behave as you’d expect. A couple of Exchange Rules can be created to manipulate the messages around to end up doing what you’d expect.

This relies on having some unique text in your iPhone signature to identify emails coming from the device. Something like “Sent via iPhone” would do the trick. Also, the iPhone (or other device) should be set to BCC all sent messages to your email address. Entourage will then be able to determine which messages come from you from the device and move the appropriately using the following two rules:

ActiveSync Sent Items Fix

ActiveSync Sent Items Fix

ActiveSync Sent Items Cleanup

ActiveSync Sent Items Cleanup

Make sure that the rules have been added to the Exchange tab in the Entourage Rules section and are enabled and that should do it. Keep in mind that this is a local client rule and won’t take affect until the messages are downloaded onto the Mac running the rules. The side-effect of this is that you’ll receive a copy of all sent emails on your iPhone if your Mac is not open and able to apply the rules, but once you open Entourage, it will move everything around to its proper place and everything will eventually work out.

iPhone 3.0 Thoughts, Bugs & Complaints June 18, 2009

Posted by bigmaconcampus in Mac Tech.
Tags: , , , , , , , ,
add a comment

Ok, after playing with the new iPhone/iPod Touch 3.0 OS, I’ve come across a few items.

Let me temper those with saying, so far, I do like the new version. Three major items have been missing from my iPhone life (since I also use a Blackberry with work).

1. Searching email (I do this regularly)
2. Reading email in landscape (I receive far too many html emails that I can’t easily read on the iPhone)
3. Cut/Copy/Paste (Everyone’s been waiting for this one. That was my original surprise and complaint on the very 1st version of the iPhone software and it’s been a long wait)

All of these were solved with version 3.0, thankfully.

I’m still wondering just how many undos I can actually do on the device. I’ve tested it up to 3 times and got bored.

Bugs:

The bugs (and one complaint) I’ve seen so far:

1. Syncing Notes: First, it took me and another techie co-worker a few guesses to figure out just WHERE the notes would sync. I eventually guessed right that it would try to stick it in the Notes section of the Mail.app (which sucks since we tend to use Entourage here, not that I like Entourage). Mail in turn won’ t let you even open the Application without setting up an email account. Then the original syncing wouldn’t work until my co-worker figured out that a note had to be created within the Mail.app before any syncing would occur. It must need the file where notes are stored created on the computer first even though there are items on the device beforehand. This a bug in my book.

2. iPhone wants to “Backup” constantly: I’ve synced several times in the past day and already the I’m having bad flashbacks to the switch from Version 1 to 2 of the iPhone OS. That version ALWAYS wanted to do a backup of the device which usually took an hour for a simple sync. Apple eventually fixed this with an update, but it seems to be happening again in an only lesser form. Grrrrrrr.

Complaint:

The only complaint I’ve had so far is Apple not allowing iPhone 2G to use the tethering. People have been doing this for 2 years on jailbroken phones, so I know it’s technically feasible. Can’t think of a rationale for not allowing it other than AT&T complaining that the EDGE network couldn’t handle it. Double-Grrrrrrr.

Now, that is justice… April 12, 2009

Posted by bigmaconcampus in Rhinoism.
Tags: , ,
add a comment

Rhinoism of the day:

“Can you kill someone, if they killed you first?”

Mirror, mirror on my Mac April 2, 2009

Posted by bigmaconcampus in Mac Tech.
2 comments

While working on a lockdown mechanism recently, I needed to activate mirroring on displays when necessary via command-line. The method uses Applescript and GUI scripting, not my preferred method but does what it needs.

In the applescript, I pass it a variable from the parent script, either on or off and expect to possibly get a returned variable of true, if applicable, so I can run the command again later if I need to turn mirror mode back off.

*Note* Scripts tend to cut off visually on screen. You can copy/paste the script to grab it.


on run argv
set TOGGLE to item 1 of argv
if TOGGLE is "on" then
set TOGGLE to "1" as integer
else
set TOGGLE to "0" as integer
end if
try
tell application "System Preferences"
activate
reveal anchor "displaysArrangementTab" of pane id "com.apple.preference.displays"
tell application "System Events"
tell application process "System Preferences"
tell window 1
tell group 1 of tab group 1
if value of checkbox "Mirror Displays" is not TOGGLE then
set TurnOffMirror to "true"
click checkbox "Mirror Displays"
tell application "System Preferences" to quit
return TurnOffMirror
end if
end tell
end tell
end tell
end tell
end tell
on error
tell application "System Events"
tell application process "System Preferences"
keystroke return
end tell
end tell
end try
tell application "System Preferences" to quit
end run

An alternative I found works well, but didn’t totally fit my needs. It toggles mirror mode on and off. I need it to toggle only under certain circumstances. Still, might be useful to someone else, and best of all it’s open source.

http://www.fabiancanas.com/Fabian_Canas/Projects/Entries/2009/2/4_Mirror_Displays.html

Wireless installer for the masses… March 25, 2009

Posted by bigmaconcampus in Mac Tech.
16 comments

~~~~~ 8/27/09 ATTENTION! ~~~~~
The information on this version of the installer is outdated. There is a newer version of this installer available. However, the info on this page does provide a detailed description of what is being accomplished and should not necessarily be ignored, but at least reviewed before reading the updated version.

We now join you local broadcast, already in progress…
~~~~~~~~~~~~~~~~~~~~~~~~~~~~

After wrestling and much trial-and-error (a years worth of tinkering, on-and-off), I finally ended up with a version (only took 3 tries) of a wireless installer I can be somewhat proud of. 

The background info:
I had need of an automated wireless installer for various reason.

  1. Needed to setup hundreds of student Macs for start of semesters and such.
  2. Needed an easy tool for faculty and staff to use
  3. We were changing our wireless network and needed to deploy/change networks somewhat rapidly and smoothly
  4. There were known issues with people not setting up the network correctly even with a guide

Although, I’d found several methods for doing this on Mac OS X 10.4, none would work with Mac OS X 10.5. This installer will setup a connection for an Enterprise WPA network and remove previous settings (usually botched). It will also remove any legacy networks you might want to get rid of on the client’s computer. You will need to edit these scripts to do your bidding. I attempted to make it fairly easy to edit, but YMMV.

I have posted a flat-file .pkg on a website at our University for students/employees to download and run themselves. I decided to deploy this batch of scripts via a Packaged installer, making it dump a payload of scripts into a /tmp folder and then engage via postscript. It is comprised of shell, applescript and python (one-line). I confess it might not be pretty code, but it gets the job done. It accomplishes most tasks by editing the appropriate plist files and uses applescript to make modifications to the keychain items. There is one step that relies on GUI scripting to click a single button at the end of the installation to allow the eapolclient access to the keychain item. I’d developed another method but it relied on more GUI scripting and I preferred to keep that to a minimum due to flackiness of GUI scripting. The applescript parts that prompt for the Mac password, and wireless username and password, test the validity of the authentication credentials. The wireless credentials are tested by smb mounting a server on our internal network. Remove if not necessary.

I had also ran into a last minute issue with turning on Assistive devices. When I would create the invisible file at /var/db/.accessibilityAPIEnabled, it wouldn’t recognize later while the script was running on brand new machines, fresh out of the box (fix seems to be restarting the Finder). I left a step in where I just copy the file into the correct location rather than touch it to create it. Figured it should work either way.

The real beauty of this script is that it doesn’t harm any existing wireless settings, except for the ones you want it to touch. More of a scalpel instead of a hand-grenade approach when dealing with computers that you don’t own.

Please feel free to use, modify, test these at your location as I have found many pieces from various forums, primarily http://www.macscripter.net and macosxhints.com. If there are others out there I got help from and failed to acknowledge, let me know.

My installation package installs all the certificates and applescripts to a /tmp/wireless directory. The installer runs as the local user (due to needing to access the proper login.keychain) and runs certain steps as sudo when necessary. It also installs the PlistBuddy to /tmp/wireless, although you could possibly have it search the local computer for a copy since Apple uses that for their upgrades. I also installed a copy of .accessibilityAPIEnabled into the /tmp/wireless folder to copy to /var/db in the script, but you could just touch /var/db/.accessibilityAPIEnabled instead.

The Main Shell Script:


#!/bin/sh
PATH=/bin:/usr/bin:/sbin:/usr/sbin export PATH
#################################################
# Wireless Setup Script #
# Created by Bryan S. Lee 2009 #
#################################################

###################################################
### VARIABLES THAT MUST BE SET BEFORE RUNNING!!!!!#
###################################################

### Temp folder location for installation files
TEMP="/private/tmp/wireless"

### Location of PlistBuddy
PLISTBUDDY="$TEMP/PlistBuddy"

### New Wireless Network to be setup and legacy networks to remove
WIRELESSNETWORKNAME="nameofwirelessnetwork"
LEGACYNETWORK1="nameofoldwirelessnetwork"
LEGACYNETWORK2="nameofoldopenwirelessnetwork"

##########################################################
### Initial state variables that probably don't change ###
##########################################################


### Variable that tests whether a previous setup is detected later in the script
PREV_WIRELESS_EXISTS=""

### Variable that tests if a legacy network is present. To be used later in the script
PREV_LEGACY1_EXISTS=""

### Variable that tests if a second legacy network is present. To be used later in the script
PREV_LEGACY2_EXISTS=""

### Set other variables
LOCALUSER=`whoami`
HOME=`dscl . -read /Users/$LOCALUSER home | sed -e 's|dsAttrTypeNative:home: ||g'`
LOG=$HOME/Library/Logs/Wireless_Setup.log
OSVERSION=`system_profiler -detailLevel mini | grep "System Version:" | cut -c 32-35`

### Setup Error log for later use in case of errors. Duh!
ERRORLOG="$TEMP/error.log"
ERROR=""
rm -rf $TEMP/error.log
touch $TEMP/error.log

# Check hardware to see if computer is a MacBookAir, if so, change Wireless Interface variable to en0
# instead of en1 to accomodate hardware difference (no ethernet at en0 on MacBookAir, airport is en0 instead)
# Also, set variable MBAirPresent to pass to get_wireless_pass.scpt, to bypass network test if applicable.
WIRELESSINTERFACE="en1"
CHECKFORAIR=`system_profiler -detailLevel mini | grep MacBookAir`
if [ "$CHECKFORAIR" != "" ]; then
echo "MacBookAir detected, changing Wireless Interface to en0..." >> $LOG
WIRELESSINTERFACE="en0"
MBAirPresent="true"
else
MBAirPresent="false"
fi

#####################
### FUNCTIONS ###
#####################

# Function for checking error log file for any possible errors coming from Applescript portions
CHECK_FOR_ERRORS ()
{
ERROR=`grep exit $ERRORLOG | cut -c 1-7`
if [ "$ERROR" != "" ]; then
$REPORTER
rm -rf /tmp/wireless
$ERROR
fi
}

# Fuction that will report back the position counts in plist files to the Log
PLISTCOUNTER ()
{
((PLISTITEMCOUNT=$PLISTITEMCOUNT+1))
echo "Entries start at 0, and current number of entries is " $PLISTITEMCOUNT >> $LOG
echo "Next entry number position will be " $PLISTITEMCOUNT >> $LOG
}

# Function that toggles the airport between on and off. Expects on or off as variables of the function
TOGGLEAIRPORT ()
{
echo "Turning $1 Airport wireless..." >> $LOG
if [ "$OSVERSION" = "10.5" ]; then
networksetup -setairportpower $1
else
if [ "$OSVERSION" = "10.6" ]; then
networksetup -setairportpower $WIRELESSINTERFACE $1
else
osascript -e "tell application \"Finder\" to activate"
osascript -e "tell application \"Finder\" to display dialog \"An error occurred while attempting to turn the wireless on or off. Please try the installer again or contact whoever for help.\" buttons {\"OK\"} with icon caution"
osascript -e "tell application \"Installer\" to activate"
echo "exit 20 Error occurred while changing airport power due to unknown operating system version." >> $LOG
echo "exit 20 Error occurred while changing airport power due to unknown operating system version." > $ERRORLOG
fi
fi
echo "Airport wireless turned $1" >> $LOG
}

######################
### Starting Setup ###
######################

# Setup the log so we know what's going on later...
echo "------------------------------------------------------------------" >> $LOG
echo "Wireless Setup started at `date`" >> $LOG
echo "Starting Wireless Setup..." >> $LOG
echo "------------------------------------------------------------------" >> $LOG
echo "" >> $LOG

system_profiler -detailLevel mini | grep "System Version:" | cut -c 7-50 >> $LOG

# Turn on Airport to test if Wireless network to join is present
TOGGLEAIRPORT on

CHECK_FOR_ERRORS

### Check to see if Wireless Network is within range (only works with broadcast SSID)
echo "Checking to see if wireless network, $WIRELESSNETWORKNAME, is within range for setup to continue..." >> $LOG
WIRELESSINRANGE=`/System/Library/PrivateFrameworks/Apple80211.framework/Versions/Current/Resources/airport --scan=$WIRELESSNETWORKNAME`
if [ "$WIRELESSINRANGE" = "No networks found" ]; then
echo "$WIRELESSNETWORKNAME not within range, installation will quit" >> $LOG
osascript -e "tell application \"Finder\" to activate"
osascript -e "tell application \"Finder\" to display dialog \"The wireless network, $WIRELESSNETWORKNAME, is not within range.\" & return & return & \"The installer will now quit. Please move to within range of the wireless signal and try again.\" buttons {\"OK\"} with icon caution"
osascript -e "tell application \"Installer\" to activate"
echo "exit 10 Wireless Network not within range" >> $LOG
echo "exit 10 Wireless Network not within range" > $ERRORLOG
fi

CHECK_FOR_ERRORS

echo "Wireless network, $WIRELESSNETWORKNAME, is within range. Setup will continue..." >> $LOG

### Prompt for Mac Admin Password, Wireless Username and Wireless Password
### Applescripts perform tests for validity and return variables
echo "Prompting user for Mac Admin password..." >> $LOG
MACPASS=`osascript "$TEMP/get_mac_pass.scpt" $LOG $ERRORLOG`

CHECK_FOR_ERRORS

echo "Mac Admin Password authenticated successfully..." >> $LOG

echo "Prompting user for Wireless username and password..." >> $LOG
WIRELESSPASS=`osascript "$TEMP/get_wireless_pass.scpt" $MACPASS $LOG $ERRORLOG $MBAirPresent`
WIRELESSUSER=`ls $TEMP | grep WirelessUserNameIs | cut -c 19-30`

### Clean up clutter from getting WirelessUserName
echo $MACPASS | sudo -S rm -rf $TEMP/WirelessUserNameIs*

CHECK_FOR_ERRORS

### Update Log
echo "User to configure: $WIRELESSUSER" >> $LOG
if [ "$CHECKFORAIR" != "" ]; then
echo "Network Password not tested due to presence of MacBookAir hardware..." >> $LOG
else
echo "Wireless Password authenticated successfully..." >> $LOG
fi

# Get MAC Addresses
hwAddress=`ifconfig en0 | awk '/ether/ { gsub(":", ""); print $2 }'`
hwAddresswithColons=`ifconfig en0 | awk '/ether/ { gsub(":", "\\\\:"); print $2 }'`
echo "Computer Hardware address: $hwAddress" >> $LOG

AirAddress=`ifconfig $WIRELESSINTERFACE | awk '/ether/ { gsub(":", ""); print $2 }'`
AirAddresswithColons=`ifconfig $WIRELESSINTERFACE | awk '/ether/ { gsub(":", "\\\\:"); print $2 }'`
AirAddresswithColons2=`ifconfig $WIRELESSINTERFACE | awk '/ether/ { gsub(":", "\\:"); print $2 }'`
echo "Computer Airport address: $AirAddress" >> $LOG

# Get some Unique Identifiers to use in the plists...
uuid=`uuidgen`
netuuid=`uuidgen`
OLD_UUID=""

# DYNAMICALLY SET THE LEOPARD UUID FOR THE BYHOST FILE NAMING
if [[ `ioreg -rd1 -c IOPlatformExpertDevice | grep -i "UUID" | cut -c27-50` == "00000000-0000-1000-8000-" ]]; then
LEOUUID=`ioreg -rd1 -c IOPlatformExpertDevice | grep -i "UUID" | cut -c51-62 | awk {'print tolower()'}`
elif [[ `ioreg -rd1 -c IOPlatformExpertDevice | grep -i "UUID" | cut -c27-50` != "00000000-0000-1000-8000-" ]]; then
LEOUUID=`ioreg -rd1 -c IOPlatformExpertDevice | grep -i "UUID" | cut -c27-62`
fi

# Define the 4 plist files that will be changed...
PREFSPATH="/Library/Preferences/SystemConfiguration/preferences.plist"
AirportPref="/Library/Preferences/SystemConfiguration/com.apple.airport.preferences.plist"
EAPProfiles="$HOME/Library/Preferences/com.apple.eap.profiles.plist"
EAPBindings="$HOME/Library/Preferences/ByHost/com.apple.eap.bindings.$LEOUUID.plist"

# Turn off Airport
TOGGLEAIRPORT off

CHECK_FOR_ERRORS

# Turn on Assistive Devices and set variable to possibly turn off later
if [ -e /private/var/db/.AccessibilityAPIEnabled ]; then
echo "Assistive Devices already turned on..." >> $LOG
ASSISTDEVOFF="false"
else
echo "Assistive Devices is off..." >> $LOG
ASSISTDEVOFF="true"
echo "Turning on Assistive Devices Setting..." >> $LOG
echo $MACPASS | sudo -S cp /private/tmp/wireless/AccessibilityAPIEnabled /private/var/db/.AccessibilityAPIEnabled
echo $MACPASS | sudo -S chmod 444 /private/var/db/.AccessibilityAPIEnabled
fi

##############################
##### Cleanup Section ########
##############################

###
### Search preferences.plist for matching previous wireless networks and remove if found
###

echo "Determining if previous tigernet installation exists..." >> $LOG
echo "Starting Cleanup of any previously detected legacy networks..." >> $LOG

# Create a backup copy of com.apple.preferences.plist, JUST IN CASE
echo "Backing up Preferences plist file" >> $LOG
echo $MACPASS | sudo -S cp $PREFSPATH "/Library/Preferences/SystemConfiguration/preferences.plist.old"

# Search all entries in com.apple.preferences.plist to find and delete previously set connections.
# If more than 100 wireless networks present, number may
# need to be increased in COUNTER (hopefully, no one has more than 100 wireless network connections)

# Search to figure out the UUID for the SETS entry in the preferences.plist
SETUUID=`grep "/Sets/" $PREFSPATH | cut -c 16-51`

# Loop through the com.apple.preferences.plist file looking for matches of wireless networks to remove and then removing them.
for ((COUNTER=0; COUNTER <= 100 ; COUNTER=COUNTER+1))
do
TESTFORNETWORK=`"$PLISTBUDDY" -c "Print :Sets:$SETUUID:Network:Interface:$WIRELESSINTERFACE:AirPort:PreferredNetworks:$COUNTER" $PREFSPATH | grep "$WIRELESSNETWORKNAME"`
if [ "$TESTFORNETWORK" != "" ]; then
echo "Previous $WIRELESSNETWORKNAME connection found and deleted" >> $LOG
echo $MACPASS | sudo -S "$PLISTBUDDY" -c "Delete :Sets:$SETUUID:Network:Interface:$WIRELESSINTERFACE:AirPort:PreferredNetworks:$COUNTER" $PREFSPATH
((COUNTER=COUNTER-1))
fi
TESTFORNETWORK=`"$PLISTBUDDY" -c "Print :Sets:$SETUUID:Network:Interface:$WIRELESSINTERFACE:AirPort:PreferredNetworks:$COUNTER" $PREFSPATH | grep "$LEGACYNETWORK1"`
if [ "$TESTFORNETWORK" != "" ]; then
echo "Previous $LEGACYNETWORK1 connection found and deleted" >> $LOG
echo $MACPASS | sudo -S "$PLISTBUDDY" -c "Delete :Sets:$SETUUID:Network:Interface:$WIRELESSINTERFACE:AirPort:PreferredNetworks:$COUNTER" $PREFSPATH
((COUNTER=COUNTER-1))
fi
TESTFORNETWORK=`"$PLISTBUDDY" -c "Print :Sets:$SETUUID:Network:Interface:$WIRELESSINTERFACE:AirPort:PreferredNetworks:$COUNTER" $PREFSPATH | grep "$LEGACYNETWORK2"`
if [ "$TESTFORNETWORK" != "" ]; then
echo "Previous $LEGACYNETWORK2 connection found and deleted" >> $LOG
echo $MACPASS | sudo -S "$PLISTBUDDY" -c "Delete :Sets:$SETUUID:Network:Interface:$WIRELESSINTERFACE:AirPort:PreferredNetworks:$COUNTER" $PREFSPATH
((COUNTER=COUNTER-1))
fi
done

###
### Delete com.apple.airport.preferences.plist file to clear previously cached settings for ALL networks (no harm done)
###

echo $MACPASS | sudo -S rm -rf $AirportPref

###
### Search EAP Profile plist to cleanup if necessary
###

# Search all entries to find and delete previously set connections. If more than 20 Enterprise
# wireless networks present, number may
# need to be increased in COUNTER (hopefully, no one has more than 20 enterprise network connections)
for ((COUNTER=0; COUNTER <= 20 ; COUNTER=COUNTER+1))
do
TESTFORNETWORK=`"$PLISTBUDDY" -c "Print :Profiles:$COUNTER" $EAPProfiles | grep "$WIRELESSNETWORKNAME"`
if [ "$TESTFORNETWORK" != "" ]; then
echo "Previous $WIRELESSNETWORKNAME found and deleted in EAP Profile" >> $LOG
echo $MACPASS | sudo -S "$PLISTBUDDY" -c "Delete :Profiles:$COUNTER" $EAPProfiles
((COUNTER=COUNTER-1))
fi
done

###
### Search EAP Bindings plist to cleanup if necessary
###

# Search all entries to find and delete previously set connections. If more than 20 Enterprise
# wireless networks present, number may
# need to be increased in COUNTER (hopefully, no one has more than 20 enterprise network connections)
for ((COUNTER=0; COUNTER <= 20 ; COUNTER=COUNTER+1))
do
TESTFORNETWORK=`"$PLISTBUDDY" -c "Print :$AirAddresswithColons:$COUNTER" $EAPBindings | grep "$WIRELESSNETWORKNAME"`
if [ "$TESTFORNETWORK" != "" ]; then
echo "Previous $WIRELESSNETWORKNAME found and deleted in EAP Bindings" >> $LOG
echo $MACPASS | sudo -S "$PLISTBUDDY" -c "Delete :$AirAddresswithColons:$COUNTER" $EAPBindings
((COUNTER=COUNTER-1))
fi
done

##########################################
### Add entries to PLIST files section ###
##########################################

###
### Scan preferences.plist file to figure out how many entries exist under Preferred Networks
###

PLISTITEMCOUNT=-1
for ((COUNTER=0; COUNTER <= 100 ; COUNTER=COUNTER+1))
do
TESTFORNETWORK=`"$PLISTBUDDY" -c "Print :Sets:$SETUUID:Network:Interface:$WIRELESSINTERFACE:AirPort:PreferredNetworks:$COUNTER" $PREFSPATH | grep SSID_STR`
if [ "$TESTFORNETWORK" != "" ]; then
((PLISTITEMCOUNT=$PLISTITEMCOUNT+1))
fi
done

PLISTCOUNTER

###
### Add new entry for wireless network into com.apple.preferences.plist
###

echo $MACPASS | sudo -S "$PLISTBUDDY" -c "Add :Sets:$SETUUID:Network:Interface:$WIRELESSINTERFACE:AirPort:PreferredNetworks array" $PREFSPATH
echo $MACPASS | sudo -S "$PLISTBUDDY" -c "Add :Sets:$SETUUID:Network:Interface:$WIRELESSINTERFACE:AirPort:PreferredNetworks:$PLISTITEMCOUNT dict" $PREFSPATH
echo $MACPASS | sudo -S "$PLISTBUDDY" -c "Add :Sets:$SETUUID:Network:Interface:$WIRELESSINTERFACE:AirPort:PreferredNetworks:$PLISTITEMCOUNT:SSID_STR string $WIRELESSNETWORKNAME" $PREFSPATH
echo $MACPASS | sudo -S "$PLISTBUDDY" -c "Add :Sets:$SETUUID:Network:Interface:$WIRELESSINTERFACE:AirPort:PreferredNetworks:$PLISTITEMCOUNT:SecurityType string WPA2\ Enterprise" $PREFSPATH
echo $MACPASS | sudo -S "$PLISTBUDDY" -c "Add :Sets:$SETUUID:Network:Interface:$WIRELESSINTERFACE:AirPort:PreferredNetworks:$PLISTITEMCOUNT:Unique\ Network\ ID string $uuid" $PREFSPATH

###
### Add new entry for wireless network into com.apple.airport.preferences.plist
###

echo "Adding $WIRELESSNETWORKNAME to Airport Preferences..." >> $LOG
# "$PLISTBUDDY" -c "Delete :KnownNetworks" $AirportPref ;# Remove any previous entry.

echo $MACPASS | sudo -S "$PLISTBUDDY" -c "Add :KnownNetworks dict" $AirportPref
echo $MACPASS | sudo -S "$PLISTBUDDY" -c "Add :KnownNetworks:$uuid dict" $AirportPref
echo $MACPASS | sudo -S "$PLISTBUDDY" -c "Add :KnownNetworks:$uuid:Remembered\ Channels array" $AirportPref
echo $MACPASS | sudo -S "$PLISTBUDDY" -c "Add :KnownNetworks:$uuid:Remembered\ Channels:0 integer 11" $AirportPref
echo $MACPASS | sudo -S "$PLISTBUDDY" -c "Add :KnownNetworks:$uuid:Remembered\ Channels:1 integer 6" $AirportPref
echo $MACPASS | sudo -S "$PLISTBUDDY" -c "Add :KnownNetworks:$uuid:Remembered\ Channels:2 integer 1" $AirportPref
echo $MACPASS | sudo -S "$PLISTBUDDY" -c "Add :KnownNetworks:$uuid:SCAN_DIRECTED bool Yes" $AirportPref
echo $MACPASS | sudo -S "$PLISTBUDDY" -c "Add :KnownNetworks:$uuid:SSID_STR string $WIRELESSNETWORKNAME" $AirportPref
echo $MACPASS | sudo -S "$PLISTBUDDY" -c "Add :KnownNetworks:$uuid:SecurityType string WPA2\ Enterprise" $AirportPref
echo $MACPASS | sudo -S "$PLISTBUDDY" -c "Add :KnownNetworks:$uuid:_timeStamp date 1995-06-21T14\:00\:00Z" $AirportPref
echo $MACPASS | sudo -S "$PLISTBUDDY" -c "Add :Version integer 6" $AirportPref
echo $MACPASS | sudo -S "$PLISTBUDDY" -c "Add :$WIRELESSINTERFACE dict" $AirportPref
echo $MACPASS | sudo -S "$PLISTBUDDY" -c "Add :$WIRELESSINTERFACE:RecentNetworks array" $AirportPref
echo $MACPASS | sudo -S "$PLISTBUDDY" -c "Add :$WIRELESSINTERFACE:RecentNetworks:0 dict" $AirportPref
echo $MACPASS | sudo -S "$PLISTBUDDY" -c "Add :$WIRELESSINTERFACE:RecentNetworks:0:SSID_STR string $WIRELESSNETWORKNAME" $AirportPref
echo $MACPASS | sudo -S "$PLISTBUDDY" -c "Add :$WIRELESSINTERFACE:RecentNetworks:0:SecurityType string WPA2\ Enterprise" $AirportPref
echo $MACPASS | sudo -S "$PLISTBUDDY" -c "Add :$WIRELESSINTERFACE:RecentNetworks:0:Unique\ Network\ ID string $uuid" $AirportPref

###
### Rebuild new entries for com.apple.eap.profiles.plist
###

echo "Building the User's EAPProfiles setting at $EAPProfiles..." >> $LOG

###
### Scan EAP Profile plist file to figure out how many entries exist
###

PLISTITEMCOUNT=-1
for ((COUNTER=0; COUNTER <= 20 ; COUNTER=COUNTER+1))
do
TESTFORNETWORK=`"$PLISTBUDDY" -c "Print :Profiles:$COUNTER" $EAPProfiles | grep EAP`
if [ "$TESTFORNETWORK" != "" ]; then
((PLISTITEMCOUNT=$PLISTITEMCOUNT+1))
fi
done

PLISTCOUNTER

"$PLISTBUDDY" -c "Add :Profiles array" $EAPProfiles
"$PLISTBUDDY" -c "Add :Profiles:$PLISTITEMCOUNT dict" $EAPProfiles
"$PLISTBUDDY" -c "Add :Profiles:$PLISTITEMCOUNT:ConnectByDefault bool Yes" $EAPProfiles
"$PLISTBUDDY" -c "Add :Profiles:$PLISTITEMCOUNT:EAPClientConfiguration dict" $EAPProfiles
"$PLISTBUDDY" -c "Add :Profiles:$PLISTITEMCOUNT:EAPClientConfiguration:AcceptEAPTypes array" $EAPProfiles
"$PLISTBUDDY" -c "Add :Profiles:$PLISTITEMCOUNT:EAPClientConfiguration:AcceptEAPTypes:0 integer 25" $EAPProfiles
"$PLISTBUDDY" -c "Add :Profiles:$PLISTITEMCOUNT:EAPClientConfiguration:Description string Automatic" $EAPProfiles
"$PLISTBUDDY" -c "Add :Profiles:$PLISTITEMCOUNT:EAPClientConfiguration:EAPFASTProvisionPAC bool Yes" $EAPProfiles
"$PLISTBUDDY" -c "Add :Profiles:$PLISTITEMCOUNT:EAPClientConfiguration:EAPFASTProvisionPACAnonymously bool No" $EAPProfiles
"$PLISTBUDDY" -c "Add :Profiles:$PLISTITEMCOUNT:EAPClientConfiguration:EAPFASTUsePAC bool Yes" $EAPProfiles
"$PLISTBUDDY" -c "Add :Profiles:$PLISTITEMCOUNT:EAPClientConfiguration:OuterIdentity string " $EAPProfiles
"$PLISTBUDDY" -c "Add :Profiles:$PLISTITEMCOUNT:EAPClientConfiguration:TLSVerifyServerCertificate bool Yes" $EAPProfiles
"$PLISTBUDDY" -c "Add :Profiles:$PLISTITEMCOUNT:EAPClientConfiguration:TTLSInnerAuthentication string MSCHAPv2" $EAPProfiles
"$PLISTBUDDY" -c "Add :Profiles:$PLISTITEMCOUNT:EAPClientConfiguration:UserName string $WIRELESSUSER" $EAPProfiles
"$PLISTBUDDY" -c "Add :Profiles:$PLISTITEMCOUNT:EAPClientConfiguration:UserPasswordKeychainItemID string $uuid" $EAPProfiles
"$PLISTBUDDY" -c "Add :Profiles:$PLISTITEMCOUNT:UniqueIdentifier string $uuid" $EAPProfiles
"$PLISTBUDDY" -c "Add :Profiles:$PLISTITEMCOUNT:UserDefinedName string WPA:\ $WIRELESSNETWORKNAME" $EAPProfiles

###
### Rebuild new entries for com.apple.eap.bindings.X.plist
###

echo "Building the User's EAPBindings settings at $EAPBindings..." >> $LOG

###
### Scan EAP Bindings plist file to figure out how many entries exist
###

PLISTITEMCOUNT=-1
for ((COUNTER=0; COUNTER <= 20 ; COUNTER=COUNTER+1))
do
TESTFORNETWORK=`"$PLISTBUDDY" -c "Print :$AirAddresswithColons:$COUNTER" $EAPBindings | grep UniqueIdentifier`
if [ "$TESTFORNETWORK" != "" ]; then
((PLISTITEMCOUNT=$PLISTITEMCOUNT+1))
fi
done

PLISTCOUNTER

"$PLISTBUDDY" -c "Add :$AirAddresswithColons array" $EAPBindings
"$PLISTBUDDY" -c "Add :$AirAddresswithColons:$PLISTITEMCOUNT dict" $EAPBindings
# "$PLISTBUDDY" -c "Add :$AirAddresswithColons:0:Hardware\ Address string $AirAddresswithColons2" $EAPBindings
"$PLISTBUDDY" -c "Add :$AirAddresswithColons:$PLISTITEMCOUNT:UniqueIdentifier string $uuid" $EAPBindings
"$PLISTBUDDY" -c "Add :$AirAddresswithColons:$PLISTITEMCOUNT:Wireless\ Network string $WIRELESSNETWORKNAME" $EAPBindings

###############################
### Security Setup Section ####
###############################

### A vast section of the security setup must be accomplished in applescript due to
### technical limitations of bash shell access to the keychain.
### A single step (clicking the 'Allow Always' button of the SecurityAgent) must be
### accomplished using GUI scripting via Applescript

# Add certificate to System Keychain for all users
echo "Adding Certificate to System Keychain..." >> $LOG
echo $MACPASS | sudo -S security add-trusted-cert -d -r trustAsRoot -k /Library/Keychains/System.keychain $TEMP/name.of.certificate.pem
echo "Certificate added successfully..." >> $LOG

# Add generic password item to login.keychain for network settings to attach to
echo "Checking login.keychain for previous keychain passwords to remove and adding new keychain item..." >> $LOG
osascript /tmp/cu_wireless/setup_wireless_keychain.scpt $MACPASS $WIRELESSNETWORKNAME $uuid $WIRELESSUSER $WIRELESSPASS $LOG $ERRORLOG

CHECK_FOR_ERRORS

# Report Password item added successfully to log
echo "Password Item added successfully..." >> $LOG

### Turn on Wireless
TOGGLEAIRPORT on

CHECK_FOR_ERRORS

### Attaching to wireless network
# echo $MACPASS | sudo -S /System/Library/PrivateFrameworks/Apple80211.framework/Versions/Current/Resources/airport --associate=$WIRELESSNETWORKNAME

### Applescript step that relies on GUI scripting
echo "Setting ACL of keychain item to allow eapolclient..." >> $LOG
osascript "/tmp/cu_wireless/allow_keychain_acl.scpt" $MACPASS $LOG $ERRORLOG

CHECK_FOR_ERRORS

# Report no error setting ACL of keychain to log
echo "ACL of keychain item set..." >> $LOG

# Turn off Assistive Devices if originally off
if [ $ASSISTDEVOFF = "true" ]; then
echo "Turning off Assistive Devices Setting..." >> $LOG
echo $MACPASS | sudo -S rm -rf /private/var/db/.AccessibilityAPIEnabled
echo "Assistive Devices turned off successfully..." >> $LOG
fi

CHECK_FOR_ERRORS

echo "Wireless Setup completed successfully" >> $LOG

# Remove all setup files when finished
echo $MACPASS | sudo -S rm -rf /tmp/wireless

exit 0

 

AppleScript portions referred to in the above Shell script:

get_mac_pass.scpt


-- Script created
-- by Bryan S. Lee 2009

-- This script will prompt user for the Admin Mac Password and test the password for validity
-- This script expects to receive all logs locations from the parent script

on run argv
set LOGS to item 1 of argv
set ERRORLOG to item 2 of argv
set theUser to (do shell script "echo $USER")
set myMacPass to ""
set myMacPassTest to ""

-- Prompt user for Mac Password
tell application "Finder"
activate
repeat until myMacPassTest is not ""
set myMacPassDialog to display dialog "Please enter your Mac password." & return & "(This is the password you created while registering your Mac)" default answer "" buttons {"Quit", "OK"} default button 2 with title "Wireless Setup" with hidden answer
set myMacPass to the text returned of myMacPassDialog
if button returned of myMacPassDialog is "Quit" then
tell me
do shell script "echo \"exit 99 User cancelled installation.\" 2>&1 > " & ERRORLOG
do shell script "echo \"exit 99 User cancelled installation.\" 2>&1 >> " & LOGS
tell application "Installer" to activate
return
end tell
end if
-- Test to see if Mac Password is correct
tell me
try
do shell script "sudo touch /private/tmp/mac_password_test" user name theUser password myMacPass with administrator privileges
if myMacPass is "" then
tell application "Finder"
activate
tell me
do shell script "echo \"exit 98 Cancelled installation due to blank Mac password.\" 2>&1 > " & ERRORLOG
do shell script "echo \"exit 98 Cancelled installation due to blank Mac password.\" 2>&1 >> " & LOGS
end tell
set dialogReply to display dialog "It is HIGHLY recommended that your Mac Password not be blank due to security concerns." & return & return & "You MUST create a Mac password to continue using this installer." & return & return & "Please create a Mac Password by clicking the 'Create Mac Password' button below. Then click the 'Change Password' button that appears in the next window." & return & return & "This installer will now exit with an error. Please run it again after creating a Mac Password." with title "Wireless Setup" buttons {"Quit", "Create Mac Password"} default button 2 with icon caution
tell application "Installer" to activate
set myMacPassTest to ""
if button returned of dialogReply is "Create Mac Password" then
tell application "System Preferences"
activate
reveal anchor "passwordPref" of pane "Accounts"
activate pane id "com.apple.preferences.users"
end tell
end if
return
end tell
end if
set myMacPassTest to "true"
on error
tell application "Finder"
activate
set dialogReply to display dialog "Mac Password entered was incorrect, please try again." with title "Wireless Setup" buttons {"Quit", "OK"} default button 2 with icon caution
set myMacPassTest to ""
if button returned of dialogReply is "Quit" then
tell me
do shell script "echo \"exit 99 User cancelled installation.\" 2>&1 > " & ERRORLOG
do shell script "echo \"exit 99 User cancelled installation.\" 2>&1 >> " & LOGS
tell application "Installer" to activate
return
end tell
end if
end tell
end try
end tell
end repeat
end tell

-- cleanup password test file
do shell script "sudo rm -rf /private/tmp/mac_password_test" user name theUser password myMacPass with administrator privileges

-- Bring Installer.app to frontmost
tell application "Installer" to activate

return myMacPass
end run

get_wireless_pass.scpt


-- Script created
-- by Bryan S. Lee 2009

-- Prompt for Network username and password. Write username to a file and return the password to the main script
-- This script expects to receive the Mac Admin password, Logs locations and MBAirPresent variable from the parent script as arguments
-- Ex. osascript /path/to/this/script $MACPASS $LOG $ERRORLOG $MBAirPresent

on run argv
set myMacPass to item 1 of argv
set LOGS to item 2 of argv
set ERRORLOG to item 3 of argv
set MBAirPresent to item 4 of argv
set theUser to (do shell script "echo $USER")
set myPass to ""
set counter to 1

tell application "Finder"
activate
repeat until myPass is not ""
if counter < 6 then
set acctBox to display dialog "Please enter your wireless USERNAME" & return & "(Ex. USERNAME@somedomain.edu)" default answer "" buttons {"Quit", "OK"} default button 2 with title "Wireless Setup"
set myAcct to the text returned of acctBox
if button returned of acctBox is "Quit" then
tell me
do shell script "echo \"exit 99 User cancelled installation.\" 2>&1 > " & ERRORLOG
do shell script "echo \"exit 99 User cancelled installation.\" 2>&1 >> " & LOGS
end tell
tell application "Installer" to activate
return
end if
if button returned of acctBox is "OK" then
if myAcct is not "" then

-- Remove any trailing @mydomain.com information from network name
if myAcct contains "@" then
set myAcct to text 1 through ((offset of "@" in myAcct) - 1) of myAcct
end if

-- Test to see if Network password is correct
set myPassBox to display dialog "Please enter your wireless password:" & return & return & "Be careful to enter it correctly!" & return & "This password is case-sensitive!" default answer "" buttons {"Quit", "OK"} default button 2 with title "Wireless Setup" with hidden answer
if button returned of myPassBox is "Quit" then
tell me
do shell script "echo \"exit 99 User cancelled installation.\" 2>&1 > " & ERRORLOG
do shell script "echo \"exit 99 User cancelled installation.\" 2>&1 >> " & LOGS
end tell
tell application "Installer" to activate
return
end if
set myPass to the text returned of myPassBox

-- test to see if network password is blank
if myPass is not "" then

-- Convert any illegal symbols in password to hexadecimal to function correctly in URL of Volume mount test
try
tell me
set fixedPassword to do shell script "python -c 'import sys, urllib; print urllib.quote(sys.argv[1])' " & quoted form of myPass
end tell
on error
tell me
do shell script "echo \"exit 90 Password possibly contains unsupported characters, such as backslash or double quotes. Please reset password and try again.\" 2>&1 > " & ERRORLOG
do shell script "echo \"exit 90 Password possibly contains unsupported characters, such as backslash or double quotes. Please reset password and try again.\" 2>&1 >> " & LOGS
end tell
tell application "Finder"
set dialogReply to display dialog "Password possibly contains unsupported characters, such as backslash or double quotes. Please reset password and try again." buttons {"Reset Password", "Quit"} default button 1 with icon caution
if button returned of dialogReply is "Reset Password" then
open location "https://reset.password.webpage.edu"
else
return
end if
end tell
tell application "Installer"
activate
end tell
return
end try

-- Test to see if Network Password is correct
if MBAirPresent is "false" then
tell me
try
do shell script "sudo mkdir '/Volumes/Share'" user name theUser password myMacPass with administrator privileges
do shell script "sudo mount_smbfs '//" & myAcct & ":" & fixedPassword & "@share.server.edu/Share' /Volumes/Share/" user name theUser password myMacPass with administrator privileges
on error
do shell script "sudo rmdir /Volumes/Share/" user name theUser password myMacPass with administrator privileges
set myPass to ""
if counter < 5 then
tell application "Finder"
display dialog "Password entered was incorrect or network cable was disconnected. Please check cable and try again." with title "Wireless Setup" buttons {"OK"} default button 1 with icon caution
end tell
do shell script "echo \"Network password entered incorrectly or wired connection failure, asking user to re-enter and trying again...\" 2>&1 >> " & LOGS
end if
end try
end tell
end if
else
display dialog "Password cannot be blank!" buttons {"OK"} default button 1 with icon caution
end if
else
display dialog "Username cannot be blank!" buttons {"OK"} default button 1 with icon caution
end if
end if
else
tell me
do shell script "echo \"exit 2 Password not accepted by network.\" 2>&1 > " & ERRORLOG
do shell script "echo \"exit 2 Password not accepted by network.\" 2>&1 >> " & LOGS
end tell
tell application "Finder"
set dialogReply to display dialog "Password is not accepted. Possibly due to a case-sensitivity difference. Please reset your password and try again." buttons {"Reset Password", "Quit"} default button 1 with icon caution
if button returned of dialogReply is "Reset Password" then
open location "https://change.password.webpage.edu"
end if
set myPass to "exit loop"
end tell
tell application "Installer"
activate
end tell
return
end if
set counter to counter + 1
end repeat
end tell
delay 0.5
if MBAirPresent is "false" then
try
do shell script "sudo umount /Volumes/Share/" user name theUser password myMacPass with administrator privileges
on error
do shell script "echo \"exit 3 Could not unmount network test drive.\" 2>&1 > " & ERRORLOG
do shell script "echo \"exit 3 Could not unmount network test drive.\" 2>&1 >> " & LOGS
tell application "Finder"
display dialog "Could not disconnect network drive during network password test" buttons {"OK"} default button 1 with icon caution
end tell
tell application "Installer"
activate
end tell
return
end try
end if

-- Write username to file for parent script to pickup
tell me
do shell script "touch /private/tmp/wireless/WirelessUserNameIs" & myAcct user name theUser password myMacPass with administrator privileges
end tell

tell application "Installer"
activate
end tell

-- Send wireless password to parent script
return myPass

end run

 

setup_wireless_keychain.scpt


-- Script created
-- by Bryan S. Lee 2009

-- This script will remove all necessary keychain items.
-- This includes previous keychain entry and legacy network keychain items.
-- Then it will add the new keychain item
-- Removal Section of script should be edited with the names of the keychains you wish to be removed

-- IMPORTANT INFO!!!
-- This script expects to receive the following as arguments directly following the command:
-- Mac Administrative password
-- Name of the wireless
-- UUID (Unique ID number)
-- Wireless Network Username
-- Wireless Network password

-- Like the sample below
-- osascript path_to_this_script.scpt MacPassword WirelessName UUID WirelessUsername WirelessPassword

on run argv
-- set incoming variables
set MacPassword to item 1 of argv
set WirelessName to item 2 of argv
set UUID to item 3 of argv
set USER to item 4 of argv
set pass to item 5 of argv
set LOGS to item 6 of argv
set ERRORLOG to item 7 of argv

-- Set other variables
set KeychainName to "WPA: " & WirelessName

-- Removal Section (PLEASE EDIT AS NECESSARY)
try
tell application "Keychain Access"
quit
end tell
tell application "Keychain Scripting"
tell keychain "login.keychain"
unlock with password MacPassword
repeat 5 times -- to catch possible, multiple keychain items with same name
repeat with this_key in (get keys)
if (get name of this_key) = KeychainName then
do shell script "echo \"Keychain item, wireless_name, found...\" 2>&1 >> " & LOGS
delete this_key
do shell script "echo \"Keychain item, wireless_name, deleted...\" 2>&1 >> " & LOGS
exit repeat
end if
end repeat
repeat with this_key in (get keys)
if (get name of this_key) = "Network password for wireless_name Profile" then
do shell script "echo \"Keychain item, Network password for wireless_name Profile, found...\" 2>&1 >> " & LOGS
delete this_key
do shell script "echo \"Keychain item, Network password for wireless_name Profile, deleted...\" 2>&1 >> " & LOGS
exit repeat
end if
end repeat
repeat with this_key in (get keys)
if (get name of this_key) = "wireless_name2" then
do shell script "echo \"Keychain item, wireless_name2, found...\" 2>&1 >> " & LOGS
delete this_key
do shell script "echo \"Keychain item, wireless_name2, deleted...\" 2>&1 >> " & LOGS
exit repeat
end if
end repeat
end repeat
end tell
end tell
on error
do shell script "echo \"exit 4 Error attempting to remove previous wireless keychain items. Probably due to a corrupt login.keychain. Please remove and try again.\" 2>&1 > " & ERRORLOG
do shell script "echo \"exit 4 Error attempting to remove previous wireless keychain items. Probably due to a corrupt login.keychain. Please remove and try again.\" 2>&1 >> " & LOGS
tell application "Finder"
activate
display dialog "Error attempting to remove previous wireless keychain items. Probably due to a corrupt login.keychain. Please remove and try again." buttons {"OK"} default button 1 with icon caution
end tell
tell application "Installer"
activate
end tell
return
end try

-- This section will add the keychain item to the login.keychain and create all necessary settings except setting ACL for eapolclient

tell application "Keychain Scripting"
tell keychain "login.keychain"
unlock with password MacPassword
set namename to KeychainName
set servicename to UUID
set accountname to USER
set commentname to " Wireless Installer created by Bryan S. Lee and maintained by Your_name "
set passwordname to pass
try
make new generic key with properties {name:namename, kind:"application password", account:accountname, service:servicename, comment:commentname, password:passwordname}
on error
do shell script "echo \"exit 5 Error attempting to create wireless keychain item.\" 2>&1 > " & ERRORLOG
do shell script "echo \"exit 5 Error attempting to create wireless keychain item.\" 2>&1 >> " & LOGS
tell application "Finder"
activate
display dialog "Error attempting to create wireless keychain item." buttons {"OK"} default button 1 with icon caution
end tell
tell application "Installer"
activate
end tell
return
end try
end tell
end tell
end run

 

allow_keychain_acl.scpt


-- Script created
-- by Bryan S. Lee 2009
-- This script will wait for the until the Security Agent prompts the user
-- to Alway Allow, Deny or Allow the eapolclient to access the keychain item
-- then it will select Always Allow

-- This script expects to receive the Logs location and Error Logs location from the parent script as arguments
-- Ex. osascript /path/to/this/script $LOG $ERRORLOG

on run argv

set theUser to (do shell script "echo $USER")
set myMacPass to item 1 of argv
set LOGS to item 2 of argv
set ERRORLOG to item 3 of argv
set counter to 0

-- Leaving Sys Prefs open can cause a conflict
tell application "System Preferences" to quit

 

try
-- restart the Finder to make sure it notices that Assistive Devices is turned on
tell application "System Events"
repeat until (name of every process) does not contain "Finder"
tell application "Finder" to quit
delay 1
end repeat
end tell
tell application "Finder" to launch
tell application "System Events"
repeat until exists process "Finder"
delay 1
end repeat
end tell
delay 1
tell application "Installer" to activate
tell application "System Events"
tell application process "SecurityAgent"
repeat until (exists window 1)
delay 0.1
if counter > 900 then
do shell script "echo \"exit 6 Setting ACL of keychain timed out.\" 2>&1 > " & ERRORLOG
do shell script "echo \"exit 6 Setting ACL of keychain timed out.\" 2>&1 >> " & LOGS
tell application "Finder"
activate
display dialog "Setting ACL of keychain timed out, possibly due to weak wireless signal." & return & return & "If a dialog appears later asking to allow the EAPOLCLIENT access to your password, click 'ALWAYS ALLOW', or try the installer again within range of the wireless signal." buttons {"OK"} default button 1 with icon caution
end tell
tell application "Installer"
activate
end tell
return
end if
set counter to counter + 1
end repeat
click button "Always Allow" of group 1 of window 1
end tell
end tell
on error
do shell script "echo \"exit 7 Encountered an error attempting to set ACL of keychain. Possibly due to Assistive Devices being off.\" 2>&1 > " & ERRORLOG
do shell script "echo \"exit 7 Encountered an error attempting to set ACL of keychain. Possibly due to Assistive Devices being off.\" 2>&1 >> " & LOGS
tell application "Finder"
activate
display dialog "An error occurred that requires a restart of your computer." & return & return & "Please restart your computer and try the wireless installer again." buttons {"OK"} default button 1 with icon caution
end tell
tell application "Installer"
activate
end tell
end try
end run