Archive for the ‘Open Source’ Category

uNUI – Building a Multi-touch Table

Sunday, April 6th, 2008

My newest project: breaking interface boundaries. A couple of my friends at work and I have decided to build a multi-touch table based on the technique of frustrated total internal reflection (FTIR). This can be described by a diagram easier than words, so here we go:

FTIR diagram
FTIR diagram (image from Tim Roth’s Multi-touch Dev Blog)

This design for multi-touch interfaces has been popularized by Jeff Han, a researcher from NYU. Infrared LEDs are placed around two sides of a sheet of acrylic, causing the IR light to be reflected within it. Then, when a finger or object touches it, the light is “frustrated” and refracts off of the object and out of the acrylic. An IR camera below the screen then sees this as a blob of IR light which can be interpreted by a computer for recognition of gestures, touches, and movement.

uNUI Group

This is a very exciting and fun project with which to be involved. The potential is amazing—multi-touch interfaces are the next paradigm in computing and will replace standard keyboard and mouse input in the relatively near future. My friends and I decided to document our progress as we build our devices and software, so we created the uNUI Group site as an extension of the NUI Group community. Check out the Resources page for links, blogs and videos about what we and the community are doing—we’d also love to hear your feedback.

Python XML-RPC Client with Cookie Handling and SSL

Sunday, March 9th, 2008

The following is an adaptation of Vaibhav Bhatia’s cookie-handling XML-RPC client (text source) with a few changes to implement SSL for HTTPS transport in place of the basic HTTP transport.

This was done specifically for use with CherryPy sessions so that the XML-RPC client (the server proxy object) could be stored in a session variable, giving each user an individual client and thus allowing webservice permissions to be handled on a per-user basis (without having to authenticate and determine permissions on every webservice method invocation). To do this, make sure that you’re storing CherryPy sessions in memory, not in a file, and then create the proxy object (sorry for the gigantic class name):

cherrypy.session['proxy'] = \
xmlrpclib.ServerProxy(url, transport=CookieAuthXMLRPCSafeTransport())

xmlrpcclient.py

import os
import base64
import xmlrpclib
import urllib2
import cookielib
 
class CookieAuthXMLRPCSafeTransport(xmlrpclib.SafeTransport):
""" xmlrpclib.Transport that sends HTTPS Authentication"""
 
user_agent = '*py*'
credentials = ()
cookiefile = 'cookies.lwp'
 
def send_basic_auth(self, connection):
"""Include HTTPS Authentication data in a header"""
 
auth = base64.encodestring("%s:%s"%self.credentials).strip()
auth = 'Basic %s' %(auth,)
connection.putheader('Authorization',auth)
 
def send_cookie_auth(self, connection):
"""Include Cookie Authentication data in a header"""
 
cj = cookielib.LWPCookieJar()
cj.load(self.cookiefile)
 
for cookie in cj:
if cookie.name == 'session_id':
uuidstr = cookie.value
connection.putheader("Cookie",cookie.name+'='+cookie.value)
 
## override the send_host hook to also send authentication info
def send_host(self, connection, host):
xmlrpclib.SafeTransport.send_host(self, connection, host)
if os.path.exists(self.cookiefile):
self.send_cookie_auth(connection)
elif self.credentials != ():
self.send_basic_auth(connection)
 
def request(self, host, handler, request_body, verbose=0):
# dummy request class for extracting cookies
class CookieRequest(urllib2.Request):
pass
 
# dummy response class for extracting cookies
class CookieResponse:
def __init__(self, headers):
self.headers = headers
def info(self):
return self.headers
 
crequest = CookieRequest('https://'+host+'/')
 
# issue XML-RPC request
h = self.make_connection(host)
if verbose:
h.set_debuglevel(1)
 
self.send_request(h, handler, request_body)
self.send_host(h, host)
self.send_user_agent(h)
 
# creating a cookie jar for my cookies
cj = cookielib.LWPCookieJar()
 
