theObfuscated http://www.theobfuscated.org | A Project By Joseph Viscomi Thu, 27 Sep 2012 03:45:10 +0000 en hourly 1 http://wordpress.org/?v=3.2.1 Leveraging OpenSource and Freely Available Technology http://www.theobfuscated.org/2011/12/22/leveraging-opensource-and-freely-available-technology/ http://www.theobfuscated.org/2011/12/22/leveraging-opensource-and-freely-available-technology/#comments Thu, 22 Dec 2011 15:40:34 +0000 Joseph Viscomi http://www.theobfuscated.org/?p=508 Read more »

]]>
Recently I gave a talk at the Annual TABS conference about various OpenSource technologies and how they can relate to operating more efficiently and effectively with special attention to Unix/Linux/OSX infrastructures. I think it went over very well, and I was truly surprised how little of this stuff was used by schools. Especially when everyone is focused on keeping costs down. Many schools spend their money on services and contracts for software instead on great IT people that can be innovative for education, instead they are always putting out fires. So here are the slides : TABS Slides

]]>
http://www.theobfuscated.org/2011/12/22/leveraging-opensource-and-freely-available-technology/feed/ 0
Integrating Open Directory and Google Apps (Natively Syncing Open Directory Passwords to Google Apps) http://www.theobfuscated.org/2011/07/11/integrating-google-apps-with-open-directory/ http://www.theobfuscated.org/2011/07/11/integrating-google-apps-with-open-directory/#comments Tue, 12 Jul 2011 04:56:09 +0000 Joseph Viscomi http://www.theobfuscated.org/?p=428 Read more »

]]>

I have been reviewing for some time the different ways which are available to push password change updates from a Apple Open Directory (OpenLDAP) Master to our Google Apps domain, and I have waited for some time for a solution I could go with. However, I was and have been unsatisfied with the solutions which are available for OS X. I wanted a very simple, secure, and natively run solution – running on my snow leopard server or lion server. Simple is a major part here, while some people don’t mind getting into configs and changing them I wanted it to be, run a installer, answer some easy questions, and bam! So below are my personal requirements for this first round of development.

 

Integrating Google Apps with Open Directory Requirements

  1. Do NOT store a plaintext password on disk.
  2. No extra services (such as MySQL), I wanted to use a simple flat file structure, similar to svn, because it is one less thing to fail.
  3. Easily configurable, easy to extend, easy to archive, easy to remove.
  4. When a user changes their LDAP password it should change their Google Apps password.
  5. If a user sets a password on a LDAP account which does not exist in Google Apps, it should be created.
  6. It should work for multiple Google Apps Domains.
  7. Install it & forget about it.

So I wrote a simple series of bash scripts, and an easy installer & uninstaller to accomplish what I wanted. While this is my first iteration of this tool it is currently in the last stages of production deployment testing, and I believe this to be ready to be used by most. I tried reasonably well to make the setup easy and very straight forward. Everything that is needed for this to work is already on OS X Server or included in the installer.

This is designed to be installed on your ODM, while the installer is NOT fool proof – I believe it to handle the most common cases and setups without problem. I will be developing this more and maturing the features, but I am currently focusing on my own needs, so I would really like to hear what would be popular to add.

It makes heavy use of openssl for storing confidential information using public key cryptography, this also allows root to actually recover a password if the situation ever arises. The tools that are installed with this are required to be run by root as well as access to the flat file structure it uses to store information in, this is intentional so that it adds a measure of security as to who can access it. Because if someone has access to your ODM as root all bets are off anyway.

It also uses Apple’s native launchd instead of cron because of the discontinuing support of cron on Apple’s platform. I believe this is the easiest most straight forward solution I have come across for syncing passwords from OpenDirectory to Google Apps on OS X.

There are some conventions to follow in order for this to work properly and they are as follows:

  1. In each of the user accounts in OD make sure their full Google App email account is entered under the user info tab, it should be the only email address entered.
  2. In each of the Google App domains make sure you create the SAME domain admin user (the part before the @) with the SAME password.

All messages are printed to the system.log file, so watch this file if you want to see any errors or it just working. You might have to issue a -HUP or restart PasswordServer or ODM for changes to take effect, but I did not have to. Formal documentation will follow after the next release.

 

Installation is simple:

  1. Download latest zip file to Open Directory Master.
  2. Unzip file.
  3. Open Terminal
  4. Change to the setup directory inside the package (this is a must!).
  5. CD to the newly unzipped folder
  6. Run: sudo ./install.sh

googlePasswordSync Release Log:

CURRENT RELEASE: org.theObfuscated.googlePasswordSync

SPECIAL NOTE: Bugs should be filed under the issues section on GitHub at https://github.com/jjviscomi/googlePasswordSync/issues. Please include all the output from the logs and whatever else is necessary to help correct or identify the issue.

- Added Google Apps Directory Sync Integration Capability. (If you choose to it will now modify the users LDAP record to include a SHA hash of the password so that GADS can push that information to Google Apps.) However if you choose this option make sure you use DACL to prevent everyone from seeing this information.

—— RELEASE HISTORY ——

- Completely re-written from the ground up.

- Every account now has its own private / public key pair

- Will now sync all registered accounts to Google Apps at specified intervals (not just when a password is changed in ldap)

- Better diagnostic information during install

- Tested & confirmed working with the following servers: 10.5, 10.6 & 10.7

- Moved development to GitHub https://github.com/jjviscomi/googlePasswordSync

 

  • Minor Release Update: 07/22/2011 (DO NOT USE – REMOVED)

 - Updated a more generic ldap topology (thanks to Petter Olsson)

 Google Password Sync: org.theObfuscated.googlePasswordSync-0.1b4.zip

 

  • Minor Release Update: 07/22/2011 (DO NOT USE – REMOVED)

 - Updated a more generic ldap search path (thanks to Petter Olsson)

 Google Password Sync: org.theObfuscated.googlePasswordSync-0.1b3.zip

 

  • Minor Release Update: 07/12/2011 (DO NOT USE – REMOVED)

 - Added log files under /var/log/googlePasswordSync/

 - Corrected installer bugs (but did not effect functionality).

 Google Password Sync: org.theObfuscated.googlePasswordSync-0.1b2.zip


  • Initial Release Date: 07/11/2011 (REMOVED)

