Wednesday, 17 February 2010

Ubuntu: How to automatically lock & unlock screen with Android phone

Evan Boldt has a useful script: Unlock your screen with ANY USB device. I've modified it slightly to work with my HTC Magic / Google Android device. A script is run every minute, which polls the system log every 2 seconds to determine when the USB device is plugged in in or unplugged. It then forwards the relevant command to GNOME Screensaver. The script is posted below for your interest.

Firstly, run lsusb and locate your phone. In my case, it was the highlighted line:

Bus 002 Device 002: ID 08ff:2580 AuthenTec, Inc. AES2501 Fingerprint Sensor
Bus 002 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
Bus 003 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
Bus 004 Device 002: ID 045e:0752 Microsoft Corp.
Bus 004 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
Bus 005 Device 002: ID 045e:0039 Microsoft Corp. IntelliMouse Optical
Bus 005 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
Bus 001 Device 006: ID 0bb4:0c02 High Tech Computer Corp.
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub


Copy everything from ID to the end of the line (i.e. "ID 0bb4:0c02 High Tech Computer Corp.") This will be the ID used to determine when your device is plugged in & unplugged.

Paste this file into your /home/username/bin folder:

#!/bin/bash

#Replace with the ID of your USB device
id="ID 0bb4:0c02 High Tech Computer Corp." # Example: id="ID 05ac:1292 Apple, Inc"

#runs every 2 seconds
for ((i=0; i<=30; i++))
do
if [ -z "`lsusb | grep "$id"`" ]
then

    echo "Device is NOT plugged in"

    if [ -n "`DISPLAY=:0 gnome-screensaver-command --query | grep "is active"`" ]
    then
    if [ -e /tmp/autoUnlock.lock ]
    then
    #stop locking the screen
    rm /tmp/autoUnlock.lock

fi

elif [ -e /tmp/autoUnlock.lock ]
then

    DISPLAY=:0 notify-send -t 5000 –icon=dialog-info “Device Disconnected” “Bye!”

    #lock the desktop
    DISPLAY=:0 gnome-screensaver-command --lock

    rm /tmp/autoUnlock.lock

fi
else

    echo "Android IS plugged in"
    if [ ! -e /tmp/autoUnlock.lock ]
    then
    DISPLAY=:0 gnome-screensaver-command --deactivate
    DISPLAY=:0 notify-send -t 5000 --icon=dialog-info "Device Connected" "Welcome Back!"
    touch /tmp/autoUnlock.lock

    ##Uncomment the 3 following lines if you would like your computer to remind you if you lock your screen without disconnecting the device
    #echo "Don't forget your device!" > /tmp/androidReminder
    #DISPLAY=:0 festival --tts /tmp/androidReminder
    #rm /tmp/androidReminder
    fi

fi
sleep 2
done


Now you simply add a line to your crontab to run this script every minute:

crontab -e


add the line:

* * * * * bash /home/username/bin/autoUnlock & >/dev/null 2>&1


That's it! Now, when you unplug your Android phone it should lock the screen. When you plug in again, the screen unlocks. Easy!

More information:
http://echowarp.neomenlo.org/2009/scripts/unlock-your-screen-with-any-usb-device
https://help.ubuntu.com/community/UsbDriveDoSomethingHowto

ERROR: Creating templock /var/lock/mrtg/.....: No such file or directory [How to Fix]

I have been running MRTG on Ubuntu server 8.10, and recently it stopped running for no obvious reason. Examining the MRTG log, I found many lines like this:

ERROR: Creating templock /var/lock/mrtg/_etc_mrtg.cfg_l_5012: No such file or directory at /usr/bin/mrtg line 1645.
ERROR: Creating templock /var/lock/mrtg/_etc_mrtg.cfg_l_5020: No such file or directory at /usr/bin/mrtg line 1645.
ERROR: Creating templock /var/lock/mrtg/_etc_mrtg.cfg_l_5041: No such file or directory at /usr/bin/mrtg line 1645.
ERROR: Creating templock /var/lock/mrtg/_etc_mrtg.cfg_l_5046: No such file or directory at /usr/bin/mrtg line 1645.
ERROR: Creating templock /var/lock/mrtg/_etc_mrtg.cfg_l_5074: No such file or directory at /usr/bin/mrtg line 1645.
ERROR: Creating templock /var/lock/mrtg/_etc_mrtg.cfg_l_5100: No such file or directory at /usr/bin/mrtg line 1645.
ERROR: Creating templock /var/lock/mrtg/_etc_mrtg.cfg_l_5112: No such file or directory at /usr/bin/mrtg line 1645.
ERROR: Creating templock /var/lock/mrtg/_etc_mrtg.cfg_l_5121: No such file or directory at /usr/bin/mrtg line 1645.
ERROR: Creating templock /var/lock/mrtg/_etc_mrtg.cfg_l_5129: No such file or directory at /usr/bin/mrtg line 1645.
ERROR: Creating templock /var/lock/mrtg/_etc_mrtg.cfg_l_5148: No such file or directory at /usr/bin/mrtg line 1645.
ERROR: Creating templock /var/lock/mrtg/_etc_mrtg.cfg_l_5173: No such file or directory at /usr/bin/mrtg line 1645.
ERROR: Creating templock /var/lock/mrtg/_etc_mrtg.cfg_l_5905: No such file or directory at /usr/bin/mrtg line 1645.
ERROR: Creating templock /var/lock/mrtg/_etc_mrtg.cfg_l_6004: No such file or directory at /usr/bin/mrtg line 1645.
ERROR: Creating templock /var/lock/mrtg/_etc_mrtg.cfg_l_6023: No such file or directory at /usr/bin/mrtg line 1645.
ERROR: Creating templock /var/lock/mrtg/_etc_mrtg.cfg_l_6049: No such file or directory at /usr/bin/mrtg line 1645.
ERROR: Creating templock /var/lock/mrtg/_etc_mrtg.cfg_l_6065: No such file or directory at /usr/bin/mrtg line 1645.
ERROR: Creating templock /var/lock/mrtg/_etc_mrtg.cfg_l_6092: No such file or directory at /usr/bin/mrtg line 1645.
ERROR: Creating templock /var/lock/mrtg/_etc_mrtg.cfg_l_6191: No such file or directory at /usr/bin/mrtg line 1645.
ERROR: Creating templock /var/lock/mrtg/_etc_mrtg.cfg_l_6247: No such file or directory at /usr/bin/mrtg line 1645.


Turns out there is a bug with running MRTG on Ubuntu/Debian which removes the MRTG lock file on every reboot. To fix this, create a new text file (as root) in /etc/rcS.d/ called "S91mrtg-lock-dir.sh" and paste the following code into it:

#!/bin/sh
# Create the lock directory for MRTG
# This is needed due to a bug for Ubuntu/Debian which erases this directory at shutdown
echo "Creating MRTG lock directory...."
mkdir -m 0755 /var/lock/mrtg


This will create a new /var/lock/mrtg directory every time the computer starts up. You may need to reboot to enable this, or simply run the command mkdir -m 0755 /var/lock/mrtg.

More information:
http://www.enterprisenetworkingplanet.com/netos/article.php/3663941
http://ubuntuforums.org/showthread.php?t=249393
http://www.directadmin.com/forum/showthread.php?t=7843&page=3
http://www.google.com/search?hl=en&q=ERROR%3A+Creating+templock%3A+No+such+file+or+directory&aq=f&aqi=&oq=

Thursday, 11 February 2010

Google Buzz: How to publish to Twitter automatically

At present, Google Buzz has the ability to import, index and display your Tweets. One feature that is notably missing, however, is the ability to tweet from Buzz. You can't export Google Buzz to Twitter. At least, not officially.

I've written a python script to grab your Google Buzz feed (as detailed in the Buzz API), and automatically post your Buzz-es to Twitter. It includes a link back to the original Buzz URL (shortened with Bit.ly) It also uses a local sqlite database to store previous posts, and print bit.ly statistics for your published links.

You'll need to have python installed, and the following modules:
python-twitter
python-bitly
python-sqlite
feedparser
You'll also need a free account at Twitter and Bit.ly, and a Bit.ly API key.

Download the python source code from Google Code, or copy the text below. Please let me know if you found this useful, or have any improvements or modifications to suggest.