self.send_content(h, request_body)
 
errcode, errmsg, headers = h.getreply()
 
cresponse = CookieResponse(headers)
cj.extract_cookies(cresponse, crequest)
 
if len(cj) > 0 and self.cookiefile != None:
cj.save(self.cookiefile)
 
if errcode != 200:
raise xmlrpclib.ProtocolError(
host + handler,
errcode, errmsg,
headers
)
 
self.verbose = verbose
 
return self.parse_response(h.getfile())

Secure Screen Sharing in OS X Leopard Through SSH Tunneling

Wednesday, February 13th, 2008

Here’s a quick tutorial on how to secure the Screen Sharing application in Leopard by tunneling your connection through an encrypted SSH channel.

The new Screen Sharing application is basically just glorified VNC, but it does come with some nice features (dual-screen view, for example). However, just turning on the service will open up a couple of ports that may expose your system to exploitation.

WaterRoof MenuFirst, we’ll want to lock down your firewall. Leopard comes with two firewalls: ipfw (ipfirewall—the underlying Unix firewall) and an application layer firewall (the one that pops up sometimes and asks if you want to allow an application to accept incoming connections). You can manage the application layer firewall through System Preferences > Security > Firewall, but in order to block some ports we’ll need to set up some rules through ipfw. In order to do this, you can either learn the shell syntax (which isn’t terribly complicated) or use a GUI app to interface with it. I chose to use WaterRoof—a frontend open-source GUI for ipfw.

Once you have downloaded WaterRoof, run the application and click on Static Rules. Click the + icon to add a new rule, and use the following information:

Protocol: IP
Rule Action: Deny
Source: not me
Port or range: (leave blank)
Destination address, subnet, or network: me
Port or range: 5900
In, Out, or In/Out: Select the In radio button

This will block port 5900, the default VNC listening port that is opened when you start Screen Sharing. Also, you’ll want to block port 88 unless you are using Kerberos for authentication (I believe this is also opened by Screen Sharing and a couple of other apps). Add a new rule and use the same above parameters, but use incoming port 88 instead of 5900.

You should now have two new rules in your table:

deny ip from not me to me dst-port 5900 in
deny ip from not me to me dst-port 88 in

Click Tools > Rules Configuration > Save to startup configuration. Then, click Tools > Startup Script > Install Startup Script. This will make these new rules persist when you restart (otherwise, the system will reset to defaults on the next restart).

Open System Preferences > Sharing and enable the Screen Sharing and Remote Login services.

On your other Mac…

Now, from your client computer, open up Terminal and run the following (for reasoning, see the LifeHacker article Add More Functionality to Leopard’s Screen Sharing):

defaults write com.apple.ScreenSharing ShowBonjourBrowser_Debug 1

and (to enable quality control settings)…

defaults write com.apple.ScreenSharing \
'NSToolbar Configuration ControlToolbar' -dict-add 'TB Item Identifiers' \
'(Scale,Control,Share,Curtain,Capture,FullScreen,GetClipboard,SendClipboard,Quality)'

Finally…

Now, any time you want to securely connect to your Mac, all you have to do is type the following in Terminal:

ssh username@ip_address_or_hostname -L 5900:localhost:5900

Leopard Screen Sharing Application WindowThe -L flag is the key to all this—it enables local port forwarding and specifies that anything that happens on the specified local port will be forwarded to the given remote host and port (see the man page for more info). The format of the -L option is port:host:hostport so the first 5900 is your local client port, the next option is the host to which to forward, and the third is the remote port. It’s slightly confusing at first, but this localhost isn’t the client you’re connecting from, it is the remote computer to which you are connecting—it means that when the remote host gets forwarded data, it won’t pass it on to some other host.

Now, leave that terminal window open and open up /System/Library/CoreServices/Screen Sharing.app (you can drag it to your dock).