-Google Password Sync: org.theObfuscated.googlePasswordSync-0.1b1.zip

]]>
http://www.theobfuscated.org/2011/07/11/integrating-google-apps-with-open-directory/feed/ 32
One of the best lectures I have ever watched … http://www.theobfuscated.org/2011/05/04/randy-pausch/ http://www.theobfuscated.org/2011/05/04/randy-pausch/#comments Thu, 05 May 2011 02:21:06 +0000 Joseph Viscomi http://www.theobfuscated.org/?p=414 Read more »

]]>
The Last LectureRandy Pausch gave probably the best and bravest lecture I have ever witnessed by an academic, this is truly inspiring. Really an unbelievable take on truly how to live your life. It has been around a while but it really makes no difference, if you haven’t seen it you need to …

 

]]>
http://www.theobfuscated.org/2011/05/04/randy-pausch/feed/ 0
What does a degree give you? http://www.theobfuscated.org/2011/05/02/what-is-a-college-degree/ http://www.theobfuscated.org/2011/05/02/what-is-a-college-degree/#comments Mon, 02 May 2011 18:38:53 +0000 Joseph Viscomi http://www.theobfuscated.org/?p=393 Read more »

]]>
GraduationThe impending end for many successful college students is near, graduation is upon us! I remember my wife’s (although not at the time) and my own undergraduate commencement cerimonies and that got me thinking of the thoughts I had upon ending my undergraduate career. I remember when making the choice to attend school, it wasn’t to “get a job” or give me a sense of “enlightenment” – it was to get a degree.

So just let me clarify that little bit …

I was brought up to work out and solve problems, to think analytically, basically to use your brain to figure things out. I was  a problem solver, self reliant, and very hard working (not necessarily true about school work). I had some great mentors and loving people that guided me, they were part of my alliance and not people that adored me. There is a distinct difference between people that are on your team v. people that adore you. People that adore you don’t tell you your faults, your problems, or when they generally are dissatisfied and upset with you. It is very easy to surround yourself with people that adore you. People on your team however will tell you when you do a good job, but they will also be critical of you and tell you when you are not, what they don’t like about what you are doing and offer suggestions to improve yourself. This is the kind of people you want around you! Because in the process of getting to where I am now I screwed up a lot, and I made some really bad decisions along the way. It was these people that pointed them out (if they were not already evident) and then supported me in understanding and learning form them.

It is also important to note that I tried to surrond myself with very smart people – people that knew more than I did, had more experience than I did, and were willing to show me how they thought. You see you cannot improve yourself or your knowledge base in anything if there are not better people around you to push you, guide you, and challenge you.

The most importiant thing I realized, when it came to problem solving, which was pointed out to me when I was very young by my uncle was “it is the thought process that is important”, it is how you go about solving a problem – NOT ABOUT WHAT YOU KNOW!  Good problem solvers can be placed in any situation (any domain) and in a matter of minutes be asking the right questions to lead them down the path to find the solution. This is because they understand how to break apart problems and attack it correctly, this is perhaps the most valuable skill I have ever learned. So it is not in the answer that one gains knowledge, it is in the act of actually solving the problem. So when my mentors talked out the problems with me, shared what they were thinking, and why. It was giving me a glimpse into their thinking process – which is perhaps the tool I use the most to this day.

This all circles back around now to my post title, What Does a Degree Give You. It gave me a piece of paper … I am a firm believer that this type of skill is not normally learned in a classroom it was a part of my life and those around me made an active effort to teach me. Let there be NO mistake about it, they knew what they were doing and I am grateful.

You cannot place emphasis on college to teach you everything you will ever need to know, or for that matter to effectively prepare you for a career. Let me give you an example:

After 3 years as a computer science student I was able to land a job as a software engineer (something I have already been doing). The interview process was great fun, I was presented with fantastic problems that involved logic, coding, and commonly know algorithms. I thought it was enjoyable to talk with well established engineers and discuss with them about how I would solve the problems, now I assume I did well since I got the job, but I don’t remember one question that I was asked that I studied for in college, although I would have to say as far as a difficulty level it would rank as harder then any test I have ever taken (at least as an undergraduate). An example of one of the coding questions I was asked is: In an array of integers return a sub array with the largest sum, ensure that the resulting function runs in O(n).

The point being here is they were testing my ability to solve problems, I was presented with 4 other questions and was given 10 min to solve each of them. When I started I was excited. I took a seat at my desk and they introduced me to their environment, and then Bam! They hit me with their own custom embedded language, over a million line API … In school I learned LISP and C/C++, I had experience in another dozen or so languages, but I considered myself to be an expert in these languages. It suddenly didn’t matter that I knew almost every construct in LISP and C, I though to myself how am I ever going to learn this and be worth my pay?

So to keep an already long story short, I did and it all worked out. Turns out LISP and C are the two best languages to know (at least in my opinion) between the two of them I was familiar with all the cool things you can do in programming so it was just a matter of syntax I didn’t have to comprehend concepts like dynamic typing, pointers, preprocessing, classes, objects, and closures. I simply took home the documentation read it and learned it. In about a week I was churning out quality code for the company, and I felt pretty good.

However no one showed me, I was never taught how to use their language. I was expected after given a toolset to be able to utilize their documentation and solve problems. Because how good in am employee that has to keep asking how or why, then two people are not working!

Now in my current position I routinely have to deal with problems that often are very complicated in nature, and there are no documented solutions so we have to invent them. This is no big deal, but it can be frustrating. How did college help me with this? It didn’t again I bring this back to my experience of growing up and how I was raised. I am sure I learned somethings in college, mostly high level mathematics, and some other pretty useless stuff for the ordinary person. Other than that college was and extremely fun time it let me come into my own, it let me experience life without the parental units watching over anything I did. I developed my own opinions, I was exposed to culture outside of my normal home life, and I made some great friends. This is the value of college in my mind, it allow you to come into your own and that is why I have a high value for someone who “went away” for college.