Update: To run this script every minute, add the following line to your crontab:
* * * * * /path/to/buzz-twitter-bot.py
This will update Twitter with your Google Buzz posts at least once per minute.

Code:

#!/usr/bin/python
from time import strftime
import sqlite3
import sys
import re

import twitter     #http://code.google.com/p/python-twitter/
import bitly       #http://code.google.com/p/python-bitly/
import feedparser  #available at feedparser.org


DATABASE = "tweets.sqlite"

BITLY_LOGIN = "username"
BITLY_API_KEY = "insert_your_key"

TWITTER_USER = "username"
TWITTER_PASSWORD = "secret"

def print_stats():
conn = sqlite3.connect(DATABASE)
conn.row_factory = sqlite3.Row
c = conn.cursor()

b = bitly.Api(login=BITLY_LOGIN,apikey=BITLY_API_KEY)

c.execute('SELECT title, url, short_url from RSSContent')
all_links = c.fetchall()

for row in all_links:

short_url = row['short_url']

if short_url is None:
short_url = b.shorten(row['url'])
c.execute('UPDATE RSSContent SET `short_url`=? WHERE `url`=?',(short_url,row['url']))


stats = b.stats(short_url)
print "%s - User clicks %s, total clicks: %s" % (row['title'], stats.user_clicks,stats.total_clicks)

conn.commit()

def tweet_rss(url):
print "Opening database...."
conn = sqlite3.connect(DATABASE)
conn.row_factory = sqlite3.Row
c = conn.cursor()
print "Database opened."

#create the table if it doesn't exist
c.execute('CREATE TABLE IF NOT EXISTS RSSContent (`url`, `title`, `dateAdded`, `content`, `short_url`)')

print "Logging in to Twitter...."
api = twitter.Api(username=TWITTER_USER, password=TWITTER_PASSWORD)
print "Logging in to Bitly...."
b = bitly.Api(login=BITLY_LOGIN,apikey=BITLY_API_KEY)

print "Parsing feed...."
d = feedparser.parse(url)

for entry in d.entries:

#check for duplicates
c.execute('select * from RSSContent where url=?', (entry.link,))
if not c.fetchall():
print entry
#Get data from this entry
title = entry.title
content = entry.content[0].value
link = entry.link
updated = entry.updated
#Strip HTML from content
r = re.compile(r'<[^<]*?/?>')
content = r.sub('', content)

print "Found new item"
print "Title: "+title
print "Content: "+content
print "Link: "+link
tweet_text = "Buzz: %s" % content

#Shorten link
print "Shortening link...."
shortened_link = b.shorten(link)
print "Shortened link: "+shortened_link

#Add this entry to the database
t = (link, title, updated, content, shortened_link)
c.execute('insert into RSSContent (`url`, `title`,`dateAdded`, `content`, `short_url`) values (?,?,?,?,?)', t)
print "%s.. %s" % (tweet_text[:115], shortened_link)

#Post to twitter
print "Posting to twitter...."
api.PostUpdate("%s.. %s" % (tweet_text[:115], shortened_link))
print "Post complete."

conn.commit()

if __name__ == '__main__':
tweet_rss(sys.argv[1])
print "Listing stats...."
print_stats()

Special Thanks to Halotis for the RSS Twitter Bot, and love-python.blogspot.com for how to strip HTML tags.

Tuesday, 9 February 2010

How to extract / unzip a .tar.gz file into a different directory

What happens if you need to extract a .tar.gz file, but don't have enough free disk space in the directory? It might show you an error like this:

tar: Wrote only 9216 of 10240 bytes
tar: Skipping to next header
tar: Error exit delayed from previous errors


Tar and Gunzip will only extract into the current directory. Here is a command that will unzip a .tar.gz archive into a new directory.

cd /new-directory
gzip -dc /path/file.tar.gz|tar xvf --

Sunday, 7 February 2010

VFS: busy inodes on changed media or resized disk sr0

(Ubuntu 9.10 Karmic) If you get a lot of error messages like this:

Feb 7 14:38:58 theta kernel: [564762.288036] VFS: busy inodes on changed media or resized disk sr0
Feb 7 14:38:58 theta kernel: [564762.297408] VFS: busy inodes on changed media or resized disk sr0
Feb 7 14:38:59 theta kernel: [564763.286910] VFS: busy inodes on changed media or resized disk sr0
Feb 7 14:39:00 theta kernel: [564764.288880] VFS: busy inodes on changed media or resized disk sr0
Feb 7 14:39:00 theta kernel: [564764.298198] VFS: busy inodes on changed media or resized disk sr0
Feb 7 14:39:01 theta kernel: [564765.288943] VFS: busy inodes on changed media or resized disk sr0
Feb 7 14:39:02 theta kernel: [564766.287691] VFS: busy inodes on changed media or resized disk sr0
Feb 7 14:39:02 theta kernel: [564766.297007] VFS: busy inodes on changed media or resized disk sr0
Feb 7 14:39:03 theta kernel: [564767.339877] VFS: busy inodes on changed media or resized disk sr0
Feb 7 14:39:04 theta kernel: [564768.288076] VFS: busy inodes on changed media or resized disk sr0
Feb 7 14:39:04 theta kernel: [564768.297457] VFS: busy inodes on changed media or resized disk sr0
Feb 7 14:39:05 theta kernel: [564769.288688] VFS: busy inodes on changed media or resized disk sr0
Feb 7 14:39:06 theta kernel: [564770.292023] VFS: busy inodes on changed media or resized disk sr0
Feb 7 14:39:06 theta kernel: [564770.301389] VFS: busy inodes on changed media or resized disk sr0
Feb 7 14:39:07 theta kernel: [564771.316633] VFS: busy inodes on changed media or resized disk sr0
Feb 7 14:39:08 theta kernel: [564772.287440] VFS: busy inodes on changed media or resized disk sr0
Feb 7 14:39:08 theta kernel: [564772.296807] VFS: busy inodes on changed media or resized disk sr0
Feb 7 14:39:09 theta kernel: [564773.288408] VFS: busy inodes on changed media or resized disk sr0
Feb 7 14:39:10 theta kernel: [564774.288406] VFS: busy inodes on changed media or resized disk sr0
Feb 7 14:39:10 theta kernel: [564774.297774] VFS: busy inodes on changed media or resized disk sr0
Feb 7 14:39:11 theta kernel: [564775.286283] VFS: busy inodes on changed media or resized disk sr0
Feb 7 14:39:12 theta kernel: [564776.288231] VFS: busy inodes on changed media or resized disk sr0
Feb 7 14:39:12 theta kernel: [564776.297599] VFS: busy inodes on changed media or resized disk sr0
Feb 7 14:39:13 theta kernel: [564777.294194] VFS: busy inodes on changed media or resized disk sr0
Feb 7 14:39:14 theta kernel: [564778.288487] VFS: busy inodes on changed media or resized disk sr0
Feb 7 14:39:14 theta kernel: [564778.297790] VFS: busy inodes on changed media or resized disk sr0
Feb 7 14:39:15 theta kernel: [564779.287965] VFS: busy inodes on changed media or resized disk sr0
Feb 7 14:39:16 theta kernel: [564780.288390] VFS: busy inodes on changed media or resized disk sr0
Feb 7 14:39:16 theta kernel: [564780.297835] VFS: busy inodes on changed media or resized disk sr0
Feb 7 14:39:17 theta kernel: [564781.288703] VFS: busy inodes on changed media or resized disk sr0

It means your cdrom drive has been ejected without unmounting. Check this by typing this in your terminal:
mount
If this shows a line like:
/dev/sr0 on /media/cdrom1 type iso9660 (ro,nosuid,nodev,utf8)
then your cdrom has been ejected. Try typing:
sudo umount /dev/sr0
This should unmount the cdrom. If it doesn't work, maybe try:
sudo umount -f /dev/sr0

Thursday, 4 February 2010

How to setup FreeRADIUS to integrate with Active Directory Authentication

I used the tutorial found at http://deployingradius.com/documents/configuration/active_directory.html for FreeRadius Active Directory integration, but modified it slightly to suit my needs, and fixed some errors which I encountered.

You may also want to read how to link Linux to a domain.

Firstly, setup Samba to link your computer to the domain:

Once Samba has been installed on your system, you should edit the smb.conf file, and configure the [global] section to point to your NT server, including hostname and NT domain.
# workgroup = NT-Domain-Name
workgroup = MYDOMAIN
...
# Security mode. Most people will want user level security. See
# security_level.txt for details.
security = ads
# Use password server option only with security = server
password server = nt-server-hostname.company.com
...
realm = realm.company.com
You will also have to edit the /etc/krb5.conf file, to add an entry that points to the Active Directory Server
[realms]
...
realm.company.com = {
kdc = nt-server-hostname.company.com
}
...
Start the Samba and Kerberos servers, and as root join the domain:
$ net join -U Administrator
Enter the administrator password at the prompt.
Next, verify that a user in the domain can be authenticated:
$ wbinfo -a user%password
You should see a number of lines of text, followed by authentication succeeded . The next step is to try the same login with the ntlm_auth program, which is what FreeRADIUS will be using:
$ ntlm_auth --request-nt-key --domain=MYDOMAIN --username=user --password=password
If all goes well, you should see authentication succeeding ( NT_STATUS_OK ). You should also see the NT_KEY output, which is needed in order for FreeRADIUS to perform MS-CHAP authentication.

Next, setup FreeRADIUS with ntlm_auth, and test it:

Configuring FreeRADIUS to use ntlm_auth
Once you have verified that Samba is installed and working correctly, and that the ntlm_auth program works, you can proceed with configuring FreeRADIUS to use ntlm_auth. For initial testing, we will be using the exec module, and will run the exact command line used above.
Create a file /etc/freeradius/modules/ntlm_auth , and put the following text in it:
exec ntlm_auth {
wait = yes
program = "/path/to/ntlm_auth --request-nt-key --domain=MYDOMAIN --username=%{mschap:User-Name} --password=%{User-Password}"
}
This configuration tells the server to run the ntlm_auth program with the user name and password obtained from the Access-Request. You will also have to list ntlm_auth in the authenticate sections of each the /etc/freeradius/sites-enabled/default file, and of the /etc/freeradius/sites-enabled/inner-tunnel file:
authenticate {
...
ntlm_auth
...
}
and add the following text for testing purposes only to the top of the users file.
DEFAULT Auth-Type = ntlm_auth
This configuration says "for all users, if the authenticate method has not been set, set it to use the ntlm_auth program".
Start the server using freeradius -X (you may have to stop the automatic daemon by /etc/init.d/freeradius stop), and wait for the debugging text to stop scrolling by. If all goes well, you should see the following text:
Ready to process requests.
In another terminal window on the same machine, type the following command:
$ radtest user password localhost 0 testing123
If all goes well, you should see the server returning an Access-Accept message, and the window with radtest should print text similar to the following:
rad_recv: Access-Accept packet from host 127.0.0.1 port 1812, length=20
This text means that authentication succeeded. A few lines above this text, the debug output will also show the exact command line used to run ntlm_auth.
Note: You may get this error: radclient: socket: cannot initialize udpfromto: Function not implemented.
This means for some reason it can't resolve the hostname localhost. Change localhost to 127.0.0.1 and it should work.

Then setup MS-CHAP with ntlm_auth:

Configuring FreeRADIUS to use ntlm_auth for MS-CHAPOnce you have the previous steps working, configuring FreeRADIUS to use ntlm_auth for MS-CHAP is simple. First, if you use any other authentication types (such as local UNIX accounts) delete the testing entry used above from the users file, as leaving it in will break other authentication types. Instead, move it to the bottom of the file, so that other authentication types still work.
Then, fine the mschap module in /etc/freeradius/modules/mschap file, and look for the line containing ntlm_auth = . It is commented out by default, and should be uncommented, and edited to be as follows. As before, update the fields in bold to match your local configuration.
ntlm_auth = "/path/to/ntlm_auth --request-nt-key --username=%{mschap:User-Name:-None} --domain=%{%{mschap:NT-Domain}:-MYDOMAIN} --challenge=%{mschap:Challenge:-00} --nt-response=%{mschap:NT-Response:-00}"
Start the server and use a test client to send an MS-CHAP authentication request. The radclient cannot currently be used to send this request, unfortunately, which makes testing a little difficult If everything goes well, you should see the server returning an Access-Accept message as above.