In the connect field, type localhost:0 (don’t forget the :0). The last part is important because it means to connect to display zero, which translates to port 5900 in VNC land and, for some reason, Leopard will tell you that “You cannot share your own computer” if you type in just localhost (though, you actually can by enabling Screen Sharing and typing that same host, it just creates an pseudo-infinite loop of VNC windows).

Once you type in your username and password, you’re done! You can now control your computer remotely through Leopard’s Screen Sharing app over a tunneled SSH connection. Here’s an example of the Screen Sharing interface (notice the nice dual-monitor support):

Leopard Screen SharingAlso, because Screen Sharing uses VNC as its base protocol you can interface with your Mac from any Linux, Mac, or Windows VNC client by port forwarding in the same way (on Windows, you’ll have to use an SSH client like PuTTY) and connecting to localhost port 5900 with any standard VNC client.

Networking Via Carrier Pigeon

Monday, December 31st, 2007

Let me just trace where this is coming from for you: while laughing again at an XKCD comic, I was led to Google the name “Eric S. Raymond” (the references to Richard Stallman and Linus Torvalds I got, but I didn’t know much about ESR), which then led me to his home page and then to the Jargon file (a classic collection of terms and information on hacker culture) and to the Meaning of Hack section.

This story is probably well-known to many seasoned hackers, but it gave me a good laugh:

1990’s addition to the hallowed tradition of April Fool RFCs was RFC 1149, A Standard for the Transmission of IP Datagrams on Avian Carriers. This sketched a method for transmitting IP packets via carrier pigeons.

Eleven years later, on 28 April 2001, the Bergen Linux User’s Group successfully demonstrated CPIP (Carrier Pigeon IP) between two Linux machines running on opposite sides of a small mountain in Bergen, Norway. Their network stack used printers to hex-dump packets onto paper, pigeons to transport the paper, and OCR software to read the dumps at the other end and feed them to the receiving machine’s network layer.

Here is the actual log of the ping command they successfully executed. Note the exceptional packet times.

Script started on Sat Apr 28 11:24:09 2001
vegard@gyversalen:~$ /sbin/ifconfig tun0
tun0      Link encap:Point-to-Point Protocol
          inet addr:10.0.3.2  P-t-P:10.0.3.1  Mask:255.255.255.255
          UP POINTOPOINT RUNNING NOARP MULTICAST  MTU:150  Metric:1
          RX packets:1 errors:0 dropped:0 overruns:0 frame:0
          TX packets:2 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0
          RX bytes:88 (88.0 b)  TX bytes:168 (168.0 b)
 
vegard@gyversalen:~$ ping -i 450 10.0.3.1
PING 10.0.3.1 (10.0.3.1): 56 data bytes
64 bytes from 10.0.3.1: icmp_seq=0 ttl=255 time=6165731.1 ms
64 bytes from 10.0.3.1: icmp_seq=4 ttl=255 time=3211900.8 ms
64 bytes from 10.0.3.1: icmp_seq=2 ttl=255 time=5124922.8 ms
64 bytes from 10.0.3.1: icmp_seq=1 ttl=255 time=6388671.9 ms
 
— 10.0.3.1 ping statistics —
9 packets transmitted, 4 packets received, 55% packet loss
round-trip min/avg/max = 3211900.8/5222806.6/6388671.9 ms
vegard@gyversalen:~$ exit
 
Script done on Sat Apr 28 14:14:28 2001

A web page documenting the event, with pictures, is at http://www.blug.linux.no/rfc1149/. In the finest Internet tradition, all software involved was open-source; the custom parts are available for download from the site.

While all acknowledged the magnitude of this achievement, some debate ensued over whether BLUG’s implementation was properly conformant to the RFC. It seems they had not used the duct tape specified in 1149 to attach messages to pigeon legs, but instead employed other methods less objectionable to the pigeons. The debate was properly resolved when it was pointed out that the duct-tape specification was not prefixed by a MUST, and was thus a recommendation rather than a requirement.