People that have left everyone and everything behind them. This adds something to a persons character that I don’t believe happens any other way, or at least it takes a person much longer if at all to truly develop their self.

So to sum it all up then …

A college degree gets you; a piece of paper, a bunch of friends, your own views & opinions, exposed to culture, and a basic set of common knowledge.

A college degree doesn’t; get you a job, give you true knowledge, get you experience, prepare you for a life long career, make you intelligent.

So focus on really learning and maximizing your experiences – it is not just about a grade!

 

]]>
http://www.theobfuscated.org/2011/05/02/what-is-a-college-degree/feed/ 0
A simple look on perspective … http://www.theobfuscated.org/2011/05/01/a-simple-look-on-perspective/ http://www.theobfuscated.org/2011/05/01/a-simple-look-on-perspective/#comments Sun, 01 May 2011 18:40:24 +0000 Joseph Viscomi http://www.theobfuscated.org/?p=361 Read more »

]]>
Picture of EarthThis is a simple little lecture  by Carl Sagan titled – The Little Blue Dot. I believe it puts things into perspective in a very elegant way. I thought it splendid and wanted to share it.

People don’t often take the time to reflect and realize what does matter and where we stand in the vastness of the universe. When you do think about it the perspective is very humbling…

 

]]>
http://www.theobfuscated.org/2011/05/01/a-simple-look-on-perspective/feed/ 0
Removing ‘other’ Users Home Folders – in a mobile home folder environment http://www.theobfuscated.org/2011/04/10/deleting-other-users-home-folders/ http://www.theobfuscated.org/2011/04/10/deleting-other-users-home-folders/#comments Sun, 10 Apr 2011 15:15:56 +0000 Joseph Viscomi http://www.theobfuscated.org/?p=159 Read more »

]]>
OS X Home FolderIf you have a large network that uses mobile home folders which allows multiple users to access any given machine, but each machine is assigned a primary user then this little addition to your login hook might be for you. Let me clarify when I say ‘Allow multiple users access’, I mean they can authenticate to a machine but normally DO NOT work on it. The ‘Primary User’ is the person who is expected to be logged into this machine the majority of the time, but say another user need to check their e-mail or get a document, or something where they need access for a limited time – then this little bit of code will remove any of their personal files when the ‘Primary User’ logs back in.

# Author: Joseph J. Viscomi    E-Mail: jjviscomi [at] gmail [dot] com || jviscomi [at] brehm [dot] org
# Date: 3/11/2011
# Description: This script can be included in a login hook when you want to remove all mobile or other home folders that
#              do not belong to the primary user of this computer. Mainly used to remove unwanted files and free disk space.
#              Once this script is applied in order for it to work correctly the first person that logs in must be the
#              'Primary User' of the computer.
#
#		Every time the 'Primary User' signs on to the computer it will remove all other home folders.
#
#              If you want to reset the 'Primary User' run the command - sudo rm -f /var/log/currentUser.log
#              then restart the computer and login as the 'Primary User'

#REMOVE HOME FOLDERS FOR NON-PRIMARY USERS
#CHECK TO MAKE SURE THE USER LOGGING IN HAS A HOME FOLDER
if [ -d "/Users/$1" ]; then
	#CHECKS TO SEE IF THE FILE THAT CONTAINS THE 'PRIMARY USER' EXISTS
	if [ -e "/var/log/currentUser.log" ]; then
		#CHECK TO SEE IF THE CURRENT USER IS THE 'PRIMARY USER'
		if [ `cat /var/log/currentUser.log` = $1 ]; then
                        #REMOVE ALL OTHER USER HOME FOLDERS - NOTE: DO NOT REMOVE Shared FOLDER, THIS CAN CAUSE PROBLEMS!
			#LOG THE OPERATIONS TO SYSLOG
			ls  /Users/ | grep -v `cat /var/log/currentUser.log` | grep -v Shared | xargs -I {} sudo rm -vrf /Users/{} >> /var/log/system.log
		fi
	else
		#IF THE FILE WHICH CONTAINS THE CURRENT USER DOESN'T EXISTS THEN THE PERSON THAT IS LOGGIN IN MUST THE 'PRIMARY USER'
		#RECORD THEIR USER NAME IN THE LOG FILE FOR FUTURE USE.
		sudo echo $1 > /var/log/currentUser.log
	fi
fi

The above script has been simplified for easy readability and commented to improve understanding of what is going on.

]]>
http://www.theobfuscated.org/2011/04/10/deleting-other-users-home-folders/feed/ 0
Tracking a Mac laptop over the internet (locating a stolen laptop) http://www.theobfuscated.org/2011/04/08/tracking-a-mac-over-the-internet/ http://www.theobfuscated.org/2011/04/08/tracking-a-mac-over-the-internet/#comments Fri, 08 Apr 2011 08:41:24 +0000 Joseph Viscomi http://www.theobfuscated.org/?p=209 Read more »

]]>
This is an example of what you can achieve with just a little work, this is meant to provide more of an idea than an actual production piece of code (however it seems like a good place to start). So the problem I want to address is the ability to track Mac laptops in the wild, via the internet. I want to know where in the entire world and when my laptops are on line, even be able for them to fetch commands (future post) based on their status. This is ment to be simple I threw this idea together in about two hours (from start to finish) so not polished, but effective. This tutorial has a couple of distinct pieces you need:

  1. Client computers running os x, 10.6 in this case, but 10.5 should also work.
  2. A web server that is accessible over the internet and able to run PHP server side scripts.
  3. A mysql server accessible by the web server.

Lets begin by examining the client bash script that will send data to our web server, there are a few things to configure in it.

#!/bin/bash

