Last modified: 2007-03-13 13:10:33 UTC

Wikimedia Bugzilla is closed!

Wikimedia migrated from Bugzilla to Phabricator. Bug reports are handled in Wikimedia Phabricator.
This static website is read-only and for historical purposes. It is not possible to log in and except for displaying bug reports and their history, links might be broken. See T2814, the corresponding Phabricator task for complete and up-to-date bug report information.
Bug 814 - LDAP Authentication
LDAP Authentication
Status: CLOSED FIXED
Product: MediaWiki
Classification: Unclassified
User login and signup (Other open bugs)
1.10.x
All All
: Normal enhancement with 4 votes (vote)
: ---
Assigned To: Ryan Lane
http://meta.wikimedia.org/wiki/LDAP_A...
: patch
Depends on: 892
Blocks:
  Show dependency treegraph
 
Reported: 2004-11-01 16:39 UTC by Ryan Lane
Modified: 2007-03-13 13:10 UTC (History)
15 users (show)

See Also:
Web browser: ---
Mobile Platform: ---
Assignee Huggle Beta Tester: ---


Attachments
Diff of changes to 1.5 (20.00 KB, patch)
2005-02-03 15:03 UTC, Ryan Lane
Details
Patch for mediawiki 1.5 (5.60 KB, application/x-gzip)
2005-02-11 05:51 UTC, Ryan Lane
Details
Patch for mediawiki 1.4 (5.21 KB, application/x-gzip)
2005-02-11 05:57 UTC, Ryan Lane
Details
Updated patch to add LDAP authentication to mediawiki (7.29 KB, application/x-gzip)
2005-02-14 02:43 UTC, Ryan Lane
Details
Version .8 of the LDAP patch (For Mediawiki 1.4) (6.74 KB, application/x-gzip)
2005-04-09 22:55 UTC, Ryan Lane
Details
Version 1.0 of the LDAP patch (For Mediawiki 1.5) (7.36 KB, application/x-gzip)
2005-05-15 22:37 UTC, Ryan Lane
Details
Patch DefaultSettings and Setup ($wgAuth) (1.57 KB, patch)
2005-08-14 17:07 UTC, D. Datzert
Details
Version 1.0a of the LdapAuthentication.php (For Mediawiki 1.5) (=v1.0 plus changes in #50 #51 and #52) (17.64 KB, text/plain)
2005-10-07 14:13 UTC, Udo Adametz
Details
Patch to 1.0.a for require attribute (2.89 KB, patch)
2005-11-01 21:27 UTC, Jeff Mandel
Details
Version 1.0b of the LdapAuthentication.php Plugin (for Mediawiki 1.5) (17.89 KB, text/plain)
2005-11-02 23:44 UTC, Ryan Lane
Details
Version 1.0c of the LdapAuthentication.php Plugin (for Mediawiki 1.5) (18.18 KB, text/plain)
2005-11-03 16:06 UTC, Ryan Lane
Details
Version 1.0d of the LdapAuthentication.php Plugin (for Mediawiki 1.5) (17.28 KB, text/plain)
2006-02-22 19:10 UTC, Ryan Lane
Details
Version 1.0e of the LdapAuthentication.php Plugin (for Mediawiki 1.5) (17.27 KB, text/plain)
2006-03-03 00:00 UTC, Ryan Lane
Details
Version 1.0f of the LdapAuthentication.php Plugin (for Mediawiki 1.5-1.7) (22.00 KB, text/plain)
2006-07-05 03:51 UTC, Ryan Lane
Details
Version 1.0g of the LdapAuthentication.php Plugin (for Mediawiki 1.5-1.7) (27.62 KB, application/x-php)
2006-08-12 01:14 UTC, Ryan Lane
Details
Version 1.0h of the LdapAuthentication.php Plugin (for Mediawiki 1.5+) (28.42 KB, application/x-php)
2006-11-13 22:54 UTC, Ryan Lane
Details
Ldap Group Support against 1.0e (5.13 KB, patch)
2006-11-30 07:55 UTC, Alfons Zitterbacke
Details
Version 1.1a of the LdapAuthentication.php plugin (for Mediawiki 1.6+) (35.84 KB, application/x-php)
2006-12-04 19:15 UTC, Ryan Lane
Details
Version 1.1b of the LdapAuthentication.php plugin (for Mediawiki 1.6+) (36.14 KB, application/x-php)
2006-12-06 22:14 UTC, Ryan Lane
Details
Patch to 1.1b including hacks to support NTLM (3.21 KB, patch)
2006-12-13 19:21 UTC, Alastair Hole
Details
Version 1.1c of the LdapAuthentication.php plugin (for Mediawiki 1.6+) (45.04 KB, application/x-php)
2006-12-22 21:49 UTC, Ryan Lane
Details
Version 1.1d of the LdapAuthentication.php plugin (for Mediawiki 1.6+) (46.25 KB, application/x-php)
2007-02-02 22:06 UTC, Ryan Lane
Details

Description Ryan Lane 2004-11-01 16:39:35 UTC
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.'

includes/User.php (diff -u old new):

--- User.php.new.old	2004-11-01 09:43:28.000000000 -0600
+++ User.php.new	2004-11-01 09:30:39.000000000 -0600
@@ -1010,6 +1010,12 @@
 	 */
 	function checkPassword( $password ) {
 		$this->loadFromDatabase();
+                if ( 0 == strcmp( "", $password ) ) {
+                        return false;
+                }
+                if ( $this->checkLDAPPassword( $password ) && 0 !=
strcmp('local', $_SESSION["ldapdomain"]->mDomain ) ) {
+                        return true;
+                }
 		$ep = $this->encryptPassword( $password );
 		if ( 0 == strcmp( $ep, $this->mPassword ) ) {
 			return true;
@@ -1025,6 +1031,42 @@
 		}
 		return false;
 	}
-}
 
+
+        function checkLDAPPassword( $password ) {
+                global $wgLDAPDomainNames, $wgLDAPServerNames,
$wgLDAPSearchStrings;
+                global $wgLDAPUseLocal, $wgLDAPUseSSL;
+
+                if ( $wgLDAPUseSSL ) {
+                        $serverpre = "ldaps://";
+                } else {
+                        $serverpre = "ldap://";
+                }
+
+                $domain = $_SESSION["ldapdomain"]->mDomain;
+                $tmpservers = $wgLDAPServerNames["$domain"];
+                $tok = strtok($tmpservers, " ");
+                while ($tok) {
+                        $servers = $servers . " " . $serverpre . $tok;
+                        $tok = strtok(" ");
+                }
+                $servers = rtrim($servers);
+
+                $tmpuserdn = $wgLDAPSearchStrings["$domain"];
+                $userdn = str_replace("USER-NAME",$this->mName,$tmpuserdn);
+                $userpass = $password;
+                $ldapconn = @ldap_connect( $servers );
+                if ( $ldapconn ) {
+                        ldap_set_option( $ldapconn, LDAP_OPT_PROTOCOL_VERSION, 3);
+                        $bind = @ldap_bind( $ldapconn, $userdn, $userpass );
+                        if (!$bind) {
+                                return false;
+                        }
+                } else {
+                        return false;
+                }
+                return true;
+        }
+
+}
 ?>

includes/SpecialUserlogin.php (diff -u old new):

--- SpecialUserlogin.php.new.old	2004-11-01 09:57:41.000000000 -0600
+++ SpecialUserlogin.php	2004-11-01 10:02:01.000000000 -0600
@@ -32,11 +32,12 @@
 class LoginForm {
 	var $mName, $mPassword, $mRetype, $mReturnto, $mCookieCheck, $mPosted;
 	var $mAction, $mCreateaccount, $mCreateaccountMail, $mMailmypassword;
-	var $mLoginattempt, $mRemember, $mEmail;
+	var $mLoginattempt, $mRemember, $mEmail, $mDomain;
 	
 	function LoginForm( &$request ) {
 		global $wgLang, $wgAllowRealName;
 
+		$this->mDomain = $request->getVal( 'wpDomain' );
 		$this->mName = $request->getText( 'wpName' );
 		$this->mPassword = $request->getText( 'wpPassword' );
 		$this->mRetype = $request->getText( 'wpRetype' );
@@ -149,15 +150,18 @@
 		global $wgUser, $wgOut;
 		global $wgMaxNameChars;
 		global $wgMemc, $wgAccountCreationThrottle, $wgDBname, $wgIP;
+		global $wgUseLDAP, $wgLDAPUseLocal;
 
 		if (!$wgUser->isAllowedToCreateAccount()) {
 			$this->userNotPrivilegedMessage();
 			return;
 		}
 
-		if ( 0 != strcmp( $this->mPassword, $this->mRetype ) ) {
-			$this->mainLoginForm( wfMsg( 'badretype' ) );
-			return;
+		if ( !$wgUseLDAP || 0 == strcmp('local', $this->mDomain ) ) {
+			if ( 0 != strcmp( $this->mPassword, $this->mRetype ) ) {
+				$this->mainLoginForm( wfMsg( 'badretype' ) );
+				return;
+			}
 		}
 		
 		$name = trim( $this->mName );
@@ -194,8 +198,21 @@
 			}
 		}
 
+		if ( $wgUseLDAP && 0 != strcmp('local', $this->mDomain ) ) { 
+	                if (!$u->checkPassword( $this->mPassword )) {
+        	                $this->mainLoginForm( wfMsg( 'wrongpassword' ) );
+	                        return;
+        	        }
+		} else {
+			# We shouldn't allow blank passwords, even on 
+			# local accounts
+			if ( 0 == strcmp( "", $this-mPassword ) ) {
+				return;
+			}
+		}
+
 		$u->addToDatabase();
-		$u->setPassword( $this->mPassword );
+		if ( !$wgUseLDAP ) { $u->setPassword( $this->mPassword ); }
 		$u->setEmail( $this->mEmail );
 		$u->setRealName( $this->mRealName );
 
@@ -224,14 +241,16 @@
 		}
 		$id = $u->idForName();
 		if ( 0 == $id ) {
-			$this->mainLoginForm( wfMsg( 'nosuchuser', $u->getName() ) );
+			$this->mainLoginForm( wfMsg( 'nosuchuser', $u->getName()) );
 			return;
 		}
 		$u->setId( $id );
 		$u->loadFromDatabase();
+
+		$_SESSION["ldapdomain"] = $this;
 		if (!$u->checkPassword( $this->mPassword )) {
-			$this->mainLoginForm( wfMsg( 'wrongpassword' ) );
-			return;
+			$this->mainLoginForm( wfMsg( 'wrongpassword' ) );	
+			return;	 
 		}
 
 		# We've verified now, update the real record
