<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Evan Hoffman&#039;s silly writings.</title>
	<atom:link href="http://www.evanhoffman.com/evan/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.evanhoffman.com/evan</link>
	<description>Stuff, and more stuff.</description>
	<lastBuildDate>Sun, 07 Mar 2010 14:34:51 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Cablevision loses WABC (Channel 7)?</title>
		<link>http://www.evanhoffman.com/evan/2010/03/07/cablevision-loses-wabc-channel-7/</link>
		<comments>http://www.evanhoffman.com/evan/2010/03/07/cablevision-loses-wabc-channel-7/#comments</comments>
		<pubDate>Sun, 07 Mar 2010 14:34:51 +0000</pubDate>
		<dc:creator>evan</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[cablevision]]></category>
		<category><![CDATA[fios]]></category>
		<category><![CDATA[internet]]></category>
		<category><![CDATA[long island]]></category>
		<category><![CDATA[money]]></category>
		<category><![CDATA[ool]]></category>
		<category><![CDATA[optimum]]></category>

		<guid isPermaLink="false">http://www.evanhoffman.com/evan/?p=348</guid>
		<description><![CDATA[Wow.  Glad I left.  I imagine this will be temporary (like the HGTV ordeal earlier this year). 
On another note, I got my 3rd FiOS bill &#8211; still running a credit.  That&#8217;s $43 for 3.5 months of great service.  Good luck competing with that, Optimum.
]]></description>
			<content:encoded><![CDATA[<p>Wow.  Glad I left.  I imagine this will be temporary (like the HGTV ordeal earlier this year). </p>
<p>On another note, I got my 3rd FiOS bill &#8211; still running a credit.  That&#8217;s $43 for 3.5 months of great service.  Good luck competing with that, Optimum.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.evanhoffman.com/evan/2010/03/07/cablevision-loses-wabc-channel-7/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Free DNS Hosting?</title>
		<link>http://www.evanhoffman.com/evan/2010/02/24/free-dns-hosting/</link>
		<comments>http://www.evanhoffman.com/evan/2010/02/24/free-dns-hosting/#comments</comments>
		<pubDate>Wed, 24 Feb 2010 07:07:41 +0000</pubDate>
		<dc:creator>evan</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[evan hoffman]]></category>
		<category><![CDATA[evanhoffman]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[money]]></category>
		<category><![CDATA[sleepy]]></category>

		<guid isPermaLink="false">http://www.evanhoffman.com/evan/?p=346</guid>
		<description><![CDATA[My Bluehost renewal is coming up soon and I&#8217;m really debating cancelling it.  It&#8217;s like $8/month, but with my email going directly to Gmail now, this dumb blog is the only thing of note at evanhoffman.com, and I can move that anywhere.  I already copied all the content to another server but I [...]]]></description>
			<content:encoded><![CDATA[<p>My Bluehost renewal is coming up soon and I&#8217;m really debating cancelling it.  It&#8217;s like $8/month, but with my email going directly to Gmail now, this dumb blog is the only thing of note at evanhoffman.com, and I can move that anywhere.  I already copied all the content to another server but I can&#8217;t find free DNS hosting anywhere.  Maybe i&#8217;ll just run my own nameserver.</p>
<p>MAYBE!!!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.evanhoffman.com/evan/2010/02/24/free-dns-hosting/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>2nd FiOS connectivity problem</title>
		<link>http://www.evanhoffman.com/evan/2010/02/13/2nd-fios-connectivity-problem/</link>
		<comments>http://www.evanhoffman.com/evan/2010/02/13/2nd-fios-connectivity-problem/#comments</comments>
		<pubDate>Sat, 13 Feb 2010 14:39:06 +0000</pubDate>
		<dc:creator>evan</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[fios]]></category>
		<category><![CDATA[internet]]></category>
		<category><![CDATA[MI424WR-GEN2]]></category>

		<guid isPermaLink="false">http://www.evanhoffman.com/evan/?p=344</guid>
		<description><![CDATA[This is the second time this has happened:  All the wifi devices in my house lose their connection to the FiOS router/access point (ActionTec MI424WR-GEN2).  I checked my wired desktop and it wasn&#8217;t able to get an IP from the DHCP server (the router).  The &#8220;Internet&#8221; light on the router was out. [...]]]></description>
			<content:encoded><![CDATA[<p>This is the second time this has happened:  All the wifi devices in my house lose their connection to the FiOS router/access point (ActionTec MI424WR-GEN2).  I checked my wired desktop and it wasn&#8217;t able to get an IP from the DHCP server (the router).  The &#8220;Internet&#8221; light on the router was out.  I unplugged the router and plugged it back in and it came back up fine.  But this happened about a month ago too &#8211; I wonder if it&#8217;s a monthly thing?  Either way, it&#8217;s annoying.  Other than this, the internet service is phenomenal still.</p>
<p><img src="http://www.speedtest.net/result/715595934.png" width="300" height="135"></p>
]]></content:encoded>
			<wfw:commentRss>http://www.evanhoffman.com/evan/2010/02/13/2nd-fios-connectivity-problem/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Got my second FiOS bill</title>
		<link>http://www.evanhoffman.com/evan/2010/02/12/got-my-second-fios-bill/</link>
		<comments>http://www.evanhoffman.com/evan/2010/02/12/got-my-second-fios-bill/#comments</comments>
		<pubDate>Fri, 12 Feb 2010 21:21:18 +0000</pubDate>
		<dc:creator>evan</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[cablevision]]></category>
		<category><![CDATA[fios]]></category>
		<category><![CDATA[internet]]></category>
		<category><![CDATA[long island]]></category>
		<category><![CDATA[money]]></category>
		<category><![CDATA[ool]]></category>

		<guid isPermaLink="false">http://www.evanhoffman.com/evan/?p=342</guid>
		<description><![CDATA[So I got my second FiOS bill a couple of weeks ago.  After the issue with my first bill was straightened out I ended up paying about $43 for the first 6 weeks of service.  Well, my second bill was about $90, but applied a $180 credit on my account, so the bill [...]]]></description>
			<content:encoded><![CDATA[<p>So I got my second FiOS bill a couple of weeks ago.  After the issue with my first bill was straightened out I ended up paying about $43 for the first 6 weeks of service.  Well, my second bill was about $90, but applied a $180 credit on my account, so the bill showed -$91.  So basically the first 3 months of service will end up costing me about $43.  Even if it comes to $90/month for the remainder of the contract, this is such a huge savings that I don&#8217;t see how Cablevision could match it.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.evanhoffman.com/evan/2010/02/12/got-my-second-fios-bill/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Running MRTG cfgmaker across your entire subnet?</title>
		<link>http://www.evanhoffman.com/evan/2010/01/27/running-mrtg-cfgmaker-across-your-entire-subnet/</link>
		<comments>http://www.evanhoffman.com/evan/2010/01/27/running-mrtg-cfgmaker-across-your-entire-subnet/#comments</comments>
		<pubDate>Wed, 27 Jan 2010 17:00:30 +0000</pubDate>
		<dc:creator>evan</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[bash]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[mrtg]]></category>
		<category><![CDATA[nmap]]></category>
		<category><![CDATA[perl]]></category>
		<category><![CDATA[routers2.cgi]]></category>
		<category><![CDATA[work]]></category>

		<guid isPermaLink="false">http://www.evanhoffman.com/evan/?p=336</guid>
		<description><![CDATA[I realized recently that I had a bunch of newly-provisioned VMs that weren&#8217;t being monitored by MRTG (one of the tools we use to monitor network usage and other fun stats).  Rather than manually run cfgmaker against all the new machines, I decided to script my way out of this.

Step 1: Build a list [...]]]></description>
			<content:encoded><![CDATA[<p>I realized recently that I had a bunch of newly-provisioned VMs that weren&#8217;t being monitored by MRTG (one of the tools we use to monitor network usage and other fun stats).  Rather than manually run cfgmaker against all the new machines, I decided to script my way out of this.</p>
<p><span id="more-336"></span></p>
<p><strong>Step 1: Build a list of hosts to monitor</strong></p>
<p>For this I used an nmap ping test to generate a list of &#8220;up&#8221; hosts:</p>
<p><code>nmap -sP 10.0.0.0/24 -oG 10.0.0.0-255.255.255.0</code></p>
<p>This creates a list of IPs that are up in a format like this:</p>
<p><code><br />
Host: 10.0.0.60 ()      Status: Up<br />
Host: 10.0.0.61 ()      Status: Up<br />
Host: 10.0.0.63 ()      Status: Up<br />
Host: 10.0.0.64 ()      Status: Up<br />
Host: 10.0.0.65 ()      Status: Up<br />
</code></p>
<p><strong>Step 2: Parse out the IP address and run cfgmaker</strong></p>
<p>Here&#8217;s the command I ran:</p>
<p><code>$ for i in `perl -ne 'chomp; next if $_ =~ /^#/; my @a = split(/ /); print "$a[1]\n";' 10.0.0.0-255.255.255.0`; do /usr/bin/cfgmaker --global 'LogFormat: rrdtool' --global 'WorkDir: /mrtg/data/mrtg' --global 'Options[_]: growright,bits' --global 'XSize[_]: 600' --global 'YSize[_]: 400' public@$i > /etc/mrtg/mrtg-$i ; done</code></p>
<p>This parses out the IP address from the input file and for each address, runs cfgmaker and puts the output in /etc/mrtg/mrtg-[ipaddress] . </p>
<p>Taking this a step further, I used gethostbyaddr to resolve the IPs to hostnames, so the MRTG files have the proper  hostnames in them:</p>
<p><code>$ for i in `perl -MSocket -ne 'chomp; next if $_ =~ /^#/; my @a = split(/ /); my $ip = inet_aton($a[1]); my $host = gethostbyaddr($ip, AF_INET); print "$host\n";' 10.0.0.0-255.255.255.0`; do /usr/bin/cfgmaker --global 'LogFormat: rrdtool' --global 'WorkDir: /mrtg/data/mrtg' --global 'Options[_]: growright,bits' --global 'XSize[_]: 600' --global 'YSize[_]: 400' public@$i  > /etc/mrtg/mrtg-$i ; done</code></p>
<p>Then all of the mrtg .cfg config files are in /etc/mrtg/, but who wants to put in all those cron entries to run each one?  Not me.  Simple fix?</p>
<p><code> cat /etc/mrtg/*.cfg > /etc/mrtg-all.cfg</code></p>
<p>Then you only have one cron entry.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.evanhoffman.com/evan/2010/01/27/running-mrtg-cfgmaker-across-your-entire-subnet/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>My Apple tablet prediction.</title>
		<link>http://www.evanhoffman.com/evan/2010/01/23/my-apple-tablet-prediction/</link>
		<comments>http://www.evanhoffman.com/evan/2010/01/23/my-apple-tablet-prediction/#comments</comments>
		<pubDate>Sun, 24 Jan 2010 00:13:31 +0000</pubDate>
		<dc:creator>evan</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[apple]]></category>
		<category><![CDATA[hype]]></category>
		<category><![CDATA[tablet]]></category>

		<guid isPermaLink="false">http://www.evanhoffman.com/evan/?p=334</guid>
		<description><![CDATA[I know nobody cares, but I figured I&#8217;d hop on the hypewagon and write down my guess for the Apple tablet.  I think a &#8220;big iPod Touch&#8221; would be pretty boring, and not worth making.  My guess (based on nothing): the unit will be controlled by eye tracking, and it&#8217;ll be able to [...]]]></description>
			<content:encoded><![CDATA[<p>I know nobody cares, but I figured I&#8217;d hop on the hypewagon and write down my guess for the Apple tablet.  I think a &#8220;big iPod Touch&#8221; would be pretty boring, and not worth making.  My guess (based on nothing): the unit will be controlled by eye tracking, and it&#8217;ll be able to zoom in on whatever you&#8217;re looking at.</p>
<p>That is all.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.evanhoffman.com/evan/2010/01/23/my-apple-tablet-prediction/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Victory!  Change Active Directory Password via LDAP through browser</title>
		<link>http://www.evanhoffman.com/evan/2010/01/13/victory-change-active-directory-password-via-ldap-through-browser/</link>
		<comments>http://www.evanhoffman.com/evan/2010/01/13/victory-change-active-directory-password-via-ldap-through-browser/#comments</comments>
		<pubDate>Wed, 13 Jan 2010 17:51:43 +0000</pubDate>
		<dc:creator>evan</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[active directory]]></category>
		<category><![CDATA[change password]]></category>
		<category><![CDATA[howto]]></category>
		<category><![CDATA[ldap]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[password]]></category>
		<category><![CDATA[perl]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[unicodePwd]]></category>
		<category><![CDATA[victory]]></category>
		<category><![CDATA[windows]]></category>
		<category><![CDATA[work]]></category>

		<guid isPermaLink="false">http://www.evanhoffman.com/evan/?p=321</guid>
		<description><![CDATA[I had to give up on PHP and go to Perl, but it turned out not to be so bad.  Users can now change their Active Directory passwords via a self-service web page that doesn&#8217;t require admin credentials.  The Perl code is below.  Authentication to the script is done via .htaccess LDAP authentication, [...]]]></description>
			<content:encoded><![CDATA[<p>I had to give up on PHP and go to Perl, but it turned out not to be so bad.  Users can now change their Active Directory passwords via a self-service web page that doesn&#8217;t require admin credentials.  The Perl code is below.  Authentication to the script is done via .htaccess LDAP authentication, so the REMOTE_USER env variable is assumed to contain the user&#8217;s username (sAMAccountName) by the time this script is called.  There is a simple check for $ENV{HTTPS} to ensure the script is called via SSL, and AD requires password changes to be done via ldaps, so the whole thing <em>should</em> be encrypted end to end.</p>
<p><span id="more-321"></span></p>
<pre>#!/usr/bin/perl
#
# Evan Hoffman (evanhoffman@evanhoffman.com)
# 13 January, 2010
#
# Base functionality from: http://search.cpan.org/~gbarr/perl-ldap/lib/Net/LDAP/FAQ.pod#..._in_MS_Active_Directory_?

print "Content-Type: text/html\n\n";

use Net::LDAP;
use Unicode::Map8;
use Unicode::String qw(utf16);
use MIME::Base64;
use CGI::Lite;

# build the conversion map from your local character set to Unicode
my $charmap = Unicode::Map8-&gt;new('latin1')  or  die;

my $host = 'ldaps://activedirectory.example.com';	

my $bind_dn = 'CN=ldapuser,OU=Utility,OU=Users,DC=example,DC=com';
my $bind_pw = 'secret';
my $base_dn = 'DC=example,DC=com';
my $search_filter = '(!(userAccountControl:1.2.840.113556.1.4.803:=2))';

my $ldap = Net::LDAP-&gt;new($host)  or  die "$@";

print '&lt;html&gt;&lt;title&gt;Active Directory Password Changer $Id$&lt;/title&gt;&lt;body&gt;';

die "REMOTE_USER not set.\n" unless $ENV{'REMOTE_USER'};

unless ( $ENV{'HTTPS'} eq 'on' ) {
	print "&lt;b&gt;This script requires HTTPS.&lt;/b&gt;\n";
	die;

}

print "Logged in as &lt;b&gt;$ENV{REMOTE_USER}&lt;/b&gt;.  LDAP URI is &lt;b&gt;$host&lt;/b&gt;.&lt;br&gt;\n";

$cgi = new CGI::Lite;

%form = $cgi-&gt;parse_form_data;

if ($form{'op'} eq 'submit') {
	my $user_dn = $form{'dn'};
	my $user_pw = $form{'oldpassword'};
	my $newpw1 = $form{'newpw1'};
	my $newpw2 = $form{'newpw2'};

	die 'Password mismatch.'  unless ( $newpw1 eq $newpw2 );
	die 'No DN specified.' unless $user_dn;

	print "Attempting to bind as &lt;b&gt;$user_dn&lt;/b&gt; ... ";

	my $mesg = $ldap-&gt;bind($user_dn,
			password =&gt; $user_pw);
	if ($mesg-&gt;is_error) {
		my $err = "Error attempting to bind as $user_dn: ". $mesg-&gt;error;
		print "&lt;pre&gt;$err&lt;/pre&gt;";
		die $err;
	}

	print " OK.&lt;br&gt;\n";

	my $oldUniPW = $charmap-&gt;tou('"'.$user_pw.'"')-&gt;byteswap()-&gt;utf16();
	my $newUniPW = $charmap-&gt;tou('"'.$newpw1.'"')-&gt;byteswap()-&gt;utf16();

	print "Attempting to modify password for &lt;b&gt;$user_dn&lt;/b&gt; ... ";

	$mesg = $ldap-&gt;modify($user_dn,
			changes =&gt; [
			delete =&gt; [ unicodePwd =&gt; $oldUniPW ],
			add    =&gt; [ unicodePwd =&gt; $newUniPW ] ]);

	print "OK&lt;br&gt;\n";

#	$mesg-&gt;is_error &amp;&amp; die ('Modify error: '. $mesg-&gt;error);
	if ($mesg-&gt;is_error) {
		my $err = 'Modify error: '. $mesg-&gt;error;
		print "&lt;pre&gt;$err&lt;/pre&gt;\n";
		die $err;
	}

	$ldap-&gt;unbind();
	print "&lt;blink&gt;VICTORY!!&lt;/blink&gt; Successfully changed password for user $ENV{REMOTE_USER}, DN &lt;b&gt;$user_dn&lt;/b&gt;, msg ID: ".$mesg-&gt;mesg_id ."\n";

} else {

# bind as dummy to lookup the user's DN
	my $mesg = $ldap-&gt;bind($bind_dn, password =&gt; $bind_pw );
	$mesg-&gt;is_error &amp;&amp; die ('Bind error: '. $mesg-&gt;error);

	$mesg = $ldap-&gt;search(
			base =&gt; $base_dn,
			scope =&gt; 'sub',
			attrs =&gt; ['dn','cn','mail'],
			filter =&gt; "(&amp;(samaccountname=$ENV{REMOTE_USER})$search_filter)"
			);
	$mesg-&gt;is_error &amp;&amp; die ( 'Search failed: '. $mesg-&gt;error );

	$mesg-&gt;count || die ("Search for user '$ENV{REMOTE_USER}' returned no results.");

	my $entry = $mesg-&gt;entry( 0 );

	$ldap-&gt;unbind();

	print "LDAP DN for user '$ENV{REMOTE_USER}': &lt;b&gt;".$entry-&gt;dn.'&lt;/b&gt;';

	print "&lt;form action='$ENV{REQUEST_URI}' METHOD='POST'&gt;\n";
	print "&lt;input type='hidden' name='op' value='submit'&gt;\n";
	print "&lt;input type='hidden' name='dn' value='".$entry-&gt;dn."'&gt;\n";

	print "&lt;table border='0'&gt;\n";
	print "&lt;tr&gt;&lt;td&gt;Current password for &lt;b&gt;$ENV{REMOTE_USER}&lt;/b&gt;:&lt;/td&gt;&lt;td&gt;&lt;input type='password' name='oldpassword' size='30'&gt;&lt;/td&gt;&lt;/tr&gt;\n";
	print "&lt;tr&gt;&lt;td&gt;New password for &lt;b&gt;$ENV{REMOTE_USER}&lt;/b&gt;:&lt;/td&gt;&lt;td&gt;&lt;input type='password' name='newpw1' size='30'&gt;&lt;/td&gt;&lt;/tr&gt;\n";
	print "&lt;tr&gt;&lt;td&gt;New password for &lt;b&gt;$ENV{REMOTE_USER}&lt;/b&gt; &lt;i&gt;again&lt;/i&gt;:&lt;/td&gt;&lt;td&gt;&lt;input type='password' name='newpw2' size='30'&gt;&lt;/td&gt;&lt;/tr&gt;\n";
	print "&lt;tr&gt;&lt;td colspan='2'&gt;&lt;input type='submit' name='submit' value='Change Password'&gt;&lt;input type='reset' value='Reset Form'&gt;&lt;/td&gt;&lt;/tr&gt;\n";
	print "&lt;/form&gt;\n";
	print "&lt;/table&gt;\n";

}

print '&lt;/body&gt;&lt;/html&gt;';
</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.evanhoffman.com/evan/2010/01/13/victory-change-active-directory-password-via-ldap-through-browser/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>LDAP-Active Directory authentication, Part 3</title>
		<link>http://www.evanhoffman.com/evan/2010/01/08/ldap-active-directory-authentication-part-3/</link>
		<comments>http://www.evanhoffman.com/evan/2010/01/08/ldap-active-directory-authentication-part-3/#comments</comments>
		<pubDate>Fri, 08 Jan 2010 23:12:34 +0000</pubDate>
		<dc:creator>evan</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[active directory]]></category>
		<category><![CDATA[apache]]></category>
		<category><![CDATA[DSID-03190F00]]></category>
		<category><![CDATA[DSID-031A0F44]]></category>
		<category><![CDATA[ldap]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[unicodePwd]]></category>
		<category><![CDATA[work]]></category>

		<guid isPermaLink="false">http://www.evanhoffman.com/evan/?p=309</guid>
		<description><![CDATA[So I got everything working with .htaccess and AD/LDAP authentication.  Just add LDAPVerifyServerCert Off to the httpd config to let Apache authenticate against an AD server with a self-signed certificate (without dealing with the annoyance of putting the cert on each Apache server).  
With that piece of the puzzle largely solved, I moved [...]]]></description>
			<content:encoded><![CDATA[<p>So I got everything working with .htaccess and AD/LDAP authentication.  Just add <tt>LDAPVerifyServerCert Off</tt> to the httpd config to let Apache authenticate against an AD server with a self-signed certificate (without dealing with the annoyance of putting the cert on each Apache server).  </p>
<p>With that piece of the puzzle largely solved, I moved on to another: how will users change their passwords (which are all stored in Active Directory)?  For users running Windows this is pretty trivial &#8212; they can do it right in Windows when they&#8217;re logged into the domain.  But what about Linux users?  I figured the easiest thing to do would be to make a web form to do this.  The user would login (with the http/LDAP auth I previously setup) and the form would ask for their password (twice) and update it in Active Directory.  Sounds pretty simple to me.  I think if this were OpenLDAP it probably would be, but being AD, it&#8217;s not.</p>
<p><span id="more-309"></span></p>
<p>I&#8217;d already spent an hour or two writing the script (in PHP) when I was able to test its basic functionality.  What I got was this:</p>
<p><code>Warning: ldap_mod_replace() [function.ldap-mod-replace]: Modify: Insufficient access in /home/evan/public_html/authtest/index.php</code></p>
<p>After some hair pulling I realized that I was binding with my &#8220;dummy&#8221; user when attempting to change the password.  I figured the solution would be to re-bind as the user whose password I was attempting to change, which is what I did.  I verified that the new bind worked, but I still couldn&#8217;t change the password.  I decided to fall back to command line and started issuing some ldapmodify commands to see what I could and couldn&#8217;t do as the user.  For whatever reason, it appears that even though the user CAN change his password in AD (the &#8220;user cannot change password&#8221; setting is NOT selected &#8212; I checked), the user cannot change his password through LDAP.</p>
<p><code><br />
$ ldapmodify -vv -x -d8 -D "CN=Boba Fett,OU=Utility,OU=Users,DC=example,DC=com" -w secret -H ldaps://activedirectory.example.com -f bfett.ldif<br />
ldap_initialize( ldaps://activedirectory.example.com )<br />
TLS certificate verification: Error, unable to get local issuer certificate<br />
request done: ld 0x9dd86e8 msgid 1<br />
replace unicodePwd:<br />
        "<br />
modifying entry "CN=Boba Fett,OU=Utility,OU=Users,DC=example,DC=com"<br />
modify complete<br />
request done: ld 0x9dd86e8 msgid 2<br />
ldapmodify: Insufficient access (50)<br />
        additional info: 00000005: SecErr: DSID-031A0F44, problem 4003 (INSUFF_ACCESS_RIGHTS), data 0<br />
</code></p>
<p>I Googled for the error code &#8211; <a href="http://www.google.com/search?q=DSID-031A0F44">DSID-031A0F44</a> &#8211; and found a couple of threads about people with the same problem, but no solutions.</p>
<p>The LDIF file I fed in looks like this:</p>
<p><code><br />
dn: CN=Boba Fett,OU=Utility,OU=Users,DC=example,DC=com<br />
changetype: modify<br />
replace: unicodePwd<br />
unicodePwd::IgBhAGIAYwBkAGUAZgBnAGgAIgA=<br />
-<br />
</code></p>
<p>When I run the same command with my own DN/password for binding it works fine (though I did discover that you can assign multiple values to unicodePwd, meaning that, until I fixed it, the test user had <b>two valid passwords</b>, which seems like a bug on Microsoft&#8217;s part), I assume because I&#8217;m a domain admin.  An &#8220;easy&#8221; out would be simply to have the script bind as a domain admin, but that means I&#8217;d be hardcoding a Domain Admin password in the script, which I&#8217;m against.  I&#8217;ll have to put some more thought into this.  Maybe Linux users will just have to log in to a Windows workstation to change their passwords.  That&#8217;s not ideal, but it does already work.</p>
<p>Grr&#8230;</p>
]]></content:encoded>
			<wfw:commentRss>http://www.evanhoffman.com/evan/2010/01/08/ldap-active-directory-authentication-part-3/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Single sign-on with Linux clients and Active Directory LDAP, Part 2</title>
		<link>http://www.evanhoffman.com/evan/2010/01/05/single-sign-on-with-linux-clients-and-active-directory-ldap-part-2/</link>
		<comments>http://www.evanhoffman.com/evan/2010/01/05/single-sign-on-with-linux-clients-and-active-directory-ldap-part-2/#comments</comments>
		<pubDate>Tue, 05 Jan 2010 22:45:55 +0000</pubDate>
		<dc:creator>evan</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[active directory]]></category>
		<category><![CDATA[ldap]]></category>
		<category><![CDATA[linux]]></category>

		<guid isPermaLink="false">http://www.evanhoffman.com/evan/?p=298</guid>
		<description><![CDATA[Following up on my previous post, it turned out not to be as big of a deal as I&#8217;d originally expected to have Apache authenticate against AD and only allow users whose accounts weren&#8217;t disabled.  In a nutshell, here&#8217;s what I did:

In your .htaccess file:

AuthBasicProvider ldap
AuthType basic
AuthName "AD LDAP Test"
AuthLDAPURL     [...]]]></description>
			<content:encoded><![CDATA[<p>Following up on <a href="http://www.evanhoffman.com/evan/2009/12/25/single-sign-on-with-linux-clients-and-active-directory-ldap-part-1/">my previous post</a>, it turned out not to be as big of a deal as I&#8217;d originally expected to have Apache authenticate against AD and only allow users whose accounts weren&#8217;t disabled.  In a nutshell, here&#8217;s what I did:</p>
<p><span id="more-298"></span></p>
<p>In your .htaccess file:</p>
<pre>
AuthBasicProvider ldap
AuthType basic
AuthName "AD LDAP Test"
AuthLDAPURL     "ldap://activedirectory.example.com/OU=Users,DC=example,DC=com?sAMAccountName?sub?(!(userAccountControl:1.2.840.113556.1.4.803:=2))"
AuthzLDAPAuthoritative On
AuthLDAPGroupAttribute member
AuthLDAPBindDN ldapuser@example.com
AuthLDAPBindPassword password
Require ldap-group CN=Sysadmins,OU=Internal Groups,OU=Groups,DC=example,DC=com
</pre>
<p>The key here is this LDAP filter: <b>(!(userAccountControl:1.2.840.113556.1.4.803:=2))</b>.  This is the bitwise &#8220;AND&#8221; of the userAccountControl field and the decimal number 2, which is Microsoft&#8217;s value for &#8220;account is disabled.&#8221;  The codes are listed here: <a href="http://support.microsoft.com/kb/305144">http://support.microsoft.com/kb/305144</a></p>
<p>In httpd.conf (or some other server config file &#8211; I did it in /etc/httpd/conf.d/mod_authz_ldap.conf inside the <IfModule> section), add this directive:</p>
<pre>LDAPOpCacheEntries 0</pre>
<p>This tells Apache not to cache the results of the LDAP op.  If you don&#8217;t put this in there, the server will cache the result of the user&#8217;s login for whatever the TTL is, and the user will be able to login even after you disable the account (until the cache expires).  There may be other ways around this issue, but this works for me.</p>
<p>This works pretty well so far.  Now I can create a &#8220;SVN Users&#8221; group in Active Directory, put the people I want in that group, use the above method for authentication and everyone&#8217;s SVN login will be the same as their domain login. Single sign-on one step closer.  Yay!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.evanhoffman.com/evan/2010/01/05/single-sign-on-with-linux-clients-and-active-directory-ldap-part-2/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>.jobs domains &#8211; $120/year?</title>
		<link>http://www.evanhoffman.com/evan/2010/01/03/jobs-domains-120year/</link>
		<comments>http://www.evanhoffman.com/evan/2010/01/03/jobs-domains-120year/#comments</comments>
		<pubDate>Sun, 03 Jan 2010 23:58:58 +0000</pubDate>
		<dc:creator>evan</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[cablevision]]></category>
		<category><![CDATA[internet]]></category>
		<category><![CDATA[money]]></category>

		<guid isPermaLink="false">http://www.evanhoffman.com/evan/?p=293</guid>
		<description><![CDATA[I saw that Cablevision has www.cablevision.jobs as the link for its jobs page.  Curious, I looked up how much a .jobs domain cost.  GoDaddy has them for $119!  That&#8217;s insane!
]]></description>
			<content:encoded><![CDATA[<p>I saw that Cablevision has <a href="http://www.cablevision.jobs/">www.cablevision.jobs</a> as the link for its jobs page.  Curious, I looked up how much a .jobs domain cost.  <a href="https://www.godaddy.com/gdshop/tlds/jobs.asp?se=%2B&#038;ci=3551">GoDaddy</a> has them for <b>$119!</b>  That&#8217;s insane!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.evanhoffman.com/evan/2010/01/03/jobs-domains-120year/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