# Author: Joseph J. Viscomi    E-Mail: jjviscomi [at] gmail [dot] com || jviscomi [at] brehm [dot] org
# Website: http://www.theobfuscated.org
# Date: 4/6/2011
# Description: This script when run will send information about itself to a webserver.
#              It can be used to track computers in the wild, on the internet. This is
#              the first of two files that will need to be installed on the clients.
#              For full functionality you will also need the server side code to handle
#              this script.
#              I have provided a basic verson of this for educational purposes only.
#              This is an attempt to show you what can be possible, this can be extended
#              to relay any information back to a server, and it can even be used for
#              two-way communications (post to follow).

# STEP 1.
#       CREATE A DIRECTORY ON THE CLIENT MACHINES: sudo mkdir /etc/.callHome/
#       CHANGE THE HOMEADDRESS TO POINT TO THE CORRECT DIRECTORY ON YOUR WEBSERVER WHERE THE callHome.php IS LOCATED
#       SET THE UNIQUE LOCATIONID - USE ONLY UPPERCASE AND NUMBERS, UPTO 64 CHARS
#       SAVE AND SET THE FILE TO EXECUTABLE, sudo chmod +x callHome.sh
#       PLACE THIS FILE IN /etc/.callHome/

# STEP 2.
#       PLACE THE org.theObfuscated.callHome.plist FILE IN THE /Library/LaunchDaemons/ DIRECTORY
#       IT IS SET TO CALL IN EVERY 10 MIN, THIS CAN BE CHANGED.

# STEP 3.
#       launchctl load /Library/LaunchDaemons/org.theObfuscated.callHome.plist

#THIS IS THE ADDRESS THE COMPUTER CALLS HOME TO, IP OR FQDN
# - CHANGE THIS TO REFLECT WHERE THE SERVER SIDE SCRIPT RESIDES
HOMEADDRESS="www.theobfuscated.org/callHome/"
#THIS IS THE NAME OF THE SERVER SIDE SCRIPT TO HANDLE THE REQUEST
SCRIPTNAME="checkin.php"

#THIS IS LIKE A SITE PASSWORD, JUST A BASIC SECURITY MEASURE - MAKE SURE IT MATCHES WHAT YOU HAVE IN THE DB
#EACH SITE SHOULD HAVE A UNIQUE LOCATIONID
LOCATIONID="SDJELK45689DSK"

#GET THE MAC ADDRESS OF THE MACHINE THAT IS CALLING HOME
LOCALMAC=`(/sbin/ifconfig en0 | awk '/ether/ { gsub(":", ""); print $2 }')`
#GET THE PUBLIC IP ADDRESS OF WHERE THIS MACHINE IS CURRENTLY CONNECTED TO THE INTERNET
EXTERNALIP=`(curl -s http://checkip.dyndns.org | awk '{print $6}' | awk ' BEGIN { FS = "<" } { print $1 } ')`
#GET THE SERIAL NUMBER OF THIS MACHINE
SERIALNUMBER=`ioreg -l | grep IOPlatformSerialNumber | awk '{ print $4 }' | sed "s/^\([\"']\)\(.*\)\1\$/\2/g"`
#GET THE TIME IN DAYS SINCE THE LAST RESTART
UPTIMEDAYS=`(uptime | awk '{ print $3 }')`
#GET THE USERNAME OF THE CURRENT USER
CURRENTUSER=`whoami`
#GET THE CURRENT HOSTNAME
HOSTNAME=`hostname`

#CHECKIN SITE
HOMESITE="http://"$HOMEADDRESS"/"$SCRIPTNAME"?mac="$LOCALMAC"&hostname="$HOSTNAME"&user="$CURRENTUSER"&days="$UPTIMEDAYS"&ip="$EXTERNALIP"&serial="$SERIALNUMBER"&loc="$LOCATIONID

#GET THE RESPONSE FROM THE SERVER
HOMERESPONSE=`(curl -s $HOMESITE)`

#RECORD IN THE LOCAL LOG
echo "$HOMERESPONSE" >> /Library/Logs/callHome.log

The above script can be download here, for simplicity call it what we do, callHome.sh. The first thing you will need to edit the script at line # 32
HOMEADDRESS="www.theobfuscated.org/callHome/"
It should point to the directory on your web server where the server side script will reside. It is important to exclude the http:// but to include the trailing slash. Now depending on if you modify the name of the file on the server (I recommend you do not) you might need to change line # 34, this needs to be the file that will accept the client communications.

Line # 38 is the next important line, this is here for some simple security. This is a randomly generated “Location ID”, randomly type some upper case & numeric characters here (up to a maximum length of 64). However you have to write this down for a later step, we will refer to this as the LOCATIONID, this should not be shared with anyone else.

This is all the editing you have to do in this script. Save it to the following location: /etc/.callHome/callHome.sh
Make sure this script is executable (i.e. sudo chmod +x /etc/.callHome/callHome.sh). Just because we have this script now on the client computers doesn’t mean we are finished yet.

We want to make sure it will regularly contact our web server and register with it, and to do that we will run it as a Launch Deamon. To simplify this process I have created a plist file that will tell launchd to run this script every 10 minuets, it is displayed below:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
  <dict>
    <key>Label</key>
    <string>org.theObfuscated.callHome</string>
    <key>OnDemand</key>
    <true/>
    <key>StartInterval</key>
    <integer>600</integer>
    <key>ProgramArguments</key>
    <array>
      <string>/private/etc/.callHome/callHome.sh</string>
    </array>
  </dict>
</plist>

Line # 10 specifies how often the script should be run, in this case every 600 seconds. Feel free to change this, but I would suggest to wait until after you confirm this is working. This file should be called org.theObfuscated.callHome.plist , down load it here. This file needs to be saved in the following location: /Library/LaunchDaemons/org.theObfuscated.callHome.plist and then we just need to tell launchd to load it, however this should wait until we have our servers configured properly first.

 

Configuring the Server side PHP Recording Script & MySQL DB.

Copy  this file to the location you desire on your web server, it should be the same location and name as indicated earlier when configuring the client script.

