Archive

Archive for the ‘Tech HowTos’ Category

Thunderbird SSL “Domain Name Mismatch”

February 12th, 2010

Some of my servers that are only for internal/personal use have SSL certs with a mismatched hostname. The cert for my mail server is issued for the CNAME used for my mail server, not the actual hostname. Of course, this means that Thunderbird gives me some annoying errors because they’re worried:

Domain Name Mismatch in Thunderbird

Luckily, there’s an add-on called “Remember Mismatched Domains” that adds a simple “remember this decision” check box, much like the one now found in Firefox. Problem solved!

Thunderbird Domain Name Mismatch after add-on

Tech HowTos , , , ,

pnp4nagios, CentOS 5.3 and pcre

February 11th, 2010

I started testing out the pnp4nagios tool to incorporate graphs of performance data into Nagios. Despite what Klein and Sellens suggest (p. 57), I really don’t want separate tools for monitoring and trending. Cactialready handles UPS metrics, switch ports, router traffic, etc. For everything else – system load, etc. – I see no reason to have two checks run rather than just one (Nagios).

There was a CentOS package for the older pnp4nagios 0.4.x, but I opted to build and install the new 0.6.x from source. Unfortunately, I hit one snag – it requires PCRE compiled with support for Unicode properties, and I couldn’t find any package for CentOS compiled with that option. So, with a simple edit of the %configure macro in the SPEC file, I built one. Unfortunately, I wasn’t working in a real build environment – just on one of my web servers – so I only built the .i386 version, but you can feel free to build from the source rpm.

Tech HowTos , , , , ,

Using nmap to quickly ping all hosts in an address range

February 8th, 2010

At $WORK, the subnet we use for some of our workstations and test boxes was only recently setup with DHCP. Previously, we’d used IP-by-Whiteboard in the office. As a result, most of the recent machines use DHCP, but there are a few older ones still around using static addresses. I recently had to add a new machine, so I had to go through the process of finding out which IPs are in use and which aren’t (since some aren’t in DHCP).

I decided to be good and update DHCP with records for all machines in the subnet, whether they’re actually using DHCP or not. There’s a quick way to do this with nmap using the options for ping scan (-sP) and always resolve DNS (-R):

nmap -sP -R 172.16.43.129-159

Host ar01-hill-hill.example.com (172.16.43.129) appears to be up.
MAC Address: 00:11:BC:7D:28:0A (Cisco Systems)
Host ccf-hill019-1.example.com (172.16.43.130) appears to be up.
MAC Address: 00:00:AA:63:54:BB (Xerox)
Host ccf-hill019-2.example.com (172.16.43.131) appears to be down.
Host ccf-hill019-3.example.com (172.16.43.132) appears to be down.
Host ccf-hill019-4.example.com (172.16.43.133) appears to be down.
Host ccf-hill019-5.example.com (172.16.43.134) appears to be down.
Host ccf-hill019-6.example.com (172.16.43.135) appears to be down.
Host ccf-hill019-7.example.com (172.16.43.136) appears to be up.
Host speakeasy.example.com (172.16.43.137) appears to be up.
MAC Address: 00:17:A4:13:EB:57 (Global Data Services)
Host ccf-hill019-9.example.com (172.16.43.138) appears to be up.
MAC Address: 00:17:A4:13:E8:17 (Global Data Services)
Host ccf-hill019-10.example.com (172.16.43.139) appears to be down.
Host testmac01.example.com (172.16.43.140) appears to be down.
Host ccf-hill019-12.example.com (172.16.43.141) appears to be down.
Host ccf-hill019-13.example.com (172.16.43.142) appears to be up.
MAC Address: 00:0D:29:59:58:00 (Cisco)
Host ccf-hill019-14.example.com (172.16.43.143) appears to be down.
Host ccf-hill019-15.example.com (172.16.43.144) appears to be down.
Host ccf-hill019-16.example.com (172.16.43.145) appears to be down.
Host ccf-hill019-17.example.com (172.16.43.146) appears to be down.
Host ccf-hill019-18.example.com (172.16.43.147) appears to be up.
MAC Address: 00:1E:C2:0D:C1:98 (Unknown)
Host ccf-hill019-19.example.com (172.16.43.148) appears to be down.
Host ccf-hill019-20.example.com (172.16.43.149) appears to be down.
Host ccf-hill019-21.example.com (172.16.43.150) appears to be down.
Host lordkris.example.com (172.16.43.151) appears to be down.
Host ccf-hill019-23.example.com (172.16.43.152) appears to be down.
Host ccf-hill019-24.example.com (172.16.43.153) appears to be down.
Host ccf-hill019-25.example.com (172.16.43.154) appears to be down.
Host ccf-hill019-26.example.com (172.16.43.155) appears to be down.
Host ccf-hill019-27.example.com (172.16.43.156) appears to be down.
Host ccf-hill019-28.example.com (172.16.43.157) appears to be down.
Host ccf-hill019-29.example.com (172.16.43.158) appears to be down.
Host ccf-hill019-30.example.com (172.16.43.159) appears to be down.
Nmap finished: 31 IP addresses (7 hosts up) scanned in 0.892 seconds

