#!/usr/bin/perl # Basic Login Hook for OS X workstations on Novell Networks # Based on School District of Escambia County Macintosh Login Hook # Originally compiled by Johnnie Odom ( jodom@escambia.k12.fl.us ) on October 1, 2008 # Version 1.0.2 October 29, 2008 # REQUIREMENTS: GroupWise 7 or later, an LDAP server with GroupWise attributes (i.e. eDirectory) # and a logged-in user whose username on OS X is the same and unique in the LDAP server. # That is, you should ideally be using eDirectory via LDAP login or Kanaka if you use this script. # However, it will also work if a local user has the same username as an eDirectory user. # Tested with OS X 10.3 - 10.5 and Groupwise 7.x - 8.x. # LDAP searches are done in cleartext without a certificate since no passwords go across the wire. # Anything in ALL CAPS below should be replaced with site-specific information. # Since this script requires administrative rights, it should be run as a loginhook. # See http://support.apple.com/kb/HT2420 for more information. # What it does: # 1. Adds users in specific groups to the local administrator group so that they can do things # like add printers, install programs, set preferences etc. Even with these privileges, they # are still subject to any MCX preferences you set. In a school environment, these users would # be teachers and other adults. # 2. Adds all users to the local Staff group so that they can perform common, low-rights # operations such as running applications, etc. # 3. Rewrites the master Groupwise preference list to auto-populate Groupwise with the # login information for the user who has just logged into the workstation. If the user does # not have GW login credentials, it writes garbage and waits for the next valid user. # Limitations of the script (be aware of these, but don't worry about them) # 1. Users are added to local groups but never removed, so the groups get big. # 2. The GroupWise preferences file gets completely rewritten every login. # There is a local "hidden" version of Groupwise preferences, but it is easier to # manipulate the main one. # Standard variables my $userLogin = $ARGV[0]; my $ldapServer = "YOUR_LDAP_SERVER_IP_OR_DNS_NAME"; my $ldapSearchScope = "o=YOUR_ROOT_CONTAINER"; ############ ADMINISTRATIVE USER SECTION (Also creates group variables.) ############ # Get the eDirectory groups for the user. my $groupsRaw = `ldapsearch -x -LLL -H ldap://$ldapServer -b $ldapSearchScope '(cn=$userLogin)' groupMembership`; my @groupsRawArray = split /\n/, $groupsRaw ; # Now dice the ldapsearch output so that we get two arrays -- one for group names and a # corresponding one for group ou units. We only use group cn -- we don't need the entire context. my @groupName; my @groupOu; my $makeAdmin = 0; foreach $groupRawElement (@groupsRawArray){ if($groupRawElement ne $groupsRawArray[0]){ if($groupRawElement ne 'groupMembership:'){ my @tempElements = split /,/, $groupRawElement ; my @tempCn = split /=/, $tempElements[0]; my @tempOu = split /=/, $tempElements[1]; push(@groupName, $tempCn[1]); push(@groupOu, $tempOu[1]); # If the user belongs to any of the following groups, # mark to make admin of the local machine. if($tempCn[1] eq "GROUP1_CN"){ $makeAdmin += 1; } elsif($tempCn[1] eq "GROUP2_CN"){ $makeAdmin += 1; } elsif($tempCn[1] eq "GROUP3_CN"){ $makeAdmin += 1; } elsif($tempCn[1] eq "GROUP4_CN"){ $makeAdmin += 1; } } } } # If this is a confirmed power user, make them an admin on the local machine. # Note that this does make the admin group large because we keep adding them. # A large admin group doesn't actually have much of an effect on the machine. if($makeAdmin){ my $addAdminDebug = `dscl . append /Groups/admin GroupMembership $userLogin`; print "User added to admin group: $addAdminDebug\n"; } else{ print "Not a local administrative user.\n"; } # No matter who they are, we need to add them to the staff group # because that's the group with the permissions to run most applications. my $addStaffDebug = `dscl . append /Groups/staff GroupMembership $userLogin`; print "User added to admin group: $addStaffDebug\n"; ############ GROUPWISE SECTION ################## # Get the GroupWise username and the GroupWise PO name via LDAP. my $gwUserRaw = `ldapsearch -x -LLL -H ldap://$ldapServer -b $ldapSearchScope '(cn=$userLogin)' nGWObjectID`; my $gwPoRaw = `ldapsearch -x -LLL -H ldap://$ldapServer -b $ldapSearchScope '(cn=$userLogin)' nGWPostOffice`; # Now dice the LDAP output so that it is usable. my @gwUserArray = split /\s+/, $gwUserRaw; my @gwPoArray = split /\s+/, $gwPoRaw; my $gwUser = $gwUserArray[-1]; if($gwUserArray[2]){ print "Groupwise identity exists: $gwUserArray[3]\n"; my @gwPoLong = split /,/, $gwPoArray[-1]; my @gwPoCn = split /=/, $gwPoLong[0]; my $gwPo = $gwPoCn[1]; # Using the PO name, retrieve the address and port of the GroupWise server, then dice it. my $gwNetworkRaw = `ldapsearch -x -LLL -H ldap://$ldapServer -b $gwPoArray[-1] '(cn=POA)' networkAddress`; my @gwNetworkRawArray = split /\s+/, $gwNetworkRaw; my @gwNetworkChunk = split /#/, $gwNetworkRawArray[-1]; my @gwNetwork = split /:/, $gwNetworkChunk[-1]; my $gwNetAddr = $gwNetwork [0]; my $gwNetPort = $gwNetwork [1]; # We now have all the variables we need. # Now we open the preferences file to find the line we need to alter. # We do it this way because it's an easily-munged Java XML file. my $gwPrefFile = '/Applications/GroupWise.app/Contents/Info.plist'; open (GWPREF, $gwPrefFile) or die "can't open $gwPrefFile $!"; while () { $replaceLine = $. if (/>Arguments\.*\-\@u=$gwUser\ -ipa=$gwNetAddr \ -ipp=$gwNetPort\ /Applications/GroupWise.app/Contents/Info.plist.temp"; system "mv -f /Applications/GroupWise.app/Contents/Info.plist.temp /Applications/GroupWise.app/Contents/Info.plist"; } else{ print "No Groupwise User.\n"; }