<?php
/**
 * User: Joe Viscomi | jjviscomi [at] gmail [dot] com | www.theobfuscated.org
 * Date: 4/6/11
 * Time: 8:29 PM
 * Description: Simple PHP Script to handle reporting from clients.
 */

    //#CHANGE THESE SETTING TO REFLECT YOUR DATABASE
    $DBHOST="localhost";
    $DBUSER="root";
    $DBPASSWORD="root";
    $DBNAME="call_home";

    //#GET KEY VAULES TO AUTHENTICATE THE REMOTE COMPUTER
    $location_hash = $_GET['loc'];
    $mac_address = $_GET['mac'];
    $computer_serial = $_GET['serial'];

    //#CONNECT TO THE DATABASE
    $db_link = mysql_connect($DBHOST,$DBUSER,$DBPASSWORD);
    mysql_select_db($DBNAME, $db_link);

    //#THIS IS THE AUTHENTICATION QUERY
    $sql  = "SELECT `LOCATION`.`LOCATION_id`, `LOCATION`.`LOCATION_name`, `COMPUTER`.`COMPUTER_mac`, ";
    $sql .= "`STATUS`.`STATUS_name`, `STATUS`.`STATUS_id`, `COMPUTER`.`COMPUTER_id` ";
    $sql .= "FROM `LOCATION`, `COMPUTER`, `STATUS` ";
    $sql .= "WHERE `LOCATION`.`LOCATION_active` = '1' AND `LOCATION`.`LOCATION_hash` = '".$location_hash;
    $sql .= "' AND `COMPUTER`.`COMPUTER_mac` = '". $mac_address ."' AND ";
    $sql .= "`COMPUTER`.`LOCATION_id` = `LOCATION`.`LOCATION_id` AND ";
    $sql .= "`COMPUTER`.`COMPUTER_serial` = '". $computer_serial ."' AND `COMPUTER`.`COMPUTER_active` = '1' AND ";
    $sql .= "`COMPUTER`.`STATUS_id` = `STATUS`.`STATUS_id`";

    //#QUERY THE DB TO SEE IF THIS COMPUTER SHOULD EVEN CALL HOME
    $result = mysql_query($sql, $db_link);
    $computer = mysql_fetch_array($result);
    mysql_free_result($result);

    //IF $COMPUTER HAS A SIZE OF 12 THEN A RECORD EXISTS FOR THE REMOTE COMPUTER
    if(sizeof($computer) === 12){

        //GET LAST CONTACT TIME
        $sql  = "SELECT MAX(`CONTACT-LOG`.`CONTACT-LOG_doc`) FROM `CONTACT-LOG` WHERE `CONTACT-LOG`.`COMPUTER_id` = '";
        $sql .= $computer['COMPUTER_id']."' AND `CONTACT-LOG_active` = '1'";
        $result = mysql_query($sql, $db_link);
        $last = mysql_fetch_array($result);
        mysql_free_result($result);

        //LOG THE REMOTE CONTACT
        $sql  = "INSERT INTO `call_home`.`CONTACT-LOG` (`CONTACT-LOG_id`, `COMPUTER_id`, `STATUS_id`, ";
        $sql .= "`CONTACT-LOG_hostname`, `CONTACT-LOG_user`, `CONTACT-LOG_uptime`, `CONTACT-LOG_ip`, ";
        $sql .= "`CONTACT-LOG_client`, `CONTACT-LOG_doc`, `CONTACT-LOG_active`) VALUES (NULL, ";
        $sql .= "'" . $computer['COMPUTER_id'] . "', '" . $computer['STATUS_id'] . "', '" . $_GET['hostname'];
        $sql .= "', '".$_GET['user']."', '".$_GET['days']."', '".$_GET['ip']."', '" .$_SERVER['REMOTE_ADDR'];
        $sql .= "', CURRENT_TIMESTAMP, '1')";
        mysql_query($sql);

        //GET LAST CONTACT TIME - NOW
        $sql  = "SELECT MAX(`CONTACT-LOG`.`CONTACT-LOG_doc`) FROM `CONTACT-LOG` WHERE `CONTACT-LOG`.`COMPUTER_id` = '";
        $sql .= $computer['COMPUTER_id']."' AND `CONTACT-LOG_active` = '1'";
        $result = mysql_query($sql, $db_link);
        $current_date = mysql_fetch_array($result);
        mysql_free_result($result);

        //COMPUTER HAS ACCOUNT
        echo("[" . $_SERVER['SERVER_ADDR'] ."][" .$current_date['MAX(`CONTACT-LOG`.`CONTACT-LOG_doc`)'] . "]:" .
             "Computer Account Found\r\n");
        echo("[" . $_SERVER['SERVER_ADDR'] ."][" .$current_date['MAX(`CONTACT-LOG`.`CONTACT-LOG_doc`)'] . "][" .
             "STATUS]: " . $computer['STATUS_name'] . "\r\n");
        echo("[" . $_SERVER['SERVER_ADDR'] ."][" .$current_date['MAX(`CONTACT-LOG`.`CONTACT-LOG_doc`)'] . "][" .
             "TIME OF LAST CONTACT]: " . $last['MAX(`CONTACT-LOG`.`CONTACT-LOG_doc`)']);

    }else{
        echo("[" . $_SERVER['SERVER_ADDR'] ."][" .$current_date['MAX(`CONTACT-LOG`.`CONTACT-LOG_doc`)'] . "]:" .
             "Computer Account Not Found\r\n");
    }

    mysql_close($db_link);

?>

Lines # 11-14 are the only lines you need to change here, they need to reflect the setting to access your mysql database server. Then save this file as stated earlier in the proper location in you web server this can be downloaded here in zip format.

The last step is to setup the MySQL server DB and table structure and populate it with the inventory of the computers it is suposed to keep track of. You can download the sql file that will create all the necessary tables and default values for you here. It is also displayed below for you to read if you wish, however the detail is not that important.

SET SQL_MODE="NO_AUTO_VALUE_ON_ZERO";

/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
/*!40101 SET NAMES utf8 */;

--
-- Database: `call_home`
--

-- --------------------------------------------------------

--
-- Table structure for table `COMPUTER`
--

