RT3 ActiveDirectory User Attributes Sync

Ok, here is another small script to deal with RT3 and Active Directory. If you apply the apache LDAP auth described previously to your RT3 installation, you will have no problem getting people logged in, but you will still have to adjust their names and emails. Doing this manually is not the best choice, so here is a small script, which can be run from the cron (or manually) to update user info in RT3 according to user attributes in Active Directory:

#!/usr/bin/php
< ?php

# Debug flag. Set to non-zero for verbose output
$debug = 0;

# Settings to use while connecting to active directory
$ldap_host = "10.10.10.1"; # AD server
$ldap_user = "someuser@example.com"; # User in AD with read writes
$ldap_pass = "someuser_password"; # Password for the user above
$ldap_base = "dc=example,dc=com"; # AD base to search (recursivly)

# Settings to use while connecting to rt3 MySQL DB
$sql_host = "127.0.0.1"; # MySQL server
$sql_name = "rt3"; # RT3 DB name in MySQL
$sql_user = "rt3_user"; # User to connect to above DB
$sql_pass = "rt3_pass"; # Password for the user above

# Map of RT3 -> AD attributes
$attr_map = array(
	'RealName'		=> 'displayName',
	'EmailAddress'	=> 'mail'
);

# Connect to AD and authenticate
$ldap = ldap_connect($ldap_host);
if (!$ldap) {
	die ("Failed to connect to LDAP server: " . ldap_error() . "\n");
}
ldap_set_option($ldap, LDAP_OPT_PROTOCOL_VERSION, 3);
ldap_set_option($ldap, LDAP_OPT_REFERRALS, 0);
if (!ldap_bind($ldap,$ldap_user,$ldap_pass)) {
	die ("Failed to bind to LDAP server: " . ldap_error() . "\n");
}

# Connect to MySQL
$sql = mysql_connect($sql_host,$sql_user,$sql_pass);
if (!$sql) {
	die ("Failed to connect to MySQL server: " . mysql_error() . "\n");
}
if (!mysql_select_db($sql_name)) {
	die ("Failed to select MySQL database: " . mysql_error() . "\n");
}

# Get a list of RT3 users from MySQL
$users = get_rt3_users();

# Update attributes for each RT3 user according to AD attributes
foreach ($users as $user) {
	set_rt3_user_info($user,get_ldap_user_attr($user));
}

# Close the connections to MySQL and AD
mysql_close($sql);
ldap_unbind($ldap);

# Gets a list of RT3 users from MySQL
function get_rt3_users () {
	global $sql;

	# Skips the external users (the ones that look like email address)
	$result = mysql_query("SELECT Name FROM Users WHERE Name NOT LIKE '%@%'",$sql);
	$users = array();
	while ($user = mysql_fetch_array($result)) {
		array_push($users,$user[0]);
	}
	return $users;
}

# Gets AD attributes for the given user
function get_ldap_user_attr ($user) {
	global $ldap,$ldap_base,$attr_map,$debug;

	if ($debug) { print "Searching for user $user\n"; }
	$result = ldap_search($ldap,$ldap_base,"(sAMAccountName=$user)");
	$entries = array();
	if ($result) {
		$entries = ldap_get_entries($ldap,$result);
	} else {
		die("Failed to search LDAP: " . ldap_error($ldap) . "\n");
	}
	return $entries;
}

# Updates RT3 user in MySQL with given AD attributes
function set_rt3_user_info ($user,$attr) {
	global $sql,$attr_map;

	# Construct an update SQL query arguments
	$query = "";
	foreach ($attr_map as $k => $v) {

		# Update field only if it is set and non empty
		if (isset($attr[0][strtolower($v)][0]) and $attr[0][strtolower($v)][0] != "") {
			$query .= ",$k='" . mysql_escape_string($attr[0][strtolower($v)][0]) . "'";
		}
	}

	# Run the actual query
	$query = "UPDATE Users SET ".substr($query,1)." WHERE Name='".mysql_escape_string($user)."';";
	mysql_query($query);
}

?>

Now each time a new user logs in to RT3 and his username appears in RT3 database, this script will update his/her name and email. You can extend a list of mapped attributes to have more info updated if you want so.

Apache MS Active Directory Auth

I know there are plenty of methods to apache auth through active directory, but recently I found out that some of them didn’t work for me or didn’t do well. The more or less successfull one was perl Apache2::AuthenNTLM, but when you have a lot of users, this one blocks apache now and then and causes some real problems.

Like always, found out about apache mod_authnz_external and ended up writing my own authentication script. Here is how to make things work:

First of all download and install mod_authnz_external (google for the package and installation instructions).

Then put the next script somewhere on the apache server (for example /etc/httpd/conf/ad_login.php):

< ?php

// AD server IP address
$ldap_host = "10.10.10.1";

// AD Base
$ldap_base = "dc=example,dc=com";

// AD domain
$ldap_domain = "example.com";

// Connect to AD server
$stderr = fopen("php://stderr","w");
$ldap = @ldap_connect($ldap_host);
if (!$ldap) {
	fwrite($stderr,"AD Auth: Failed to connect to $ldap_host\n");
	fclose($stderr);
	exit(1);
}
@ldap_set_option($ldap, LDAP_OPT_PROTOCOLO_VERSION, 3);
@ldap_set_option($ldap, LDAP_OPT_REFERRALS, 0);

