Tuesday, March 27, 2012

Checking client-side certificate verification with openssl

So you have some client software that claims it checks server SSL certs are issued by a valid CA, or better, by a specific CA? How do you check its claims? Set up a simple MITM attack (works for OS X and linux):

Create a self-signed cert:
openssl req -new -x509 -days 365 -nodes -out cert.pem -keyout cert.pem
Fire up the openssl server (man s_server for more options, including simple webserver functionality):
sudo openssl s_server -debug -cert cert.pem -accept 443
Edit your /etc/hosts file and add the domain you are attacking to resolve to localhost:
127.0.0.1 secure.company.com
Run your client.

Tuesday, March 13, 2012

ComputerName vs. LocalHostName vs. HostName on OS X

Hostnames on OS X are...complicated. Using scutil is probably the easiest way to get at them, although there are others. It looks like scutil just parses this plist:

/Library/Preferences/SystemConfiguration/preferences.plist

Note: If you want to get/set these values without shelling out to scutil, check out SCPreferencesPathGetValue and SCPreferencesPathSetValue part of the SystemConfiguration Framework called from python like this.

ComputerName


This is the computer name visible in the GUI in Preferences | Sharing | Computer Name and the scutil manpage describes it as 'The user-friendly name for the system.'
scutil --get ComputerName
Apple says:
The AppleTalk name and the default name used for SLP/DA. The Network browser in the Finder uses SMB/CIFS to find computers that provide Windows file sharing.
SCPreferencesPath: /System/System/ComputerName

LocalHostName


This appears to be only used for Bonjour-aware services on the local network.
scutil --get LocalHostName
Apple says:
The name that designates a computer on a local subnet.
and as of 10.6:
Host names that contain only one label in addition to local, for example "My-Computer.local", are resolved using Multicast DNS (Bonjour) by default. Host names that contain two or more labels in addition to local, for example "server.domain.local", are resolved using a DNS server by default.
SCPreferencesPath: /System/Network/HostNames/LocalHostName

HostName


The name associated with hostname(1) and gethostname(3). Displayed in the default terminal command prompt (user@hostname).
scutil --get HostName
Apple says:
You can’t specify this name during server setup. Server Assistant sets the host name to AUTOMATIC in /etc/hostconfig. This setting causes the server’s host name to be the first name that’s true in this list:
- The name provided by the DHCP or BootP server for the primary IP address
- The first name returned by a reverse DNS (address-to-name) query for the primary IP address
- The local hostname
- The name “localhost”
SCPreferencesPath: /System/System/HostName

Thursday, March 1, 2012

Using a dictionary to populate a format string in python for human and computer-friendly error reporting

Python 2.6 has brought some interesting string formatting options to the table. I recently needed an object that could pass back error information that could be consumed by humans and other code. The new string formatting came in handy.

class ValidationError(Exception):
  """Class for reporting validation errors."""

  BAD_RECORD = 1

  def __init__(self, error, msg, **kwargs):
    """Record Validation Error.

    Requires python 2.6

    Args:
      error: ValidationError code e.g. ValidationError.BAD_RECORD
      msg: format string for human readable version of the error
      **kwargs: kwargs to populate format string
    """
    super(ValidationError, self).__init__(self)
    self.message = msg.format(**kwargs)
    self.error = error
    self.kwargs = dict(kwargs)

  def __str__(self):
    return self.message

You can use it like this:

e = ValidationError(ValidationError.BAD_RECORD,
                    'Bad record detected in {records}',
                    records=records)

So to present the info to a human:
In [18]: print e
Bad record detected in {'a': 12, 'b': 123}
and other code can use:
In [19]: e.error
Out[19]: 1
and access the relevant varaibles like:
In [20]: e.kwargs
Out[20]: {'records': {'a': 12, 'b': 123}}

Monday, January 16, 2012

Really basic wireless survey with built-in linux tools

What channel should I use for my access point? It seems like I'm always asking this question as people start new access points in my neighbourhood. Some wireless access points can pick a channel automatically, but my experience with this has been pretty poor. I suspect the algorithm is too simplistic to be of any use. A naive implementation might pick the first channel that has no other APs on it, which could be a terrible choice if the strongest interference signal is on the adjacent channel.

