I have added LDAP authentication to MediaWiki. Unfortunately, I'm not sure where to go to get the newest unstable cvs version of the software, so I have added it to the 1.3.7 version. I'm sure the difference in includes/SpecialUserLogin.php between the versions isn't great, but can anyone tell me an easy way to get the latest unstable (through a web browser preferably)?
I also have a few problems with using LDAP authentication in certain circumstances, and would like to get some input from the community on them. First let me describe how i've implemented it:
I've added 6 options to DefaultSettings.php and LocalSettings.php which are the following when used by an admin:
$wgUseLDAP = true; $wgLDAPDomainNames = array("testADdomain","testLDAPdomain"); $wgLDAPServerNames = array("testADdomain"=>"testADserver.example.com","testLDAPdomain"=>"testLDAP server.example.com testLDAPserver2.example.com"); $wgLDAPSearchStrings = array("testADdomain"=>"TDOMAIN\USER-NAME", "testLDAPdomain"=>"cn=USER-NAME,ou=people,dc=example,dc=com"); $wgLDAPUseSSL = true; $wgLDAPUseLocal = true;
In this example, there are three different domains, one is local, one is an Active Directory domain, and the other is a normal LDAP domain (Sun directory server, openLDAP, etc). The user must provide the search string for a user's distinguished name (USER-NAME is substituted in SpecialUserLogin.php with the actual user's loginname). Using SSL is optional (although it is the default) and so is using the local domain (which is the wiki itself, and is not on by default). Of course, using LDAP is off by default.
When using LDAP, passwords are not stored in the database (unless users create accounts on the local domain). Blank passwords are no longer allowed since we wouldn't want people using the local domain logging in as domain users.
The interface for logging in is slightly different when using LDAP as well. Since the LDAP directory will be managing user accounts and passwords, I have removed the "mail me a new password" button, and the validate password field (unless $wgLDAPUseLocal is true). I have added a selection box that will allow users to choose which domain they wish to authenticate against (in the above example, the options would be "testADdomain", "testLDAPdomain", and "local").
My problems are not how I have it currently implemented, but with features that could be added later. For instance, large sites (wikipedia, and the like) i'm sure do not want to handle user accounts manually; small sites, and organizations that use it internally probably do. A feature that could be added to the basic LDAP authentication is the ability for the wiki to add user accounts and manage passwords like it does currently. The problem with this is that most LDAP directories cannot work in this fashion. For instance, if the wiki was to mail a new password to a user, it would need to change the password on the LDAP directory which would cause the user's old password to no longer work. Obviously this is a huge DoS situation. Adding user accounts is less of a problem, but because of time considerations, I cannot implement it.
Below is my patch (let me know if my formatting is unusable):
DefaultSettings.php (add):
$wgUseLDAP = false; $wgLDAPDomainNames = array(""); $wgLDAPServerNames = array(""); $wgLDAPSearchStrings = array(""); $wgLDAPUseSSL = true; $wgLDAPUseLocal = false;
Language.php (add):
'yourdomainname' => 'Your LDAP Domain' 'blankpasswordnotallowed' => 'Blank passwords are not allowed.'
SpecialUserLogin.php (diff old new):
20c20 < var $mLoginattempt, $mRemember, $mEmail; ---
var $mLoginattempt, $mRemember, $mEmail, $mDomain;
24a25
$this->mDomain = $request->getVal( 'wpDomain' );
130a132
global $wgUseLDAP, $wgLDAPUseLocal;
137,138c139,140 < if ( 0 != strcmp( $this->mPassword, $this->mRetype ) ) { < $this->mainLoginForm( wfMsg( "badretype" ) ); ---
if ( "" == $this->mPassword ) { $this->mainLoginForm( wfMsg(
"blankpasswordnotallowed" ) ); 140a143,149
if ( !$wgUseLDAP || "local" == $this->mDomain ) { if ( 0 != strcmp( $this->mPassword, $this->mRetype )
) {
$this->mainLoginForm( wfMsg( "badretype" )
);
return; } }
173c182,188 < ---
if ( $wgUseLDAP && "local" != $this->mDomain ) { if ( !$this->ldapBind() ) { return; } }
175c190 < $u->setPassword( $this->mPassword ); ---
if ( !$wgUseLDAP ) { $u->setPassword( $this->mPassword ); }
192c207,208 < ---
global $wgUseLDAP;
205,208d220 < if (!$u->checkPassword( $this->mPassword )) { < $this->mainLoginForm( wfMsg( "wrongpassword" ) ); < return; < } 209a222,231
if ( $wgUseLDAP && "local" != $this->mDomain ) { if ( !$this->ldapBind() ) { return; } } else { if (!$u->checkPassword( $this->mPassword || "" ==
$this->mPassword )) {
$this->mainLoginForm( wfMsg( "wrongpassword"
) );
return; } }
231a254,297
/* private */ function ldapBind() { global $wgLDAPDomainNames, $wgLDAPServerNames,
$wgLDAPSearchStrings;
global $wgLDAPUseLocal, $wgLDAPUseSSL; if ( $wgLDAPUseSSL ) { $serverpre = "ldaps://"; } else { $serverpre = "ldap://"; } $tmpservers = $wgLDAPServerNames["{$this->mDomain}"]; $tok = strtok($tmpservers, " "); while ($tok) { $servers = $servers . " " . $serverpre . $tok; $tok = strtok(" "); } $servers = rtrim($servers); $tmpuserdn = $wgLDAPSearchStrings["{$this->mDomain}"]; $userdn =
str_replace("USER-NAME",$this->mName,$tmpuserdn);
$userpass = $this->mPassword; $ldapconn = @ldap_connect( $servers ) or die( "Could not
connect
to LDAP server."); if ( $ldapconn ) { ldap_set_option( $ldapconn,
LDAP_OPT_PROTOCOL_VERSION, 3
); # Some LDAP Servers will do an anonymous bind if a # blank password is used, no matter what the
username
# is. To avoid this, it shouldn't be allowed. if ( "" == $userpass ) { $this->mainLoginForm( wfMsg(
"wrongpassword" ) );
return false; } $bind = @ldap_bind( $ldapconn, $userdn, $userpass
);
if (!$bind) { $this->mainLoginForm( wfMsg(
"wrongpassword" ) );
return false; } return true; }
}
323a390
global $wgUseLDAP, $wgLDAPDomainNames, $wgLDAPUseLocal;
328a396
$ydn = wfMsg( "yourdomainname" );
385a454
$encDomain = wfEscapeHTML( $this->mDomain );
413a483,497
if ($wgUseLDAP) { foreach ($wgLDAPDomainNames as $dom) { $doms = $doms . "<option>$dom</option>"; } if ($wgLDAPUseLocal) { $doms = $doms . "<option>local</option>"; }
$wgOut->addHTML("<tr><td align='right'>$ydn:</td>
<td align='left'> <select tabindex='9' name=\"wpDomain\" value=\"{$encDomain}\"> $doms </select> </td></tr>"); }
415,416d498 < $encRetype = htmlspecialchars( $this->mRetype ); < $encEmail = htmlspecialchars( $this->mEmail ); 418c500,505 < <td align='right'>$ypa:</td> ---
<td align='right'>$nuo</td></tr>");
if (!$wgUseLDAP || $wgLDAPUseLocal) { $encRetype = htmlspecialchars( $this->mRetype );
$wgOut->addHTML("<tr><td align='right'>$ypa:</td>
422,424c509,513 < </td><td>$nuo</td></tr> < <tr> < <td align='right'>$ye:</td> ---
</td></tr>"); } $encEmail = htmlspecialchars( $this->mEmail ); $wgOut->addHTML("<tr><td align='right'>$ye:</td>
427a517
443,445c533,534 < < $wgOut->addHTML(" < <tr><td colspan='3'> </td></tr><tr> ---
$wgOut->addHTML("<tr><td colspan='3'> </td></tr><tr>
447c536,538 < <p>$efl<br /> ---
<p>$efl<br />"); if (!wgUseLDAP) { $wgOut->addHTML("
449,451c540,546 < </td></tr></table> < </form>\n" ); < $wgOut->addHTML( $endText ); ---
</td></tr>"); } else { $wgOut->addHTML("</td></tr>"); }
$wgOut->addHtml("</table></form>\n" ); $wgOut->addHTML( $endText );
---------------- Ryan Lane NAVOCEANO
On Oct 28, 2004, at 1:52 PM, Lane, Ryan wrote:
I have added LDAP authentication to MediaWiki. Unfortunately, I'm not sure where to go to get the newest unstable cvs version of the software, so I have added it to the 1.3.7 version.
You can pull from Sourceforge's anonymous CVS server, which is up to about half a day behind, or another mirror one of our devs has set up which update more frequently. See: http://meta.wikimedia.org/wiki/MediaWiki_from_CVS
It's probably best to attach patches to enhancement bug records on our bugzilla at http://bugzilla.wikipedia.org/ rather than posting them to the list; e-mail formatting can break lines and other lovely things.
I'd recommend to always use the -u option to diff, also; it makes the diff easier to read and it can be applied more reliably to modified files.
-- brion vibber (brion @ pobox.com)
On Thu, 28 Oct 2004 15:52:37 -0500, Lane, Ryan laner@navo.navy.mil wrote:
I have added LDAP authentication to MediaWiki.
I recently added authentication against a webserver (which we're using here to verify users against our Kerberos servers using mod_auth_kerb in Apache). We should probably combine our changes.
While (like you) i originally made my modifications to SpecialUserLogin.php. I later realized it made more sense to modify the User::checkPassword() function in User.php.
Since your code includes more robust error messages and such, I'm going to copy much of it to modify my existing code, and (if possible) try to abstract out some of the commonalities so that we don't end up cluttering up User:checkPassword() too much.
You can email me directly at my work address at bclark@ldc.upenn.edu, if you'd like to discuss this collaboration/integration some more.
-Bill Clark
wikitech-l@lists.wikimedia.org