More information:
http://wiki.freeradius.org/Authentication
http://tldp.org/HOWTO/8021X-HOWTO/freeradius.html
http://wiki.freeradius.org/FreeRADIUS_Active_Directory_Integration_HOWTO (Broken)
http://homepages.lu/charlesschwartz/radius/freeRadius_AD_tutorial.pdf
http://ubuntuforums.org/showthread.php?t=151388

Update: Here is my full krb5.conf file (my domain name has been replaced with "domain.local"). Note that this configuration includes many default settings which I haven't bothered to get rid of. All the MIT and standford stuff is unneccessary.


[libdefaults]
default_realm = DOMAIN.LOCAL

# The following krb5.conf variables are only for MIT Kerberos.
krb4_config = /etc/krb.conf
krb4_realms = /etc/krb.realms
kdc_timesync = 1
ccache_type = 4
forwardable = true
proxiable = true

# The following encryption type specification will be used by MIT Kerberos
# if uncommented. In general, the defaults in the MIT Kerberos code are
# correct and overriding these specifications only serves to disable new
# encryption types as they are added, creating interoperability problems.
#
# Thie only time when you might need to uncomment these lines and change
# the enctypes is if you have local software that will break on ticket
# caches containing ticket encryption types it doesn't know about (such as
# old versions of Sun Java).

# default_tgs_enctypes = des3-hmac-sha1
# default_tkt_enctypes = des3-hmac-sha1
# permitted_enctypes = des3-hmac-sha1

# The following libdefaults parameters are only for Heimdal Kerberos.
v4_instance_resolve = false
v4_name_convert = {
host = {
rcmd = host
ftp = ftp
}
plain = {
something = something-else
}
}
fcc-mit-ticketflags = true

[realms]
ATHENA.MIT.EDU = {
kdc = kerberos.mit.edu:88
kdc = kerberos-1.mit.edu:88
kdc = kerberos-2.mit.edu:88
admin_server = kerberos.mit.edu
default_domain = mit.edu
}
MEDIA-LAB.MIT.EDU = {
kdc = kerberos.media.mit.edu
admin_server = kerberos.media.mit.edu
}
ZONE.MIT.EDU = {
kdc = casio.mit.edu
kdc = seiko.mit.edu
admin_server = casio.mit.edu
}
MOOF.MIT.EDU = {
kdc = three-headed-dogcow.mit.edu:88
kdc = three-headed-dogcow-1.mit.edu:88
admin_server = three-headed-dogcow.mit.edu
}
CSAIL.MIT.EDU = {
kdc = kerberos-1.csail.mit.edu
kdc = kerberos-2.csail.mit.edu
admin_server = kerberos.csail.mit.edu
default_domain = csail.mit.edu
krb524_server = krb524.csail.mit.edu
}
IHTFP.ORG = {
kdc = kerberos.ihtfp.org
admin_server = kerberos.ihtfp.org
}
GNU.ORG = {
kdc = kerberos.gnu.org
kdc = kerberos-2.gnu.org
kdc = kerberos-3.gnu.org
admin_server = kerberos.gnu.org
}
1TS.ORG = {
kdc = kerberos.1ts.org
admin_server = kerberos.1ts.org
}
GRATUITOUS.ORG = {
kdc = kerberos.gratuitous.org
admin_server = kerberos.gratuitous.org
}
DOOMCOM.ORG = {
kdc = kerberos.doomcom.org
admin_server = kerberos.doomcom.org
}
ANDREW.CMU.EDU = {
kdc = vice28.fs.andrew.cmu.edu
kdc = vice2.fs.andrew.cmu.edu
kdc = vice11.fs.andrew.cmu.edu
kdc = vice12.fs.andrew.cmu.edu
admin_server = vice28.fs.andrew.cmu.edu
default_domain = andrew.cmu.edu
}
CS.CMU.EDU = {
kdc = kerberos.cs.cmu.edu
kdc = kerberos-2.srv.cs.cmu.edu
admin_server = kerberos.cs.cmu.edu
}
DEMENTIA.ORG = {
kdc = kerberos.dementia.org
kdc = kerberos2.dementia.org
admin_server = kerberos.dementia.org
}
DOMAIN.LOCAL = {
kdc = primaryserver.domain.local
admin_server = primaryserver.domain.local
default_domain = DOMAIN.LOCAL
}
stanford.edu = {
kdc = krb5auth1.stanford.edu
kdc = krb5auth2.stanford.edu
kdc = krb5auth3.stanford.edu
master_kdc = krb5auth1.stanford.edu
admin_server = krb5-admin.stanford.edu
default_domain = stanford.edu
}