Ideally you want to pick the channel that gives you the best signal-to-noise ratio, but where there are heaps of APs at varying strengths in different parts of the house the choice is non-obvious. Sadly there doesn't seem to be a FOSS wireless survey tool like Fluke AirMagnet, and while you can use kismet to collect signal strength data you will have to do some analysis of the data yourself (my wireless card also didn't play well with kismet).

I decided to optimise for one location - where I use the laptop the most. So I set my AP to channel 1 and:
sudo iwlist wlan0 scanning > ch1.txt
Rinse and repeat for all the other channels (setting the channel on my AP is quick, but this might be impractical if yours is slow, requires re-auth etc.). Then compare the signal strengths:
grep --before-context=4 "myessid" ch*.txt
Pick the channel with the highest quality number (best signal strength).

Root a TMobile MyTouch 4G (HTC Glacier) to install Cyanogen

This was my first time rooting an android phone. There are most probably better ways to do this, but here are my notes for better or worse. I followed these instructions, which were pretty good and I won't reproduce them, so consider this a diff. First install the jdk from the 'default-jdk' apt package.

Install the Android SDK, including the platform-tools component to get adb. If you try to use it without root you'll get a permissions error like this:
$ android-sdk-linux/platform-tools/adb devices
List of devices attached 
???????????? no permissions
Add this UDEV rule to /etc/udev/rules.d/51-android.rules. Note this gives all users write permissions:
SUBSYSTEM=="usb", SYSFS{idVendor}=="0bb4", MODE="0666"
Plug it back in:
$ android-sdk-linux/platform-tools/adb devices
List of devices attached 
XXXXXXXXXXXX device
Change the mode on the phone to 'charge-only', and unmount the SD card if it is mounted. This allows adb and subsequent rooting tools to access /sdcard. If you have it in disk drive mode you'll get errors like these from adb:
failed to copy 'Superuser.apk' to '/sdcard//Superuser.apk': Read-only file system
To do the cyangogen install you can use the 'ROM Manager' app by ClockworkMod, available in the android market.

Tuesday, January 10, 2012

Ubuntu system monitor in the taskbar post-unity (Natty and Oneiric)

With the unity changes from Natty onward, the traditional Ubuntu gnome taskbar disappeared to be replaced by a set of application panel indicators. I was used to seeing my machine vitals (cpu, network, load etc.) displayed using system monitor in the taskbar. I was pleased to see that this can still be achieved by installing the 'indicator-multiload' package.

Depending on the version you have, the autostart might not work. If it doesn't, just:
mkdir ~/.config/autostart
and toggle the 'autostart' checkbox under preferences.

Monday, January 9, 2012

Broken BCM4313 "ping: sendmsg: No buffer space available"

My Broadcom wireless card was broken on Ubuntu 11.10 Oneiric Ocelot. The card connected to my AP fine, but after a short time would barf. A ping to the AP would return a few successful replies followed by:
ping: sendmsg: No buffer space available

This is a known issue, and seems to affect quite a few people.

First I tried installing the proprietary broadcom driver from the 'broadcom-sta-common' package, but that was worse - it wouldn't even recognise the interface. I tried a whole bunch of later kernels and finally found one that worked: 3.1.8.

The ubuntu mainline kernel repo makes trying new kernels easy. Just download and install these debs:
linux-headers-3.1.8-030108_3.1.8-030108.201201061759_all.deb
linux-headers-3.1.8-030108-generic-pae_3.1.8-030108.201201061759_i386.deb
linux-image-3.1.8-030108-generic_3.1.8-030108.201201061759_i386.deb

Update: spoke too soon. This is still broken on 3.1.8 it just takes longer to manifest. I'm now also seeing a bunch of these messages:
kernel: [25244.951243] ieee80211 phy0: START: tid 1 is not agg'able

Update 2012-01-30: Now I'm also seeing lots of this:
ieee80211 phy0: brcms_c_prec_enq_head: No where to go, prec == 4
I'm going to up net.core.rmem and net.core.wmem as suggested in a comment, but that's really only treating the symptoms.

Update 2012-02-10: I realised that at some point I'd put my AP into 'high bandwidth' mode, presumably 802.11n, which worked really badly. I'm guessing that was because of the crowded 2.4GHz spectrum in my area and/or poor linux driver support. When I put it back to regular 802.11g it has been rock solid ever since.