@@ -351,11 +370,13 @@
 	function mainLoginForm( $err ) {
 		global $wgUser, $wgOut, $wgLang;
 		global $wgDBname, $wgAllowRealName;
+		global $wgUseLDAP, $wgLDAPDomainNames, $wgLDAPUseLocal;
 
 		$le = wfMsg( 'loginerror' );
 		$yn = wfMsg( 'yourname' );
 		$yp = wfMsg( 'yourpassword' );
 		$ypa = wfMsg( 'yourpasswordagain' );
+		$ydn = wfMsg( 'yourdomainname' );
 		$rmp = wfMsg( 'remembermypassword' );
 		$nuo = wfMsg( 'newusersonly' );
 		$li = wfMsg( 'login' );
@@ -392,7 +413,7 @@
 			$wgOut->addHTML( "<h2>$li:</h2>\n<p>$lp</p>" );
 		} else {
 			$wgOut->addHTML( "<h2>$le:</h2>\n<font size='+1' 
-	color='red'>$err</font>\n" );
+			color='red'>$err</font>\n" );
 		}
 		if ( 1 == $wgUser->getOption( 'rememberpassword' ) ) {
 			$checked = ' checked';
@@ -413,6 +434,7 @@
 		$encRetype = htmlspecialchars( $this->mRetype );
 		$encEmail = htmlspecialchars( $this->mEmail );
 		$encRealName = htmlspecialchars( $this->mRealName );
+		$encDomain = htmlspecialchars( $this->mDomain );
 
 		if ($wgUser->getID() != 0) {
 			$cambutton = "<input tabindex='6' type='submit' name=\"wpCreateaccountMail\"
value=\"{$cam}\" />";
@@ -436,21 +458,44 @@
 	<td align='left'>
 	<input tabindex='2' type='password' name=\"wpPassword\"
value=\"{$encPassword}\" size='20' />
 	</td>
-	<td align='left'>
-	<input tabindex='4' type='checkbox' name=\"wpRemember\" value=\"1\"
id=\"wpRemember\"$checked /><label for=\"wpRemember\">$rmp</label>
-	</td>
-	</tr>");
+	");
+
+		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>");	 
+		} else {
+		$wgOut->addHTML("
+        <td align='left'>
+        <input tabindex='4' type='checkbox' name=\"wpRemember\" value=\"1\"
id=\"wpRemember\"$checked /><label for=\"wpRemember\">$rmp</label>
+        </td></tr>");
+		}
+
 
 		if ($wgUser->isAllowedToCreateAccount()) {
 			$encRetype = htmlspecialchars( $this->mRetype );
 			$encEmail = htmlspecialchars( $this->mEmail );
 	$wgOut->addHTML("<tr><td colspan='3'>&nbsp;</td></tr><tr>
-	<td align='right'>$ypa:</td>
-	<td align='left'>
-	<input tabindex='5' type='password' name=\"wpRetype\" value=\"{$encRetype}\" 
-	size='20' />
-	</td><td>$nuo</td></tr>
-	<tr>
+	<td align='right'>$nuo</td></tr>");
+
+	if (!$wgUseLDAP || $wgLDAPUseLocal) { 	
+		$wgOut->addHTML("<td align='right'>$ypa:</td>
+		<td align='left'>
+		<input tabindex='5' type='password' name=\"wpRetype\" value=\"{$encRetype}\" 
+		size='20' />
+		</td></tr>");
+	}
+
+	$wgOut->addHTML("<tr>
 	<td align='right'>$ye:</td>
 	<td align='left'>
 	<input tabindex='7' type='text' name=\"wpEmail\" value=\"{$encEmail}\"
size='20' />
@@ -470,16 +515,22 @@
 	$cambutton
 	</td></tr>");
 		}
-	    
+
+	$wgOut->addHTML("
+        <tr><td colspan='3'>&nbsp;</td></tr><tr>
+        <td colspan='3' align='left'>
+        <p>$efl<br />");
+
+	if ( !wgUseLDAP) {
 		$wgOut->addHTML("
-	<tr><td colspan='3'>&nbsp;</td></tr><tr>
-	<td colspan='3' align='left'>
-	<p>$efl<br />
-	<input tabindex='10' type='submit' name=\"wpMailmypassword\" value=\"{$mmp}\"
/></p>
-	</td></tr></table>
-	</form>\n" );
-		$wgOut->addHTML( $endText );
+	<input tabindex='10' type='submit' name=\"wpMailmypassword\" value=\"{$mmp}\"
/></p>");
 	}
+	
+		$wgOut->addHTML("
+	</td></tr>
+	</table></form>\n $endText" );
+	}
+	
 
 	/**
 	 * @access private
@@ -531,3 +582,4 @@
 	}
 }
 ?>
+
Comment 1 Antoine "hashar" Musso (WMF) 2004-11-01 19:46:02 UTC
I am going to review and test a bit this patch in the next day.
LDAP authentication is something I am really interested in :o)

Thanks Ryan !
Comment 2 Ryan Lane 2004-11-01 21:09:06 UTC
Something to note when you test is that passwords are not encrypted when they
are sent to the LDAP server. My write up on how to use it would try to enforce
the idea of keeping SSL on (which it is by default).
Comment 3 Ryan Lane 2004-11-01 22:14:22 UTC
Hmm, it seems I forgot to mention how to use my patch. My apologies. Here is a
quick rundown:

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"=>"testLDAPserver.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").

A few problems i have 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 (locally). 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.
Comment 4 SB 2004-11-15 18:58:18 UTC
A couple bug fixes to the patch...

in includes/SpecialUserlogin.php there is one typo (a missing dollar sign) and a
minor bug...

In function mainLoginForm $dom is uninitialized (spits out a Undef. Var. NOTICE
to the log) it should be similar to:

if ($wgUseLDAP) {
    $doms="";  // added this
    foreach ($wgLDAPDomainNames as $dom) {
        $doms = $doms . "<option>$dom</option>";
    }
    if ($wgLDAPUseLocal) {
      $doms = $doms . "<option>local</option>";
    }
    ...

Also in function mainLoginForm the last few lines should read:

if ( !$wgUseLDAP) {    // fixed missing dollar sign
	$wgOut->addHTML("<input tabindex='10' type='submit' name=\"wpMailmypassword\"
value=\"{$mmp}\"> /></p>");
}


SB
Comment 5 Brion Vibber 2004-11-16 03:43:01 UTC
Since the ability to use some external authentication system 
is a fairly general need, I'm adding a plugin hook for external 
authentication systems; it should be pretty straightforward to 
rearrange the LDAP code as an extension this way.
Comment 6 Ryan Lane 2004-11-17 17:10:18 UTC
Bugfix:

Can add local users with $wgLDAPUseLocal, but cannot login afterwards because
the password isnt being stored in the wiki. Here is the fix.

In SpecialUserLogin.php, in addNewAccountInternal():

-		if ( !$wgUseLDAP ) { $u->setPassword( $this->mPassword ); }
+               if ( !$wgUseLDAP || 0 == strcmp('local', $this->mDomain) ) {
$u->setPassword( $this->mPassword ); }
Comment 7 Ryan Lane 2004-12-01 21:36:54 UTC
Bugfix:

Adding accounts is not working when LDAP is enabled (unless you add local
accounts). Here is the fix:

In SpecialUserLogin.php, in addNewAccountInternal():

+               $_SESSION["ldapdomain"] = $this;
                if ( $wgUseLDAP && 0 != strcmp('local', $this->mDomain ) ) {
                        if (!$u->checkPassword( $this->mPassword )) {
                                $this->mainLoginForm( wfMsg( 'wrongpassword' ) );
                                return;
                        }
                } else {
                        # We shouldn't allow blank passwords, even on
                        # local accounts
                        if ( 0 == strcmp( "", $this->mPassword ) ) {
                                return;
                        }
                }
Comment 8 T. Gries 2004-12-16 12:51:46 UTC
I added the link to the metawiki page about LDAP authentication. Changed to 1.5 (as I think, that I won't come with 1.4, am I 
correct ?)

Tom
Comment 9 Ryan Lane 2005-01-13 23:08:00 UTC
I have recoded this as an extension. However, it does require a minimal amount
of core code changes. Specifically, I had to remove the ability for people to
use create accounts with blank passwords or to logon with blank passwords. I
also added a small interface change (which is done in a template), which needed
a small modification of includes/SpecialUserLogin.php.

Further core code modification will be required. Specifically, the way changing
passwords works, and mailing temporary passwords. For the current extension,
these features should be disabled when $wgAuth->strict() is true, since they
would be useless.

I have talked to Thomas Gries about merging the code with enotif. So a code diff
may come from him.

Ryan
Comment 10 T. Gries 2005-01-13 23:48:47 UTC
(In reply to comment #9)
> I have recoded this as an extension. However, it does require a minimal amount
[...]
> I have talked to Thomas Gries about merging the code with enotif. So a code diff
> may come from him.
> Ryan

Ryan, just to confirm: I have read. Something coming in a while. (Please, can
you have also an eye on the accompanying meta wikipages
http://meta.wikipedia.org/LDAP_Authentication , which could be useful for our
team work, too ? It's just a reminder and can perhaps help to collaborate.)

Tom
Comment 11 Ryan Lane 2005-02-03 15:03:14 UTC
Created attachment 254 [details]
Diff of changes to 1.5

Diff of my changes to 1.5, and LdapAuthentication.php
Comment 12 Ryan Lane 2005-02-11 05:51:14 UTC
Created attachment 282 [details]
Patch for mediawiki 1.5

This is the current patch for mediawiki 1.5 to add LDAP Authentication. With
this patch the wiki is able to pull a user email address, real name, nickname,
and language preference from the LDAP directory. If the attributes in the LDAP
server are blank, the wiki will use the preferences from the local database.

This patch will NOT work with 1.4.
Comment 13 Ryan Lane 2005-02-11 05:57:51 UTC
Created attachment 283 [details]
Patch for mediawiki 1.4

This is the current patch for mediawiki 1.4 to add LDAP Authentication. With
this patch the wiki is able to pull a user email address, real name, nickname,
and language preference from the LDAP directory. If the attributes in the LDAP
server are blank, the wiki will use the preferences from the local database.

This patch will NOT work with 1.5.
Comment 14 Ryan Lane 2005-02-11 19:21:46 UTC
Bugfix on last two patches (don't know HOW this got in here). In
LdapAuthentication.php

This:
        function initUser( &$user ) {
                # Override this to do something.
                //We are creating an LDAP user, it is very important that we do
                //NOT set a local password because it could compromise the
                //security of our domain.
                $user->setPassword( '' );
                if ('' != $this->lang) {
                        $u->setOption('language',$this->lang);
                }
                if ('' != $this->nickname) {
                        $u->setOption('nickname',$this->nickname);
                }
                if ('' != $this->realname) {
                        $u->setRealName($this->realname);
                }
                if ('' != $this->email) {
                        $u->setEmail($this->email);
                }
        }

Should be:

        function initUser( &$user ) {
                # Override this to do something.
                //We are creating an LDAP user, it is very important that we do
                //NOT set a local password because it could compromise the
                //security of our domain.
                $user->setPassword( '' );
                if ('' != $this->lang) {
                        $user->setOption('language',$this->lang);
                }
                if ('' != $this->nickname) {
                        $user->setOption('nickname',$this->nickname);
                }
                if ('' != $this->realname) {
                        $user->setRealName($this->realname);
                }
                if ('' != $this->email) {
                        $user->setEmail($this->email);
                }
        }
Comment 15 Ryan Lane 2005-02-14 02:43:25 UTC
Created attachment 287 [details]
Updated patch to add LDAP authentication to mediawiki

I'm on a roll this weekend! This patch adds the ability for the wiki to use an
LDAP server to create users, update user information, change passwords, and
pull information from an LDAP server.

Unfortunately, updating users, and adding users does not currently work with
Active Directory, and its likely the users are not able to mail themselves a
password yet (with $wgAuth->strict() returning true).

This patch is only for 1.5. A backport for 1.4 should be uploaded soon
hopefully.
Comment 16 Don Seiler 2005-04-07 13:42:24 UTC
So ... if you can't add users with AD, how would you add users?  What is
different about AD's ldap interface that is causing problems?  I'm tasked with
getting auth against AD working and would be glad to help/hack however you need.
Comment 17 Don Seiler 2005-04-07 13:45:58 UTC
Let me state my confusion more precisely.  By "adding users", I mean new wiki
logins, not adding new users to AD through mediawiki.  That being said, I
haven't seen in my limited LDAP/AD/PHP experiments why adding users via AD is
different than LDAP.  Bugzilla does it just fine.
Comment 18 Don Seiler 2005-04-07 14:32:18 UTC
... what type of files are those last two patches?  firefox seems to think they
are binary.
Comment 19 Don Seiler 2005-04-07 18:06:56 UTC
Sorry to monopolize this bug all of a sudden.  I've got an upgraded demo of my
wiki site ready to test.  It looks like the non-obsoleted patches in this bug
are busted.

Can you re-post the diffs as text/plain?
Comment 20 Don Seiler 2005-04-07 18:13:42 UTC
D'oh I see it's a .tar.gz now.  If that is the case it shouldn't be labelled
"patch" IMHO.  I think just a single diff file would be preferrable for all
involved anyway.

My $0.02.
Comment 21 T. Gries 2005-04-07 18:24:23 UTC
See also http://bugzilla.wikimedia.org/show_bug.cgi?id=1360 for Auto-Login /
Auto-account-creation  ( incl. working patch for 1.4 )
Comment 22 Don Seiler 2005-04-07 19:27:28 UTC
In my case auto-login isn't necessarily desirable.  Full-bore LDAP support is
needed.

IMHO, you really shouldn't need a separate case for AD, since AD has a pretty
standard LDAP interface.  One catch in my instance is that I need to
authenticate an "app user" first to then try and authenticate logins.  Like I
would have a "Wiki User" or "Bugzilla User".
Comment 23 Don Seiler 2005-04-07 20:05:52 UTC
OK.  Your patch uses the actual bind as the authentication mechanism.  What
bugzilla does (and works in my AD case), is have a separate bind, and then do an
LDAP search to verify the login.  My in case, we only have a special set of
users that can bind.

I'll probably hack things around to get around this for now.

Please let me know what you think of this idea.
Comment 24 Don Seiler 2005-04-07 20:13:47 UTC
GOD.  Don't pay any attention to me.  Please just ignore what I spout off
without testing.
Comment 25 Ryan Lane 2005-04-09 22:55:04 UTC
Created attachment 413 [details]
Version .8 of the LDAP patch (For Mediawiki 1.4)

Lol. I used to get emails when comments were being added to this page, but it
seems i'm not getting them any more. I'll check here more often.

All of my patches allow you to add new wiki users to the wiki db. What my new
patches are starting to allow is for the wiki to use LDAP as a full blown
backend. Instead of adding a user through your LDAP server to allow them access
to the wiki, a user could create an account on the wiki, and a user would be
added to the LDAP server. I am also allowing updates to user attributes through
the wiki, because the next major versions of my plugin will allow full blown
LDAP backend support, so that all user preferences and such are stored in LDAP.


I've added options to allow/disallow this new behavior, since most people will
not want this.

There isn't a huge difference in adding users in AD. There is a slight problem
with adding passwords to AD though. I will work around this soon hopefully.
Also, there is a requirement in AD that you use SSL to add users/change
passwords, etc. Also, in general, when adding new users through LDAP in AD, the
user is created as disabled, without a password. I also don't have easy access
to an AD when doing testing, or writing the patches, so AD support will be
somewhat shaky (although, the original functionality should work with AD, even
in the newest versions).

When merging this plugin into your code, please do it by hand, people seem to
be having problems merging with diff.
Comment 26 Ryan Lane 2005-04-09 23:02:44 UTC
(In reply to comment #23)
> OK.  Your patch uses the actual bind as the authentication mechanism.  What
> bugzilla does (and works in my AD case), is have a separate bind, and then do an
> LDAP search to verify the login.  My in case, we only have a special set of
> users that can bind.
> 
> I'll probably hack things around to get around this for now.
> 
> Please let me know what you think of this idea.


In this case, you would have to have a proxyagent type user in your LDAP server,
correct? I may add this as a user defined option, because not every unix/linux
domain uses a proxyagent, and most AD domains do not. I do understand the need
for it in some cases though, if your users are in multiple ou's, then a direct
bind will not work.
Comment 27 Don Seiler 2005-04-10 23:43:22 UTC
(In reply to comment #26)
> In this case, you would have to have a proxyagent type user in your LDAP server,
> correct? I may add this as a user defined option, because not every unix/linux
> domain uses a proxyagent, and most AD domains do not. I do understand the need
> for it in some cases though, if your users are in multiple ou's, then a direct
> bind will not work.

Yes our users are in multiple ou's.  For now I just added the single bind user
and have it do a search to determine the individual user auth.

Anyway, cheers on the work so far!
Comment 28 Caius 2005-05-05 09:39:52 UTC
I'm trying to autheticate against AD. Finally it worked with these changes:

LocalSettings.php:

$wgLDAPSearchStrings = array(
  "testADdomain"=>"USER-NAME"      ### instead of TDOMAIN\\USER-NAME
  );

When I login I get these warnings:
Warning: ldap_read(): Search: Invalid DN syntax in /..../LdapAuthentication.php on line 150
Warning: ldap_get_entries(): supplied argument is not a valid ldap result resource 
in /..../LdapAuthentication.php on line 150

But it works.
Comment 29 Brion Vibber 2005-05-05 09:44:37 UTC
I'd like to get any necessary changes to the core code or AuthPlugin interface ready in the 1.5 
release so end users can easily drop in the LDAP extension.

Ryan, is there a current patch for this ready to go?
Comment 30 Ryan Lane 2005-05-08 21:14:57 UTC
(In reply to comment #29)
> I'd like to get any necessary changes to the core code or AuthPlugin interface
ready in the 1.5 
> release so end users can easily drop in the LDAP extension.
> 
> Ryan, is there a current patch for this ready to go?

Brion,

Give me a couple of days to get my new release out. It fixes the "Mail me a new
password" problem that I was having. Otherwise, the 1.5 patch is mature enough
for addition.
Comment 31 Ryan Lane 2005-05-08 21:31:07 UTC
(In reply to comment #28)
> I'm trying to autheticate against AD. Finally it worked with these changes:
> 
> LocalSettings.php:
> 
> $wgLDAPSearchStrings = array(
>   "testADdomain"=>"USER-NAME"      ### instead of TDOMAIN\\USER-NAME
>   );
> 
> When I login I get these warnings:
> Warning: ldap_read(): Search: Invalid DN syntax in
/..../LdapAuthentication.php on line 150
> Warning: ldap_get_entries(): supplied argument is not a valid ldap result
resource 
> in /..../LdapAuthentication.php on line 150
> 
> But it works.


Well, TDOMAIN should be renamed to your actual domain. But if using just the
username works, thats great too.

Those two warnings you are getting is because of the DN syntax in your
$wgLDAPSearchStrings. I really should update my documentation some. I'll clarify
some though.

My newest version of the patch allows the wiki to pull nickname, language, email
address, real name, etc. from LDAP. To do so, the LDAP plugin reads an LDAP
entry from the LDAP server. The problem with this is that it needs a complete DN. 

Your search string is not giving a full DN for your user, so the read is
failing. This won't cause problems for you, because those preferences won't be
overwritten unless they contain information (and if the read is failing, they do
not).

If you want this functionality, you'll have to give a full DN in the search
strings. If all of your users are in the same OU (i believe this is generally
the case in AD because it copies all users into ou=Users or something similar),
then you can set your search string to be
"sAMAccountName=USER-NAME,ou=Users,dc=domain,dc=com". If you have access to your
domain controller, you can check this. You can probably also check it with an
LDAP browser (there are a bunch freely available) even if you don't have access
to the domain controller.

I'm going to add an option for disabling reads in the next version so that
you'll stop getting warnings.
Comment 32 Ryan Lane 2005-05-15 22:37:06 UTC
Created attachment 551 [details]
Version 1.0 of the LDAP patch (For Mediawiki 1.5)

Sorry for the delay on the latest patch.

This is version 1.0 of the LDAP authentication patch. This release should fix
the "mail me a password" problem. This release also adds the ability to search
for users through proxy credentials (this is useful if all of your users are
not in the same ou). Also added is a option to disable fetching of user
preferences.

If you are currently using the LDAP patch to add users and set preferences, the
option "$wgLDAPWikiDN" and "$wgLDAPWikiPassword" have been changed to
"$wgLDAPWriterDN" and "$wgLDAPWriterPassword".

This patch has been pretty well tested using openLDAP, and should work equally
as well with Sun Directory Server. I have not had a chance to test this version
of the patch with Active Directory. If you notice any problems with the new
features on Active Directory, let me know (the normal authentication should
work perfectly fine).

Currently not working in this version, that will be fixed in the next is: If
using proxy credentials, you can only use one domain, and the local domain. If
using proxy credentials, you cannot add users to your LDAP server through the
wiki (you can still add local users).

I will hopefully post a 1.4 version of this patch in the next week. I will also
update my documentation at: http://meta.wikimedia.org/wiki/LDAP_Authentication
Comment 33 Edward Rudd 2005-05-16 15:52:21 UTC
I have one quick question about this patch.. Which is, with this patch will I be
able to require authentication off of the LDAP (via a possible filter so only
certain accounts can access it). And if you are not authenticated you can not
see any content in the Wiki??? Or is the only way of accomplishing that via HTTP
Auth?
Comment 34 Ryan Lane 2005-05-16 16:55:10 UTC
(In reply to comment #33)
> I have one quick question about this patch.. Which is, with this patch will I be
> able to require authentication off of the LDAP (via a possible filter so only
> certain accounts can access it). And if you are not authenticated you can not
> see any content in the Wiki??? Or is the only way of accomplishing that via HTTP
> Auth?

Using just LDAP authentication (minimal options), the wiki will only
authenticate users in LDAP, not users in the mysql database. You should be able
to use the normal options for stopping users from viewing and editing pages
unless they are logged in. Filtering users is left upon you. 

One way to filter would be to have a seperate OU for wiki users. Another way
would be to use a proxyagent (available this version, see the caveats), and make
an aci that only allows the proxyagent to access specific users, or users in a
specific group. A proxyagent searches the directory for a user matching the
username, and then binds as the user. This is probably a good way to go.

You shouldn't need HTTP auth at all using this patch.
Comment 35 Edward Rudd 2005-05-16 18:36:47 UTC
(In reply to comment #34)
> 
> One way to filter would be to have a seperate OU for wiki users. Another way
> would be to use a proxyagent (available this version, see the caveats), and make
> an aci that only allows the proxyagent to access specific users, or users in a
> specific group. A proxyagent searches the directory for a user matching the
> username, and then binds as the user. This is probably a good way to go.
> 

So there is no way to currently specify an LDAP filter? ie. (wikiAcces=TRUE) for
the proxy "Search" credentials? 
Comment 36 Ryan Lane 2005-05-16 19:56:23 UTC
(In reply to comment #35)
> (In reply to comment #34)
> > 
> > One way to filter would be to have a seperate OU for wiki users. Another way
> > would be to use a proxyagent (available this version, see the caveats), and make
> > an aci that only allows the proxyagent to access specific users, or users in a
> > specific group. A proxyagent searches the directory for a user matching the
> > username, and then binds as the user. This is probably a good way to go.
> > 
> 
> So there is no way to currently specify an LDAP filter? ie. (wikiAcces=TRUE) for
> the proxy "Search" credentials? 
> 

No, not in this version. I will add this next version. If you want to add this
yourself, the following code change should work:

In LdapAuthentication.php (in function getUserDN() ), change:

$filter = "(" . $wgLDAPSearchAttributes[$_SESSION['wsDomain']] . "=$username)";

to:

$filter =
str_replace("USER-NAME",$username,$wgLDAPSearchAttributes[$_SESSION['wsDomain']]);

In LocalSettings.php, put (these are proxyagent settings, you'll still need
$wgLDAPServerNames and $wgLDAPDomainNames):

$wgLDAPProxyAgent = "cn=proxyagent,ou=profile,dc=base,dc=dn";
$wgLDAPProxyAgentPassword = "password"; //this should work with hashes btw
$wgLDAPBaseDNs = array("yourdomainname"=>"dc=base,dc=dn");
$wgLDAPSearchAttributes =
array("yourdomainname"=>"(uid=USER-NAME)(wikiAccess=TRUE)");

If you want to be able to update LDAP from the wiki, you'll need:

$wgLDAPWriterDN = "cn=writer,dc=base,dc=dn";
$wgLDAPWriterPassword = "password"; //this should work with hashes
$wgLDAPUpdateLDAP = true; //to set password, change preferences, etc
Comment 37 Brion Vibber 2005-06-03 12:02:10 UTC
I've checked the changes to the core code into CVS HEAD, will be included in 1.5 so the plugin file can be dropped in 
easy.
Comment 38 Nicholas J Kreucher 2005-06-22 23:02:02 UTC
wondering if the 1.0 patch has been back ported to 1.4 yet... I am having a bit
of trouble getting any of the latest patches working with 1.4.5 and wanted to
check before I started digging in. thanks!
Comment 39 Ryan Lane 2005-06-23 13:19:11 UTC
(In reply to comment #38)
> wondering if the 1.0 patch has been back ported to 1.4 yet... I am having a bit
> of trouble getting any of the latest patches working with 1.4.5 and wanted to
> check before I started digging in. thanks!

No, sorry. I am probably dropping support for 1.4 in patches 1.0+. I've been
extremely busy lately and its been hard to get time to work on this. 

The latest 1.4 patch should work for you though. It probably has the
functionality you need (basic ssl encrypted LDAP authentication). If you need to
use proxy credentials, that is only available in 1.0+, so you may be out of luck
until mediawiki 1.5 comes out.

I still haven't updated my documentation for patch 1.0, i'll try to get to that
tonight (a couple variable names changed).
Comment 40 Antoine "hashar" Musso (WMF) 2005-07-13 17:08:45 UTC
Ryan lane is working on this, not me :o)
Comment 41 D. Datzert 2005-08-14 17:07:48 UTC
Created attachment 787 [details]
Patch DefaultSettings and Setup ($wgAuth)

I want to suggest appling this patch to mediawiki above 1.5beta4.
It will do the modifications described in the ticket for DefaultSettings.php
and will setup the $wgAuth object in the Setup.php to the correct
LdapAuthenticationPlugin()

Regards,
Dirk
Comment 42 Ryan Lane 2005-08-15 13:18:32 UTC
It would be better if this:

$wgLDAPUseSSL = false;

was instead this:

$wgLDAPUseSSL = true;

In DefaultSettings.php, because it is very dangerous to not use SSL. Passwords
are *NOT* sent across the line encrypted. To protect people, it would be better
for the plugin to not work for them (because their server isn't set up
correctly), than it would be for them to unknowingly send passwords across the
line in the clear.

Also, I don't know if the Setup.php additions are OK. I believe the reason
AuthenticationPlugin.php was added was so that there could be multiple
authentication plugins used just like extensions are now used. So it is probably
better if the plugin is treated the same way as an extension (the way it is
being used now).
Comment 43 Christian Meutes 2005-08-17 08:03:58 UTC
I have added "$wgLDAPScope;" to the configuration file to search for the
USER-NAME in the sub-scope OR in one-scope mode.

example:
# Scope is sub or one   
$wgLDAPScope = "sub";

following the patch for the patch version 1.4:

--- LdapAuthentication.php      Tue Aug 16 17:03:05 2005
+++ LdapAuthentication.php.old  Tue Aug 16 15:13:54 2005
@@ -50,13 +50,16 @@
        function userExists( $username ) {
                 global $wgLDAPSearchStrings, $wgLDAPAddLDAPUsers;
                global $wgLDAPWikiDN, $wgLDAPWikiPassword;
-               global $wgLDAPScope;
+
                //If we can't add LDAP users, we don't really need to check
                //if the user exists, the authenticate method will do this for
                //us. This will decrease hits to the LDAP server.
                if (!$wgLDAPAddLDAPUsers) {
                        return true;
                }
+
+                $tmpuserdn = $wgLDAPSearchStrings[$_SESSION['wsDomain']];
+                $userdn = str_replace("USER-NAME",$username,$tmpuserdn);
                $ldapconn = $this->connect();
                if ($ldapconn) {
                         ldap_set_option( $ldapconn, LDAP_OPT_PROTOCOL_VERSION, 3);
@@ -67,25 +70,7 @@
                                //user, and we don't want that.
                                        return true;
                         }
-                       if($wgLDAPScope=="sub") 
-                               {
-                               $userdn =
$wgLDAPSearchStrings[$_SESSION['wsDomain']];
-                               preg_match("/(.*?)=USER-NAME/",$userdn,$attrmatch);
-                               $searchattr=$attrmatch[1];
-                               $basedn=preg_replace("/.*?USER-NAME,/","",$userdn);
-                               $search=ldap_search($ldapconn, $basedn,
"($searchattr=$username)",$searchattr);
-                               $info  =ldap_get_entries($ldapconn, $search);
-                               if($info["count"]==1) 
-                                       {
-                                       $entry=ldap_first_entry($ldapconn,$search);
-                                       }
-                               } 
-                               else
-                               {
-                               $tmpuserdn =
$wgLDAPSearchStrings[$_SESSION['wsDomain']];
-                                       $userdn =
str_replace("USER-NAME",$username,$tmpuserdn);
-                               $entry = @ldap_read($ldapconn, $userdn,
"objectclass=*");
-                       }
+                        $entry = @ldap_read($ldapconn, $userdn, "objectclass=*");
                        if (isset($wgLDAPProxyDN)) {
                                //lets clean up
                                @ldap_unbind();
@@ -145,46 +130,28 @@
         */
        function authenticate( $username, $password ) {
                 global $wgLDAPSearchStrings;
-               global $wgLDAPScope;
 
                if ( '' == $password ) {
                        return false;
                }
-               $ldapconn = $this->connect( );
-               if ( $ldapconn ) {
-                       if($wgLDAPScope=="sub")
-                       {
-                               $userdn =
$wgLDAPSearchStrings[$_SESSION['wsDomain']];
-                               ldap_set_option( $ldapconn,
LDAP_OPT_PROTOCOL_VERSION, 3);
-                               preg_match("/(.*?)=USER-NAME/",$userdn,$attrmatch);
-                               $searchattr=$attrmatch[1];
-                               $basedn=preg_replace("/.*?USER-NAME,/","",$userdn);
-                               $search=ldap_search($ldapconn, $basedn,
"($searchattr=$username)");
-                               $entry=ldap_first_entry($ldapconn,$search);
-                               $binddn=ldap_get_dn($ldapconn,$entry);
-                               $bind = @ldap_bind( $ldapconn, $binddn, $password );
-                               if (!$bind) {
-                                       return false;
-                               } 
-                       }
-                       else
-                       {
-                               $tmpuserdn =
$wgLDAPSearchStrings[$_SESSION['wsDomain']];
-                               $userdn =
str_replace("USER-NAME",$username,$tmpuserdn);
-                               $bind = @ldap_bind( $ldapconn, $userdn, $password );
-                                if (!$bind) {
-                                        return false;
-                                       }
-                       }
 
-               $entry = ldap_read($ldapconn, $binddn, "objectclass=*");
-               $info = ldap_get_entries($ldapconn, $entry);
-               $this->email = $info[0]["mail"][0];
-               $this->lang = $info[0]["preferredlanguage"][0];
-               $this->nickname = $info[0]["displayname"][0];
-               $this->realname = $info[0]["cn"][0];
-               // Lets clean up.
-               @ldap_unbind();
+                $tmpuserdn = $wgLDAPSearchStrings[$_SESSION['wsDomain']];
+                $userdn = str_replace("USER-NAME",$username,$tmpuserdn);
+                $ldapconn = $this->connect( );
+                if ( $ldapconn ) {
+                        ldap_set_option( $ldapconn, LDAP_OPT_PROTOCOL_VERSION, 3);
+                        $bind = @ldap_bind( $ldapconn, $userdn, $password );
+                        if (!$bind) {
+                                return false;
+                        }
+                       $entry = ldap_read($ldapconn, $userdn, "objectclass=*");
+                       $info = ldap_get_entries($ldapconn, $entry);
+                       $this->email = $info[0]["mail"][0];
+                       $this->lang = $info[0]["preferredlanguage"][0];
+                       $this->nickname = $info[0]["displayname"][0];
+                       $this->realname = $info[0]["cn"][0];
+                       // Lets clean up.
+                       @ldap_unbind();
                 } else {
                         return false;
                 }


Comment 44 Christian Meutes 2005-08-17 08:14:33 UTC
i confused the new and the old file with the diff command, now the right patch:

--- LdapAuthentication.php.old  Tue Aug 16 15:13:54 2005
+++ LdapAuthentication.php      Tue Aug 16 17:03:05 2005
@@ -50,16 +50,13 @@
        function userExists( $username ) {
                 global $wgLDAPSearchStrings, $wgLDAPAddLDAPUsers;
                global $wgLDAPWikiDN, $wgLDAPWikiPassword;
-
+               global $wgLDAPScope;
                //If we can't add LDAP users, we don't really need to check
                //if the user exists, the authenticate method will do this for
                //us. This will decrease hits to the LDAP server.
                if (!$wgLDAPAddLDAPUsers) {
                        return true;
                }
-
-                $tmpuserdn = $wgLDAPSearchStrings[$_SESSION['wsDomain']];
-                $userdn = str_replace("USER-NAME",$username,$tmpuserdn);
                $ldapconn = $this->connect();
                if ($ldapconn) {
                         ldap_set_option( $ldapconn, LDAP_OPT_PROTOCOL_VERSION, 3);
@@ -70,7 +67,25 @@
                                //user, and we don't want that.
                                        return true;
                         }
-                        $entry = @ldap_read($ldapconn, $userdn, "objectclass=*");
+                       if($wgLDAPScope=="sub") 
+                               {
+                               $userdn =
$wgLDAPSearchStrings[$_SESSION['wsDomain']];
+                               preg_match("/(.*?)=USER-NAME/",$userdn,$attrmatch);
+                               $searchattr=$attrmatch[1];
+                               $basedn=preg_replace("/.*?USER-NAME,/","",$userdn);
+                               $search=ldap_search($ldapconn, $basedn,
"($searchattr=$username)",$searchattr);
+                               $info  =ldap_get_entries($ldapconn, $search);
+                               if($info["count"]==1) 
+                                       {
+                                       $entry=ldap_first_entry($ldapconn,$search);
+                                       }
+                               } 
+                               else
+                               {
+                               $tmpuserdn =
$wgLDAPSearchStrings[$_SESSION['wsDomain']];
+                                       $userdn =
str_replace("USER-NAME",$username,$tmpuserdn);
+                               $entry = @ldap_read($ldapconn, $userdn,
"objectclass=*");
+                       }
                        if (isset($wgLDAPProxyDN)) {
                                //lets clean up
                                @ldap_unbind();
@@ -130,28 +145,46 @@
         */
        function authenticate( $username, $password ) {
                 global $wgLDAPSearchStrings;
+               global $wgLDAPScope;
 
                if ( '' == $password ) {
                        return false;
                }
+               $ldapconn = $this->connect( );
+               if ( $ldapconn ) {
+                       if($wgLDAPScope=="sub")
+                       {
+                               $userdn =
$wgLDAPSearchStrings[$_SESSION['wsDomain']];
+                               ldap_set_option( $ldapconn,
LDAP_OPT_PROTOCOL_VERSION, 3);
+                               preg_match("/(.*?)=USER-NAME/",$userdn,$attrmatch);
+                               $searchattr=$attrmatch[1];
+                               $basedn=preg_replace("/.*?USER-NAME,/","",$userdn);
+                               $search=ldap_search($ldapconn, $basedn,
"($searchattr=$username)");
+                               $entry=ldap_first_entry($ldapconn,$search);
+                               $binddn=ldap_get_dn($ldapconn,$entry);
+                               $bind = @ldap_bind( $ldapconn, $binddn, $password );
+                               if (!$bind) {
+                                       return false;
+                               } 
+                       }
+                       else
+                       {
+                               $tmpuserdn =
$wgLDAPSearchStrings[$_SESSION['wsDomain']];
+                               $userdn =
str_replace("USER-NAME",$username,$tmpuserdn);
+                               $bind = @ldap_bind( $ldapconn, $userdn, $password );
+                                if (!$bind) {
+                                        return false;
+                                       }
+                       }
 
-                $tmpuserdn = $wgLDAPSearchStrings[$_SESSION['wsDomain']];
-                $userdn = str_replace("USER-NAME",$username,$tmpuserdn);
-                $ldapconn = $this->connect( );
-                if ( $ldapconn ) {
-                        ldap_set_option( $ldapconn, LDAP_OPT_PROTOCOL_VERSION, 3);
-                        $bind = @ldap_bind( $ldapconn, $userdn, $password );
-                        if (!$bind) {
-                                return false;
-                        }
-                       $entry = ldap_read($ldapconn, $userdn, "objectclass=*");
-                       $info = ldap_get_entries($ldapconn, $entry);
-                       $this->email = $info[0]["mail"][0];
-                       $this->lang = $info[0]["preferredlanguage"][0];
-                       $this->nickname = $info[0]["displayname"][0];
-                       $this->realname = $info[0]["cn"][0];
-                       // Lets clean up.
-                       @ldap_unbind();
+               $entry = ldap_read($ldapconn, $binddn, "objectclass=*");
+               $info = ldap_get_entries($ldapconn, $entry);
+               $this->email = $info[0]["mail"][0];
+               $this->lang = $info[0]["preferredlanguage"][0];
+               $this->nickname = $info[0]["displayname"][0];
+               $this->realname = $info[0]["cn"][0];
+               // Lets clean up.
+               @ldap_unbind();
                 } else {
                         return false;
                 }
Comment 45 Johannes Hiemer 2005-08-18 07:22:00 UTC
Hi,
I am trying for a whole day to get the ldap authentication running under 1.4.7
and 1.5beta4 but nothing works could anyone provide his/her running version, not
in diff files, but in the already changed php files? Everytime I try to patch
some files something goes wrong, not all patches succeed and so on.

Thanks a lot. 

Johannes
Comment 46 Ryan Lane 2005-08-18 13:45:00 UTC
Please try patching the code by hand, and not using the patch command. A few
people have reported trouble when using the patch command. Also, make sure you
are using the right version of the patch for the right version of the wiki.
version 1.0 of the patch will not work with the 1.4 series of mediawiki. With
1.5, I believe that the code had already been added to the main source, all you
should have to do is drop in the LDAP Authentication Plugin and include it into
the LocalSettings.php. 

I just updated my documentation at:

     http://meta.wikimedia.org/wiki/LDAP_Authentication

to reflect the newest version of my patch (1.0). Use this for mediawiki 1.5.

Use patch version .8 for mediawiki 1.4.
Comment 47 Sarith Sircar 2005-09-07 10:51:47 UTC
I’m new to PHP and therefore still have a long way to go. However, I’ve been asked to 
build a localized version for my company, using LDAP authentication. I’ve been trying 
to get this thing to work but no luck so far. I was wondering if you have a running 
version that you could send me please, or a link to a website that would help me step-
by-step with the necessary patching.

Your kind help is much appreciated.

Warm Regards,
Sarith
Comment 48 Sarith Sircar 2005-09-09 15:15:44 UTC
I’ve been trying to do the LDAP integration for Wiki but so far I am unable to get it 
working. My Version of Wiki is mediawiki-1.4.5 and the patch I am using is 
changes.8.14. Am I using the correct versions?

My problem is this:

I have manually patched the files and now am able to get my domain listed in the 
special user login page. I have made the necessary changes in the LocalSettings.php, 
DefaultSettings.php, AuthPlugin.php, User.php, Language.php, SpecialUserLogin.php, 
UserLogin.php files. However, when I go to the Special User Login page, type in my 
credentials as listed in the Active Directory of my company, and click on ‘Login’, all 
I see is a blank page on my browser. This is what I see in the URL: 
http://localhost/Wikipedia/index.php?
title=Special:Userlogin&action=submitlogin&returnto=Main_Page

Can you please help me with getting this up and running? Your expert inputs would be 
much appreciated.

Thank you
Comment 49 Edward Rudd 2005-09-09 21:13:12 UTC
This is not a support channel.  Go to IRC or the mailing lists to get support.
DO not change the bug status information like the way you did..  If you've found
a bug, file a new report, don't change the status of an enhancement bug and
"morph" into your issue.

I'm reverting the status on this bug.
Comment 50 Chris Thorman 2005-09-18 11:38:16 UTC
I found what seems to be a bug in the LdapAuthentication.php code that was affecting the "proxy:" mode; I fixed it on my running system and now have 
LDAP working in my MediaWiki!  (Thanks, guys!)

Here is what I had to change:

--- LdapAuthentication.php.old  2005-09-18 05:46:50.000000000 -0400
+++ LdapAuthentication.php      2005-09-18 06:12:49.000000000 -0400
@@ -52,6 +52,7 @@
                global $wgLDAPWriterDN, $wgLDAPWriterPassword;
                global $wgLDAPProxyAgent, $wgLDAPProxyAgentPassword;
                global $wgLDAPBaseDN;
+        global $wgLDAPSearchAttributes;
 
                //If we can't add LDAP users, we don't really need to check
                //if the user exists, the authenticate method will do this for
@@ -64,8 +65,9 @@
                $ldapconn = $this->connect();
                if ($ldapconn) {
                         ldap_set_option( $ldapconn, LDAP_OPT_PROTOCOL_VERSION, 3);
-                       if ($searchtype == "proxy" && isset($wgLDAPProxyAgent)) {
+                       if ($this->SearchType == "proxy" && isset($wgLDAPProxyAgent)) {
                                $userdn = $this->getUserDN($ldapconn, $username);
+
                                if ($userdn == '') {
                                        return false;
                                }
@@ -79,7 +81,8 @@
                         }
                        if ($this->SearchType == 'proxy') {
                                //we need to do a subbase search for the entry
-                               $filter = "($wgLDAPSearchAttribute=$username)";
+                $searchattr = $wgLDAPSearchAttributes[$_SESSION['wsDomain']];
+                               $filter = "($searchattr=$username)";
                                $entry = @ldap_search($ldapconn, $searchstring, $filter);
                        } else {
                                //search for the entry itself
Comment 51 JDPorter 2005-09-20 02:37:44 UTC
I had to change every instance of

ldap_set_option( $ldapconn, LDAP_OPT_PROTOCOL_VERSION, 3);

to 

ldap_set_option( $ldapconn, LDAP_OPT_PROTOCOL_VERSION, 3);
ldap_set_option( $ldapconn, LDAP_OPT_REFERRALS, 0);

in order to authenticate against our W2k3 servers.
Comment 52 Pierre Gambarotto 2005-09-30 12:00:37 UTC
Patch proposition for group membership :
I slightly modified LdapAuthentication.php to provide support for group membership : a user is authenticated if he can bin to the ldap
AND he is member of an ldap group (groupofnames or groupofuniques names).

New setting : 
--- in LocalSettings.php or in DefaultSettings.php
$wgLDAPGroupDN = "cn=test,ou=groups,dc=mycompany,dc=com"
---

The patch is at the end of the comment.
Default : only LDAP groups are supported (i.e. not posixgroups)
If a person provides correct authentication (login/password) but isn't member of the group,
the error message is still "Wrong password" or similar.

The patch :
--- LdapAuthentication.php.orig 2005-09-30 10:59:23.000000000 +0200
+++ LdapAuthentication.php      2005-09-30 11:30:05.000000000 +0200
@@ -146,7 +146,7 @@
                global $wgLDAPWriterDN, $wgLDAPWriterPassword;
                global $wgLDAPProxyAgent, $wgLDAPProxyAgentPassword;
                global $wgLDAPSearchAttribute;
-
+               global $wgLDAPGroupDN;
                if ( '' == $password ) {
                        return false;
                }
@@ -173,6 +173,9 @@
                                $this->nickname = $info[0]["displayname"][0];
                                $this->realname = $info[0]["cn"][0];
                        }
+                       if ($wgLDAPGroupDN) {
+                               return $this->isMemberOfLdapGroup($ldapconn, $userdn, $wgLDAPGroupDN);
+                       }
                        // Lets clean up.
                        @ldap_unbind();
                 } else {
@@ -510,6 +513,23 @@
                $userdn = $info[0]["dn"];
                return $userdn;
        }
+
+       function isMemberOfLdapGroup($ldapconn, $userDN, $groupDN) {
+               global $wgLDAPProxyAgent, $wgLDAPProxyAgentPassword;
+               global $wgLDAPSearchAttributes;
+                $bind = @ldap_bind( $ldapconn, $wgLDAPProxyAgent, $wgLDAPProxyAgentPassword );
+               if (!$bind) {
+                       return '';
+               }
+               //we need to do a subbase search for the entry
+               $filter = "(member=".$userDN.")";
+               $info=ldap_get_entries($ldapconn,@ldap_search($ldapconn, $groupDN, $filter));
+               return ($info["count"]>=1);
+
+       }
+
+
+
 }
 
 ?>
Comment 53 Don Seiler 2005-09-30 13:00:59 UTC
Using LDAP group is definitely a good idea.  A++.
Comment 54 JDPorter 2005-10-03 16:43:33 UTC
Am planning on patching User.php to set user rights according to group. Thoughts?
Comment 55 Ryan Lane 2005-10-03 16:52:09 UTC
(In reply to comment #54)
> Am planning on patching User.php to set user rights according to group. Thoughts?

Sounds good. Patch against 1.5 CVS, as all the changes in my patch except for
LdapAuthentication.php should be in the 1.5 branch already.

On another topic:

Could someone apply the last few patches that were submitted, against
LdapAuthentication.php, and add it as the current patch please? I am unable to
work on this right now as I don't have access to a non-work computer (I'm still
evacuated from Katrina).
Comment 56 Udo Adametz 2005-10-07 14:13:34 UTC
Created attachment 945 [details]
Version 1.0a of the LdapAuthentication.php (For Mediawiki 1.5) (=v1.0 plus changes in #50 #51 and #52)

Because of the wish from Ryan lane I applied the last few patches that were
submitted against LdapAuthentication.php. For me it works fine.
Comment 57 Don Seiler 2005-10-07 14:20:18 UTC
So did LDAP auth not make into already-released 1.5.0?
Comment 58 Udo Adametz 2005-10-07 15:16:20 UTC
I use Mediawiki 1.5.0 and the LdapAuthentication.php from your LDAP patch v1.0 to authenticate against our company AD. So far it is working fine. 

(In reply to comment #3)
> 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 haveremoved the "mail me a new password" button, and the validate password field(unless $wgLDAPUseLocal is true). I have added a selection box 
that will allowusers to choose which domain they wish to authenticate against (in the aboveexample, the options would 
be "testADdomain", "testLDAPdomain", and "local").

At first: I'm not very familiar with PHP, but: After reading your post i would expect that the "mail me a new password" button should disapear !? 
But even if i set $wgLDAPUseLocal=false the "mail me a new Password" button, and some other fields (Retype password, Create new account buttom, 
etc.) are always apearing on the user login page. Is this what you intented, and i only don't understand the coherences, or ist this a bug ?

Second: Unfortunately the usernames (loginname) in out AD are very cryptic, like xy15. Is the any posibillity/option that not the "cn", like xy15, 
but the "displayname", like Smith John, of the AD/LDAP users is used as wiki username? For example: i would like to log into the wiki with 
name "xy15", but on the wiki history pages should apear "Smith John". It would be very handy for us, and maby for other people to...

Thanks you, for any hints.
Comment 59 Udo Adametz 2005-10-07 15:32:24 UTC
(In reply to comment #57)
> So did LDAP auth not make into already-released 1.5.0?

Yes, but only the changes to the core files (AuthPlugin.diff,Language.diff,SpecialPreferences.diff,SpecialUserlogin.diff,User.diff,Userlogin.diff) 
are included in the 1.5.0. For a new installation you still need the LdapAuthentication.php, witch is not included in the relase 1.5.0



Comment 60 Don Seiler 2005-10-17 16:55:06 UTC
Is there an FM for me to RT?  Just curious how I set this up.  Just drop it into
a dir somewhere and it should show up as an option somewhere?
Comment 61 Ryan Lane 2005-10-17 16:57:58 UTC
(In reply to comment #60)
> Is there an FM for me to RT?  Just curious how I set this up.  Just drop it into
> a dir somewhere and it should show up as an option somewhere?


Did you happen to check out the URL at the top of this page? ;)

http://meta.wikimedia.org/wiki/LDAP_Authentication
Comment 62 Don Seiler 2005-10-17 17:00:45 UTC
/me hangs his head in shame and plunges the knife deep into his belly.
Comment 63 Ryan Lane 2005-10-17 18:14:57 UTC
(In reply to comment #58)
> I use Mediawiki 1.5.0 and the LdapAuthentication.php from your LDAP patch v1.0
to authenticate against our company AD. So far it is working fine. 
> 
> At first: I'm not very familiar with PHP, but: After reading your post i would
expect that the "mail me a new password" button should disapear !? 
> But even if i set $wgLDAPUseLocal=false the "mail me a new Password" button,
and some other fields (Retype password, Create new account buttom, 
> etc.) are always apearing on the user login page. Is this what you intented,
and i only don't understand the coherences, or ist this a bug ?
> 

Well, actually, the patch allows for mailing of a new password now. It also
allows for creation of new accounts and such. Originally the patch would remove
those fields, but now the patch for 1.5 is pretty much just
"LdapAuthentication.php", so if you would like to disable these, you can edit
function "modifyUITemplate" in "LdapAuthentication.php" and add the following: 

     $template->set( 'create', false );
     $template->set( 'useemail', false );

> Second: Unfortunately the usernames (loginname) in out AD are very cryptic,
like xy15. Is the any posibillity/option that not the "cn", like xy15, 
> but the "displayname", like Smith John, of the AD/LDAP users is used as wiki
username? For example: i would like to log into the wiki with 
> name "xy15", but on the wiki history pages should apear "Smith John". It would
be very handy for us, and maby for other people to...
> 
> Thanks you, for any hints.

Function "authenticate" in "LdapAuthentication.php" is where these attributes
are retreived. I have nickname set to "displayname" and real name set to "cn".
You may want to set real name to be "displayname" as well as the nickname.
People should be able to log into the wiki using their usernames, and have their
nickname or real name shown as their displayname if you do this.
Comment 64 Udo Adametz 2005-10-18 08:46:02 UTC
(In reply to comment #63)
> you can editfunction "modifyUITemplate" in "LdapAuthentication.php" and add the following:
>
> $template->set( 'create', false );
> $template->set( 'useemail', false );

Slowly but surely the single functions become more clearly to me. Thank you for your explanations, that works really nice for me! Perhaps you might 
want to add another variable, with controls this settings through the LocalSettings.php ?

> Function "authenticate" in "LdapAuthentication.php" is where these attributesare
> retreived. I have nickname set to "displayname" and real name set to "cn".You may
> want to set real name to be "displayname" as well as the nickname.People should
> be able to log into the wiki using their usernames, and have theirnickname or
> real name shown as their displayname if you do this.

Futher I changed in LdapAuthentication.php:

$this->nickname = $info[0]["displayname"][0];
$this->realname = $info[0]["cn"][0];

into

$this->nickname = $info[0]["displayname"][0];
$this->realname = $info[0]["displayname"][0];

but this does not work so far. After the login of a "new" user (=a user who have never been loged in bevor), the user settings (email, language, 
nickname (e.g.John Smith)) are correctly received from the AD, and are displayed in the user preferences. But the displayed Name in the upper right 
corner, and the link to the users page, are still named with the cryptic cn (e.g. xy15) an not with the displayname (e.g. Smith John).

Have you any futher suggestions? Thank you.
Comment 65 Ryan Lane 2005-10-18 13:49:05 UTC
(In reply to comment #64)
> Slowly but surely the single functions become more clearly to me. Thank you
for your explanations, that works really nice for me! Perhaps you might 
> want to add another variable, with controls this settings through the
LocalSettings.php ?

I was thinking about it, but it could possibly add quite a few new options, and
since the template could be changed (and likely will be changed) by a lot of
people when they localize their wiki, the options may not be worthwhile.

> Futher I changed in LdapAuthentication.php:
> 
> $this->nickname = $info[0]["displayname"][0];
> $this->realname = $info[0]["cn"][0];
> 
> into
> 
> $this->nickname = $info[0]["displayname"][0];
> $this->realname = $info[0]["displayname"][0];
> 
> but this does not work so far. After the login of a "new" user (=a user who
have never been loged in bevor), the user settings (email, language, 
> nickname (e.g.John Smith)) are correctly received from the AD, and are
displayed in the user preferences. But the displayed Name in the upper right 
> corner, and the link to the users page, are still named with the cryptic cn
(e.g. xy15) an not with the displayname (e.g. Smith John).
> 
> Have you any futher suggestions? Thank you.

Actually, now that I look into it, it seems that the name that shows in the
upper right hand corner is the login name of the user. The real name and
nickname do not seem to change how that is displayed. What should be displayed
for your users is whatever they log in as; so, if your AD usernames are some
weird cryptic name, then thats what will be shown.
Comment 66 Jeff Mandel 2005-10-28 22:09:25 UTC
Here's a patch that will add the ability to require the authenticated user to
have a required attribute in order to get access to the wiki. I was inspired to
do this by the require ldap-attribute of apache's mod_auth_ldap.

I started v 1.0 before the changes were included to makeup 1.0a. Hopefully I
have merged them properly, it does still work for me, though I didn't try the
group member feature. If the patch doesn't work for you, I can provide the full
file for better merging or comparison if that helps.

I moved the proxy user check to getUserDN. I noticed wherever the getUserDN was
called, a proxy check was done right before it, so I just incorporated it into
the getUserDN function.

Jeff


Additional parameters for LocalSettings:
Check for this or not:
$wgLDAPRequireAuthAttribute = true;

Look for the attribute/value, for example:
$wgLDAPAuthAttribute = array(
  "ldap"=>"businesscategory=wikiuser"
  );

Businesscategory is a  multivalued attribute in the inetorgperson schema so it's
probably there for you to use already.

--- LdapAuthentication-1.0a.php 2005-10-28 14:47:28.000000000 -0700
+++ LdapAuthentication-require-attr.php 2005-10-28 14:45:35.000000000 -0700
@@ -168,12 +168,17 @@
                if ( $ldapconn ) {
                        ldap_set_option( $ldapconn, LDAP_OPT_PROTOCOL_VERSION, 3);
                        ldap_set_option( $ldapconn, LDAP_OPT_REFERRALS, 0);
-                       if ($searchtype == "proxy" && isset($wgLDAPProxyAgent)) {
+                       // Add additional search even if non-proxy to see if the
user
+                       // has the optionally required attribute. This should really
+                       // be done in the userExists section, but userExists
also checks
+                       // the wiki, and the user might be there if their role
was once
+                       // valid.
+                       // Proxy check is moved to getUserDN, so we can apply
the proxy
+                       // and the authattribute filter in one location only. - jeff
                                $userdn = $this->getUserDN($ldapconn, $username);
                                if ($userdn == '') {
                                        return false;
                                }
-                       }
                        $bind = @ldap_bind($ldapconn, $userdn, $password);
                        if (!$bind) {
                                return false;
@@ -253,12 +258,11 @@
                if ($ldapconn) {
                        ldap_set_option( $ldapconn, LDAP_OPT_PROTOCOL_VERSION, 3);
                        ldap_set_option( $ldapconn, LDAP_OPT_REFERRALS, 0);
-                       if ($searchtype == "proxy" && isset($wgLDAPProxyAgent)) {
+                       // Proxy checking moved to the getUserDN function - jeff
                                $userdn = $this->getUserDN($ldapconn,
$user->getName());
                                if ($userdn == '') {
                                        return false;
                                }
-                       }
                        if (!isset($wgLDAPWriterDN)) {
                                return false;
                        }
@@ -305,12 +309,11 @@
                if ($ldapconn) {
                        ldap_set_option( $ldapconn, LDAP_OPT_PROTOCOL_VERSION, 3);
                        ldap_set_option( $ldapconn, LDAP_OPT_REFERRALS, 0);
-                       if ($searchtype == "proxy" && isset($wgLDAPProxyAgent)) {
+                       // Proxy checking moved to the getUserDN function - jeff
                                $userdn = $this->getUserDN($ldapconn,
$user->getName());
                                if ($userdn == '') {
                                        return false;
                                }
-                       }
                        $bind = @ldap_bind( $ldapconn, $wgLDAPWriterDN,
$wgLDAPWriterPassword );
                        if (!$bind) {
                                return false;
@@ -514,13 +517,29 @@

        function getUserDN($ldapconn, $username) {
                global $wgLDAPProxyAgent, $wgLDAPProxyAgentPassword;
-               global $wgLDAPSearchAttributes;
-               $bind = @ldap_bind( $ldapconn, $wgLDAPProxyAgent,
$wgLDAPProxyAgentPassword );
-               if (!$bind) {
-                       return '';
+               global $wgLDAPSearchAttributes, $wgLDAPRequireAuthAttribute;
+               global $wgLDAPAuthAttribute;
+               if ($searchtype == "proxy" && isset($wgLDAPProxyAgent)) {
+                       $bind = @ldap_bind( $ldapconn, $wgLDAPProxyAgent,
$wgLDAPProxyAgentPassword );
+                       if (!$bind) {
+                               return '';
+                       }
+               } else {
+               // Do the search anonymously
+                       $bind = @ldap_bind( $ldapconn );
+                       if (!$bind) {
+                               return '';
+                       }
                }
+
                //we need to do a subbase search for the entry
-               $filter = "(" . $wgLDAPSearchAttributes[$_SESSION['wsDomain']] .
"=$username)";
+               // Check that the user also has the required attribute - jeff
+               if ($wgLDAPRequireAuthAttribute) {
+                       $filter = "(" .
$wgLDAPAuthAttribute[$_SESSION['wsDomain']] . ")";
+               } else {
+                       $filter = "(" .
$wgLDAPSearchAttributes[$_SESSION['wsDomain']] . "=$username)";
+               }
+
                $entry = @ldap_search($ldapconn,
$this->getSearchString($username), $filter);
                if (!$entry) {
                        return '';
@@ -529,10 +548,10 @@
                $userdn = $info[0]["dn"];
                return $userdn;
        }
-
        function isMemberOfLdapGroup($ldapconn, $userDN, $groupDN) {
                global $wgLDAPProxyAgent, $wgLDAPProxyAgentPassword;
                global $wgLDAPSearchAttributes;
+
                $bind = @ldap_bind( $ldapconn, $wgLDAPProxyAgent,
$wgLDAPProxyAgentPassword );
                if (!$bind) {
                        return '';
Comment 67 Ryan Lane 2005-10-31 13:59:25 UTC
Comment on attachment 787 [details]
Patch DefaultSettings and Setup ($wgAuth)

This patch may cause problems, and as such, I'm not recommending it.
Comment 68 slakkie 2005-11-01 15:05:41 UTC
Hi,

I am not seeing through anymore, is there now a working solution for LDAP. If so could someone please direct us 
to the final files and documentation. As it is a bit mixed up where what is at the moment.

That would be very kind. Thank you!!

Regards
Slakkie
Comment 69 Ryan Lane 2005-11-01 15:16:03 UTC
(In reply to comment #68)
> Hi,
> 
> I am not seeing through anymore, is there now a working solution for LDAP. If
so could someone please direct us 
> to the final files and documentation. As it is a bit mixed up where what is at
the moment.
> 
> That would be very kind. Thank you!!
> 
> Regards
> Slakkie

The "URL" will lead you to the documentation. The current version of this patch
is 1.0a (I haven't obsoleted 1.0 yet because I haven't had the ability to test
1.0a fully, but others have tested it).

Is this in confusion to me obsoleting attachment 787 [details]? That was a patch to
"DefaultSettings.php" and "Setup.php", which could have caused problems to some
people.

The current patch is a working solution for authentication, and as a partial
backend to mediawiki. It should fit your needs, if not let me know what is
missing (or submit a patch for what is missing).
Comment 70 Jeff Mandel 2005-11-01 21:27:54 UTC
Created attachment 1036 [details]
Patch to 1.0.a for require attribute

This is a restructured version of the first patch submitted to add support for
requiring a user to have a certain attribute to finish authenticating to the
wiki. It now properly handles the case where no proxy user is allowed, nor is
an anonymous search allowed.

Thanks to Marcus Schwartz who suggested this change.

This is a patch against v 1.0a, and only makes changes necessary to implement
the feature. I did move the GroupDN check above retrieve prefs, since I thought
there's no need to get any prefs if the user is not allowed access. This patch
has been tested with openldap and mw 1.5.

Additional parameters for LocalSettings:
Check for this or not:
$wgLDAPRequireAuthAttribute = true;

Look for the attribute/value, for example:
$wgLDAPAuthAttribute = array(
"ldap"=>"businesscategory=wikiuser"
);

Businesscategory is a multivalued attribute in the inetorgperson schema so it's

probably there for you to use already.

Please let me know if you have any issues with the patch, I can send a fully
patched file if necessary.

Jeff
Comment 71 Ryan Lane 2005-11-02 23:44:34 UTC
Created attachment 1038 [details]
Version 1.0b of the LdapAuthentication.php Plugin (for Mediawiki 1.5)

Version 1.0b is now the current version of this plugin for Mediawiki 1.5.

This version of the plugin adds in the patch to 1.0a for role based
restriction, fixes a bug in the group based restrictions, and removes some
global variables in functions where they were not being used.

The bug in the group based restrictions could have occured when the wiki was
set up to do straight binds (when not using proxy authentication), and group
based restriction was enabled. The function "isMemberOfLdapGroup" was rebinding
as the proxy agent. To fix this problem, I just removed the rebinding, as
binding was being done before the method was called in the "authenticate"
function. This could be an issue if the user logging into the system is not
allowed to read group information in LDAP, as the last bind done in the
"authenticate" function is as the user logging in. As this is generally not the
case, this should not cause problems.
Comment 72 Ryan Lane 2005-11-03 16:06:37 UTC
Created attachment 1042 [details]
Version 1.0c of the LdapAuthentication.php Plugin (for Mediawiki 1.5)

Version 1.0c is now the current version of this plugin for Mediawiki 1.5.

This version of the plugin fixes a bug I introduced while testing in 1.0b,
where I accidentally commented something out (would only affect you if you were
using a local domain). It also fixes another bug I introduced in the
"isMemberOfLdapGroup" function. The bug would cause the function not to rebind
as the proxyagent. This was done to fix a bug where the proxyagent would rebind
whether the plugin was set to use straight binds or proxy binds (breaking
straight binds). However, the fix introduced a problem where if the user
binding did not have permissions to read groups, authentication would fail.

This fix still has a problem, but there will be problems no matter how this is
solved. With this fix, if the proxyagent does not have read permissions on
groups, then authentication will also fail. However, it is much better
situation to have the proxyagent try to read, than to have the user binding try
to read, as the proxyagent is more likely to have read access on all of the
directory (as this is generally what proxyagents are for).

So, the fix will cause the proxyagent to rebind in the "isMemberOfLdapGroup"
function if proxy authentication is being used.
Comment 73 Don Seiler 2005-11-03 18:54:36 UTC
Is the plan for this to eventually be packaged with mediawiki proper?

PS LdapAuthentication 1.0a (and now 1.0c) work just great for me.  I use
proxyAgent for binding/searching.  Haven't done group member checking yet, but
now we may.  Great work!
Comment 74 Brion Vibber 2005-11-03 22:13:54 UTC
No, it's a third-party plugin. MediaWiki is designed for public reference sites,
not for corporate intranets, so it's not something we'd be likely to maintain.
Comment 75 Kevin Grinberg 2005-11-07 23:20:19 UTC
RE: Ryan's instructions for getting group authentication to work on AD

I spent a lot longer than I should have trying to get it to work as written, but
finally debugged it down to a case-sensitivity issue:

$info[0]["distinguishedName"][0];
should be
$info[0]["distinguishedname"][0];

I'm not sure if it's just my setup (PHP 5.0.5 on Windows, authenticating against
a 2003 AD), or something more general, but making the array key names lowercase
seems like a safer bet.

Also, is there any reason not to move the "if ($wgLDAPRetrievePrefs) {" section
above the "if ($wgLDAPGroupDN) {" check?

I already pull the preferences, so I didn't see the point in duplicating the
code... just switching the order of the sections (pull LDAP properties first,
including distinguishedname, then check for group membership) seemed to work out
well for me.  Is there any reason not to make the switch in the patch?
Comment 76 Ryan Lane 2005-11-10 07:07:22 UTC
(In reply to comment #75)
> RE: Ryan's instructions for getting group authentication to work on AD
> 
> Also, is there any reason not to move the "if ($wgLDAPRetrievePrefs) {" section
> above the "if ($wgLDAPGroupDN) {" check?
> 
> I already pull the preferences, so I didn't see the point in duplicating the
> code... just switching the order of the sections (pull LDAP properties first,
> including distinguishedname, then check for group membership) seemed to work out
> well for me.  Is there any reason not to make the switch in the patch?

Well, in your case, it would work more efficiently to pull preferences first, and then check the group. If you are not using AD, then it is probably more efficient to pull 
after you check for group membership. I'll look into a better way of doing this. Thanks for the update, I'll change my documentation to reflect the lowercase requirement 
on the attribute name.
Comment 77 David Schibeci 2005-11-30 04:12:42 UTC
Thanks to Ryan for the LdapAuthentication.php Plugin and Pierre for adding group
membership.

I've modified LdapAuthentication.php to use a variable for the member attribute
as we use groupOfUniqueMembers rather than groupOfMembers.

Here is my modification if anyone else might find it useful:

--- /root/mediawiki/LdapAuthentication-1.0c.php 2005-11-30 10:41:29.000000000 +0800
+++ includes/LdapAuthentication.php     2005-11-30 10:41:49.000000000 +0800
@@ -154,6 +154,7 @@
                global $wgLDAPRetrievePrefs;
                global $wgLDAPProxyAgent;
                global $wgLDAPGroupDN;
+               global $wgLDAPMemberAttributes;
                global $wgLDAPRequireAuthAttribute, $wgLDAPAuthAttribute;
 
                if ( '' == $password ) {
@@ -183,7 +184,7 @@
                                if ($info["count"] < 1) { return false; }
                         }
                        if ($wgLDAPGroupDN) {
-                               return $this->isMemberOfLdapGroup($ldapconn,
$userdn, $wgLDAPGroupDN);
+                               return $this->isMemberOfLdapGroup($ldapconn,
$userdn, $wgLDAPGroupDN[$_SESSION['wsDomain']],
$wgLDAPMemberAttributes[$_SESSION['wsDomain']]);
                        }
                        if ($wgLDAPRetrievePrefs) {
                                $entry = @ldap_read($ldapconn, $userdn,
"objectclass=*");
@@ -541,7 +542,7 @@
                return $userdn;
        }
 
-       function isMemberOfLdapGroup($ldapconn, $userDN, $groupDN) {
+       function isMemberOfLdapGroup($ldapconn, $userDN, $groupDN, $memberattr) {
                global $wgLDAPProxyAgent, $wgLDAPProxyAgentPassword;
                global $wgLDAPSearchAttributes;
                //If we are using a proxyagent, we should search the groups
using a proxyagent.
@@ -553,7 +554,7 @@
                        }
                }
                //we need to do a subbase search for the entry
-               $filter = "(member=".$userDN.")";
+               $filter = "($memberattr=".$userDN.")";
                $info=ldap_get_entries($ldapconn,@ldap_search($ldapconn,
$groupDN, $filter));
                return ($info["count"]>=1);
        }

I also made $wgLDAPGroupDN an array which is why
$wgLDAPGroupDN[$_SESSION['wsDomain']] is sent to isMemberOfLdapGroup
Comment 78 Sarith Sircar 2005-12-21 11:12:33 UTC
I've installed Wiki 1.5.3 on IIS 5.0, Win 2K Pro, PHP 5.1, MySQL 3.23. After doing an 
LDAP integration, the authentication works fine. But when I get the "login succesful" 
page, this appears - 

Notice: Undefined variable: servers in 
C:\Wiki\mediawiki\includes\LdapAuthentication.php on line 87

Your help appreciated.
Comment 79 Edward Rudd 2005-12-21 14:08:26 UTC
(Copied from Comment #49)
This is not a support channel. Go to IRC or the mailing lists to get support.
DO not change the bug status information like the way you did.. If you've found
a bug, file a new report, don't change the status of an enhancement bug and
"morph" into your issue.

I'm reverting the status on this bug.
Comment 80 Sarith Sircar 2005-12-22 09:08:05 UTC
(In reply to comment #79)
> (Copied from Comment #49)This is not a support channel. Go to IRC or the mailing lists to get 
support.DO not change the bug status information like the way you did.. If you've founda bug, file 
a new report, don't change the status of an enhancement bug and"morph" into your issue.I'm 
reverting the status on this bug.

Well, I'd think that if a patch doesnt work 100% in the said configurations and throws exceptions, 
it should be considered a bug. If you cant replicate the error or dont have a clue, might as well 
mention that.
Comment 81 Rob Church 2005-12-22 13:10:13 UTC
(In reply to comment #80)
> (In reply to comment #79)
> > (Copied from Comment #49)This is not a support channel. Go to IRC or the
mailing lists to get 
> support.DO not change the bug status information like the way you did.. If
you've founda bug, file 
> a new report, don't change the status of an enhancement bug and"morph" into
your issue.I'm 
> reverting the status on this bug.
> 
> Well, I'd think that if a patch doesnt work 100% in the said configurations
and throws exceptions, 
> it should be considered a bug. If you cant replicate the error or dont have a
clue, might as well 
> mention that.

Was the "patch" part of the code provided in the official MediaWiki distribution
tarball?

Comment 82 Matthias Eisner 2006-01-05 09:40:58 UTC
Hi,

what do you think about making the attributes more flexible (see comment #67) e.
g. by shifting the values of

                               $this->email = $info[0]["mail"][0];
                                $this->lang = $info[0]["preferredlanguage"][0];
                                $this->nickname = $info[0]["displayname"][0];
                                $this->realname = $info[0]["cn"][0];

as variables to the Localsettings, then it would be easier to customize for not
so standard set up LDAP Servers. 
Comment 83 Matthias Eisner 2006-01-05 09:43:29 UTC
oops, i meant comment #63 - sorry
Comment 84 Matthias Eisner 2006-01-05 10:54:04 UTC
One more question on groups. As already discussed it is possible to give access
based on different groups defined on the LDAP Server. What I would like to do
ist to assign group right within the wikidb according to this information which
can easily be retrived together with the uerprefs, so I can use

 $wgGroupPermissions

rules based on the data from the LDAP. Creating the groups can be done manually
before, but assignment of users in an automatic way on (1st?) login would be
great instead of using Special:Userrights or editing the database directly.

Anybody any ideas how to achive this?
Comment 85 Ryan Lane 2006-01-06 22:48:03 UTC
(In reply to comment #82)
> Hi,
> 
> what do you think about making the attributes more flexible (see comment #67) e.
> g. by shifting the values of
> 
>                                $this->email = $info[0]["mail"][0];
>                                 $this->lang = $info[0]["preferredlanguage"][0];
>                                 $this->nickname = $info[0]["displayname"][0];
>                                 $this->realname = $info[0]["cn"][0];
> 
> as variables to the Localsettings, then it would be easier to customize for not
> so standard set up LDAP Servers. 

Next time I have a chance to update the plugin, I'll add options for these. The
biggest problem with doing this is that it adds four new options to the
configuration. I guess I'll have to look into adding a "LDAPDefaultSettings.php"
file.
Comment 86 Ryan Lane 2006-01-06 23:00:47 UTC
(In reply to comment #84)
> One more question on groups. As already discussed it is possible to give access
> based on different groups defined on the LDAP Server. What I would like to do
> ist to assign group right within the wikidb according to this information which
> can easily be retrived together with the uerprefs, so I can use
> 
>  $wgGroupPermissions
> 
> rules based on the data from the LDAP. Creating the groups can be done manually
> before, but assignment of users in an automatic way on (1st?) login would be
> great instead of using Special:Userrights or editing the database directly.
> 
> Anybody any ideas how to achive this?

This is definitely possible... It would be taxing on your LDAP servers if you
have very heavy traffic though. Since LDAP would be your authoritative source,
and since this is authorization information, you shouldn't cache the information
from LDAP. So, every time someone requests a page, it would probably cause a
lookup in LDAP. I guess you could cache the information per session if you
rarely change the info in LDAP...

I'll look into a good way to implement this, as this is also something I'd like.
No promises on time frame though, as I don't have reliable internet access. If
someone else wants to look into how to tackle this, please have at it.
Comment 87 Nick Hildebrant 2006-01-11 06:02:41 UTC
I had some issues getting LDAP Auth working in MediaWiki 1.5.5. After logging in
with a valid uname and passwd I got the error:

Call to a member function on a non-object in SpecialUserlogin.php on 314.

This seems like a mediawiki bug, and the following change to
SpecialUserlogin.php was required to make LDAP Auth work...

<                                       $u = $this->initUser( $u );
---
>                                       $u =& $this->initUser( $u );
Comment 88 Manilal K M 2006-01-11 06:08:47 UTC
I have posted this mail to the wikitech-l@wikipedia.org. But got Ryan's
instruction to post it here. 

I have just started hacking mediawiki. I am trying to apply the LDAP
authentication plugin to mediawiki-1.5.2 in a FC-4. I'm using openldap-2.2.23-5.
 I have read the  documentation at :
http://meta.wikimedia.org/wiki/LDAP_Authentication and downloaded the plugin
from :http://bugzilla.wikipedia.org/attachment.cgi?id=1042&action=view

I have dropped the above file in /includes and changed Localsettings.php
accordingly. Luckily everything seems to be working fine. But everything crashed
when I tried to Group based authentication in mediawiki. I have added group
entry to the ldap server, restarted it and then inlcuded the configuration
parameters for group based
authentication. Now my Localsettings.php looks like this:
<code>
require_once( 'LdapAuthentication.php' );
$wgAuth = new LdapAuthenticationPlugin();
$wgLDAPDomainNames = array( "libregeek" );
$wgLDAPServerNames = array( "libregeek"=>"localhost"  );
$wgLDAPSearchStrings = array(
"libregeek"=>"uid=USER-NAME,ou=People,dc=libregeek,dc=net"  );
$wgLDAPUseSSL = false;
$wgLDAPUseLocal = false;
$wgLDAPAddLDAPUsers = false;
$wgLDAPUpdateLDAP = false;
$wgLDAPMailPassword = false;
$wgLDAPRetrievePrefs = false;
$wgMinimalPasswordLength = 1;

$wgLDAPGroupDN = "cn=itpeople,ou=Groups,dc=libregeek,dc=net";
$wgLDAPProxyAgent = "cn=root,dc=libregeek,dc=net";
$wgLDAPProxyAgentPassword = "secret"; //this should work with hashes btw
$wgLDAPBaseDNs = array("libregeek"=>"dc=libregeek,dc=net");
$wgLDAPSearchAttributes =
array("libregeek"=>"(uid=USER-NAME)(wikiAccess=TRUE)");
</code>

With this configuration I can't login . It simply says "The password you entered
is incorrect (or missing). Please try again.". is there any missing
configuration items ?? I just tried to print the global variables corresponding
to Proxies in LdapAuthentication.php and it gives nothing. One more thing I
didn't got the correct idea of Proxy. is it like the "Manager" account who has
read permission to all the directory entries. 

what may have gone wrong?
please help
regards

Manilal
Comment 89 Ryan Lane 2006-01-12 01:10:41 UTC
(In reply to comment #88)
> I have posted this mail to the wikitech-l@wikipedia.org. But got Ryan's
> instruction to post it here. 
> 

Actually, I wanted you to post it to the discussion page on meta ;). This spot
is really more for people who are developing addons for the plugin.

V/r,

Ryan Lane
Comment 90 Neil M 2006-01-30 18:20:54 UTC
I modified the LDAP code to do a search before doing the bind, this is typical
of LDAP authentication mechanisms.  This is required if your LDAP does not use
uid in the DN string.  It also allows you to use other unique attributes for
login, such as "mail" or "cn".  I highly recommend that this standard
functionality be added to the next release.

        function getSearchString($username) {
            global $wgLDAPSearchStrings, $wgLDAPBaseDNs;
            $userdn = $wgLDAPBaseDNs[$_SESSION['wsDomain']];
                $this->SearchType = "proxy";
                if (!isset($userdn)) {
                        $tmpuserdn = $wgLDAPSearchStrings[$_SESSION['wsDomain']];

                        // NCM added for dn search before bind
                        $parseddn = split("USER-NAME", $tmpuserdn);
                        $searchdn = substr($parseddn[1], 1);
                        $filter = $parseddn[0] . $username;

                        $ldapconn = $this->connect();
                        if ($ldapconn) {
                                ldap_set_option( $ldapconn,
LDAP_OPT_PROTOCOL_VERSION, 3);
                                ldap_set_option( $ldapconn, LDAP_OPT_REFERRALS, 0);
                                # request these attributes
                                $justthese = array("dn");

                                $sr = ldap_search($ldapconn, $searchdn, $filter,
$justthese);
                                if ($sr !== FALSE) {
                                        $info = ldap_get_entries($ldapconn, $sr);
                                        $userdn = $info[0]["dn"];
                                } else {
                                        ldap_error($ldapconn);
                                }

                                ldap_unbind($ldapconn);
                                $this->SearchType = "nonproxy";
                        }
                        else {
                                $userdn =
str_replace("USER-NAME",$username,$tmpuserdn);
                        }
                }

                return $userdn;
        }
Comment 91 Ryan Lane 2006-01-30 20:06:01 UTC
(In reply to comment #90)
> I modified the LDAP code to do a search before doing the bind, this is typical
> of LDAP authentication mechanisms.  This is required if your LDAP does not use
> uid in the DN string.  It also allows you to use other unique attributes for
> login, such as "mail" or "cn".  I highly recommend that this standard
> functionality be added to the next release.
> 
>         function getSearchString($username) {
>             global $wgLDAPSearchStrings, $wgLDAPBaseDNs;
>             $userdn = $wgLDAPBaseDNs[$_SESSION['wsDomain']];
>                 $this->SearchType = "proxy";
>                 if (!isset($userdn)) {
>                         $tmpuserdn = $wgLDAPSearchStrings[$_SESSION['wsDomain']];
> 
>                         // NCM added for dn search before bind
>                         $parseddn = split("USER-NAME", $tmpuserdn);
>                         $searchdn = substr($parseddn[1], 1);
>                         $filter = $parseddn[0] . $username;
> 
>                         $ldapconn = $this->connect();
>                         if ($ldapconn) {
>                                 ldap_set_option( $ldapconn,
> LDAP_OPT_PROTOCOL_VERSION, 3);
>                                 ldap_set_option( $ldapconn,
LDAP_OPT_REFERRALS, 0);
>                                 # request these attributes
>                                 $justthese = array("dn");
> 
>                                 $sr = ldap_search($ldapconn, $searchdn, $filter,
> $justthese);
>                                 if ($sr !== FALSE) {
>                                         $info = ldap_get_entries($ldapconn, $sr);
>                                         $userdn = $info[0]["dn"];
>                                 } else {
>                                         ldap_error($ldapconn);
>                                 }
> 
>                                 ldap_unbind($ldapconn);
>                                 $this->SearchType = "nonproxy";
>                         }
>                         else {
>                                 $userdn =
> str_replace("USER-NAME",$username,$tmpuserdn);
>                         }
>                 }
> 
>                 return $userdn;
>         }

It looks like this change affects straight binds...

What if the directory server required authentication to search? In that case,
this change breaks straight binds. If you want to search, you should be doing a
proxy search. If you don't have a proxyagent, try setting the proxyagent
information blank to do your search.

Many people do not allow anonymous searching (I for one do not), but still want
to do straight binds (me again).

If the plugin for some reason will not allow anonymous searching, please send a
patch for that.

If I am misunderstanding what your code changes do, let me know (and please
submit changes in unified diff format in the future, as it is easier to see what
you changed).
Comment 92 Neil M 2006-02-21 22:43:48 UTC
Sorry, I think these changes should address your concerns.  If the search fails
(or bad anonymous/proxy bind occurs), then the function will kick out the
original DN with the replaced USER-NAME string just like the original function did.

--- ../extensions/LdapAuthentication.php  2006-02-21 14:00:31.000000000 -0800
+++ LdapAuthentication.php      2006-02-21 14:00:30.000000000 -0800
@@ -505,13 +505,39 @@

  function getSearchString($username) {
             global $wgLDAPSearchStrings, $wgLDAPBaseDNs;
+    global $wgLDAPProxyAgent, $wgLDAPProxyAgentPassword;
             $userdn = $wgLDAPBaseDNs[$_SESSION['wsDomain']];
     $this->SearchType = "proxy";
     if (!isset($userdn)) {
                       $tmpuserdn = $wgLDAPSearchStrings[$_SESSION['wsDomain']];
                       $userdn = str_replace("USER-NAME",$username,$tmpuserdn);
+
+     // NCM added for dn search before bind
+     $parseddn = split("USER-NAME", $tmpuserdn);
+     $searchdn = substr($parseddn[1], 1);
+     $filter = $parseddn[0] . $username;
+
+     $ldapconn = $this->connect();
+     if ($ldapconn) {
+      $bind = @ldap_bind( $ldapconn, $wgLDAPProxyAgent,
$wgLDAPProxyAgentPassword );
+      if ($bind) {
+       ldap_set_option( $ldapconn, LDAP_OPT_PROTOCOL_VERSION, 3);
+                                      ldap_set_option( $ldapconn,
LDAP_OPT_REFERRALS, 0);
+       # request these attributes
+       $justthese = array("dn");
+
+       $sr = @ldap_search($ldapconn, $searchdn, $filter, $justthese);
+       if ($sr !== FALSE) {
+        $info = ldap_get_entries($ldapconn, $sr);
+        $userdn = $info[0]["dn"];
+       } else {
+        ldap_error($ldapconn);
+       }
+      }
+      ldap_unbind($ldapconn);
      $this->SearchType = "nonproxy";
     }
+    }
     return $userdn;
  }
Comment 93 Ryan Lane 2006-02-22 19:10:10 UTC
Created attachment 1412 [details]
Version 1.0d of the LdapAuthentication.php Plugin (for Mediawiki 1.5)

This is a bugfix version of the plugin. 

This should address comments #90-92. It also fixes an issue where even if local
authentication was chosen, the plugin would try to authenticate to the LDAP
server. Notice that if you are trying to create local accounts, it will still
try to contact the LDAP server (this is so that people cannot create local
accounts with the same name as LDAP users). It also fixes a bug with proxy
authentication, where if the plugin was misconfigured just the right way, it
would let users in without authenticating (you'd notice this if it was
happening...).

The code was partially refactored. It was cleaned up quite a bit, and the way
proxy authentication was being done is now different (it was being done in a
very asinine way before). It should be a transparent change though. It does
allow you to use $wgLDAPSearchStrings and $wgLDAPBaseDN together (although
there still isn't much reason to do it).

I have not yet added variables for preference attributes, but I plan on getting
to that next release.
Comment 94 Ryan Lane 2006-02-22 19:17:01 UTC
(In reply to comment #92)
> Sorry, I think these changes should address your concerns.  If the search fails
> (or bad anonymous/proxy bind occurs), then the function will kick out the
> original DN with the replaced USER-NAME string just like the original function
did.

Well, it really doesn't. These changes don't really add anything the plugin
doesn't already do. What you were adding, is done when you do a proxy search.
I've refactored my code, and it should be a little more apparent what I'm doing
in the newest version. You can get the functionality you want, by doing a proxy
search instead of a straight bind.

Look at the configuration options at:
http://meta.wikimedia.org/wiki/LDAP_Authentication_Configuration_Examples#Single_Domain_Requiring_Proxyagent_Binding

It'll do what you need. Just leave out "$wgLDAPProxyAgent" and
"$wgLDAPProxyAgentPassword" for anonymous searches. If for some reason, I'm just
not understanding how my plugin isn't doing exactly what your code is doing
above, let me know.
Comment 95 Neil M 2006-02-23 02:31:26 UTC
Ok, that looks good except getUserDN() needs a line that reads "global
$wgLDAPBaseDNs;"  Also it wasn't clear in the documentation what the difference
between using $wgLDAPBaseDNs and $wgLDAPSearchStrings is.  I'm not using a
Proxyagent so I never looked in that section where $wgLDAPBaseDNs is referenced
until now.
Comment 96 Hackeron 2006-02-23 02:45:04 UTC
Cant get this to work with enotifWiki 3.60 + MediaWiki 1.5.6 - I get:

Warning: Missing argument 1 for inituser() in
/var/www/mediawiki1.5.6+enotifwiki3.60/includes/LdapAuthentication.php on line 484

Fatal error: Call to a member function on a non-object in
/var/www/mediawiki1.5.6+enotifwiki3.60/includes/LdapAuthentication.php on line 491

Any ideas?
Comment 97 T. Gries 2006-02-23 05:38:27 UTC
(In reply to comment #96)
> Cant get this to work with enotifWiki 3.60 + MediaWiki 1.5.6 - I get:
> 
> Warning: Missing argument 1 for inituser() in
> /var/www/mediawiki1.5.6+enotifwiki3.60/includes/LdapAuthentication.php on line 484
> Fatal error: Call to a member function on a non-object in
> /var/www/mediawiki1.5.6+enotifwiki3.60/includes/LdapAuthentication.php on line 491

Please keep in mind, that questions regarding EnotifWiki should perhaps better
be placed on the page on http://www.enotifwiki.org in order not to disturb the
main development line of MediaWiki.

In your case I am still not sure why this problem came up, but EnotifWiki has
not been tested together with LdapAuthentication and has another method built in
see [1] which perhaps can be adapted to work with LdapAuthentication. Sorry for
this limited help.

[1] http://bugzilla.wikipedia.org/show_bug.cgi?id=1360 Auto-login /
Auto-account-creation by hostname for intranet MediaWikis
Comment 98 Ryan Lane 2006-03-03 00:00:09 UTC
Created attachment 1426 [details]
Version 1.0e of the LdapAuthentication.php Plugin (for Mediawiki 1.5)

This is the latest version of the LdapAuthentication plugin.

This fixes comment #95, which was introduced with plugin version 1.0d, and may
affect proxy-style logins.
Comment 99 Mario 2006-03-10 09:30:24 UTC
I have a problem: When I change the password of a user in AD I can logon in
MediaWiki with the new and the old password. Can anyone help me?
Comment 100 Jonathan King 2006-03-13 17:11:42 UTC
Has anybody noticed that the version number of the attached files are wrong?
Presently, the version 1.0e link is to a file that has a version 1.0a notice
inside. Ryan, I assume that you are the one to update this in the future? When
1.0f comes around, can you update the internal documentation please? Thanks for
a great addition!
Comment 101 Ryan Lane 2006-03-14 00:21:35 UTC
(In reply to comment #99)
> I have a problem: When I change the password of a user in AD I can logon in
> MediaWiki with the new and the old password. Can anyone help me?

This may be a bug. The wiki may be saving the user's password in the database
(it shouldn't be). Please post this on the talk page at meta (follow the URL at
the top of this page), so that we can debug it and see if this is a bug or not.
Comment 102 Mike Vonderbecke 2006-03-22 17:50:57 UTC
I'm having some problems getting Group authentication working with Active
Directory on a Windows 2000 domain.  I've hacked the code per the documentation
and set up my wgLDAPGroupDN variable to be
"CN=wikitest,CN=Users,DC=ourdomain,DC=com" (where ourdomain obviously is the
actual value).

Every time I try to log in I get an error that the password is missing or
incorrect.  This is on a user that was already able to login via LDAP
Authentication prior to turning on group auth.  I double checked that the User
is a member of the wikitest group, I also double checked the distinguishedname
of both the group and the user using the ADSIEdit program that comes with W2k
server and they match up.

Any ideas as to why I'm having a problem?  I have 1.0e.
Comment 103 Ryan Lane 2006-03-22 19:21:49 UTC
(In reply to comment #102)
> I'm having some problems getting Group authentication working with Active
> Directory on a Windows 2000 domain.  I've hacked the code per the documentation
> and set up my wgLDAPGroupDN variable to be
> "CN=wikitest,CN=Users,DC=ourdomain,DC=com" (where ourdomain obviously is the
> actual value).
> 
> Every time I try to log in I get an error that the password is missing or
> incorrect.  This is on a user that was already able to login via LDAP
> Authentication prior to turning on group auth.  I double checked that the User
> is a member of the wikitest group, I also double checked the distinguishedname
> of both the group and the user using the ADSIEdit program that comes with W2k
> server and they match up.
> 
> Any ideas as to why I'm having a problem?  I have 1.0e.

Please use the discussion page on the LDAP Authentication page at meta. This is
not a support forum.
Comment 104 Ryan Lane 2006-03-22 23:04:23 UTC
While we are on the topic of group authentication. Justin Grote mentioned he was
going to be working on a better solution for this. I haven't heard anything back
from him (this was January 29th). If anyone knows what the status of that is,
please post it.

It seems we have a need for updated code, and if he isn't working on it I'll
start working on it.
Comment 105 Don Seiler 2006-04-07 16:22:00 UTC
Has anyone got this working with mediawiki 1.6?  We just upgraded and
authentication always fails now.

We're authenticating against AD, worked fine with 1.5.5.
Comment 106 Don Seiler 2006-04-07 16:23:41 UTC
Just noticed this error at the top of the page after auth failure as well:

<b>Warning</b>:  Compilation failed: characters with values > 255 are not yet
supported in classes at offset 33 in
<b>/usr/local/mediawiki-1.6.1/includes/User.php</b> on line <b>224</b><br />
Comment 107 Don Seiler 2006-04-07 16:41:57 UTC
(In reply to comment #106)
> Just noticed this error at the top of the page after auth failure as well:
> 
> <b>Warning</b>:  Compilation failed: characters with values > 255 are not yet
> supported in classes at offset 33 in
> <b>/usr/local/mediawiki-1.6.1/includes/User.php</b> on line <b>224</b><br />
> 

This was due to a PHP/unicode/preg_match() issue, unrelated to LDAP auth.  I
commented out that block of code and LDAP auth still fails, but the error goes
away :p
Comment 108 Don Seiler 2006-04-07 17:12:38 UTC
(In reply to comment #105)
> Has anyone got this working with mediawiki 1.6?  We just upgraded and
> authentication always fails now.
> 
> We're authenticating against AD, worked fine with 1.5.5.


GAH don't mind me.  This is a case of too many things changing at once and too
many cooks.  Other admin updated to new version of LdapAuthentication, and proxy
binding wasn't being done there.  Reverted to older version of
LdapAuthentication.php and all works fine.  I'll have to look at configs for new
version to see what is different.
Comment 109 Jared Greenwald 2006-04-07 18:03:32 UTC
I tired the .8 patch for my 1.4.15 config and I can't seem to get it working. 
I'm not even sure its setup correctly.  I followed the examples in found in the
wiki, but when I try using an ldap uid to login, it fails.
Comment 110 Ryan Lane 2006-04-12 21:16:27 UTC
(In reply to comment #109)
> I tired the .8 patch for my 1.4.15 config and I can't seem to get it working. 
> I'm not even sure its setup correctly.  I followed the examples in found in the
> wiki, but when I try using an ldap uid to login, it fails.

I gotta be honest. I probably don't remember how to setup version .8 with
mediawiki 1.4. I'd have to look back at my old code. I've dropped support for
version .8 and mediawiki 1.4. If you can, upgrade your wiki to 1.5 or 1.6
series, the documentation for that is good.
Comment 111 Hang Xie 2006-04-22 21:47:29 UTC
It will be great if user can choose the way for hashing password in LDAP.

fyi, i'm trying to integrate mediawiki with my existing LDAP, SHA generated by
this plugin will break an existing application as it knows CRYPT only.

i added a new configuration, $wgLDAPPasswordHash to get this works, here is the
diff to 1.0e:

232c232,233
<
---
>               global $wgLDAPPasswordHash;
>
241,242c242,255
<               $pwd_md5 = base64_encode(pack('H*',sha1($password)));
<               $pass = "{SHA}".$pwd_md5;
---
>
>               switch ($wgLDAPPasswordHash) {
>                       case 'crypt':
>                               $pass = '{CRYPT}' . crypt($password);
>                               break;
>                       case 'clear':
>                               $pass = $password;
>                               break;
>                       default:
>                               $pwd_md5 =
base64_encode(pack('H*',sha1($password)));
>                               $pass = "{SHA}".$pwd_md5;
>                               break;
>               }
>

more hashing can be added but i will just leave it there.
Comment 112 Ryan Lane 2006-04-23 00:11:24 UTC
(In reply to comment #111)
> It will be great if user can choose the way for hashing password in LDAP.
> 
> fyi, i'm trying to integrate mediawiki with my existing LDAP, SHA generated by
> this plugin will break an existing application as it knows CRYPT only.
> 
> i added a new configuration, $wgLDAPPasswordHash to get this works, here is the
> diff to 1.0e:
> 
> 232c232,233
> <
> ---
> >               global $wgLDAPPasswordHash;
> >
> 241,242c242,255
> <               $pwd_md5 = base64_encode(pack('H*',sha1($password)));
> <               $pass = "{SHA}".$pwd_md5;
> ---
> >
> >               switch ($wgLDAPPasswordHash) {
> >                       case 'crypt':
> >                               $pass = '{CRYPT}' . crypt($password);
> >                               break;
> >                       case 'clear':
> >                               $pass = $password;
> >                               break;
> >                       default:
> >                               $pwd_md5 =
> base64_encode(pack('H*',sha1($password)));
> >                               $pass = "{SHA}".$pwd_md5;
> >                               break;
> >               }
> >
> 
> more hashing can be added but i will just leave it there.

I'm probably wrong, but... Don't all passwords have to be base64 encoded in LDAP?
Comment 113 Ryan Lane 2006-04-23 00:12:21 UTC
(In reply to comment #111)
> It will be great if user can choose the way for hashing password in LDAP.
> 
> fyi, i'm trying to integrate mediawiki with my existing LDAP, SHA generated by
> this plugin will break an existing application as it knows CRYPT only.
> 
> i added a new configuration, $wgLDAPPasswordHash to get this works, here is the
> diff to 1.0e:
> 
> 232c232,233
> <
> ---
> >               global $wgLDAPPasswordHash;
> >
> 241,242c242,255
> <               $pwd_md5 = base64_encode(pack('H*',sha1($password)));
> <               $pass = "{SHA}".$pwd_md5;
> ---
> >
> >               switch ($wgLDAPPasswordHash) {
> >                       case 'crypt':
> >                               $pass = '{CRYPT}' . crypt($password);
> >                               break;
> >                       case 'clear':
> >                               $pass = $password;
> >                               break;
> >                       default:
> >                               $pwd_md5 =
> base64_encode(pack('H*',sha1($password)));
> >                               $pass = "{SHA}".$pwd_md5;
> >                               break;
> >               }
> >
> 
> more hashing can be added but i will just leave it there.

I'm probably wrong, but... Don't all passwords have to be base64 encoded in
LDAP? I like the patch otherwise, and I'll include it in the next version of the
plugin.
Comment 114 Kevin Grinberg 2006-05-10 20:56:46 UTC
Something I noticed: in userExists, $wgLDAPBaseDN is defined (global) but never
used... which is good, because unless I'm mistaken, it should be $wgLDAPBaseDNs
(note the "s" at the end...)

Am I missing something, or is this a bug waiting to happen?
Comment 115 Ryan Lane 2006-05-10 21:02:59 UTC
(In reply to comment #114)
> Something I noticed: in userExists, $wgLDAPBaseDN is defined (global) but never
> used... which is good, because unless I'm mistaken, it should be $wgLDAPBaseDNs
> (note the "s" at the end...)
> 
> Am I missing something, or is this a bug waiting to happen?

This must be a variable left in from the pre 1.0 days. I *thought* I cleaned out
all of the unused globals, but it looks like I missed one. I'll check my
functions again and clean out unused variables for next release.
Comment 116 Ryan Lane 2006-07-05 03:51:07 UTC
Created attachment 2050 [details]
Version 1.0f of the LdapAuthentication.php Plugin (for Mediawiki 1.5-1.7)

This is a (mostly) bugfix version of the plugin.

Fixed the version number at the top of the file.
Fixed the preferences bug from: Talk:LDAP Authentication#Problem with
preferences from LDAP
Added function in for changing usernames to lowercase to fix:
Talk:LDAP_Authentication#Username_modified_.28capital_letter.29.2C_authentication_fails
(only works in versions 1.6+)
Added debugging code (let me know what extra debugging info you want, or if
some things should be showing at a different debug level)
Cleaned out unused global variables
Added the password switching statement from #111 in this bug (notice I added it
for changing passwords, and for creating users)
Fixed an undeclared global variable $wgLDAPWriteLocation in addUsers
Added the ability to use TLS as well as LDAPS (I'm not 100% sure this is
working, let me know!)

Updated documentation at the normal place will follow soon.
Comment 117 Ryan Lane 2006-08-12 01:14:59 UTC
Created attachment 2218 [details]
Version 1.0g of the LdapAuthentication.php Plugin (for Mediawiki 1.5-1.7)

This update offers a new group based authentication check and deprecates the
old included one. The new check allows for nested groups, and can search groups
either as a proxyagent, or as the user who is authenticating. Documentation to
follow soon on meta at the normal place.
Comment 118 Buchan Milne 2006-08-16 16:35:03 UTC
I had a problem with the current patch where the filter for checking group
memberships (in the attribute value is username case) was using the uppercased
username, which did not match.

I've hacked it at line 212 to have:


                        if ($wgLDAPRequiredGroups[$_SESSION['wsDomain']]) {
                                $ldapusername = $username;
                                $ldapusername[0] = strtolower($ldapusername[0]);
                                $this->printDebug("Checking for (new style)
group membership",1);

                                if ($wgLDAPGroupUseFullDN[$_SESSION['wsDomain']]) {
                                        $inGroup =
$this->isMemberOfRequiredLdapGroup($ldapconn, $userdn);
                                } else {
                                        $inGroup =
$this->isMemberOfRequiredLdapGroup($ldapconn, $ldapusername);
                                }
Comment 119 Gunter Schmidt 2006-08-22 11:39:09 UTC
We have a similiar case problem with the groups checking.

Using:

$wgLDAPRequiredGroups = array( "REF-EDIR"=>array("cn=lht-wiki,ou=adg,ou=roles (pw),ou=LH,o=LH-DIR") );

will not find any groups, giving "Couldn't find the user in any groups (2)."

The LDAP Server returns the groups correctly, but in lower case ... ou=lh, o=lh-dir.

After changing the line to

$wgLDAPRequiredGroups = array( "REF-EDIR"=>array("cn=lht-wiki,ou=adg,ou=roles (pw),ou=lh,o=lh-dir") );

all works out fine.

Thanks for implementing the proxy user so fast.
Comment 120 Ryan Lane 2006-08-22 17:44:26 UTC
(In reply to comment #119)
> We have a similiar case problem with the groups checking.Using:$wgLDAPRequiredGroups = array( "REF-EDIR"=>array
("cn=lht-wiki,ou=adg,ou=roles (pw),ou=LH,o=LH-DIR") );will not find any groups, giving "Couldn't find the user in any 
groups (2)."The LDAP Server returns the groups correctly, but in lower case ... ou=lh, o=lh-dir.After changing the 
line to$wgLDAPRequiredGroups = array( "REF-EDIR"=>array("cn=lht-wiki,ou=adg,ou=roles (pw),ou=lh,o=lh-dir") );all 
works out fine.Thanks for implementing the proxy user so fast.

This is done on purpose. I do a tolower on the returned groups in the function getGroups. LDAP is case insensitive, 
and PHP is not, it should be impossible to enter both cn=group and cn=Group, so to avoid weird matching problems, I 
make sure everything is lowercase.

I guess I should update my documentation to inform people of this right? ;)

In response to #118. I don't see where I'm matching anywhere for usernames; LDAP is case insensitive on this matter, 
so it shouldn't be an issue for the username to be cased. I'll look a little harder, but I won't make this change 
just yet.
Comment 121 Buchan Milne 2006-08-23 07:11:19 UTC
Right, I should have included a bit more information on my group setup, which is using the 
nis.schema/posixAccount/posixGroup-type stuff, so I have:

$wgLDAPRequiredGroups = array( "mycontext"=>array("cn=build,ou=group,dc=mydomain,dc=com") );
$wgLDAPGroupUseFullDN = array( "mycontext"=>false );
$wgLDAPGroupObjectclass = array( "mycontext"=>"posixGroup" );
$wgLDAPGroupAttribute = array( "mycontext"=>"memberUid" );
$wgLDAPGroupSearchNestedGroups = array( "mycontext"=>false );

memberUid (according to nis.schema - and rfc2307bis seems to be the same) is:
attributetype ( 1.3.6.1.1.1.1.12 NAME 'memberUid'
        EQUALITY caseExactIA5Match
        SUBSTR caseExactIA5SubstringsMatch
        SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )

So, for the memberUid attribute, case does matter:

[bgmilne@comanche ~]$ ldapsearch -LLL -x "(memberUid=bgmilne)" dn
dn: cn=sysadmins,ou=Group,dc=mydomain,dc=com

dn: cn=build,ou=Group,dc=mydomain,dc=com

[bgmilne@comanche ~]$ ldapsearch -LLL -x "(memberUid=Bgmilne)" cn
[bgmilne@comanche ~]$


"LDAP is case insensitive" is an invalid generalisation, some attributes, such as dn, are case insensitive, but this 
doesn't mean that all attributes are. Eg, the uid attribute is case insentitive, and usually the same string appears 
in the memebrUid attribute, but this attribute is case sensitive.

Since the group membership attribute is configurable, it could be case sensitive, so case should be preserved (at 
least in the $wgLDAPGroupUseFullDN=false case) when doing group membership checks. The question is which case to 
preserve (the one the user entered, or the result of a search), the result of the search would probably be best.

(I should probably consider migrating to rfc2307bis where member attribute is the dn, but ... a lot of people still 
use nis.schema).

I'll look at doing a better fix for this and supplying a patch.
Comment 122 Ryan Lane 2006-08-23 14:50:08 UTC
(In reply to comment #121)
> "LDAP is case insensitive" is an invalid generalisation, some attributes, such
as dn, are case insensitive, but this 
> doesn't mean that all attributes are. Eg, the uid attribute is case
insentitive, and usually the same string appears 
> in the memebrUid attribute, but this attribute is case sensitive.
> 

[snip]

> (I should probably consider migrating to rfc2307bis where member attribute is
the dn, but ... a lot of people still 
> use nis.schema).
> 
> I'll look at doing a better fix for this and supplying a patch.

Sorry about the generalization. I usually leave out the part about "for specific
attributes". I thought I had taken into account for nis.schema, but it looks
like Sun's nis schema is different from openldap's nis schema, and I'm using Sun
Directory Server with the nis schema. (Thanks Sun for screwing me again, I
looked at the RFC and it DOES indeed say caseExactIA5Match).

No need to send in a patch. This fix only really has to do with groups, so I'll
add it into "isMemberOfRequiredLdapGroup". 
Comment 123 Gunter Schmidt 2006-08-23 16:38:17 UTC
moving to our production environment, I have a serious performance problem.

The group check takes about 4 Minutes. I included the debug listing, where I added a time stamp.

Search string: (&(member=cn=X1234,ou=HAM,ou=LHT,ou=LH,o=LH-DIR)(objectclass=groupofnames))Wed, 23 Aug 2006 18:12:48
Binding as the proxyagentDN Wed, 23 Aug 2006 18:12:48 +0200
Binding finished Wed, 23 Aug 2006 18:12:48 +0200
Returned groups:cn=role-hamtisfa,ou=governor,ou=roles (pw),ou=lh,o=lh-dir,cn=wlan,ou=applications,ou=roles 
(pw),ou=lh,o=lh-dir, --- snip --- Wed, 23 Aug 2006 18:17:07 +0200
GroupCount = 14
Found user in a group. Wed, 23 Aug 2006 18:17:07 +0200

Has anybody noticed similar problems or is this a configuration problem of our LDAP-Server?


Comment 124 Ryan Lane 2006-08-23 18:29:29 UTC
(In reply to comment #123)
> moving to our production environment, I have a serious performance problem.The group check takes about 4 Minutes. I 
included the debug listing, where I added a time stamp.Search string: (&(member=cn=X1234,ou=HAM,ou=LHT,ou=LH,o=LH-DIR)
(objectclass=groupofnames))Wed, 23 Aug 2006 18:12:48Binding as the proxyagentDN Wed, 23 Aug 2006 18:12:48 
+0200Binding finished Wed, 23 Aug 2006 18:12:48 +0200Returned groups:cn=role-hamtisfa,ou=governor,ou=roles 
(pw),ou=lh,o=lh-dir,cn=wlan,ou=applications,ou=roles (pw),ou=lh,o=lh-dir, --- snip --- Wed, 23 Aug 2006 18:17:07 
+0200GroupCount = 14Found user in a group. Wed, 23 Aug 2006 18:17:07 +0200Has anybody noticed similar problems or is 
this a configuration problem of our LDAP-Server?

Support requests should be added to the talk page of the meta article. I'll copy and paste it into there with my 
response. This is for bugs and patches only.
Comment 125 Douglas Pace 2006-09-05 18:04:43 UTC
(In reply to comment #70)
> Created an attachment (id=1036) [edit]
> Patch to 1.0.a for require attribute
> 
> This is a restructured version of the first patch submitted to add support for
> requiring a user to have a certain attribute to finish authenticating to the
> wiki. It now properly handles the case where no proxy user is allowed, nor is
> an anonymous search allowed.

First let me say I love this feature but I have a suggestion about it. I
currently have need to use the AuthAttribute to filter based on a protected
attribute in LDAP, specifically class enrollment. 

I have two options. One is a proxy user, which is highly frowned upon because of
security and clear text passwords in world readable files, etc. The second is to
only check the attribute after binding as the user, which seems to be a better
solution anyway. But currently the AuthAttribute is checked twice. Once in
getUserDN as either anonymous or as the proxy user(which is where this breaks in
this situation) and again after the user binds. I understand this first check
does save work on users who don't have the attribute, but it doesn't seem as
robust since the user themselves will almost always have more access than
anonymous and possibly even more than the proxy user?

--- LdapAuthentication-1.0g.php 2006-09-05 11:01:41.665817575 -0700
+++ LdapAuthentication.php      2006-09-05 10:59:04.722809051 -0700
@@ -693,18 +693,8 @@ class LdapAuthenticationPlugin extends A
                }

                //we need to do a subbase search for the entry
-
-               //Why waste a bind later, if a user is missing an auth attribute
-               //let's catch it here.
-               if ($wgLDAPRequireAuthAttribute) {
-                       $auth_filter = "(" .
$wgLDAPAuthAttribute[$_SESSION['wsDomain']] . ")";
-                       $srch_filter = "(" .
$wgLDAPSearchAttributes[$_SESSION['wsDomain']] . "=$username)";
-                       $filter = "(&" . $srch_filter . $auth_filter . ")";
-                       $this->printDebug("Created an auth attribute filter:
$filter",2);
-               } else {
-                       $filter = "(" .
$wgLDAPSearchAttributes[$_SESSION['wsDomain']] . "=$username)";
-                       $this->printDebug("Created a regular filter: $filter",2);
-               }
+               $filter = "(" . $wgLDAPSearchAttributes[$_SESSION['wsDomain']] .
"=$username)";
+               $this->printDebug("Created a regular filter: $filter",2);

                $attributes = array("dn");
                 $base = $wgLDAPBaseDNs[$_SESSION['wsDomain']];
Comment 126 Thomas Clavier 2006-10-08 20:41:16 UTC
in setPassword function, to not eraze password, we can change :
$pass = $this->getPasswordHash($pass);
by 
$pass = $this->getPasswordHash($password);
Comment 127 Ryan Lane 2006-10-10 13:15:56 UTC
(In reply to comment #126)
> in setPassword function, to not eraze password, we can change :
> $pass = $this->getPasswordHash($pass);
> by 
> $pass = $this->getPasswordHash($password);


Wow, now *there* is a real for deal bug. I don't know how this ever worked (and
I know I tested it at one point). Good catch, this will be fixed next release.
Comment 128 Hermann Gottschalk 2006-10-27 09:18:19 UTC
(In reply to comment #122)
> (In reply to comment #121)
> > "LDAP is case insensitive" is an invalid generalisation, some attributes, such
> as dn, are case insensitive, but this 
> > doesn't mean that all attributes are. Eg, the uid attribute is case
> insentitive, and usually the same string appears 
> > in the memebrUid attribute, but this attribute is case sensitive.
> > 
> 
> [snip]
> 

> No need to send in a patch. This fix only really has to do with groups, so I'll
> add it into "isMemberOfRequiredLdapGroup". 

When will this adjustment be made? Meanwhile i did a dirty hack, which only
works for our environment...
Comment 129 Ryan Lane 2006-10-28 20:08:58 UTC
(In reply to comment #128)
> When will this adjustment be made? Meanwhile i did a dirty hack, which only
> works for our environment...

Sorry, I've been out of the country, and my laptop was broken, so I haven't had
much of a chance to work on this. Hopefully I'll have a new release soon. I'll
try to have one out in the next couple of weeks.
Comment 130 Manuel Schneider 2006-11-09 15:47:34 UTC
Little problem:

The first login throws an error "Fatal error: Call to a member function on a
non-object in /srv/www/htdocs/wiki/includes/SpecialUserlogin.php on line 320".

Later logins work without problems. Is there a possibility to get rid of this
error message?

Concerning versions:
- MediaWiki 1.6.8
- mod_php4
Comment 131 Ryan Lane 2006-11-09 15:55:50 UTC
(In reply to comment #130)
> Little problem:The first login throws an error "Fatal error: Call to a member function on anon-object 
in /srv/www/htdocs/wiki/includes/SpecialUserlogin.php on line 320".Later logins work without problems. Is there a 
possibility to get rid of thiserror message?Concerning versions:- MediaWiki 1.6.8- mod_php4

I'm using the same setup and not having that problem. I also don't manage SpecialUserlogin.php, you'll need to put a 
new bug report in if you believe there is a bug in that class.

You may just have a configuration error. If you need support, please post your question on the discussion page for 
the plugin's documentation on meta.
Comment 132 Ryan Lane 2006-11-13 22:54:48 UTC
Created attachment 2697 [details]
Version 1.0h of the LdapAuthentication.php Plugin (for Mediawiki 1.5+)

This is a bugfix version of the plugin. The following fixes have been made:

# Comment #118 (lowercasing the username in the groups checking)
# Comment #125 (redundant auth attr check)
# Comment #126 (setPassword function erasing the user's password in LDAP)

In regards to the fix for comment #125: This fix disabled the check, it did not
remove it. If you would like to re-enable it for performance reasons, just
uncomment the section that was commented.

In regards to the fix for comment #118: The fix proposed may have caused issues
with other users who need case sensitive searches. I've added the fix as a
boolean option ($wgLDAPGroupLowerCaseUsername).
Comment 133 Clemens Steinkogler 2006-11-16 10:08:35 UTC
I have problems with the group authentication, can anybody please help? My LDAP section looks like this:

<code>
 # LDAP
 require_once( 'LdapAuthentication.php' );
 $wgAuth = new LdapAuthenticationPlugin();
 $wgLDAPDomainNames = array("olymp");
 $wgLDAPServerNames = array("olymp"=>"neptun.xxx.yyy.at");
 $wgLDAPSearchStrings = array("olymp"=>"OLYMP\USER-NAME");
 $wgLDAPSearchAttributes = array("olymp"=>"sAMAccountName");
 $wgLDAPUseSSL = false;
 $wgLDAPUseLocal = false;
 $wgMinimalPasswordLength = 1;
 $wgLDAPRetrievePrefs = false;
 
 # GROUP AUTHENICATION
 $wgLDAPRequiredGroups = array( "olymp"=>array("cn=standby,ou=test,dc=neptun,dc=xxx,dc=yyy,dc=at") );
 $wgLDAPGroupUseFullDN = array( "olymp"=>true );
 $wgLDAPGroupObjectclass = array( "olymp"=>"group" );
 $wgLDAPGroupAttribute = array( "olymp"=>"member" );
 $wgLDAPGroupSearchNestedGroups = array( "olymp"=>false );
 $wgLDAPBaseDNs = array( "olymp"=>"dc=neptun,dc=xxx,dc=yyy,dc=at" );
 
 $wgGroupPermissions['*']['createaccount'] = false;
 $wgGroupPermissions['*']['edit'] = false;
 $wgWhitelistRead = array("Hauptseite","Spezial:Userlogin", "-","MediaWiki:Monobook.css");
 $wgGroupPermissions['*']['read'] = false;
 $wgShowIPinHeader = true;
</code>

Our Windows 2000 Server "neptun" with active directory has an OU "test" with a group "standby". I'm now member of the 
group "standby". If I now want to log in to the wiki there appears following error:

<b>Warning</b>:  ldap_get_entries(): supplied argument is not a valid ldap result resource in 
<b>/var/www/standby/includes/LdapAuthentication.php</b> on line <b>857</b><br />
<br />
<b>Warning</b>:  array_shift() function.array-shift: The argument should be an array in 
<b>/var/www/standby/includes/LdapAuthentication.php</b> on line <b>860</b><br />
<br />
<b>Warning</b>:  Invalid argument supplied for foreach() in <b>/var/www/standby/includes/LdapAuthentication.php</b> 
on line <b>863</b><br />
Password wrong: blabla

So what could be wrong here. I can imagine that it's something small but I'm trying now for days and can't find the 
error. Without groupauthenication it works. Hope that it is allowed to post this here. Thanks for any help.
Comment 134 Ryan Lane 2006-11-16 14:40:37 UTC
(In reply to comment #133)
> I have problems with the group authentication, can anybody please help? My
LDAP section looks like this:

[snip]

I don't know how many times I (and others) have to write this here, but this
bugzilla page is *NOT* a support forum, it is for bugs and release information
only!!

There are at least a couple places you can ask this question. One is on the
discussion page of the LDAP Authentication article on meta, the other is on the
Mediawiki Enterprise list:

http://mail.wikimedia.org/mailman/listinfo/mediawiki-enterprise

I've even been occasionally known to answer questions on the mediawiki-l list as
well (although I don't like to bug everyone else there with LDAP support issues).

I'll give support on one of those places, but not here. When you post your
question in the correct place, make sure you give debug information as well
using $wgLDAPDebug = 4, making sure to snip out any sensitive information. Also
include the version of mediawiki, and the version of the plugin you are using.
Comment 135 Alfons Zitterbacke 2006-11-29 15:47:04 UTC
Hi,

this is patch agains 1.0e (LdapPlugin from April 2006).
It adds ldap group support to mediawiki, where a ldap group overrides any
membership setting of a local group.
this is useful for example for restricted namespaces.

sincerly,
mbraun

*** LdapAuthentication.php.bck	Wed Nov 29 12:49:38 2006
--- LdapAuthentication.php	Wed Nov 29 16:25:04 2006
***************
*** 44,50 ****
  require_once( 'AuthPlugin.php' );
  
  class LdapAuthenticationPlugin extends AuthPlugin {
! 	var $email, $lang, $realname, $nickname, $SearchType;
  	/**
  	 * Check whether there exists a user account with the given name.
  	 * The name will be normalized to MediaWiki's requirements, so
--- 44,50 ----
  require_once( 'AuthPlugin.php' );
  
  class LdapAuthenticationPlugin extends AuthPlugin {
! 	var $email, $lang, $realname, $nickname, $SearchType, $groups, $allLdapGroups;
  	/**
  	 * Check whether there exists a user account with the given name.
  	 * The name will be normalized to MediaWiki's requirements, so
***************
*** 155,161 ****
--- 155,165 ----
  		global $wgLDAPProxyAgent;
  		global $wgLDAPGroupDN;
  		global $wgLDAPRequireAuthAttribute, $wgLDAPAuthAttribute;
+ 		global $wgLDAPGrpBase;
  		
+ 		$this->groups=Array();
+ 		$this->allLdapGroups=Array();
+ 
  		if ( '' == $password ) {
  			return false;
  		}
***************
*** 183,189 ****
  				if ($info["count"] < 1) { return false; }
                          }
  			if ($wgLDAPGroupDN) {
! 				return $this->isMemberOfLdapGroup($ldapconn, $userdn, $wgLDAPGroupDN);
  			}
  			if ($wgLDAPRetrievePrefs) {
  				$entry = @ldap_read($ldapconn, $userdn, "objectclass=*");
--- 187,194 ----
  				if ($info["count"] < 1) { return false; }
                          }
  			if ($wgLDAPGroupDN) {
! 				if (! $this->isMemberOfLdapGroup($ldapconn, $userdn, $wgLDAPGroupDN))
! 					return false;
  			}
  			if ($wgLDAPRetrievePrefs) {
  				$entry = @ldap_read($ldapconn, $userdn, "objectclass=*");
***************
*** 193,198 ****
--- 198,225 ----
  				$this->nickname = $info[0]["displayname"][0];
  				$this->realname = $info[0]["cn"][0];
  			}
+ 
+ 			// get groups
+ 		        $grpRes = ldap_search($ldapconn,
$wgLDAPGrpBase[$_SESSION[wsDomain]],
"memberUid=".strtolower($username)."",Array("cn"));
+ 			for ($entryID=ldap_first_entry($ldapconn,$grpRes);
+ 			      $entryID!=false;
+ 		              $entryID=ldap_next_entry($ldapconn,$entryID))
+ 			      {
+ 			      $cGroup = ldap_get_values($ldapconn,$entryID,'cn');
+ 			      $cGroup=$cGroup[0];
+ 			      $this->groups[] = $cGroup;
+ 			      }
+ 
+ 			$grpRes = ldap_search($ldapconn, $wgLDAPGrpBase[$_SESSION[wsDomain]],
"objectClass=posixGroup",Array("cn"));
+ 			for ($entryID=ldap_first_entry($ldapconn,$grpRes);
+ 				$entryID!=false;
+ 				$entryID=ldap_next_entry($ldapconn,$entryID))
+ 				{
+ 				$cGroup = ldap_get_values($ldapconn,$entryID,'cn');
+ 				$cGroup=$cGroup[0];
+ 				$this->allLdapGroups[] = $cGroup;
+ 				}
+ 
  			// Lets clean up.
  			@ldap_unbind();
                  } else {
***************
*** 450,457 ****
--- 477,512 ----
  		if ('' != $this->email) {
                  	$user->setEmail($this->email);
  		}
+ 		# add groups permissions
+ 		$localAvailGrps = $user->getAllGroups();
+ 		$localUserGrps = $user->getEffectiveGroups();
+ 		# note: $localUserGrps does not need to be updated with $cGroup added,
+ 		#       as $localAvailGrps contains $cGroup only once.
+ 		foreach ($localAvailGrps as $cGroup) {
+ 			# did we once add the user to the group?
+ 			if (in_array($cGroup,$localUserGrps)) { 
+ 			   if ((!$this->hasLDAPGroup($cGroup)) && ($this->isLDAPGroup($cGroup))) {
+ 			      # die LDAP Gruppe überschreibt die lokale Gruppe
+ 			      # d.h. wenn sie existiert, und der user nicht enthlaten ist, dann
muss er auch aus der wiki grp raus
+ 			      $user->delGroup($cGroup);
+ 			      }
+ 			} else { # no, but maybe the user has just been added to the group
+ 				if ($this->hasLDAPGroup($cGroup)) {
+ 					# so use the addGroup function
+ 					$user->addGroup($cGroup);
+ 					# completedfor $cGroup.
+ 				}
+ 			}
+ 		}
          }
  
+ 	function hasLDAPGroup($group) {
+ 		return in_array($group, $this->groups);
+ 	}
+ 
+ 	function isLDAPGroup($group) {
+ 		return in_array($group, $this->allLdapGroups);
+ 	}
  	/**
  	 * Return true to prevent logins that don't authenticate here from being
  	 * checked against the local database's password fields.
***************
*** 553,559 ****
  			}
  		}
  		//we need to do a subbase search for the entry
! 		$filter = "(member=".$userDN.")";
  		$info=ldap_get_entries($ldapconn,@ldap_search($ldapconn, $groupDN, $filter));
  		return ($info["count"]>=1);
  	}
--- 608,614 ----
  			}
  		}
  		//we need to do a subbase search for the entry
! 		$filter = "(memberUid=".$userDN.")";
  		$info=ldap_get_entries($ldapconn,@ldap_search($ldapconn, $groupDN, $filter));
  		return ($info["count"]>=1);
  	}
Comment 136 Alfons Zitterbacke 2006-11-29 15:50:09 UTC
My last patch introduces a new configuration option: $wgLDAPGrpBase : Array
(Domain => Ldap search base for groups).
The names posixGroup, memberUid, cn are currently fixed in code.
Comment 137 Ryan Lane 2006-11-29 16:00:59 UTC
(In reply to comment #135)
> Hi,
> 
> this is patch agains 1.0e (LdapPlugin from April 2006).
> It adds ldap group support to mediawiki, where a ldap group overrides any
> membership setting of a local group.
> this is useful for example for restricted namespaces.
> 
> sincerly,
> mbraun

Great work! I'm glad you've sent me a patch for this, because this was pretty
low on my hit-list. I'll take a look at the patch and rework it to be a little
more generic. I'll probably add some debugging info, and might change some of
the options to conform to the other options.

Is there any way you can translate the comments? I can't read german (that is
german right?).

I'm about to release a pretty big update to the plugin to add smartcard support,
so it may take me a while to integrate this (especially since this is a patch
against 1.0e...).

V/r,

Ryan Lane
Comment 138 Alfons Zitterbacke 2006-11-30 07:52:18 UTC
Hi,

okay, here is the patch with the english-only comments.
There are two comments added and the delGroup-function is actually named
removeGroup (bug fix).

sincerly,
 mbraun

*** LdapAuthentication.php.bck	Wed Nov 29 12:49:38 2006
--- LdapAuthentication.php	Thu Nov 30 08:47:58 2006
***************
*** 44,50 ****
  require_once( 'AuthPlugin.php' );
  
  class LdapAuthenticationPlugin extends AuthPlugin {
! 	var $email, $lang, $realname, $nickname, $SearchType;
  	/**
  	 * Check whether there exists a user account with the given name.
  	 * The name will be normalized to MediaWiki's requirements, so
--- 44,50 ----
  require_once( 'AuthPlugin.php' );
  
  class LdapAuthenticationPlugin extends AuthPlugin {
! 	var $email, $lang, $realname, $nickname, $SearchType, $groups, $allLdapGroups;
  	/**
  	 * Check whether there exists a user account with the given name.
  	 * The name will be normalized to MediaWiki's requirements, so
***************
*** 155,161 ****
--- 155,165 ----
  		global $wgLDAPProxyAgent;
  		global $wgLDAPGroupDN;
  		global $wgLDAPRequireAuthAttribute, $wgLDAPAuthAttribute;
+ 		global $wgLDAPGrpBase;
  		
+ 		$this->groups=Array();
+ 		$this->allLdapGroups=Array();
+ 
  		if ( '' == $password ) {
  			return false;
  		}
***************
*** 183,189 ****
  				if ($info["count"] < 1) { return false; }
                          }
  			if ($wgLDAPGroupDN) {
! 				return $this->isMemberOfLdapGroup($ldapconn, $userdn, $wgLDAPGroupDN);
  			}
  			if ($wgLDAPRetrievePrefs) {
  				$entry = @ldap_read($ldapconn, $userdn, "objectclass=*");
--- 187,194 ----
  				if ($info["count"] < 1) { return false; }
                          }
  			if ($wgLDAPGroupDN) {
! 				if (! $this->isMemberOfLdapGroup($ldapconn, $userdn, $wgLDAPGroupDN))
! 					return false;
  			}
  			if ($wgLDAPRetrievePrefs) {
  				$entry = @ldap_read($ldapconn, $userdn, "objectclass=*");
***************
*** 193,198 ****
--- 198,225 ----
  				$this->nickname = $info[0]["displayname"][0];
  				$this->realname = $info[0]["cn"][0];
  			}
+ 
+ 			// get information on ldap groups and this user group memberships
+ 		        $grpRes = ldap_search($ldapconn,
$wgLDAPGrpBase[$_SESSION[wsDomain]],
"memberUid=".strtolower($username)."",Array("cn"));
+ 			for ($entryID=ldap_first_entry($ldapconn,$grpRes);
+ 			      $entryID!=false;
+ 		              $entryID=ldap_next_entry($ldapconn,$entryID))
+ 			      {
+ 			      $cGroup = ldap_get_values($ldapconn,$entryID,'cn');
+ 			      $cGroup=$cGroup[0];
+ 			      $this->groups[] = $cGroup;
+ 			      }
+ 
+ 			$grpRes = ldap_search($ldapconn, $wgLDAPGrpBase[$_SESSION[wsDomain]],
"objectClass=posixGroup",Array("cn"));
+ 			for ($entryID=ldap_first_entry($ldapconn,$grpRes);
+ 				$entryID!=false;
+ 				$entryID=ldap_next_entry($ldapconn,$entryID))
+ 				{
+ 				$cGroup = ldap_get_values($ldapconn,$entryID,'cn');
+ 				$cGroup=$cGroup[0];
+ 				$this->allLdapGroups[] = $cGroup;
+ 				}
+ 
  			// Lets clean up.
  			@ldap_unbind();
                  } else {
***************
*** 450,458 ****
--- 477,521 ----
  		if ('' != $this->email) {
                  	$user->setEmail($this->email);
  		}
+ 		# add groups permissions
+ 		$localAvailGrps = $user->getAllGroups();
+ 		$localUserGrps = $user->getEffectiveGroups();
+ 		# note: $localUserGrps does not need to be updated with $cGroup added,
+ 		#       as $localAvailGrps contains $cGroup only once.
+ 		foreach ($localAvailGrps as $cGroup) {
+ 			# did we once add the user to the group?
+ 			if (in_array($cGroup,$localUserGrps)) { 
+ 			   if ((!$this->hasLDAPGroup($cGroup)) && ($this->isLDAPGroup($cGroup))) {
+ 			      # the ldap group overrides the local group
+ 			      # so as the user is currently not a member of the ldap group, he
shall be removed from the local group
+ 			      $user->removeGroup($cGroup);
+ 			      }
+ 			} else { # no, but maybe the user has recently been added to the ldap group?
+ 				if ($this->hasLDAPGroup($cGroup)) {
+ 					# so use the addGroup function
+ 					$user->addGroup($cGroup);
+ 					# completedfor $cGroup.
+ 				}
+ 			}
+ 		}
          }
  
  	/**
+ 	 * returns true if the last authenticated user is member of this group, else
false
+ 	 * will always return false if the last user did not authenticate
successfully with ldap
+ 	 */
+ 	function hasLDAPGroup($group) {
+ 		return in_array($group, $this->groups);
+ 	}
+ 
+ 	/**
+ 	 * returns true if a ldap group with this name exists, else false
+ 	 * will always return false if the last user did not authenticate
successfully with ldap
+ 	 */
+ 	function isLDAPGroup($group) {
+ 		return in_array($group, $this->allLdapGroups);
+ 	}
+ 	/**
  	 * Return true to prevent logins that don't authenticate here from being
  	 * checked against the local database's password fields.
  	 *
***************
*** 553,559 ****
  			}
  		}
  		//we need to do a subbase search for the entry
! 		$filter = "(member=".$userDN.")";
  		$info=ldap_get_entries($ldapconn,@ldap_search($ldapconn, $groupDN, $filter));
  		return ($info["count"]>=1);
  	}
--- 616,622 ----
  			}
  		}
  		//we need to do a subbase search for the entry
! 		$filter = "(memberUid=".$userDN.")";
  		$info=ldap_get_entries($ldapconn,@ldap_search($ldapconn, $groupDN, $filter));
  		return ($info["count"]>=1);
  	}
Comment 139 Alfons Zitterbacke 2006-11-30 07:55:35 UTC
Created attachment 2798 [details]
Ldap Group Support against 1.0e

as described yesterday.
Comment 140 Johannes 2006-12-04 13:21:38 UTC
Someone have any experiences with Apache 2.2 and the LDAP Patch ?
We have a System where the Patch works fine, but on a new System with the Apache 2.2 nothing works.
Comment 141 Ryan Lane 2006-12-04 14:18:02 UTC
(In reply to comment #140)
> Someone have any experiences with Apache 2.2 and the LDAP Patch ?
> We have a System where the Patch works fine, but on a new System with the
Apache 2.2 nothing works.

I haven't tried the plugin with Apache 2.2; however, I have no clue why the
plugin wouldn't work with it. The plugin doesn't use anything Apache specific.
Make a section on the discussion page on meta and we'll investigate this further
(you didn't exactly give me much to work with). Since this is only for bugs and
release notices, I'll post the bug/bugfix here whenever we figure out what it is.
Comment 142 Ryan Lane 2006-12-04 19:15:20 UTC
Created attachment 2823 [details]
Version 1.1a of the LdapAuthentication.php plugin (for Mediawiki 1.6+)

This is a major version update of the plugin. A number of options have changed
syntax, and a new form of authentication, using autoauthenticate, has been
added. Updated documentation should follow shortly; you may not want to use
this version until the documentation is available. The following has changed
with this version:

# Fixed bug in getGroups, searchNestedGroups, and isMemberOfRequiredLdapGroup
where warnings are thrown if no groups are found. This was a symptom of a
problem in Comment #133 (this would not fix that issue however).
# Fixed bug with pulled preferences not being saved in the local database.
# Options have changed to work for multiple domains. All options that make
sense with multi-domain support can be configured to work for multiple domains.

# Smartcard/CAC support has been added to the plugin using the AutoAuthenticate
hook.
#* Most options supported by password authentication are supported in smartcard
authentication
#* Only a single smartcard domain can be used due to the way AutoAuthenticate
works; however, smartcard authentication and password authentication can be
mixed allowing multiple domains through the use of clever hackery
#* Smartcard authentication does not have to be turned on for the entire
server, but can instead be turned on for certain locations, or even specific
wiki pages

Smartcard authentication requires the getCanonicalName() function which is only
available in MediaWiki 1.6+. Do not use this version of the plugin for
mediawiki 1.5 as it has not been tested and will not be supported; instead,
please use version 1.0h.
Comment 143 Michael Kirschenbaum 2006-12-06 14:36:13 UTC
I receive this error the first time someone logs into the wiki.   After a
refresh it is fine. 

Fatal error: Call to a member function on a non-object in
c:\inetpub\wwwroot\wiki\includes\SpecialUserlogin.php on line 321

Which points to SpecialUserlogin.php

line 321-->		if (!$u->checkPassword( $this->mPassword )) {
			$this->mainLoginForm( wfMsg( $this->mPassword == '' ? 'wrongpasswordempty' :
'wrongpassword' ) );
			return;
		}

Does anyone know a solution?

Comment 144 Ryan Lane 2006-12-06 14:44:54 UTC
(In reply to comment #143)
> I receive this error the first time someone logs into the wiki.   After a
> refresh it is fine. 

1: Don't change ANY of the information associated with this plugin in the
bugzilla, ever; you don't manage this plugin
2: This bugzilla page is for the LDAP plugin, not SpecialUserlogin
3: You didn't provide any information about your environment (like versions of
stuff)
4: This isn't a support forum; if you can't be bothered to pay attention to the
other comments that chastise people for asking support questions here, why
should I be bothered to pay attention to your problem?

You should probably post this to the mediawiki-l email list, taking into account
#3 in the above list. Unless you have a specific bug with the LdapAuthentication
plugin, don't post here.
Comment 145 Ryan Lane 2006-12-06 22:14:30 UTC
Created attachment 2830 [details]
Version 1.1b of the LdapAuthentication.php plugin (for Mediawiki 1.6+)

This is a bugfix update of the LdapAuthentication plugin.

There was an issue with user's preferences being overwritten when
$wgLDAPRetrievePrefs was not set, or was set to false. The issue should only
have affected 1.1a; 1.0h should not be affected.
Comment 146 Alastair Hole 2006-12-13 19:21:17 UTC
Created attachment 2857 [details]
Patch to 1.1b including hacks to support NTLM
Comment 147 Alastair Hole 2006-12-13 19:23:22 UTC
Comment on attachment 2857 [details]
Patch to 1.1b including hacks to support NTLM

For Ryan's perusal, with a view to possibly include NTLM support
Comment 148 Ryan Lane 2006-12-22 21:49:55 UTC
Created attachment 2924 [details]
Version 1.1c of the LdapAuthentication.php plugin (for Mediawiki 1.6+)

This is a bugfix and update version of the plugin (and an early christmas
present to all the enterprises out there). The following has been
changed/added:

* Added support for Mediawiki security groups based upon LDAP groups
* Added an option to disable auto-creation of accounts
($wgLDAPDisableAutoCreate)
* Fixed TLS/SSL issue discussed in the Suggestions section on the Meta page
** Removed options $wgLDAPUseSSL and $wgLDAPUseTLS; added option
$wgLDAPEncryptionType (a string) with allowed values "ssl", "tls", and "clear"
* Moved $wgLDAPLowerCaseUsername a little higher up in the authentication chain

* Added $wgLDAPGroupUseRetrievedUsername so that you can use the exact username
pulled from LDAP to search for groups
* Changed $wgLDAPUseSmartcardAuth to $wgLDAPAutoAuthMethod (a string); this
will allow users to define which type of auto authenticate methods they would
like to use. Smartcard auth will only be available at first, but other methods
will follow.
* Changed $wgLDAPGroupLowerCaseUsername to allow for multiple domains
* Moved authenticate part of smartcard login out of getCanonicalName to the
SSLAuth function (I have no clue what I was thinking before ;) )

Updated documentation to follow at the usual spot. It may be a good idea to
wait until the documentation is updated before using this version. Hopefully
I'll have the documentation updated today.
Comment 149 Antoine Musso 2007-01-10 10:55:02 UTC
Ryan, can't you get subversion access to commit that in the extension
directory at http://svn.wikimedia.org/viewvc/mediawiki/trunk/extensions/

That might be easier to get than using a bug report ?
Comment 150 Hermann Gottschalk 2007-01-11 16:22:47 UTC
(In reply to comment #129)
> (In reply to comment #128)
> > When will this adjustment be made? Meanwhile i did a dirty hack, which only
> > works for our environment...
> 
> Sorry, I've been out of the country, and my laptop was broken, so I haven't had
> much of a chance to work on this. Hopefully I'll have a new release soon. I'll
> try to have one out in the next couple of weeks.


What's about this?
Comment 151 Ryan Lane 2007-01-11 18:45:38 UTC
(In reply to comment #150)
> What's about this?

Huh? If you are asking whether or not this was added... yes it was. Otherwise I
don't know what you mean.
Comment 152 Ryan Lane 2007-01-11 19:28:22 UTC
(In reply to comment #149)
> Ryan, can't you get subversion access to commit that in the extension
> directory at http://svn.wikimedia.org/viewvc/mediawiki/trunk/extensions/
> 
> That might be easier to get than using a bug report ?

*shrug*

This has been a pretty easy way to do it so far. I use a subversion server
locally and send ready updates here. This also notified interested parties when
a new version is ready. If the developers would rather me use svn, and close
this ticket, I'm fine with that too. For the time being I'll keep the process
the same as to not confuse people who are used to coming here.
Comment 153 Russ Lavoie 2007-01-23 19:32:18 UTC
I am having a problem getting mediawiki 1.9.0 working with this plugin.  I
downloaded the above that Ryan posted and added the below to the
Localsettings.php file:

require_once( 'LdapAuthentication.php' );
$wgAuth = new LdapAuthenticationPlugin();

$wgLDAPDomainNames = array("domain");
$wgLDAPServerNames = array(
        "domain"=>"server.domain.com","server.domain.com");
$wgLDAPUseLocal = false;


# LDAP BIND info

$wgLDAPProxyAgent = array(
        "domain"=>"cn=ldapquery,cn=Users,dc=domain,dc=com");
$wgLDAPProxyAgentPassword = array(
        "domain"=>"passwordgoeshere");

# LDAP Login Restrictions

$wgLDAPRequiredGroups = array(
        "domain"=>array("cn=wikigroup,ou=Groups,dc=domain,dc=com"));

$wgLDAPGroupSearchNestedGroups = array(
        "domain"=>true);


I see traffic but no errors on the Windows server... 

Can I get some assistance?
Comment 154 Chris Porter 2007-01-23 20:08:29 UTC
add $wfLDAPDebug = 3 to your LocalSettings.php file. I suspect it is complaining
about not being able to update user preferences. The way it is designed it wants
to update user preferences and write into the LDAP database. If you create a
"local" user account with the same name and password (to be secure) it should work.
Comment 155 Ryan Lane 2007-01-23 23:15:41 UTC
(In reply to comment #154)
> add $wfLDAPDebug = 3 to your LocalSettings.php file. I suspect it is complaining
> about not being able to update user preferences. The way it is designed it wants
> to update user preferences and write into the LDAP database. If you create a
> "local" user account with the same name and password (to be secure) it should
work.

*Sigh*. Maybe I *should* shut this bug page down and switch to svn... This isn't
the support page...

There is an outstanding bug with MediaWiki 1.9. The SpecialUserlogin.php and
User.php changes with regards to passwords conflict with authentication plugins.

Authentication plugins should return false if users aren't allowed to change
passwords, but the change password function in the plugin shouldn't be called
when users aren't allowed to change passwords. This isn't the case currently. I
need to file a bug report, but without being able to test 1.9 right now I can't
test a fix.

For the time being, please use the following workaround:

http://meta.wikimedia.org/wiki/Talk:LDAP_Authentication#Authentication_against_AD_does_not_work_using_1.9

Notice there is another bug that needs a workaround applied as well:

http://meta.wikimedia.org/wiki/Talk:LDAP_Authentication#User_creation_errors.2C_user_still_created

I plan on fixing the latter soon.
Comment 156 Ryan Lane 2007-02-02 22:06:30 UTC
Created attachment 3173 [details]
Version 1.1d of the LdapAuthentication.php plugin (for Mediawiki 1.6+)

This is a bugfix version of the plugin. The following has changed:

* Get the user's DN if straight binds are used with AD style binds
(DOMAIN\\USER-NAME, USER-NAME@DOMAIN) to allow for group checking, group
pulling, retrieving preferences, etc. 
* Fix the problem with group based restrictions causing failures even when they
aren't being used.
* Allow $wgLDAPRequiredGroups to have uppercase letters, and automatically
convert to lowercase for comparison to search results. 
* Fix part of the compability issues with MediaWiki 1.9 
* Fix Talk:LDAP_Authentication#Bug_in_hasLDAPGroup.28.29_and_isLDAPGroup.28.29 


If you want the plugin to pull the userdn when using AD style straight binds,
you'll need to set $wgLDAPBaseDNs, and $wgLDAPSearchAttributes for the domain.
Comment 157 Walter Padron 2007-02-12 17:32:15 UTC
Ryan, on Windows Server 2003 SP1, IIS 6, mediawiki 1.10, PHP 5.2.0,
LDAPAuthentication 1.1d

Problem: The getAllGroups function is not returning empty AD groups resulting in
incorrect user access permissions.

IMHO, must work this way, if a user has a wikimedia effective group 'nsGroup'
and the AD group 'nsGroup' has no members, the nsGroup must be removed from
user's effective groups because the user don't belongs to the AD group.

* As a workaround i make a sysop a member of all AD groups used for sync.
Comment 158 Garen 2007-02-19 23:42:21 UTC
Using MediaWiki 1.9.x, LdapAuthentication.php version 1.1d, and the the patch
listed here:

http://bugzilla.wikipedia.org/show_bug.cgi?id=8815

I can now successfully login against LDAP/AD!  I do however see these two
warnings after login:

Notice: Undefined variable: updateLDAP in
/var/www/swtools/mediawiki-1.9.0/extensions/LdapAuthentication.php on line 596
Notice: Undefined variable: mailPassword in
/var/www/swtools/mediawiki-1.9.0/extensions/LdapAuthentication.php on line 596

It looks like those two variables aren't defined.  If I add a simple "global
$updateLDAP, $mailPassword;" at the top of the function, the warnings go away.
Comment 159 Ryan Lane 2007-02-21 15:40:41 UTC
(In reply to comment #158)
> Using MediaWiki 1.9.x, LdapAuthentication.php version 1.1d, and the the patchlisted 
here:http://bugzilla.wikipedia.org/show_bug.cgi?id=8815I can now successfully login against LDAP/AD! I do however see 
these twowarnings after login:Notice: Undefined variable: updateLDAP in/var/www/swtools/mediawiki-
1.9.0/extensions/LdapAuthentication.php on line 596Notice: Undefined variable: mailPassword 
in/var/www/swtools/mediawiki-1.9.0/extensions/LdapAuthentication.php on line 596It looks like those two variables 
aren't defined. If I add a simple "global$updateLDAP, $mailPassword;" at the top of the function, the warnings go 
away.

Ah. Yeah, I see that. Neither of the variables are ever getting initialized. The fix is to add:

                $updateLDAP = false;
                $mailPassword = false;

before the if statements, so that the defaults get set (and the variables get initialized). This will be fixed next 
release.
Comment 160 Christian Neubauer 2007-02-23 16:42:04 UTC
Ryan,

I'm using your extension with our PKI infrastructure (via the smartcard code)
and everything works fine.  But for MediaWiki 1.9.1, I had to modify the
function SSLAuth() to make a new user before User::LoadFromSession is called
since this function is not ... whats the term... a static function?  It makes
references to $this now.  So anyway, I changed SSLAuth() to make an anonymous
user $tmpuser = new User(); and then called $tmpuser->LoadFromSession() in the
if statement below where $tmpuser->isLoggedIn() was being called
(LoadFromSession returns true if the user is logged in.)
Comment 161 Jason Adolf 2007-02-26 04:49:19 UTC
Ryan,

I left you a PM on mwusers.com.  Here is the problem we are experiencing with the current plugin.

http://www.mwusers.com/forums/showthread.php?t=2812

many thanks,

jA
Comment 162 Christian Neubauer 2007-03-02 14:06:53 UTC
Another bug with 1.9.1 and 1.1d using PKI authentication (smartcard auth).  When
a user attempts to log in and exists in the LDAP but not in the local database,
I get an infinite unstub loop (see the header of includes/StubObject.php for
more info).  It's caused by SSLAuth creating a new LoginForm (~line 1551).  If
the function gets to that point, it realizes the user is in the LDAP but not in
the local database and it tries to setup a new LoginForm to init the user. 
However, something in the LoginForm chain fires the AutoAuthenticate hook again
which calls SSLAuth again hence the loop.  I worked around this by adding a flag
to wgAuth called isBusy which gets set at the start of SSLAuth() and cleared
before that function returns.  Then at the start of the function I check to see
if its set and if so return.  This ensures that SSLAuth is never called twice in
one request.
Comment 163 Ryan Lane 2007-03-02 14:25:24 UTC
(In reply to comment #162)
> Another bug with 1.9.1 and 1.1d using PKI authentication (smartcard auth). Whena user attempts to log in and exists 
in the LDAP but not in the local database,I get an infinite unstub loop (see the header of includes/StubObject.php 
formore info). It's caused by SSLAuth creating a new LoginForm (~line 1551). Ifthe function gets to that point, it 
realizes the user is in the LDAP but not inthe local database and it tries to setup a new LoginForm to init the user. 
However, something in the LoginForm chain fires the AutoAuthenticate hook againwhich calls SSLAuth again hence the 
loop. I worked around this by adding a flagto wgAuth called isBusy which gets set at the start of SSLAuth() and 
clearedbefore that function returns. Then at the start of the function I check to seeif its set and if so return. 
This ensures that SSLAuth is never called twice inone request.

Thanks for the info on SSLAuth and 1.9.1. I'm not able to move to php5 yet, so I can't test anything above MediaWiki 
1.6.x right now. Hopefully in a couple months I'll be able to start testing higher versions of MediaWiki, and these 
problems will go away. Unfortunately, I won't be able to add your changes in until I've been able to test them.

I'll add these to the list of things I need to fix.

Comment 164 Ryan Lane 2007-03-04 06:55:33 UTC
The plugin will no longer be released on this bugzilla page. Instead, the
software will be hosted in MediaWiki's svn, new version releases will be
announced on mediawiki-l, support will be given at:
http://meta.wikimedia.org/wiki/Talk:LDAP_Authentication and plugin information
(including links to downloads) will be maintained at:
http://meta.wikimedia.org/wiki/LDAP_Authentication
Comment 165 Michael Newton 2007-03-12 22:42:47 UTC
Since I can't update the article at MW, I'll add this here.  Trying to apply
group requirements to users, I was unable to find certain users in any groups
(in getGroups() function.)  It turns out that if a DN has any special characters
in it, they need to be escaped.  I made this change from 1.1d, and have had
success authenticating some users who had parentheses in their names:

@@ -1214,7 +1214,8 @@
                $nameattribute = $wgLDAPGroupNameAttribute[$_SESSION['wsDomain']];

                //Search for the groups this user is in
-               $filter = "(&($attribute=$dn)(objectclass=$objectclass))";
+               $filterdn = ($dn == '*') ? '*' : $filterdn =
preg_replace('/([\\*\\(\\)\\\])/', '\\\\$1', $dn);
+               $filter = "(&($attribute=$filterdn)(objectclass=$objectclass))";

                $this->printDebug("Search string: $filter",2);

The ldap_search() function on line 1229 is what was failing; it would be nice if
that were checked for a non-boolean false value before proceeding with the search.
Comment 166 Ryan Lane 2007-03-13 13:10:33 UTC
(In reply to comment #165)
> Since I can't update the article at MW, I'll add this here.  Trying to apply
> group requirements to users, I was unable to find certain users in any groups
> (in getGroups() function.)  It turns out that if a DN has any special characters
> in it, they need to be escaped.  I made this change from 1.1d, and have had
> success authenticating some users who had parentheses in their names:
> 
> @@ -1214,7 +1214,8 @@
>                 $nameattribute = $wgLDAPGroupNameAttribute[$_SESSION['wsDomain']];
> 
>                 //Search for the groups this user is in
> -               $filter = "(&($attribute=$dn)(objectclass=$objectclass))";
> +               $filterdn = ($dn == '*') ? '*' : $filterdn =
> preg_replace('/([\\*\\(\\)\\\])/', '\\\\$1', $dn);
> +               $filter = "(&($attribute=$filterdn)(objectclass=$objectclass))";
> 
>                 $this->printDebug("Search string: $filter",2);
> 
> The ldap_search() function on line 1229 is what was failing; it would be nice if
> that were checked for a non-boolean false value before proceeding with the search.

You can't update a page that is writable by anyone in the world? Did you even
bother to read any of the documentation? This is something that is going to be
fixed next release; if you read the roadmap you'd have noticed this, or if you
took at look at the talk page, you'd also have noticed that many people have
sent in fixes for this (and I mentioned specifically that I'd be using one of
the fixes).

Do *not* comment on this closed bug, it is closed for a reason.

Note You need to log in before you can comment on or make changes to this bug.


Navigation
Links