// Try to login with the supplied username and password
// (using environment to pass the stuff)
if (!@ldap_bind($ldap,$_ENV['USER'] . '@' . $ldap_domain,$_ENV['PASS'])) {
	fwrite($stderr,"AD Auth: Failed to authenticate " . $_ENV['USER'] . "\n");
	fclose($stderr);

	// if failed - exit with 1
	exit(1);
}

ldap_unbind($ldap);
fclose($stderr);

// exit with 0 on success
exit(0);

?>

Next, add the following into VirtualHost (or similar) definition in apache config:

AddExternalAuth ad "/usr/bin/php -f /etc/httpd/conf/ad_login.php"
SetExternalAuthMethod ad environment

# This can go into Location or Directory sections
AuthType basic
AuthName "My Closed Zone"
AuthBasicProvider external
AuthExternal "ad"
require valid-user

Restart apache and you are done.

How does it work? Simple. Each time apache will need to authenticate a user, it will start a script (ad_login.php) and pass it username and password as environment variables. The script, in turn, will try to connect to AD and authenticate itself as given user. If that fails – login fails, otherwise – login ok. So basically, if a user has writes to connect to AD, (s)he has write to login to apache.

And of course you can extend the PHP script with some extras, like additional checks on username, caching and so on.

Ericsson p910, Linux, Mobical

Finally I got my p910 back from the repairs (had problems with screen). Playing around with it during weekends (oh yes – I was missing it a lot) and I have managed to sync my contacts from p910 via bluetooth and my laptop running fedora 8 to mobical. This was more than critical for me after I didn’t have access to my phone contacts for few months.

The major problem for me was to make p910 utilize internet of my laptop through bluetooth. There are a lot of how-tos, but all of them were missing smthing :(. Here how it worked for me (originally found here):
Put the following into /etc/ppp/peers/dun

460800
debug
ipcp-accept-remote
192.168.1.1:192.168.1.2
MS-DNS <IP of DNS server used by linux box>
lock
crtscts
noauth
defaultroute

Then put this to /etc/sysconfig/iptables:

*filter
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
:RH-Firewall-1-INPUT – [0:0]
-A INPUT -j RH-Firewall-1-INPUT
-A FORWARD -j RH-Firewall-1-INPUT
-A RH-Firewall-1-INPUT -i lo -j ACCEPT
-A RH-Firewall-1-INPUT -i ppp0 -j ACCEPT
-A RH-Firewall-1-INPUT -p icmp –icmp-type any -j ACCEPT
-A RH-Firewall-1-INPUT -p 50 -j ACCEPT
-A RH-Firewall-1-INPUT -p 51 -j ACCEPT
-A RH-Firewall-1-INPUT -p UDP –dport 5353 -d 224.0.0.251 -j ACCEPT
-A RH-Firewall-1-INPUT -p UDP -m UDP –dport 631 -j ACCEPT
-A RH-Firewall-1-INPUT -m state –state ESTABLISHED,RELATED -j ACCEPT
-A RH-Firewall-1-INPUT -j REJECT –reject-with icmp-host-prohibited
COMMIT
*mangle
:PREROUTING ACCEPT [0:0]
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0]
-A PREROUTING -i ppp0 -j MARK –set-mark 0×9
COMMIT
*nat
:PREROUTING ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0]
-A POSTROUTING -m mark –mark 0×9 -j MASQUERADE
COMMIT

Then run the next set of commands (as root):

/sbin/service bluetooth start
/sbin/sysctl net.ipv4.conf.all.forwarding=1
/sbin/service iptables restart
dund –listen –encrypt call dun

Here we finished with Linux setup. Now get yourself a GnuBox application for p910. Follow the instructions on how to set it up on the GnuBox website. Finally, open gnubox, go to Options -> 2box Bluetooth -> LAN Access server, select your linux box in a list of devises, tell “Yes” when asked about encryption. Done, now you can use internet with “Bt” dialup account from your phone (refer to GnuBox setup instructions) and it will take you the whole path through linux to internet :)

The mobical part is easy – just register there and you will get an auto-configuration SMS for your p910. Now you can sync in any direction :)

Transport Tycoon Delux data files

I see a lot of hits for the Open Transport Tycoon Deluxe post which I made quite a long time ago and where I have mentioned the download of the full pack of OpenTTD with original data files. This download is not available from that server anymore (for some time already as well), but since I (still) have data files, here is an archive of a full data folder from OpenTTD, just get what is missing from there for your setup.

IDE vs Text Editor for Web

I see more and more people are starting to do web programming (including HTML, JavaScript, PHP/Perl) in kind of IDEs like Dreamwaver, Frontpage, Nvu and so on. It looks a bit weired for me. First of all coding in proper text editor (like Vim) gives you all kinds of features like text highlighting, tags auto completion, multi-file editing and so on. Second, while writing your code directly in editor you specify proper names of styles/classes/whatever from the beginning instead of your IDE assigning some stupid names like style1, id15 and similar and than you going over to correct them (or sometimes navigating through 100 GUI menus to change them or even leaving them like that). Third, you can write all-browsers-compatible code from the start instead of dropping elements here/there which will perfectly work in let’s say Internet Explorer and then trying understand what code was generated by IDE and adjust it. Finally, coding with text editors makes you think more and thus make better code then just letting things go as they done automatically and then correct a bunch of problems and not taking into consideration other bunch of problems because your IDE couldn’t do it well and you haven’t thought about it since you even haven’t seen the code.