CREATE TABLE `COMPUTER` (
  `COMPUTER_id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `LOCATION_id` int(10) unsigned NOT NULL,
  `COMPUTER_serial` varchar(64) NOT NULL,
  `COMPUTER_mac` varchar(64) NOT NULL,
  `STATUS_id` smallint(5) unsigned NOT NULL DEFAULT '1',
  `COMPUTER_active` smallint(5) unsigned NOT NULL DEFAULT '1',
  PRIMARY KEY (`COMPUTER_id`),
  UNIQUE KEY `COMPUTER_serial` (`COMPUTER_serial`,`COMPUTER_mac`),
  KEY `COMPUTER_active` (`COMPUTER_active`),
  KEY `LOCATION_id` (`LOCATION_id`),
  KEY `STATUS_id` (`STATUS_id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ;

--
-- Dumping data for table `COMPUTER`
--

-- --------------------------------------------------------

--
-- Table structure for table `CONTACT-LOG`
--

CREATE TABLE `CONTACT-LOG` (
  `CONTACT-LOG_id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
  `COMPUTER_id` int(10) unsigned NOT NULL,
  `STATUS_id` smallint(5) unsigned NOT NULL,
  `CONTACT-LOG_hostname` varchar(128) NOT NULL,
  `CONTACT-LOG_user` varchar(128) NOT NULL,
  `CONTACT-LOG_uptime` smallint(5) unsigned NOT NULL,
  `CONTACT-LOG_ip` varchar(64) NOT NULL,
  `CONTACT-LOG_client` varchar(64) NOT NULL,
  `CONTACT-LOG_doc` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  `CONTACT-LOG_active` smallint(5) unsigned NOT NULL DEFAULT '1',
  PRIMARY KEY (`CONTACT-LOG_id`),
  KEY `CONTACT-LOG_hostname` (`CONTACT-LOG_hostname`,`CONTACT-LOG_user`,`CONTACT-LOG_uptime`,`CONTACT-LOG_ip`,`CONTACT-LOG_client`),
  KEY `CONTACT-LOG_active` (`CONTACT-LOG_active`),
  KEY `COMPUTER_id` (`COMPUTER_id`),
  KEY `STATUS_id` (`STATUS_id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ;

--
-- Dumping data for table `CONTACT-LOG`
--

-- --------------------------------------------------------

--
-- Table structure for table `LOCATION`
--

CREATE TABLE `LOCATION` (
  `LOCATION_id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `LOCATION_hash` varchar(64) NOT NULL,
  `LOCATION_name` varchar(128) NOT NULL,
  `LOCATION_active` smallint(6) NOT NULL DEFAULT '1',
  PRIMARY KEY (`LOCATION_id`),
  UNIQUE KEY `LOCATION_hash` (`LOCATION_hash`),
  KEY `LOCATION_active` (`LOCATION_active`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ;

--
-- Dumping data for table `LOCATION`
--

-- --------------------------------------------------------

--
-- Table structure for table `STATUS`
--

CREATE TABLE `STATUS` (
  `STATUS_id` smallint(5) unsigned NOT NULL AUTO_INCREMENT,
  `STATUS_name` varchar(64) NOT NULL,
  `STATUS_active` smallint(6) NOT NULL DEFAULT '1',
  PRIMARY KEY (`STATUS_id`),
  KEY `STATUS_name` (`STATUS_name`,`STATUS_active`)
) ENGINE=MyISAM  DEFAULT CHARSET=latin1 AUTO_INCREMENT=6 ;

--
-- Dumping data for table `STATUS`
--

INSERT INTO `STATUS` VALUES(1, 'NORMAL', 1);
INSERT INTO `STATUS` VALUES(2, 'UPDATES REQUIRED', 1);
INSERT INTO `STATUS` VALUES(3, 'CRITICAL ERRORS', 1);
INSERT INTO `STATUS` VALUES(4, 'FORCE SHUTDOWN', 1);
INSERT INTO `STATUS` VALUES(5, 'STOLEN', 1);

Just make sure you create a database with the same name that is configured in the php file above (i.e. $DBNAME=”call_home”;). I suggest using a tool like phpMyAdmin to import the sql file and to make the following inserts, we will not cover this in this article, I will assume you can do/ figure this out:

INSERT INTO  `call_home`.`LOCATION` (
`LOCATION_id` ,
`LOCATION_hash` ,
`LOCATION_name` ,
`LOCATION_active`
)
VALUES (
NULL ,  'SDFA78ASDFA98F',  'MY HOME',  '1'
);

The insert above registers your LOCATIONID that was set on the client script, so replace SDFA78ASDFA98F with what ever you set earlier. Also Replace MY HOME with a description that is meaningful to your site location. Next we need to insert inventory of all the client computers this server can expect to hear from:

INSERT INTO  `call_home`.`COMPUTER` (
`COMPUTER_id` ,
`LOCATION_id` ,
`COMPUTER_serial` ,
`COMPUTER_mac` ,
`STATUS_id` ,
`COMPUTER_active`
)
VALUES (
NULL ,  '1',  'SERIALNUMBER',  'MACADDRESS',  '1',  '1'
);

Please note that you need to insert the serial number and the mac address for each Mac you want to track, you can get that by running the following commands respectively, then simply copy and paste it in place of  ’SERIALNUMBER’ and ‘MACADDRESS’:

ioreg -l | grep IOPlatformSerialNumber | awk '{ print $4 }' | sed "s/^\([\"']\)\(.*\)\1\$/\2/g"
/sbin/ifconfig en0 | awk '/ether/ { gsub(":", ""); print $2 }'

That is all we have to do to prepare the MySQL Server to record the clients announcements. It is importiant that if you do not insert the correct values then the computer calls will NOT be recorded by the server.

You can view the results in phpMyAdmin or you can include this server side script to display a simple table of the latest requests from all registered clients (I know this is sloppy but, again it is just a proof of concept):

<?php
/**
 * User: Joe Viscomi | jjviscomi [at] gmail [dot] com | www.theobfuscated.org
 * Date: 4/6/11
 * Time: 8:41 PM
 * Description: To Display the latest results from all registered clients!
 */

    //#CHANGE THESE SETTING TO REFLECT YOUR DATABASE
    $DBHOST="localhost";
    $DBUSER="root";
    $DBPASSWORD="root";
    $DBNAME="call_home";

    $db_link = mysql_connect($DBHOST,$DBUSER,$DBPASSWORD);
    mysql_select_db($DBNAME, $db_link);

    $sql  = "SELECT MAX(`CONTACT-LOG`.`CONTACT-LOG_doc`), `CONTACT-LOG`.`CONTACT-LOG_user`, `CONTACT-LOG`.`CONTACT-LOG_ip`, ";
    $sql .= "`CONTACT-LOG`.`CONTACT-LOG_client`, `CONTACT-LOG`.`CONTACT-LOG_hostname`, `CONTACT-LOG`.`CONTACT-LOG_uptime` FROM `CONTACT-LOG` ";
    $sql .= "WHERE EXISTS (SELECT * FROM COMPUTER WHERE `CONTACT-LOG`.COMPUTER_id = COMPUTER.COMPUTER_id ";
    $sql .= "AND COMPUTER_active = 1)";

    $result = mysql_query($sql,$db_link);

    $lastContactPage  = "<table class=\"sample\">\n";
    $lastContactPage .= "<tr>";
    $lastContactPage .= " <th>HOSTNAME</th>\n";
    $lastContactPage .= " <th>PUBLIC IP</th>\n";
    $lastContactPage .= " <th>CLIENT IP</th>\n";
    $lastContactPage .= " <th>USER</th>\n";
    $lastContactPage .= " <th>UP TIME (DAYS)</th>\n";
    $lastContactPage .= " <th>TIME OF LAST CONTACT</th>\n";
    $lastContactPage .= "</tr>";

    while($row = mysql_fetch_array($result)){
        $lastContactPage .= "<tr>\n";
        $lastContactPage .= "  <td>" . $row['CONTACT-LOG_hostname'] . "</td>\n";
        $lastContactPage .= "  <td>" . $row['CONTACT-LOG_ip'] . "</td>\n";
        $lastContactPage .= "  <td>" . $row['CONTACT-LOG_client'] . "</td>\n";
        $lastContactPage .= "  <td>" . $row['CONTACT-LOG_user'] . "</td>\n";
        $lastContactPage .= "  <td>" . $row['CONTACT-LOG_uptime'] . "</td>\n";
        $lastContactPage .= "  <td>" . $row['MAX(`CONTACT-LOG`.`CONTACT-LOG_doc`)'] . "</td>\n";
        $lastContactPage .= "</tr>\n";
    }

    $lastContactPage .= "</table>\n";

    mysql_free_result($result);
    mysql_close($db_link);

    echo "<html><head><title>Client Up Time</title>";
    echo "<style type=\"text/css\">" .
         "  table.sample {" .
	     "    border-width: 0px;" .
	     "    border-spacing: 2px;" .
	     "    border-style: none;" .
	     "    border-color: gray;" .
	     "    border-collapse: separate;" .
	     "    background-color: white;" .
         "  }" .
         "  table.sample th {" .
	     "    border-width: 0px;" .
	     "    padding: 2px;" .
	     "    border-style: inset;" .
	     "    border-color: gray;" .
	     "    background-color: rgb(250, 240, 230);" .
	     "    -moz-border-radius: ;" .
         "  }" .
         "  table.sample td {" .
	     "    border-width: 0px;" .
	     "    padding: 2px;" .
	     "    border-style: inset;" .
	     "    border-color: gray;" .
	     "    background-color: rgb(250, 240, 230);" .
	     "   -moz-border-radius: ;" .
         "  }" .
         "</style>";
    echo "</head>";
    echo "  <body>".$lastContactPage."</body>";
    echo "</html>";

That is it all we have to do now is enable the clients, or load our script to launchd. So on each of the clients run the following command:

launchctl load /Library/LaunchDaemons/org.theObfuscated.callHome.plist

That should be it … I have tested this, but in my hurry to put this together I might have included some errors in this post, please let me know so that I can correct them! I hope this provides a clear and clean example of how this all could work. Eventually I might post a more polished packaged solution that can be used by anyone.

Feel free to extend this or clean it up, and let me know so I can put it on the site.

]]>
http://www.theobfuscated.org/2011/04/08/tracking-a-mac-over-the-internet/feed/ 2
Getting the size of a directory using bash http://www.theobfuscated.org/2011/04/07/directory-size-in-bash/ http://www.theobfuscated.org/2011/04/07/directory-size-in-bash/#comments Thu, 07 Apr 2011 17:41:53 +0000 Joseph Viscomi http://www.theobfuscated.org/?p=188 Read more »

]]>
Sometimes as a system admin you would like to automate tasks based on how large a particular directory/folder is on a computer, or for a homework assignment in school. The very simple script below takes one argument, a path to the folder you would like to know the size of. It then will calculate the total size on the disk this folder and it contents take up and return in MB the folder size. It is a very simple script so I could see this being helpful to people new to bash scripting.

#!/bin/bash

# Author: Joseph J. Viscomi   E-Mail: jviscomi [at] brehm [dot] org || jviscomi [at] brehm [dot] org
# Date:   3/23/2011
# Arguments: Absolute path to a folder.
# Description: Prints the size of the folder in MB to standard out.
# Erros: Should handle all errors gracfully by returning -1.

# Checks to see that you gave it a directory and that it
# exists!
if [ $# = 1 ] && [ -d $1 ]
then
  du -sm $1 | cut -f 1
else
  # Echo -1 since NO folder can take up -1 M
  echo -1
fi

exit
]]>
http://www.theobfuscated.org/2011/04/07/directory-size-in-bash/feed/ 0
How to reset an Open Directory Administrator’s password http://www.theobfuscated.org/2011/04/05/reset-open-directory-admin-password/ http://www.theobfuscated.org/2011/04/05/reset-open-directory-admin-password/#comments Tue, 05 Apr 2011 23:09:06 +0000 Joseph Viscomi http://www.theobfuscated.org/?p=174 Read more »

]]>
Resting a Open Directory PasswordThis is a trivial task when you are a Directory Administrator, however what if you find yourself in a situation of when your admin has left or disappeared without notice and no one else has the directory admin password … or in my case: Something really bad happened to your Open Directory Master and the directory administrator can no longer access the directory.

In the latter some might say restore from backups, but that should be an absolute last resort, and in reality backups are good for data restoration NOT system states. Well the key here is you still have to have full (root) access to the Directory Master (locally). In plain english you need to retrive the slot-id for the directory administrator and change its db password hash. I think if I have to explain it all to you then you probably shouldn’t be the one in charge to remedy this situation or you will understand by just looking how to do it. So for both cases here is a little script changeDirectoryAdminPassword.sh.

#!/bin/bash

# Author: Joseph J. Viscomi    E-Mail: jjviscomi [at] gmail [dot] com || jviscomi [at] brehm [dot] org
# Date: 2/10/2010
# Description: This script is interactive, it prompts you for a new password. It
#              will get the slot-id for the given user and attempt to change it's
#              password. This needs to be run using sudo.

if [ $# = 1 ]; then
  echo "Going to change password for $1"
  echo -n "slot id: "
  echo `sudo mkpassdb -dump | grep $1 | awk '{ print $3 }'`
  sudo mkpassdb -setpassword `sudo mkpassdb -dump | grep $1 | awk '{ print $3 }'`
fi

The above script takes exactly one argument, the short name of the directory administrator.  If you follow the manual when creating your Open Directory Master it is labeled as diradmin (which should be changed …) so this command would be run like the following:

sudo ./changeDirectoryAdminPassword.sh diradmin

Simply follow it if you want to know what it is doing, line 13 is where the magic happens! I have never actually run this script so their might be a typo or something. If there is a problem let me know and I will correct it, but it looks good. I hope no one ever needs to deal with this.

]]>
http://www.theobfuscated.org/2011/04/05/reset-open-directory-admin-password/feed/ 0
How to make a bootable flash drive in OS X http://www.theobfuscated.org/2011/04/04/making-a-bootable-flash-drive-in-osx/ http://www.theobfuscated.org/2011/04/04/making-a-bootable-flash-drive-in-osx/#comments Mon, 04 Apr 2011 05:14:47 +0000 Joseph Viscomi http://www.theobfuscated.org/?p=109 Read more »

]]>
This tutorial has to do with making a bootable flash drive, this would be useful when you do not want to burn a bootable image to a CD or DVD instead loading it to a flash drive. I am sure most of you know by now you just cannot copy the files over and reboot to the device. This will explain how to make such a device bootable using OS X, but can be easily translated to Linux or other versions of Unix. Now there exist other tutorials on the internet, and they are probably better – but this was a request from a friend so here it goes…

First of all you need to get a bootable image that you want to install to the flash drive, in this tutorial the type of file will have to be of type .img. However most files are not that you will more commonly find a .iso file on the net, in that case we can use a program called hdiutil to convert it to the file type we want, in general hdiutil is a program to manipulate disk images, it is a very hand program and I would suggest reading it’s man page.

To convert from .iso to .img you would use the following command:

hdiutil convert -format UDRW -o destination.img source.iso

Sometimes OS X appends a .dmg file extension, simple rename it. Next you have to know what device file your flash drive mounts as. This is easy enough to figure out, we simply run another program. This time we will use diskutil, another very hand program. Among other things diskutil can list all of the device files that are currently mounted, make sure your flash drive is not connected then issue the following command:

diskutil list

Please take a note of which disks are there, on my machine the output is listed below:

theObfuscated$ diskutil list
/dev/disk0
   #:                       TYPE NAME                    SIZE       IDENTIFIER
   0:      GUID_partition_scheme                        *121.3 GB   disk0
   1:                        EFI                         209.7 MB   disk0s1
   2:                  Apple_HFS Macintosh HD            121.0 GB   disk0s2

Please make note of your output, then insert the flash drive you would like to use, and again run diskutil. My output again is listed below:

theObfuscated$ diskutil list
/dev/disk0
   #:                       TYPE NAME                    SIZE       IDENTIFIER
   0:      GUID_partition_scheme                        *121.3 GB   disk0
   1:                        EFI                         209.7 MB   disk0s1
   2:                  Apple_HFS Macintosh HD            121.0 GB   disk0s2
/dev/disk1
   #:                       TYPE NAME                    SIZE       IDENTIFIER
   0:     FDisk_partition_scheme                        *4.0 GB     disk1
   1:                 DOS_FAT_32 MY STUFF                4.0 GB     disk1s1

Notice the new section listed after the old one, here it begins on line 7. On that line it indicates what device file your flash drive is mounted to, in this case the information we want is:

/dev/disk1

Next we need to unmount the disk, again we will use the diskutil command to accomplish this:

diskutil unmountDisk /dev/disk1

The only difference you might have for this command is to substitue /dev/disk1 with your device file. Now we will getto the meat of it, actually writing the image to the device. Again we will use another program, this time it is the old dd command. This command is to convert and copy files, it has been around as long as I can remember and if you want more info I suggest to check out it’s man page.

This command needs to be run as root so the command to copy the image to the device is:

sudo dd if=source.img of=/dev/rdisk1 bs=1m

Now there are a few things to state about this command.

  1. You should supply the complete path to your source.img file.
  2. I used /dev/rdisk1 instead of /dev/disk1 this is just to improve speed of the operation.
  3. This might take a while depending on the size of the image.
  4. It will completely erase all data currently on the flash drive.

Once this operation has finished we need to saftly eject the flash drive, and you might have guested it by now we will use our friend diskutil:

diskutil eject /dev/disk1

Remove your flash drive and you are finished. You should now be able to boot from it! Hope this little how to has helped!

 

]]>
http://www.theobfuscated.org/2011/04/04/making-a-bootable-flash-drive-in-osx/feed/ 0