[domain_realm]
.mit.edu = ATHENA.MIT.EDU
mit.edu = ATHENA.MIT.EDU
.media.mit.edu = MEDIA-LAB.MIT.EDU
media.mit.edu = MEDIA-LAB.MIT.EDU
.csail.mit.edu = CSAIL.MIT.EDU
csail.mit.edu = CSAIL.MIT.EDU
.whoi.edu = ATHENA.MIT.EDU
whoi.edu = ATHENA.MIT.EDU
.stanford.edu = stanford.edu
.slac.stanford.edu = SLAC.STANFORD.EDU
.domain.local = DOMAIN.LOCAL
domain.local = DOMAINL.LOCAL

[login]
krb4_convert = true
krb4_get_tickets = false

Monday, 1 February 2010

How to setup Linux (Ubuntu) Active Directory Authentication with Cached Credentials (Kerberos)

Running Linux, I'm using Kerberos & Samba to authenticate myself using Microsoft Windows Active Directory credentials from our domain controller. I used the guide for Ubuntu to get this setup. However, this would not allow me to login to my computer using AD credentials unless I was connected to the network (and it could access the domain controller). This is how I enabled "credential caching" for offline kerberos / Active Directory authentication on Ubuntu Linux.

I used two tutorials - Ubuntu Community Howto, and Cat in the Red Hat. Basically, since I already had Kerberos authentication working, I just installed the necessary packages:

sudo apt-get install nss-updatedb libnss-db libpam-ccreds

and then edited my /etc/pam.d/common-auth file as per Cat in the Red Hat's instructions.

Listed here is the entire contents of my /etc/pam.d/common-auth file (this allows me to authenticate using first AD credentials, then Unix accounts, then cached credentials):

auth sufficient pam_unix.so nullok try_first_pass
auth requisite pam_succeed_if.so uid >= 500 quiet
auth [default=ignore success=1 service_err=reset] pam_krb5.so use_first_pass
auth [default=die success=done] pam_ccreds.so action=validate use_first_pass
auth sufficient pam_ccreds.so action=store use_first_pass
auth required pam_deny.so
# prime the stack with a positive return value if there isn't one already;
# this avoids us returning an error just because nothing sets a success code
# since the modules above will each just jump around
auth required pam_permit.so
# and here are more per-package modules (the "Additional" block)
# end of pam-auth-update config


Some of the errors I encountered:

Firstly, caching will not work if you have a line like the following:

#Windows Domain Auth
#auth sufficient pam_winbind.so krb5_auth krb5_ccache_type=FILE


This basically skips everything else when a successful kerberos authentication is made. I just commented this line out, and it worked fine.

If you receive an error such as "su: Error in service module" when trying to login, it may be that your file is misconfigured. Check whether /var/cache/.security.db is being created or updated - if it isn't, then most likely PAM isn't reaching the line where pam_ccreds.so is referenced. Check that you don't have any auth sufficient lines where they shouldn't be.

If you're interested, there's also quite a nice GUI for Active Directory integration at Likewise. I haven't used it, but looks like an easy way to setup AD authentication from Ubuntu without editing heaps of config files.

How to connect to MSSQL (ODBC) from Linux PHP

Marcin Gil has an excellent guide about how to setup ODBC drivers on Linux to talk to a Microsoft MSSQl Server running on Windows. This uses the FreeTDS drivers & unixODBC, along with standard PHP/Apache setup.

After following these instructions, I found my database was still giving me the following error:

Warning: odbc_connect() [function.odbc-connect]: SQL error: [unixODBC][FreeTDS][SQL Server]Unable to connect to data source, SQL state S1000 in SQLConnect in /var/www/testdatabase/stdFunctions.php on line 49
Couldn't connect to SQL Server database


This was due to my database code not passing the correct username and password. I had to edit the odbc_connect() line to read as follows:

odbc_connect("database", "DOMAIN\username", "password");