As you can see, the results also (very usefully) include MAC addresses, so it’s pretty easy to update DHCP as needed.

Tech HowTos , , ,

Subversion ‘is missing or not locked’ error

January 29th, 2010

Recently I was doing some work on a few PHP scripts, and came by a rather annoying error while trying to commit to subversion:

svn: Commit failed (details follow):
svn: Working copy '/srv/www/htdocs/newcall/stats/generated' is missing or not locked

The problem was a directory, “generated”. This particular app makes use of libchart to draw simple charts in PHP. Libchart writes the charts to files, and therefore needs a directory writable by the Apache user. So, I created the generated/ directory for these output files, and chowned wwwrun:www. Now, apparently, the subversion svn add command doesn’t check ownership/writable permissions before adding a directory. So, it added generated/ to the main list of files, but couldn’t write the .svn directory and add a lock. IMHO, this is an error in the svn client.

I couldn’t find any solutions to the problem online. Essentially, I have an empty directory (or at least nothing useful in it) that got partially added to svn – it was added to the .svn/entries file in the parent directory, but never had its own .svn directory created.

The only solution that I found is to manually edit the .svn/entries file in the parent directory. WARNING: this isn’t for the faint of heart. Be sure you don’t screw anything up.

  1. Open the .svn/entries file in the parent directory in a text editor (i.e. if the problem directory is stats/generated, edit stats/.svn/entries
  2. Find the entry node with the correct “name” attribute for the directory in question. For stats/generated, in the stats/.svn/entries file, it should look like:
    <entry
       name="generated"
       kind="dir"
       schedule="add"/>
  3. Make the entries file writable (chmod u+w entries)
  4. Remove the entry from the file.
  5. Set the entries file back to non-writable (chmod u-w entries)
  6. Remove any save files if they were created (i.e. entries~ for emacs)
  7. Remove the directory itself and re-create it, this time adding to svn before setting the ownership.
  8. Commit. It should now work.

Tech HowTos , ,

Using Google Maps to produce usable, printable maps

December 1st, 2009

This is a follow-up to my Making maps from GIS data with Inkscape post. After playing around with Inkscape for quite a while, and coming up with the dismal results seen in that post, I decided there has to be an easier way. A little Googling turned up this video tutorial on how to print large scale maps from Google Maps. It turns out that the Google Maps API will honor almost any pixel resolution that it’s passed. The Screengrab add-on for Firefox has the wonderful capability of being able to capture a screengrab of page content, at actual resolution, regardless of screen resolution. So load up a 5000×5000 pixel Google Map, use the Screengrab addon, and end up with a full 5000×5000 pixel image file.

After testing this a bit, I decided to go the Google Maps route. This also has a lot of other added bonuses – I can store my overlay data in simple XML files, add and remove layers on-the-fly, and also make it available online (and, theoretically, to any Google Maps-equipped device used by responders). This even opens up the possibility of using paper maps as a last resort, and providing the Fire Department with live hydrant maps on GPS-enabled handheld devices and phones.

The quirks, however, may need some serious photoshopping (err, rather, gimping) to fix:

  1. With all of the background color, how will this look when printed?
  2. How do I make the town borders easily defined? It would be a lot of raster editing to remove the background color of areas outside of town.
  3. How do I overlay a grid for a street name index?

The first step was to setup a large Google Map to develop with. I used PHP and Monte Ohrt’s GoogleMapAPI PHP wrapper class. It was simple enough to setup a big (3300×5100px) map, zoom out in Firefox, and start adding some stuff. My examples and development pages, if you want to take a peek at the code, are here.

The first step was to draw a polygon for the outline of the town. I found some very detailed information on how to get zip code boundary lines on Matt Cutts’ blog. Apparently, he’s a Google software engineer, heading up their webspam team. I grabbed the files from the Census, as described, and came up with the boundary for my zip code looking like:

        60      -0.741427638843858E+02       0.409963180802469E+02
      -0.741375870000000E+02       0.410075970000000E+02
      -0.741308870000000E+02       0.410061970000000E+02
      -0.741308870000000E+02       0.410061970000000E+02
      -0.741307260000000E+02       0.410032600000000E+02
      -0.741326870000000E+02       0.409955970000000E+02
      -0.741278870000000E+02       0.409943970000000E+02
      -0.741280870000000E+02       0.409938970000000E+02
      -0.741327870000000E+02       0.409853970000000E+02
      -0.741352870000000E+02       0.409830970000000E+02
      -0.741369600000000E+02       0.409818620000000E+02
      -0.741410520000000E+02       0.409821940000000E+02
      -0.741412870000000E+02       0.409826970000000E+02
      -0.741412870000000E+02       0.409826970000000E+02
      -0.741417870000000E+02       0.409847970000000E+02
      -0.741427870000000E+02       0.409863970000000E+02
      -0.741482870000000E+02       0.409868970000000E+02
      -0.741536880000000E+02       0.409899970000000E+02
      -0.741510880000000E+02       0.409929970000000E+02
      -0.741531880000000E+02       0.409965970000000E+02
      -0.741571880000000E+02       0.409988970000000E+02
      -0.741557880000000E+02       0.410013970000000E+02
      -0.741461870000000E+02       0.410018970000000E+02
      -0.741400870000000E+02       0.410065970000000E+02
 
      -0.741375870000000E+02       0.410075970000000E+02
END

As per Matt’s instructions, I stripped off the first and last lines, converted everything to normal decimal notation, and built it into a PHP array:

$MP_boundary = array();
$MP_boundary[] = array(-74.137587, 41.007597);
$MP_boundary[] = array(-74.130887, 41.006197);
$MP_boundary[] = array(-74.130887, 41.006197);
$MP_boundary[] = array(-74.130726, 41.003260);
$MP_boundary[] = array(-74.132687, 40.995597);
$MP_boundary[] = array(-74.127887, 40.994397);
$MP_boundary[] = array(-74.128087, 40.993897);
$MP_boundary[] = array(-74.132787, 40.985397);
$MP_boundary[] = array(-74.135287, 40.983097);
$MP_boundary[] = array(-74.136960, 40.981862);
$MP_boundary[] = array(-74.141052, 40.982194);
$MP_boundary[] = array(-74.141287, 40.982697);
$MP_boundary[] = array(-74.141287, 40.982697);
$MP_boundary[] = array(-74.141787, 40.984797);
$MP_boundary[] = array(-74.142787, 40.986397);
$MP_boundary[] = array(-74.148287, 40.986897);
$MP_boundary[] = array(-74.153688, 40.989997);
$MP_boundary[] = array(-74.151088, 40.992997);
$MP_boundary[] = array(-74.153188, 40.996597);
$MP_boundary[] = array(-74.157188, 40.998897);
$MP_boundary[] = array(-74.155788, 41.001397);
$MP_boundary[] = array(-74.146187, 41.001897);
$MP_boundary[] = array(-74.140087, 41.006597);
$MP_boundary[] = array(-74.137587, 41.007597);

Though this data doesn’t seem exactly 100% accurate (at least by my knowledge of the town, and every map I can find) it’s quite close and a very good start.

I’ll update later this week when I have some more done…

Tech HowTos , , , , ,

Making maps from GIS data with Inkscape

November 25th, 2009

NOTE- I more or less dropped this project, in favor of a more precise approach, as outlined in Using Google Maps to produce usable, printable maps. This is being left just to give other people ideas.

Background

I was recently asked by one of the officers of our volunteer fire department if I could come up with a good map of our town that could be laminated and put in the trucks. We currently have a really simple PDF map of our town, but it was done by a for-profit entity and is only available as the single-size PDF. The map itself looks like:

town map

Data

With a little research, I was able to find quite a lot of GIS data on the NJ Department of Environmental Protection GIS site. While the GIS viewer software by ESRI seems to be the usual choice, I found that the GPL’ed Quantum GIS project (available in the OpenSuSE Application:Geo repository) displayed the data quite nicely. The only major issue was with street names – there was no way to label lines with two fields from the metadata (the TIGER/Line files have separate fields for the street name and the st/rd/ln suffix). More importantly, I needed something that both looked nice and included overlays (specifically of the fire department’s hydrant map).

SVG

A little research led me to the shptosvg perl script that converts a shapefile to SVG. As the streets within our town won’t change any time soon, I figured it was the most logical solution, when producing a map for print where I would need to re-scale and edit overlay layers – to just get the data I needed into SVG and do the rest there. I was able to export both the county roads shapefile and the state municipal boundaries shapefile to an SVG drawing, and then open that in Inkscape. To export them, I used:

perl shptosvg.pl -x3300 -y5100 -p1 -d0.5 berrds00.shp muni_boundaries/nj_munis.shp > test2.svg

where berrds00.shp is the TIGER/Line roads shapefile for our county (from the 2000 census) and muni_boundaries/nj_munis.shp is the shapefile for the NJ municipal boundaries. The x and y sizes (3300px and 5100px, respectively) were based on an 11×17″ sheet printed at 300dpi.

Initial Work

The initial work was a real pain. I moved each group of objects (the municipal boundaries and the county road lines) to a separate layer and then ungrouped them. Next, I began the painstaking process of deleting all of the objects outside of our town boundary, except the roads directly around our town. Once this was done, I used File -> Document Properties -> Fit to Page Selection to “crop” the canvas to the remaining objects. Thanks to the nature of SVG, I was able to crop the page down and then scale it up again to 11×17″ without any loss of data or quality. I then moved the roads outside of our town (luckily, most of the roads from the TIGER data ended up being made up of a series of line segments, with most of them having a break at the town boundary) to another layer, so that they could be easily given a light gray color. I also gave the down boundary a nice red color. Finally, as I neglected to include a railroad shapefile when I did the original conversion to SVG, and adding one would obviously not jive with the massive deletion and re-scaling I’d done, I drew in the one railroad line running through town by hand, and gave it a nice dashed line type.

At this point, I ended up with something that looked like:

inkscape work version 1

Cleaning Up

I now had the following tasks to perform:

  1. Find a nicer way to show the street lines. The ideal would be a line made up of 1-2px lines on either side, with a white center. Second best would just be thinner lines.
  2. Cleanup the roads around the town boundary – make sure they’re black within the town and gray outside. If need be. delete some lines and re-draw them to split at the town boundary.
  3. Add labels for the bordering towns.
  4. The big one – add street name labels.
  5. Perhaps add in icons/labels/boxes for churches, schools, municipal buildings, etc.
  6. Add in, once I get a copy of the map, the fire department hydrant locations as another layer.

And the added bonuses that I’d like to do:

  1. Add house numbering on a block level for each street.
  2. Add a grid overlay, with an index of streets by grid square on the back.

As of right now (about 9AM on November 25, 2009) this is where I stand. I’ll update a bit more when I get farther along.

Tech HowTos , , , ,

root on a Cyclades ACS console server

November 18th, 2009

At work we have a Cyclades ACS16 console server (running Cyclades-ACS16-Linux V_3.2.0 (Jan/04/08)). While the docs claim all sorts of LDAP features, there’s nothing (either in the web GUI or the CLI configuration tool) to setup LDAP with TLS or required group membership. I tried modifying the /etc/ldap.conf and /etc/nsswitch.conf files, running saveconf and runconf and even rebooting, but no luck. It was apparent that I needed root on the box. Unfortunately, they don’t give you root, and their sudo command is locked down. But, I figured, if sudo would let me and chown and cat and mv (enough to switch out the ldap.conf and nsswitch.conf files), root should be pretty easy.

The failing of Cyclades’ sudo lockdown is that it allows sudo execution of a few random shell scripts, and also allows `mv`.

The /etc/sudoers:

# sudoers file.
#
# This file MUST be edited with the 'visudo' command as root.
#
# See the sudoers man page for the details on how to write a sudoers file.
#
 
# User alias specification
 
# Runas alias specification
 
# Host alias specification
 
# Cmnd alias specification
Cmnd_Alias     SH_CMDS = /bin/cp,\
                         /bin/chown,\
                         /bin/egrep,\
                         /bin/grep,\
                         /bin/cat,\
                         /bin/tar,\
                         /bin/kill,\
                         /bin/mkdir,\
                         /bin/mv,\
                         /bin/rm,\
                         /bin/sed,\
                         /bin/touch,\
                         /sbin/reboot,\
                         /usr/bin/killall,\
                         /usr/bin/w,\
                         /bin/w_cas,\
                         /bin/sess_mngt,\
                         /sbin/route,\
                         /bin/what
 
Cmnd_Alias     CONF_FILES = /bin/vi /etc/network/st_routes,\
                            /bin/vi /etc/portslave/pslave.conf,\
                            /bin/vi /etc/resolv.conf
 
Cmnd_Alias     APPLICATIONS = /bin/pmCommand,\
                              /bin/saveconf,\
                              /bin/restoreconf,\
                              /bin/runconf,\
                              /bin/daemon.sh,\
                              /bin/manageService.sh,\
                              /bin/dsviewKillAdmin, \
                              /bin/pmfwupgrade, \
                              /bin/adsap2_clear, \
                              /bin/upgrade_power.sh, \
                              /bin/signal_ras
 
# User privilege specification
# root can run any command on any host as any user.
root    ALL = (ALL) ALL
 
# admin user group command specification.
%admin      ALL = NOPASSWD: SH_CMDS, CONF_FILES, APPLICATIONS

So, /bin/upgrade_power.sh doesn’t look like we’re using it too much. Here’s our root procedure. Before doing this, create the /home/admin/foo.sh script.

sudo cp /bin/upgrade_power.sh /bin/upgrade_power.sh.SAVE
sudo chown root:root /home/admin/foo.sh
sudo mv /home/admin/foo.sh /bin/upgrade_power.sh
sudo /bin/upgrade_power.sh
sudo cat /etc/sudoers # just to verify that it worked
sudo mv /bin/upgrade_power.sh.SAVE /bin/upgrade_power.sh # set things back to the way they were

And the key to all of it is the simple /home/admin/foo.sh script:

#!/bin/bash
 
chmod u+w /etc/sudoers
echo "%admin      ALL = NOPASSWD: ALL" >> /etc/sudoers
chmod u-w /etc/sudoers

That’s it!

Tech HowTos , ,

Motorola Droid – Volume way too low

November 17th, 2009

I’m not sure how I did it, but I’ve had my Droid for a few hours under a week – the phone’s uptime is about 187 hours – and I’ve already got a major problem. Sometime this weekend, somehow, the volume for everything got set way too low. Incoming call ringer, notifications, alarms, Google Maps Navigation, everything seems to be playing through the speaker at the regular in-call volume – i.e. the volume that it should be at if the handset is up to my ear.

I happened by one blog post mentioning this issue. The two resolutions mentioned were a soft reset and a replacement of the phone. Hoping for the former, I performed a soft reset – using the good ‘ol Ctrl + Alt + Del sequence – and this seems to have fixed it. Now I just have to hope that it stays fixed…

My personal theory is that some application – whether a code problem or a crash – left the speaker in a low-volume state. Most likely was my poking around in the hidden menus which, at one point, killed the Phone app process.

Tech HowTos ,

Running a script on USB drive insertion

November 11th, 2009

Before I even get into how to do this, be warned: this is a really bad idea unless you can ensure total physical access control to the machine. About the only place I’d ever use it is in a non-networked embedded system in a secure location. Its original intent is to handle loading of pictures onto a Linux-based digital photo frame.

So, you want to run a specific script on insertion of a USB drive. Here’s how to use udev to do it:

  1. Create /etc/udev/rules.d/99-usbhook.rules:
    ACTION=="add",KERNEL=="sd*", SUBSYSTEMS=="usb", ATTRS{product}=="Mass Storage", RUN+="/root/bin/usbhook %k"

    This will run “/root/bin/usbook”, passing it the device name as an argument, every time a USB Mass Storage device is plugged in.

  2. run udevcontrol reload_rules
  3. Create your usbhook script.
  4. Enjoy

Here is my usbhook script to copy all files from a USB mass storage disk to a specific location. It includes quite a bit of debugging, and also checks for the presence of a file called “foobarbaz.txt” on the device before copying the files over.

#!/bin/bash
 
# script to move over all files from a USB key
# when it is inserted into the system.
 
# should be called from a udev rule like:
#ACTION=="add",KERNEL=="sd*", SUBSYSTEMS=="usb", ATTRS{product}=="Mass Storage", RUN+="/root/bin/usbhook %k"
 
# Copyright 2009 Jason Antman. <jason@jasonantman.com> <http://www.jasonantman.com>
# <http://blog.jasonantman.com/2009/11/running-a-script-on-usb-drive-insertion/>
 
# CONFIGURATION
DEBUG=1 # set to 1 for debugging output
DEST="/home/foo/" # destination for files
 
 
DEVICE="$1" # the device name
LOGFACILITY="kernel.info" # for debugging output
 
 
if [ ${DEBUG:=0} == 1 ]; then logger "$LOGFACILITY" usbhook called with arguments: "$DEVICE"; fi
 
sleep 5 # delay 5 seconds to wait for mount
 
mount | grep "$DEVICE"
FOO="$?"
 
if [ $FOO == 0 ];
then
    if [ ${DEBUG:=0} == 1 ]; then logger "$LOGFACILITY" usbhook device mounted: "$DEVICE"; fi
else
    if [ ${DEBUG:=0} == 1 ]; then logger "$LOGFACILITY" usbhook device NOT mounted: "$DEVICE" - exiting; fi
    exit 0
fi
 
BAR=`mount | grep "$DEVICE" | awk '{ print $3 }'`
 
if [ -e "$BAR/foobarbaz.txt" ]
then
    if [ ${DEBUG:=0} == 1 ]; then logger "$LOGFACILITY" usbhook "$BAR"/foobarbaz.txt found; fi
else
    if [ ${DEBUG:=0} == 1 ]; then logger "$LOGFACILITY" usbhook "$BAR"/foobarbaz.txt NOT found - exiting; fi
    exit 0
fi
 
cp -R "$DEVICE"/* "$DEST"

This was tested on OpenSuSE 10.3.

Tech HowTos , , ,

Nagios and check plugins run as root

November 5th, 2009

No matter how much we may not like it, and no matter how insecure it can potentially be, we occasionally have to run Nagios check scripts (written in scripting languages) as root. (On a side note, this method is also used for my MultiBindAdmin project’s DNS file push). Here’s how to do it:

  1. Write your check script in the language of your choice and test as root.
  2. Grab setuid-prog.c.
  3. uncomment the DEFINE for FULL_PATH, change the string to the full path to your script.
  4. Be sure your script is owned by root, and is chmod at most 755.
  5. Compile setuid-prog.c:
    gcc -o {check_script_name}-wrapper setuid-prog.c
  6. Put the resulting binary in your plugin directory.
  7. Assuming your checks run as user nagios and group nagios, chown the binary to root:nagios and chmod 4755.

This allows the use of the SUID bit with scripts.

Use at your own risk. I only recommend this on systems where the Nagios account is strongly authenticated, and where ALL users are trusted.

Tech HowTos